🌎 Terraform で AWSのS3を作成しCloudFrontと連携するシンプルな手順

# 📌 概要

AWS の S3 バケットを Terraform で作成を解説します 🎯

# 📌 事前に準備するもの

##### main.tf

main.tf の作成がまだの方は以下の記事を参考にファイルを作成してください。

https://qiita.com/nobumory/items/624275ac0b08660a2637

# 📌 ディレクトリ構成

```
terraform-project/
│── main.tf
│── modules
│   ├── s3
│   │   ├── main.tf
```

# 📌 コード

### main.tf

AWS のプロバイダーを設定し必要なモジュールを読み込みます。

```hcl
provider "aws" {
  region = "ap-northeast-1"
}

module "s3" {
  source = "./s3"
}
```

### s3/main.tf

```hcl
# -------- S3 バケットの作成
resource "aws_s3_bucket" "s3_bucket" {
  bucket = "sandbox-terraform-mory-bucket"

  tags = {
    Name = "sandbox-terraform-mory-bucket"
  }
}

# -------- S3 のパブリックアクセスブロック
resource "aws_s3_bucket_public_access_block" "s3_buckets_access" {
  bucket = aws_s3_bucket.s3_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# -------- S3 のバージョニング設定
resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.s3_bucket.id

  versioning_configuration {
    status = "Enabled"
  }
}

# -------- S3 のライフサイクルポリシー
resource "aws_s3_bucket_lifecycle_configuration" "lifecycle" {
  bucket = aws_s3_bucket.s3_bucket.id

  rule {
    id     = "delete-old-versions"
    status = "Enabled"

    noncurrent_version_expiration {
      noncurrent_days = 30 # 30 日経過した古いバージョンのオブジェクトを削除
    }
  }
}


# -------- S3 の暗号化設定
resource "aws_s3_bucket_server_side_encryption_configuration" "s3_buckets_encryption" {
  bucket = aws_s3_bucket.s3_bucket.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
    bucket_key_enabled = true
  }
}

# -------- Cloudfrontの設定

# CloudFront の OAC (Origin Access Control) の設定
resource "aws_cloudfront_origin_access_control" "origin_access_control" {
  name                              = "sandbox-terraform-mory-bucket-oac"
  description                       = "OAC for sandbox-terraform-mory-bucket S3"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

# CloudFront ディストリビューションの作成
resource "aws_cloudfront_distribution" "cloudfront_distribution" {
  enabled = true
  comment = "CloudFront for sandbox-terraform-mory-bucket"

  origin {
    domain_name              = "${aws_s3_bucket.s3_bucket.id}.s3.amazonaws.com"
    origin_id                = "s3-${aws_s3_bucket.s3_bucket.id}"
    origin_access_control_id = aws_cloudfront_origin_access_control.origin_access_control.id
  }

  # デフォルトのキャッシュ動作設定
  default_cache_behavior {
    target_origin_id         = "s3-${aws_s3_bucket.s3_bucket.id}"
    viewer_protocol_policy   = "redirect-to-https"
    allowed_methods          = ["GET", "HEAD"]
    cached_methods           = ["GET", "HEAD"]
    default_ttl              = 3600
    min_ttl                  = 0
    max_ttl                  = 86400

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }

  # --- CloudFront デフォルトの証明書を使用 ---
  viewer_certificate {
    cloudfront_default_certificate = true
    # acm_certificate_arn      = "arn:aws:acm:us-east-1:123456789012:certificate/xxxx-xxxx-xxxx"
    # ssl_support_method       = "sni-only"
    # minimum_protocol_version = "TLSv1.2_2021"
  }

  # 地域制限（今回はなし）
  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  tags = {
    Name = "sandbox-terraform-mory-bucket"
  }
}


# -------- S3 の CloudFront 用ポリシー設定
data "aws_iam_policy_document" "s3_policy" {
  statement {
    sid = "AllowCloudFrontServicePrincipal"

    principals {
      type        = "Service"
      identifiers = ["cloudfront.amazonaws.com"]
    }

    actions = [
      "s3:GetObject"
    ]

    resources = [
      "${aws_s3_bucket.s3_bucket.arn}/*"
    ]

    condition {
      test     = "StringEquals"
      variable = "AWS:SourceArn"
      values   = [
        aws_cloudfront_distribution.cloudfront_distribution.arn
      ]
    }
  }
}

# S3 バケットポリシーを設定し、CloudFront のみが S3 にアクセスできるようにする
resource "aws_s3_bucket_policy" "s3_bucket_policy" {
  bucket = aws_s3_bucket.s3_bucket.id
  policy = data.aws_iam_policy_document.s3_policy.json
} 
```

[参考リポジトリ]

https://gitlab.com/Morykun/sandbox-terraform

# 📌 実行

準備ができたらコマンド実行しましょう！

1. `terraform init`
2. `terraform plan`
3. `terraform apply`

Terraform関連のコマンドについては以下の記事を参考にしてください ☺️

https://qiita.com/nobumory/items/9f3c84f016fbf37363ed