開発日報

窓際エンジニアの開発備忘。日報は嘘です。

【連載】terraform によるAWS環境構築入門 第4回 ~ S3バケットの作成 ~

はじめに

この記事ではterraformを用いたVPC構築・セキュリティグループの作成方法について学びます。
マルチAZにも対応させましょう。

連載記事一覧

本連載での使用技術

  • AWS
  • Docker
  • VPC
  • ECS(fargate)
  • ELB
  • S3
  • IAM
  • Route53
  • RDS
  • ElastiCache
  • codexxx

1. プライベートバケットの作成

バケットの作成

バケット名は全世界で一意であることが必須です。
「private-semigeek-terraform」の部分はお好きな名前に変更してください。
server_side_encryption_configurationで暗号化を有効にしましょう。

# プライベートバケットの定義
resource "aws_s3_bucket" "private" {
  # バケット名は世界で1意にしなければならない
  bucket = "private-semigeek-terraform"

  versioning {
    enabled = true
  }

  # 暗号化を有効
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}

パブリックアクセスのブロック

ブロックパブリックアクセスを設定すると、予期しないオブジェクトの公開を抑止でき ます。privateバケットであれば有効にしましょう。

# ブロックパブリックアクセス
resource "aws_s3_bucket_public_access_block" "private" {
  bucket                  = aws_s3_bucket.private.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

2. パブリックバケットの作成

バケットの作成

次にパブリックバケットを作成してみましょう

アクセス権は「acl」で設定します。ACLのデフォルトは「private」なのでリスト6.3は明示的に「public-read」を指定し、インターネットからの読み込みを許可しています。
cors_ruleで許可するオリジンやメソッドを設定します

resource "aws_s3_bucket" "public" {
  bucket = "public-semigeek-terraform"
  acl    = "public-read"

  cors_rule {
    allowed_origins = ["https://example.com"]
    allowed_methods = ["GET"]
    allowed_headers = ["*"]
    max_age_seconds = 3000
  }
}

3. ログバケットの作成

バケットの作成

ここでは、今後必要になる ALB のアクセスログ用バケットを作成します。
「lifecycle_rule」を設定することで、60日経過したファイルを自動的に削除し、無限にファイルが増えないようにします。

resource "aws_s3_bucket" "alb_log" {
  bucket = "alb-log-semigeek-terraform"

  lifecycle_rule {
    enabled = true

    expiration {
      days = "60"
    }
  }
}

バケットポリシー

バケットポリシーで、S3 バケットへのアクセス権を設定します。
ALB のような AWS のサービスから、S3 へ書き込みを行う場合に必要です。
バケットポリシーはリスト 6.5 のように実装します。

ALBの場合は、AWSが管理しているアカウントから書き込みます。
そのため「identifiers」゙書き込みを行うアカウントID(582318560864)を指定しています。
ALBアカウントIDはリージョンごとに異なります。

# バケットポリシーの定義
resource "aws_s3_bucket_policy" "alb_log" {
  bucket = aws_s3_bucket.alb_log.id
  policy = data.aws_iam_policy_document.alb_log.json
}

data "aws_iam_policy_document" "alb_log" {
  statement {
    effect    = "Allow"
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::${aws_s3_bucket.alb_log.id}/*"]

    principals {
      type        = "AWS"
      identifiers = ["582318560864"]
    }
  }
}

4. まとめ(最終成果物の作成)

以上の解説をまとめて、最終成果物を作成しましょう。
フォルダ構成は以下の通り。
今回新しくS3.tfが追加になります。

exaple
 |
 |--- iam_role
 |    |___ main.tf
 |
 |--- security_group
 |    |___ main.tf
 |
 |--- main.tf
 |
 |--- network.tf
 |
 |___ S3.tf (新)

バケット定義

「S3.tf」に上記のバケット定義を記載しましょう。
以下のようになります。

# プライベートバケットの定義
resource "aws_s3_bucket" "private" {
  # バケット名は世界で1意にしなければならない
  bucket = "private-semigeek-terraform"

  versioning {
    enabled = true
  }

  # 暗号化を有効
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}

# ブロックパブリックアクセス
resource "aws_s3_bucket_public_access_block" "private" {
  bucket                  = aws_s3_bucket.private.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# パブリックバケットの定義
resource "aws_s3_bucket" "public" {
  bucket = "public-semigeek-terraform"
  acl    = "public-read"

  cors_rule {
    allowed_origins = ["https://example.com"]
    allowed_methods = ["GET"]
    allowed_headers = ["*"]
    max_age_seconds = 3000
  }
}

# ログバケットの定義
resource "aws_s3_bucket" "alb_log" {
  bucket = "alb-log-semigeek-terraform"

  lifecycle_rule {
    enabled = true

    expiration {
      days = "60"
    }
  }
}

# バケットポリシーの定義
resource "aws_s3_bucket_policy" "alb_log" {
  bucket = aws_s3_bucket.alb_log.id
  policy = data.aws_iam_policy_document.alb_log.json
}

data "aws_iam_policy_document" "alb_log" {
  statement {
    effect    = "Allow"
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::${aws_s3_bucket.alb_log.id}/*"]

    principals {
      type        = "AWS"
      identifiers = ["582318560864"]
    }
  }
}

5. 実行

まずはinitしましょう。これをやらないと、モジュールの呼び出しができません。

$ terraform init

実行計画の確認。前回にも書きましたが、破壊的な変更が入っていないか入念に確認しましょう。

$ terraform plan

実行。実行されたら、AWSの管理画面から確認しましょう。
うまくいっていればIAMページ左上の「Search IAM」のフォームに「describe-regions-for-ec2」と入力て検索ができるはずです。

$ terraform apply