如何在AWS CloudFormation的PolicyDocument Statement中使用自定义条件?
解决CloudFormation S3桶策略按环境动态添加权限的问题
你遇到的报错是因为混淆了两个完全不同的「条件」概念:
- CloudFormation的全局条件(Conditions块定义的):用来控制整个资源是否创建,或者资源属性的动态赋值
- IAM策略的语句级条件:是IAM权限逻辑的一部分,用来控制这条权限在什么场景下生效(比如IP范围、时间等)
你直接把CloudFormation的NotProd条件放到IAM策略的Statement里,CloudFormation会认为你定义的全局条件没被使用,同时IAM也不认识这个自定义条件,所以报错。
不需要拆分两个桶策略,用CloudFormation的!If函数就能实现动态生成Statement数组,只在非生产环境加入s3:getBucketLocation权限:
Conditions: NotProd: !Not [!Equals [!Ref Environment, production]] # 假设你已经定义了Bucket资源 Bucket: Type: AWS::S3::Bucket # 桶的其他配置... BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref Bucket PolicyDocument: Statement: # 所有环境都生效的getObject权限 - Action: s3:getObject Effect: Allow Principal: AWS: '*' Resource: !Sub '${Bucket.Arn}/*' # 动态添加非生产环境的getBucketLocation权限 !If - NotProd - Action: s3:getBucketLocation Effect: Allow Principal: AWS: '*' Resource: !Sub '${Bucket.Arn}' - !Ref 'AWS::NoValue' # 生产环境下忽略这条语句
关键说明:
!If函数会根据NotProd的结果动态生成内容:当非生产环境时,把s3:getBucketLocation的Statement加入数组;生产环境时,用!Ref 'AWS::NoValue'让CloudFormation自动忽略这个元素,不会在Statement里留空项- 修正了Resource的写法:
s3:getBucketLocation的目标资源是桶本身的ARN,s3:getObject是桶内所有对象的ARN,用!Sub引用桶的ARN比写*更严谨,也符合IAM策略的最佳实践
内容的提问来源于stack exchange,提问作者Sabo Boz
相关产品推荐
相关产品推荐

