利用CloudFormation技巧从账号ID列表生成ARN列表
我之前刚好处理过一模一样的需求,给你分享两个实用的实现方案,看你环境情况选就行:
方案一:使用AWS语言扩展(推荐)
这个方案利用CloudFormation的AWS Language Extensions提供的Fn::Map函数,能直接遍历账号ID列表生成对应的ARN,代码简洁易读,现在大部分AWS区域都支持这个扩展。
完整示例模板
AWSTemplateFormatVersion: '2010-09-09' # 启用AWS语言扩展,才能使用Fn::Map函数 Transform: AWS::LanguageExtensions Parameters: AccountIds: Type: CommaDelimitedList Description: 输入需要转换为ARN的AWS账号ID列表(逗号分隔,比如"123456789012,987654321098") TargetBucket: Type: String Description: 示例中要授权的S3桶名称 Resources: # 示例:给指定账号授权S3读取权限的桶策略 AuthorizedBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref TargetBucket PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: # 核心逻辑:用Fn::Map遍历账号ID,逐个生成ARN AWS: !Map - AccountId # 遍历过程中每个元素的变量名 - !Ref AccountIds # 要遍历的账号ID列表 - !Sub arn:aws:iam::${AccountId}:root # 生成ARN的模板 Action: s3:GetObject Resource: !Sub arn:aws:s3:::${TargetBucket}/*
原理说明
!Map(即Fn::Map)是语言扩展提供的遍历函数,它会把AccountIds列表里的每个账号ID代入!Sub模板,自动生成对应的ARN数组,完美适配CloudFormation中需要ARN列表的场景(比如Principal.AWS)。
方案二:兼容旧环境方案(无扩展依赖)
如果你的环境暂时无法启用AWS Language Extensions,可以用Fn::Split+Fn::Join的组合来实现,不过这个方法需要借助一个不会出现在ARN里的临时分隔符:
示例代码片段
# 模板开头无需加Transform AWSTemplateFormatVersion: '2010-09-09' Parameters: AccountIds: Type: CommaDelimitedList Description: 输入需要转换为ARN的AWS账号ID列表(逗号分隔) TargetBucket: Type: String Description: 示例中要授权的S3桶名称 Resources: AuthorizedBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref TargetBucket PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: AWS: !Split - '|SEP|' # 自定义临时分隔符,确保不会出现在ARN中 - !Join - '|SEP|' - !Sub - 'arn:aws:iam::${Id}:root' - Id: !Split [",", !Join [",", !Ref AccountIds]] Action: s3:GetObject Resource: !Sub arn:aws:s3:::${TargetBucket}/*
原理说明
- 先用
!Join把账号ID列表转成逗号分隔的字符串,再用!Split转回数组(这一步是为了确保处理的是标准数组); - 用
!Sub给每个账号ID加上ARN前缀后缀,再用自定义分隔符拼接成字符串; - 最后用
!Split按自定义分隔符拆分,得到最终的ARN数组。
不过这个方法不如方案一简洁,而且需要注意临时分隔符不能和ARN内容冲突,所以优先推荐方案一。
内容的提问来源于stack exchange,提问作者Sam Hammamy
相关产品推荐
相关产品推荐

