■ はじめに
Terraformを用いて、S3 + CloudFrontによる静的Webサイト配信環境を構築した際に、CloudFrontのURLへアクセスすると「AccessDenied」エラーが発生しました。
本記事では、その原因と解決方法について解説します。
■ 構成
■ 発生した問題
CloudFrontのディストリビューションドメインにアクセスしたところ、以下のエラーが表示されました。

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
</Error>
■ 原因
主な原因は以下の通りです。
- S3バケットが非公開設定になっている
- CloudFrontからS3へのアクセス権限が不足している
- S3のエンドポイント設定が不適切
■ 解決方法
以下の対応を行うことで解決しました。
■ ① S3をパブリック非公開に設定
resource "aws_s3_bucket_public_access_block" "site" {
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
■ ② CloudFrontのOAC(Origin Access Control)を設定
resource "aws_cloudfront_origin_access_control" "oac" {
name = "s3-oac"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
■ ③ S3バケットポリシーを設定
CloudFrontからのアクセスのみ許可します。
resource "aws_s3_bucket_policy" "site_policy" {
bucket = aws_s3_bucket.site.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "cloudfront.amazonaws.com"
}
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.site.arn}/*"
}
]
})
}
■ ④ S3のエンドポイントに注意
CloudFrontのorigin設定では、以下を使用する必要があります。
domain_name = aws_s3_bucket.site.bucket_regional_domain_name
※ 静的サイトホスティングURL(s3-websiteエンドポイント)は使用できないため注意
■ 学び
今回のトラブルを通じて、以下の点を学びました。
- CloudFrontとS3のアクセス制御の重要性
- OACの役割と設定方法
- エンドポイントの違いによる挙動の差
■ まとめ
CloudFrontとS3を組み合わせた構成では、セキュリティを確保するためにS3を非公開とし、CloudFront経由のみアクセス可能にする設計が重要です。
AccessDeniedが発生した場合は、以下を確認すると解決の糸口になります。
- バケットポリシー
- OAC設定
- エンドポイント設定
