AccessControlListNotSupported エラーの解決(AWS S3 バケット ACL作成時)
問題の説明
Terraform で aws_s3_bucket_acl
リソースをデプロイしようとすると、以下のエラーが発生します:
Error: error creating S3 bucket ACL for bucket-name: AccessControlListNotSupported: The bucket does not allow ACLs
status code: 400
このエラーは2023年4月以降のAWSのセキュリティ変更が原因です。AWSはデフォルトでS3バケットのACL(アクセスコントロールリスト)を無効化するように変更しました。
背景
AWSはセキュリティ強化のため、以下を実施:
- 新規バケットでのACLデフォルト無効化
- オブジェクト所有権設定の導入
- [BucketOwnerEnforced] がテラフォームのデフォルト設定
以下のドキュメントで変更が確認できます:
Amazon S3 セキュリティ変更 (2023年4月)
解決方法
方法 1: 所有権制御の設定(推奨)
aws_s3_bucket_ownership_controls
リソースを追加し、オブジェクト所有権を適切に設定します:
resource "aws_s3_bucket_ownership_controls" "example" {
bucket = aws_s3_bucket.my_bucket.id
rule {
object_ownership = "BucketOwnerPreferred" # ACLを有効にする設定
}
}
resource "aws_s3_bucket_acl" "example" {
bucket = aws_s3_bucket.my_bucket.id
acl = "private"
# 依存関係を明示(所有権設定が先に作成されることを保証)
depends_on = [aws_s3_bucket_ownership_controls.example]
}
重要
リソースの作成順序が影響します。depends_on
で所有権設定がACLより先に適用されるように強制してください。
方法 2: バケットポリシーを使用(AWS推奨)
ACLの代わりにバケットポリシーを使用する別アプローチ:
resource "aws_s3_bucket_policy" "example" {
bucket = aws_s3_bucket.my_bucket.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = "*"
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.my_bucket.arn}/*"
}
]
})
}
terraform-aws-modules/s3-bucket モジュール使用時
モジュールを使用している場合、以下の設定を追加:
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "~> 3.0"
bucket = "my-bucket"
# ACLを有効化する設定
control_object_ownership = true
object_ownership = "BucketOwnerPreferred"
}
エラーの根本原因
解決策を理解するためのキーポイント:
所有権設定の不一致
TerraformのデフォルトはBucketOwnerEnforced
(ACL完全無効)だが、ACLリソースには互換性がないリソース適用順序問題
ACLリソースが所有権設定より先に適用されるとエラーが発生有効な所有権設定値
ACLを使うには次の中から選択必須:ObjectWriter
BucketOwnerPreferred
非推奨設定
BucketOwnerEnforced
を設定したままACLを使用すると、常にエラーが発生します。両者は互換性がありません。
ベストプラクティス
ACLよりバケットポリシーを優先
セキュリティと細かな制御のため、ACLよりバケットポリシーの使用がAWSから推奨されています所有権設定の明示的定義
モジュール使用時でもcontrol_object_ownership
を常に設定することで動作を予測可能にリソース依存関係の管理
depends_on
で作成順序を制御し、所有権設定が確実に先に適用されるようにする