Terraform创建CloudTrail遇S3/KMS权限不足问题求助
问题现象
用Terraform创建关联S3存储日志的CloudTrail时,报错如下:
Error: Error creating CloudTrail: InsufficientEncryptionPolicyException: Insufficient permissions to access S3 bucket $BUCKET_NAME or KMS key arn:aws:kms:eu-west-1:$ACCOUNT_ID:key/1234567890.
其他资源都能正常创建,AWS控制台手动配置完全没问题,但复制控制台生成的权限到Terraform后,还是卡在这里。
核心修复点
1. S3桶策略硬编码值未动态替换
当前cloudtrail-s3-policy.json里直接写死了BUCKET_NAME和ACCOUNT_ID,控制台手动创建时是填实际值,但Terraform需要动态注入这些变量,否则策略里的ARN和实际资源不匹配,CloudTrail自然没权限访问。
改法:
把cloudtrail-s3-policy.json改成模板,用变量占位:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Allow Cloudtrail to access S3 bucket", "Effect": "Allow", "Principal": { "Service": ["cloudtrail.amazonaws.com", "config.amazonaws.com"] }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::${bucket_name}" }, { "Sid": "AWS cloudtrail global", "Effect": "Allow", "Principal": { "Service": ["cloudtrail.amazonaws.com", "config.amazonaws.com"] }, "Action": "s3:*", "Resource": "arn:aws:s3:::${bucket_name}/*" }, { "Sid": "Allow Cloudtrail to write in S3 bucket", "Effect": "Allow", "Principal": { "Service": ["cloudtrail.amazonaws.com", "config.amazonaws.com"] }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::${bucket_name}/*", "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control", "AWS:SourceArn": "arn:aws:cloudtrail:eu-west-1:${account_id}:trail/TRAIL" } } } ] }
然后修改Terraform的S3桶策略资源,用templatefile替换file来传变量:
resource "aws_s3_bucket_policy" "logs" { bucket = aws_s3_bucket.BUCKET_NAME.id policy = templatefile("${path.module}/cloudtrail-s3-policy.json", { bucket_name = aws_s3_bucket.BUCKET_NAME.id, account_id = data.aws_caller_identity.current.account_id }) }
2. KMS策略的SourceArn条件阻碍创建
KMS策略里允许CloudTrail加密日志的语句加了AWS:SourceArn条件,限制只有特定CloudTrail ARN能调用KMS。但Terraform创建CloudTrail时,这个ARN还不存在,导致权限校验失败——控制台是先建CloudTrail再绑KMS,所以没这个问题。
改法:
临时去掉AWS:SourceArn的条件限制(创建完成后可以再收紧):
{ "Sid": "Allow CloudTrail to encrypt logs", "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": "kms:GenerateDataKey*", "Resource": "*", "Condition": { "StringLike": { "kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:${account_id}:trail/*" } } }
3. 显式声明CloudTrail的依赖关系
虽然Terraform会自动处理依赖,但有时候策略生效有延迟,显式声明依赖能确保S3桶策略和KMS策略完全生效后再创建CloudTrail:
resource "aws_cloudtrail" "TRAIL" { name = "TRAIL" cloud_watch_logs_role_arn = aws_iam_role.cloudtrail-cloudwatch-events-role.arn cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.loggroup.arn}:*" enable_log_file_validation = "false" enable_logging = "true" is_multi_region_trail = "false" kms_key_id = aws_kms_key.cloudtrail-logs-kms-key.arn s3_bucket_name = aws_s3_bucket.BUCKET_NAME.id depends_on = [ aws_s3_bucket_policy.logs, aws_kms_key.cloudtrail-logs-kms-key ] }
4. 优化S3公共访问配置
当前S3公共访问配置里ignore_public_acls和restrict_public_buckets设为false,虽然不是直接报错原因,但为了安全建议改成true,避免潜在权限问题:
resource "aws_s3_bucket_public_access_block" "BUCKET_NAME-access" { bucket = aws_s3_bucket.BUCKET_NAME.id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true }
验证步骤
- 执行
terraform plan检查配置是否有语法错误 - 执行
terraform apply重新部署 - 若仍失败,用AWS CLI测试权限:
# 测试KMS生成数据密钥权限 aws kms generate-data-key --key-id <你的KMS密钥ARN> --key-spec AES_256 # 测试S3写入权限 aws s3 put-object --bucket <你的S3桶名> --key test.txt --body test.txt
内容的提问来源于stack exchange,提问作者DisplayName

