🌍 TerraformでCloudFrontのディストリビューションを設定するシンプルな手順

# 📌 概要

Terraform を使って AWS の CloudFront を設定する方法 を解説します



# 📌 事前に準備するもの

##### main.tf

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

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

##### S3

S3のバケットを作成していない方は以下の記事を参考に作成します

https://qiita.com/nobumory/items/cdb00a7eb7e05b342737


## 📌 コード

```hcl
resource "aws_cloudfront_origin_access_control" "origin_access_control" {
  name                              = "sample-domain-oac"
  description                       = "OAC for sample domain S3"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "cloudfront_distribution" {
  enabled = true
  comment = "CloudFront for sample domain"

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

  default_cache_behavior {
    target_origin_id         = "s3-sample"
    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"
      }
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }
}

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
      ]
    }
  }
}

resource "aws_s3_bucket_policy" "s3_bucket_policy" {
  bucket = aws_s3_bucket.s3_bucket.id
  policy = data.aws_iam_policy_document.s3_policy.json
}
```

### 📌 CloudFront の OAC を作成

CloudFrontにS3へのアクセス権を与えます

```hcl
resource "aws_cloudfront_origin_access_control" "origin_access_control" {
  name                              = "sample-domain-oac"
  description                       = "OAC for sample-domain S3"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}
```

### 📌 CloudFront ディストリビューションの作成

```hcl
resource "aws_cloudfront_distribution" "cloudfront_distribution" {
  enabled = true
  comment = "CloudFront for sample-domain"

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

  default_cache_behavior {
    target_origin_id         = "s3-sample"
    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"
      }
    }
  }

  # --- ACM 証明書未設定のため 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"
    }
  }
}
```
### 📌 S3 のバケットポリシーを設定

「CloudFront だけが S3 にアクセスできる」ようにするポリシーを作ります 🔐✨  

```hcl
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
      ]
    }
  }
}

resource "aws_s3_bucket_policy" "s3_bucket_policy" {
  bucket = aws_s3_bucket.s3_bucket.id
  policy = data.aws_iam_policy_document.s3_policy.json
}
```

📌 解説

### S3 バケットの作成

aws_s3_bucket.sample は CloudFront のオリジンとなる S3 バケット です。

### CloudFront の OAC（オリジンアクセス制御）を作成

aws_cloudfront_origin_access_control.origin_access_control は S3 との安全なアクセスを制御 します。

### CloudFront ディストリビューションの作成

aws_cloudfront_distribution.cloudfront は S3 をオリジンとする CloudFront の CDN を作成 します。

### S3 のバケットポリシーを設定

aws_s3_bucket_policy.sample_policy は CloudFront からのみ S3 へアクセスを許可 するバケットポリシーです。


# 📌 実行

準備ができたら、以下の記事を参考にTerraform を実行しましょう！  

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