CloudFormation模板S3权限配置异常:多账号CloudTrail日志路径参数缺失
解决CloudFormation中S3权限Resource路径账号缺失的问题
我之前碰到好几个用户在配置多账号CloudTrail日志汇总时,遇到过和你一模一样的!Join语句问题——参数值没被正确解析,导致Resource路径里出现//*的异常格式。咱们一步步来排查修复:
问题根源分析
这种账号ID缺失的情况,90%以上是参数引用语法错误导致的。CloudFormation里如果直接写参数名(比如MasterAccNum)而不用!Ref来引用,模板会把它当成普通字符串,而不是解析成你输入的12位账号ID。一旦参数没被正确解析,就会在路径里留下空值,自然就出现了连续的斜杠。
举个例子,你原来的错误代码大概率是类似这样的:
Resources: CloudTrailBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref CloudTrailBucket PolicyDocument: Statement: - Effect: Allow Principal: AWS: !Sub arn:aws:iam::${ProdAccNum}:root Action: s3:PutObject Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref CloudTrailBucket - '/' - MasterAccNum # 这里没加!Ref,直接写参数名会被当成字符串 - '/*'
修正后的解决方案
我推荐两种修复方式,第二种更简洁直观,不容易出错:
方法1:修正!Join的参数引用
在!Join的数组元素里,给参数名加上!Ref,确保CloudFormation能正确解析你输入的账号ID:
Resources: CloudTrailBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref CloudTrailBucket PolicyDocument: Statement: - Effect: Allow Principal: AWS: !Sub arn:aws:iam::${ProdAccNum}:root Action: s3:PutObject Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref CloudTrailBucket - '/' - !Ref MasterAccNum # 正确引用参数 - '/*' - Effect: Allow Principal: AWS: !Sub arn:aws:iam::${MasterAccNum}:root Action: s3:PutObject Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref CloudTrailBucket - '/' - !Ref ProdAccNum # 正确引用参数 - '/*'
方法2:用!Sub替代!Join(更推荐)
!Sub语法比!Join更直观,直接在字符串里用${参数名}就能引用,完全避免拼接错误:
Resources: CloudTrailBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref CloudTrailBucket PolicyDocument: Statement: - Effect: Allow Principal: AWS: !Sub arn:aws:iam::${ProdAccNum}:root Action: s3:PutObject Resource: !Sub arn:aws:s3:::${CloudTrailBucket}/${MasterAccNum}/* - Effect: Allow Principal: AWS: !Sub arn:aws:iam::${MasterAccNum}:root Action: s3:PutObject Resource: !Sub arn:aws:s3:::${CloudTrailBucket}/${ProdAccNum}/*
验证步骤
- 修正模板后,先用CloudFormation控制台的Validate template功能检查语法是否正确;
- 启动栈时再次确认输入的
MasterAccNum和ProdAccNum是12位无连字符的纯数字账号ID; - 栈创建完成后,查看S3桶的权限策略,确认Resource路径已经正确显示账号ID,比如
arn:aws:s3:::your-bucket/123456789012/*。
另外别忘了,要让CloudTrail日志确实写入对应文件夹,还要在各账号的CloudTrail配置里,把日志存储路径指定为你的桶名/${对应账号ID}/,这样权限和实际存储路径就能完全匹配了。
内容的提问来源于stack exchange,提问作者Goran K.
相关产品推荐
相关产品推荐

