Terraform创建CloudTrail时触发AccessDeniedException权限问题求助
问题概述
使用Terraform创建CloudTrail并将日志存储到S3桶,部署角色为管理员角色,但执行terraform apply时触发以下错误:
Error: creating CloudTrail Trail (audit-logs): operation error CloudTrail: CreateTrail, https response error StatusCode: 400, RequestID: abdc7ed4-22c4-4462-9ff9-4f8bda32e509, api error AccessDeniedException: Access Denied: You do not have permission to operate on this resource.
配置代码
Provider配置
terraform { required_version = "~> 1.3, < 1.6" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
资源配置
resource "aws_kms_key" "cloudtrail_kms_key" { description = "KMS key for Cloudtrail S3 Bucket" enable_key_rotation = true } resource "aws_kms_key_policy" "cloudtrail_kms_key_policy" { key_id = aws_kms_key.cloudtrail_kms_key.id policy = jsonencode({ Version = "2012-10-17", Id = "test", Statement : [ { Sid = "Enable IAM User Permissions" Effect = "Allow" Principal = { AWS = "arn:aws:iam::${var.aws_account_id}:root" } Action = "kms:*" Resource = "*" }, { Sid = "Permitted KMS Key Services" Effect = "Allow" Principal = { Service = ["cloudtrail.amazonaws.com"] AWS = "arn:aws:iam::${var.aws_account_id}:root" } Action = ["kms:GenerateDataKey*", "kms:Decrypt"] Resource = "*", "Condition" : { "StringEquals" : { "aws:SourceArn" : "arn:aws:cloudtrail:${var.aws_region}:${var.aws_account_id}:trail/${var.trail_name}" } } } ] }) } resource "aws_s3_bucket" "cloudtrail_bucket" { bucket = "${var.bucket_name}-${var.aws_region}-${var.aws_account_id}-ls" } resource "aws_s3_bucket_server_side_encryption_configuration" "cloudtrail_bucket_sse_configuration" { bucket = aws_s3_bucket.cloudtrail_bucket.id rule { apply_server_side_encryption_by_default { kms_master_key_id = aws_kms_key.cloudtrail_kms_key.arn sse_algorithm = "aws:kms" } } resource "aws_s3_bucket_ownership_controls" "cloudtrail_bucket_ownership_controls" { bucket = aws_s3_bucket.cloudtrail_bucket.id rule { object_ownership = "BucketOwnerPreferred" } } resource "aws_s3_bucket_versioning" "cloudtrail_bucket_versioning" { bucket = aws_s3_bucket.cloudtrail_bucket.id versioning_configuration { status = "Enabled" } } data "aws_iam_policy_document" "cloudtrail_bucket_policy" { statement { sid = "AWSCloudTrailAclCheck" effect = "Allow" principals { type = "Service" identifiers = ["cloudtrail.amazonaws.com"] } actions = ["s3:GetBucketAcl"] resources = [aws_s3_bucket.cloudtrail_bucket.arn] condition { test = "StringEquals" variable = "aws:SourceArn" values = ["arn:aws:cloudtrail:${var.aws_region}:${var.aws_account_id}:trail/${var.trail_name}"] } } statement { sid = "AWSCloudTrailWrite" effect = "Allow" principals { type = "Service" identifiers = ["cloudtrail.amazonaws.com"] } actions = ["s3:PutObject"] resources = ["${aws_s3_bucket.cloudtrail_bucket.arn}/prefix/AWSLogs/${var.aws_account_id}/*"] condition { test = "StringEquals" variable = "s3:x-amz-acl" values = ["bucket-owner-full-control"] } condition { test = "StringEquals" variable = "aws:SourceArn" values = ["arn:aws:cloudtrail:${var.aws_region}:${var.aws_account_id}:trail/${var.trail_name}"] } } } resource "aws_s3_bucket_policy" "cloudtrail_bucket_policy" { bucket = aws_s3_bucket.cloudtrail_bucket.id policy = data.aws_iam_policy_document.cloudtrail_bucket_policy.json } resource "aws_cloudtrail" "trail" { depends_on = [aws_s3_bucket_policy.cloudtrail_bucket_policy] name = var.trail_name s3_bucket_name = aws_s3_bucket.cloudtrail_bucket.id s3_key_prefix = "AWSLogs" is_organization_trail = true is_multi_region_trail = true kms_key_id = aws_kms_key.cloudtrail_kms_key.arn enable_log_file_validation = true }
错误原因分析与修复方案
1. S3桶策略路径不匹配
CloudTrail配置的s3_key_prefix是AWSLogs,但桶策略中写入权限的资源路径错误地添加了prefix/前缀,导致CloudTrail没有对应路径的写入权限。
修复:将桶策略中的资源路径修改为与s3_key_prefix一致:
resources = ["${aws_s3_bucket.cloudtrail_bucket.arn}/${aws_cloudtrail.trail.s3_key_prefix}/${var.aws_account_id}/*"]
或者直接写死匹配:
resources = ["${aws_s3_bucket.cloudtrail_bucket.arn}/AWSLogs/${var.aws_account_id}/*"]
2. KMS密钥策略条件限制(Trail未创建时ARN不存在)
创建Trail时,Trail的ARN尚未生成,KMS策略中aws:SourceArn的条件会阻止CloudTrail服务访问密钥,导致权限被拒。
修复:
- 暂时移除
aws:SourceArn条件,待Trail创建完成后再添加; - 或替换为
aws:SourceAccount条件,仅限制账号:
"Condition" : { "StringEquals" : { "aws:SourceAccount" : "${var.aws_account_id}" } }
- 或给部署的管理员角色添加KMS的
GenerateDataKey*和Decrypt权限。
3. SSE配置语法错误
原代码中aws_s3_bucket_server_side_encryption_configuration资源缺少闭合括号,会导致S3桶加密配置创建失败,间接引发权限问题。
修复:补充缺失的闭合括号:
resource "aws_s3_bucket_server_side_encryption_configuration" "cloudtrail_bucket_sse_configuration" { bucket = aws_s3_bucket.cloudtrail_bucket.id rule { apply_server_side_encryption_by_default { kms_master_key_id = aws_kms_key.cloudtrail_kms_key.arn sse_algorithm = "aws:kms" } # 补充apply_server_side_encryption_by_default的闭合 } # 补充rule的闭合 } # 补充资源的闭合
4. 组织级Trail权限缺失
若设置了is_organization_trail = true,需确保:
- 当前账号属于AWS组织;
- 管理员角色拥有
organizations:EnableAWSServiceAccess和cloudtrail:CreateTrail权限; - 已启用CloudTrail作为组织服务,可通过Terraform添加以下资源:
resource "aws_organizations_aws_service_access_principal" "cloudtrail" { service_principal = "cloudtrail.amazonaws.com" }
并在CloudTrail资源中添加depends_on = [aws_organizations_aws_service_access_principal.cloudtrail]。
内容的提问来源于stack exchange,提问作者Somethingwhatever

