CloudFront 経由で公開している S3 に Web フォントを置いて、それをクロスオリジンで利用できるようにするために Access-Control-Allow-Origin ヘッダーを返すように設定したときのメモ。
以下の 2 通りの方法が考えられるでしょうか
- CloudFront のレスポンスヘッダーポリシーで設定
- S3 で CORS を設定して CloudFront から S3 へ Origin を渡す
CloudFront のレスポンスヘッダーポリシーで設定
CloudFront のビヘイビアで次のようなレスポンスヘッダーポリシーを設定します。
resource "aws_cloudfront_response_headers_policy" "cors" { name = "example-cors" comment = "example-cors" cors_config { access_control_allow_methods { items = ["GET"] } access_control_allow_origins { items = ["example.com"] } access_control_allow_headers { items = ["*"] } access_control_allow_credentials = false origin_override = true } } resource "aws_cloudfront_distribution" "main" { // ...snip.... response_headers_policy_id = aws_cloudfront_response_headers_policy.cors.id // ...snip.... }
次のように origin ヘッダーを渡してやれば access-control-allow-origin が返ってきます。
curl -I -XGET https://xxx.cloudfront.net/example.woff -H origin:example.com | grep access-control-allow-origin #=> access-control-allow-origin: example.com
任意の origin を許可して OK なら、カスタムレスポンスヘッダーポリシーを用意しなくても SimpleCORS などのマネージドポリシーでも良いと思います。
data "aws_cloudfront_response_headers_policy" "cors" { name = "Managed-SimpleCORS" }
S3 で CORS を設定して CloudFront から S3 へ Origin を渡す
S3 で次のように CORS を設定します。
resource "aws_s3_bucket_cors_configuration" "main" { bucket = aws_s3_bucket.main.id cors_rule { allowed_methods = ["GET"] allowed_origins = ["example.com"] } }
そのうえで CloudFront のキャッシュポリシーで origin をキャッシュキーに含めます
resource "aws_cloudfront_cache_policy" "origin" { name = "example-origin" comment = "example-origin" min_ttl = 1 max_ttl = 31536000 default_ttl = 86400 parameters_in_cache_key_and_forwarded_to_origin { headers_config { header_behavior = "whitelist" headers { items = ["origin"] } } cookies_config { cookie_behavior = "none" } query_strings_config { query_string_behavior = "none" } } } resource "aws_cloudfront_distribution" "main" { // ...snip.... cache_policy_id = aws_cloudfront_cache_policy.origin.id // ...snip.... }
次のように origin ヘッダーを渡してやれば access-control-allow-origin が返ってきます。
curl -I -XGET https://xxx.cloudfront.net/example.woff -H origin:example.com | grep access-control-allow-origin #=> access-control-allow-origin: example.com
なお、キャッシュポリシーのキャッシュキーに origin を含めなくても、オリジンリクエストポリシーに origin を含めれば origin 付きのリクエストに対して access-control-allow-origin が返るようになります。ただその場合、リクエストの origin が違っていてもキャッシュが共通になるため、origin が無かったり違ったりするリクエストを元に access-control-allow-origin が無いレスポンスがキャッシュされてしまうと、正しい origin を送ったとしてもキャッシュから access-control-allow-origin が無いレスポンスが返されてしまうため、ダメです。
さいごに
CloudFront のレスポンスヘッダーポリシーで設定する方が、CloudFront がリクエストの origin を見て共通のキャッシュから access-control-allow-origin を出しわけてくれるので、こちらの方が良いですね。
S3 で CORS を使うのは CloudFront でレガシーキャッシュ設定しか使えなかった頃の名残で、もう使うことは無さそうです(CloudFront を噛まさない裸の S3 なら別ですけど)。