吉川@広島です。
今回はCDKでCloudFrontにCORSレスポンスヘッダを設定する方法を紹介します。
環境
- aws-cdk-lib 2.46.0
- constructs 10.1.43
コード
CloudFront ResponseHeadersPolicyを利用することで比較的簡単に設定できます。
import * as cdk from "aws-cdk-lib"
import { Construct } from "constructs"
export class CloudfrontStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props)
const webBucket = new cdk.aws_s3.Bucket(this, "webBucket", {
removalPolicy: cdk.RemovalPolicy.DESTROY,
})
const originAccessIdentity = new cdk.aws_cloudfront.OriginAccessIdentity(
this,
"originAccessIdentity"
)
const distribution = new cdk.aws_cloudfront.Distribution(
this,
"distribution",
{
defaultRootObject: "index.html",
errorResponses: [
{
httpStatus: 404,
responseHttpStatus: 200,
responsePagePath: "/index.html",
ttl: cdk.Duration.seconds(0),
},
{
httpStatus: 403,
responseHttpStatus: 200,
responsePagePath: "/index.html",
ttl: cdk.Duration.seconds(0),
},
],
defaultBehavior: {
allowedMethods: cdk.aws_cloudfront.AllowedMethods.ALLOW_GET_HEAD,
cachePolicy: cdk.aws_cloudfront.CachePolicy.CACHING_DISABLED,
viewerProtocolPolicy:
cdk.aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
origin: new cdk.aws_cloudfront_origins.S3Origin(webBucket, {
originAccessIdentity,
}),
responseHeadersPolicy: new cdk.aws_cloudfront.ResponseHeadersPolicy(
this,
"responseHeadersPolicy",
{
corsBehavior: {
accessControlAllowOrigins: ["https://example.com"],
accessControlAllowHeaders: ["*"],
accessControlAllowMethods: ["ALL"],
accessControlAllowCredentials: false,
originOverride: true,
},
}
),
},
}
)
new cdk.aws_s3_deployment.BucketDeployment(this, "webDeploy", {
sources: [
cdk.aws_s3_deployment.Source.data(
"/index.html",
"<html><body><h1>Hello World</h1></body></html>"
),
],
destinationBucket: webBucket,
distribution: distribution,
distributionPaths: ["/*"],
})
}
}
ポイントとなるのは見たまんまで、
responseHeadersPolicy: new cdk.aws_cloudfront.ResponseHeadersPolicy(
this,
"responseHeadersPolicy",
{
corsBehavior: {
accessControlAllowOrigins: ["https://example.com"],
accessControlAllowHeaders: ["*"],
accessControlAllowMethods: ["ALL"],
accessControlAllowCredentials: false,
originOverride: true,
},
}
),
の箇所になります。
やってみる
それでは上記をデプロイします。
npx cdk deploy
curlコマンドで動作確認します。
curl -X OPTIONS -H "Origin: https://example.com" -H "Access-Control-Request-Method: GET" --dump-header - https://xxxxxxxxxxxxx.cloudfront.net
HTTP/2 200
content-type: text/html
content-length: 46
date: Sun, 19 Feb 2023 09:42:46 GMT
last-modified: Sun, 19 Feb 2023 09:28:50 GMT
etag: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
x-amz-server-side-encryption: AES256
accept-ranges: bytes
server: AmazonS3
x-cache: Error from cloudfront
via: 1.1 xxxxxxxxxxxxxxxxxx.cloudfront.net (CloudFront)
x-amz-cf-pop: KIX50-P3
x-amz-cf-id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
access-control-allow-origin: https://example.com
vary: Origin
<html><body><h1>Hello World</h1></body></html>
access-control-allow-originが返ってくることが確認できました。
ハマった点
当初 accessControlAllowMethods
に誤った値( ALL
ではなく *
)を設定していたせいで、
Stack Deployments Failed: Error: The stack named IacStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Internal error reported from downstream service during operation 'AWS::CloudFront::ResponseHeadersPolicy'.
というエラーが出ました。どのプロパティがNGなのか分からないメッセージで少しハマったのですが、ググった過程で類似のエラーに困っているIssueを発見し、
「この場合はCloudFormationでは内部エラーとしか出ないようだ。UIでは詳細なエラーが見れる」(要約)とのことだったので、マネコンから手動でリソース設定を試したところ間違いに気づくことができました。
このようにCloudFormation/CDKというかIaCツールはたまにエラーメッセージが分かりづらいことがある気がします。その際はIaC操作のみで原因究明することに固執せずマネコンからリソースを作ってデバッグしてみましょう。
参考
- Issue creating AWS::CloudFront::ResponseHeadersPolicy · Issue #1156 · aws-cloudformation/cloudformation-coverage-roadmap
- [UPDATE] Amazon CloudFrontでResponse headers policiesがサポートされました! | DevelopersIO
- L@EとCF2が不要に?!CloudFront単体でレスポンスヘッダーが設定できるようになりました | DevelopersIO
- cURL でレスポンスヘッダを表示する - Qiita
- CloudFrontでCORS設定をするための3つのポリシーについて