CloudFormation:IAM角色策略Map键的变量替换问题
问题
定义了包含AWSAccountId、OidcProvider等参数的AWS IAM角色CloudFormation模板,在AssumeRolePolicyDocument的Condition/StringEquals部分尝试用!Sub替换Map键中的变量时触发报错,此前尝试!Join和UserData均无效,求助如何在Map键中完成变量替换。
原模板代码:
AWSTemplateFormatVersion: "2010-09-09" Parameters: AWSAccountId: Type: String OidcProvider: Type: String AppNamespace: Type: String AppServiceAccountName: Type: String Resources: CloudWatchRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Federated: - !Join ["", [ "arn:aws:iam::", !Ref AWSAccountId, ":oidc-provider/", !Ref OidcProvider ] ] Action: - "sts:AssumeRoleWithWebIdentity" Condition: StringEquals: !Sub ${OidcProvider}:sub: "system:serviceaccount:${AppNamespace}:${AppServiceAccountName}"
报错信息:
An error occurred (ValidationError) when calling the CreateStack operation: Template format error[/Resources/CloudWatchRole/Properties/AssumeRolePolicyDocument/ Statement/0/Condition/StringEquals] map keys must be strings; received a map instead
解决方案
问题出在CloudFormation的函数解析逻辑:直接在Map键的位置使用!Sub时,函数本身会被解析为一个Map对象,而非预期的字符串键,导致类型校验失败。
解决方法是通过!Sub的多行字符串形式,将整个StringEquals的JSON结构作为模板字符串进行变量替换,确保最终生成的是合法的键值对Map。修正后的模板如下:
AWSTemplateFormatVersion: "2010-09-09" Parameters: AWSAccountId: Type: String OidcProvider: Type: String AppNamespace: Type: String AppServiceAccountName: Type: String Resources: CloudWatchRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Federated: - !Join ["", [ "arn:aws:iam::", !Ref AWSAccountId, ":oidc-provider/", !Ref OidcProvider ] ] Action: - "sts:AssumeRoleWithWebIdentity" Condition: !Sub - | { "${OidcProvider}:sub": "system:serviceaccount:${AppNamespace}:${AppServiceAccountName}" } - OidcProvider: !Ref OidcProvider AppNamespace: !Ref AppNamespace AppServiceAccountName: !Ref AppServiceAccountName
关键说明
- 用
!Sub的多行模板字符串形式,将Condition的StringEquals部分整体作为JSON字符串进行变量替换,这样CloudFormation会将替换后的结果解析为合法的Map结构。 - 这种方式避免了直接在Map键位置使用函数导致的类型错误,同时完整保留了变量替换的需求。
内容的提问来源于stack exchange,提问作者Billy Billy
相关产品推荐
相关产品推荐

