TerraformでCloudFrontのキャッシュポリシーやオリジンリクエストポリシーの作成・設定をやってみた

2024.05.02

こんにちは、ゲームソリューション部のsoraです。
今回は、TerraformでCloudFrontのキャッシュポリシーやオリジンリクエストポリシーの作成・設定をやってみたことについて書いていきます。

はじめに

CloudFrontのキャッシュキーとオリジンリクエストについて、ビヘイビアごとにパラメータを直接入力して設定するレガシー設定とポリシーで指定する推奨設定があります。
CloudFrontをTerraformで構築する際に検索していると、レガシー設定のものが多く出てきたため、今回は推奨設定で設定していきます。

CloudFrontのポリシーについて

CloudFrontのポリシーには、以下3つのポリシーがあります。

・キャッシュポリシー
キャッシュの保持期間とキャッシュキーの設定をします。
キャッシュキーでは、利用者からCloudFrontへのリクエスト時にキャッシュの条件に含める値を指定します。
全ての条件が一致したときに、同一オブジェクトと判断されて、キャッシュされている内容をレスポンスとして返却します。
指定しない場合は、「CloudFrontにアクセスするためのホスト名」と「リクエストURLのリソース部分(パス、ファイル名、拡張子)」で判断されます。

・オリジンリクエストポリシー
CloudFrontからオリジンへのリクエスト時に、利用者から送信されたヘッダー・クエリ文字列・cookieを付与して送信するかどうかを設定します。
キャッシュポリシーで設定された値は自動的にオリジンに送信されるため、キャッシュキーには含めたくないけどオリジンには送信したい値を定義する用途で使用されます。

・レスポンスヘッダーポリシー
CloudFrontから利用者へのレスポンス時に、追加するHTTPヘッダーを指定します。

コードの解説

コードは以下です。

main.tf

terraform {
    # AWSプロバイダーのバージョン指定
    required_providers {
        aws = {
            source  = "hashicorp/aws"
            version = "~> 5.47.0"
        }
    }
    backend local {
        path = "tmp.tfstate"
    }
}
provider aws {
    region = "ap-northeast-1"
}

# S3バケット(contents)
resource aws_s3_bucket origin_contents {
    bucket = "sora-test-contents-bucket-202405"
}
# ファイルアップロード
resource aws_s3_object object {
    bucket = aws_s3_bucket.origin_contents.id
    key = "index.html"
    source = "file/index.html"
    etag = filemd5("file/index.html")
    content_type = "text/html"
}

# S3バケット(logs)
resource aws_s3_bucket logs {
    bucket = "sora-test-logs-bucket-202405"
}
resource aws_s3_bucket_ownership_controls logs {
    bucket = aws_s3_bucket.logs.id
    rule {
        object_ownership = "BucketOwnerPreferred"
    }
}
# ACLを設定
resource aws_s3_bucket_acl logs {
    bucket = aws_s3_bucket.logs.id
    acl    = "private"
    depends_on = [aws_s3_bucket_ownership_controls.logs]
}

# CloudFrontキャッシュポリシー
resource aws_cloudfront_cache_policy policy {
    name        = "cloudfront-cache-policy-s3-test"
    min_ttl     = 1
    max_ttl     = 6000
    default_ttl = 600
    parameters_in_cache_key_and_forwarded_to_origin {
        headers_config {
            header_behavior = "none"
        }
        cookies_config {
            cookie_behavior = "none"
        }
        query_strings_config {
            query_string_behavior = "none"
        }
        enable_accept_encoding_brotli = true
        enable_accept_encoding_gzip = true
    }
}

# CloudFrontオリジンリクエストポリシー
resource aws_cloudfront_origin_request_policy policy {
    name    = "test-origin-policy"
    headers_config {
        header_behavior = "none"
    }
    cookies_config {
        cookie_behavior = "none"
    }
    query_strings_config {
        query_string_behavior = "none"
    }
}

# CloudFrontレスポンスヘッダー
## マネージドポリシーを指定する場合は、resourceではなくdataでnameのみを指定する
data aws_cloudfront_response_headers_policy managed {
    name    = "Managed-SimpleCORS"
}

# CloudFrontディストリビューション
resource aws_cloudfront_distribution cf_distribution {
    price_class = "PriceClass_200"
    enabled = true
    default_root_object = "index.html"
    http_version = "http2and3"
    # オリジンの設定
    origin {
        domain_name = aws_s3_bucket.origin_contents.bucket_regional_domain_name
        origin_id = aws_s3_bucket.origin_contents.id
        origin_access_control_id = aws_cloudfront_origin_access_control.main.id
    }
    viewer_certificate {
        cloudfront_default_certificate = true
    }
    logging_config {
        include_cookies = true
        bucket          = aws_s3_bucket.logs.bucket_regional_domain_name
        prefix          = "cache-policy-test/"
    }
    # キャッシュの設定
    default_cache_behavior {
        target_origin_id       = aws_s3_bucket.origin_contents.id
        viewer_protocol_policy = "redirect-to-https"
        cached_methods         = ["GET", "HEAD"]
        allowed_methods        = ["GET", "HEAD"]
        compress = true
        # キャッシュポリシー
        cache_policy_id = aws_cloudfront_cache_policy.policy.id
        # オリジンリクエストポリシー
        origin_request_policy_id = aws_cloudfront_origin_request_policy.policy.id
        # レガシーなキャッシュ設定の場合は以下
        # min_ttl = 1
        # max_ttl = 6000
        # default_ttl = 600
        # forwarded_values {
        #     query_string = false
        #     headers      = []
        #     cookies {
        #         forward = "none"
        #     }
        # }
        # レスポンスヘッダーポリシー
        response_headers_policy_id = data.aws_cloudfront_response_headers_policy.managed.id
    }
    # 国ごとのコンテンツ制限がある場合はここで設定(今回はなし)
    restrictions {
        geo_restriction {
            restriction_type = "none"
        }
    }
}

# OACを作成
resource aws_cloudfront_origin_access_control main {
    name                              = "cloudfront-oac"
    origin_access_control_origin_type = "s3"
    signing_behavior                  = "always"
    signing_protocol                  = "sigv4"
}

# S3バケットポリシー
resource aws_s3_bucket_policy allow_access_from_cloudfront {
    bucket = aws_s3_bucket.origin_contents.id
    policy = templatefile("./file/s3_resource_policy.json", {
        s3_arn = aws_s3_bucket.origin_contents.arn,
        cloudfront_arn = aws_cloudfront_distribution.cf_distribution.arn
    })
}

ポリシーの作成

キャッシュポリシー・オリジンリクエストポリシーのそれぞれを作成しています。
レスポンスヘッダーポリシーはマネージドポリシーを参照するため、dataでマネージドポリシー名を指定することで参照しています。
ここでのマネージドポリシー名はポリシー一覧画面で表示される名前ではなく、ポリシーの詳細で見たときの名前です。(Managed-が頭につきます)

main.tf

# CloudFrontキャッシュポリシー
resource aws_cloudfront_cache_policy policy {
    name        = "cloudfront-cache-policy-s3-test"
    min_ttl     = 1
    max_ttl     = 6000
    default_ttl = 600
    parameters_in_cache_key_and_forwarded_to_origin {
        headers_config {
            header_behavior = "none"
        }
        cookies_config {
            cookie_behavior = "none"
        }
        query_strings_config {
            query_string_behavior = "none"
        }
        enable_accept_encoding_brotli = true
        enable_accept_encoding_gzip = true
    }
}

# CloudFrontオリジンリクエストポリシー
resource aws_cloudfront_origin_request_policy policy {
    name    = "test-origin-policy"
    headers_config {
        header_behavior = "none"
    }
    cookies_config {
        cookie_behavior = "none"
    }
    query_strings_config {
        query_string_behavior = "none"
    }
}

# CloudFrontレスポンスヘッダー
## マネージドポリシーを指定する場合は、resourceではなくdataでnameのみを指定する
data aws_cloudfront_response_headers_policy managed {
    name    = "Managed-SimpleCORS"
}

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

作成したポリシーを使用して、ディストリビューションを作成します。
レガシーの場合はコメントアウトしている通り、ディストリビューション内でパラメータを設定していたところ、ポリシーでの設定の場合はポリシーIDを指定します。

main.tf

# CloudFrontディストリビューション
resource aws_cloudfront_distribution cf_distribution {
    price_class = "PriceClass_200"
    enabled = true
    default_root_object = "index.html"
    http_version = "http2and3"
    #オリジンの設定
    origin {
        domain_name = aws_s3_bucket.origin_contents.bucket_regional_domain_name
        origin_id = aws_s3_bucket.origin_contents.id
        origin_access_control_id = aws_cloudfront_origin_access_control.main.id
    }
    viewer_certificate {
        cloudfront_default_certificate = true
    }
    logging_config {
        include_cookies = true
        bucket          = aws_s3_bucket.logs.bucket_regional_domain_name
        prefix          = "cache-policy-test/"
    }
    #キャッシュの設定
    default_cache_behavior {
        target_origin_id       = aws_s3_bucket.origin_contents.id
        viewer_protocol_policy = "redirect-to-https"
        cached_methods         = ["GET", "HEAD"]
        allowed_methods        = ["GET", "HEAD"]
        compress = true
        # キャッシュポリシー
        cache_policy_id = aws_cloudfront_cache_policy.policy.id
        # オリジンリクエストポリシー
        origin_request_policy_id = aws_cloudfront_origin_request_policy.policy.id
        # レガシーなキャッシュ設定の場合は以下
        # min_ttl = 1
        # max_ttl = 6000
        # default_ttl = 600
        # forwarded_values {
        #     query_string = false
        #     headers      = []
        #     cookies {
        #         forward = "none"
        #     }
        # }
        # レスポンスヘッダーポリシー
        response_headers_policy_id = data.aws_cloudfront_response_headers_policy.managed.id
    }
    #国ごとのコンテンツ制限がある場合はここで設定(今回はなし)
    restrictions {
        geo_restriction {
            restriction_type = "none"
        }
    }
}

デプロイ結果

デプロイして構築されたリソースを確認すると、ポリシーとそのポリシーを使用してディストリビューションが作られていることが確認できました。


最後に

今回は、TerraformでCloudFrontのキャッシュポリシーやオリジンリクエストポリシーの作成・設定をやってみたことを記事にしました。
どなたかの参考になると幸いです。