如何通过CloudFormation使用Lambda友好名或ARN获取其关联IAM角色名
解决方案
原写法失效的核心原因是Fn::GetAtt仅支持引用当前CloudFormation模板中显式声明的资源逻辑ID,直接传入Lambda ARN不属于模板内定义的资源,因此无法读取属性。同时你之前写的ARN缺少了Region字段,格式不符合要求,也是调用失败的原因之一。
推荐方案:自行指定轮转Lambda的IAM角色
这是最稳妥且不需要额外适配的方案,你可以提前定义好包含KMS解密权限的IAM角色,直接通过HostedRotationLambda的RotationLambdaRoleArn参数传入,完全不需要后续再手动附加策略:
# 自行定义的托管Lambda执行角色 rHostedLambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: # 托管Lambda运行必备的官方基础策略 - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/service-role/SecretsManagerRotationExecutionRole # 直接关联你写的KMS解密策略 - !Ref rRotationLambdaDecryptPolicy
修改你的轮转计划配置,新增角色ARN参数即可:
rSecretRotationSchedule: Type: AWS::SecretsManager::RotationSchedule Properties: SecretId: <SecretId> HostedRotationLambda: KmsKeyArn: <KmsKeyArn> MasterSecretArn: <MasterSecretArn> MasterSecretKmsKeyArn: <MasterSecretKmsKeyArn> RotationType: PostgreSQLMultiUser RotationLambdaName: SecretsManager-research-creds-rotation-lambda VpcSecurityGroupIds: <VpcSecurityGroupIds> VpcSubnetIds: <VpcSubnetIds> # 新增:传入你自定义的角色ARN,AWS不会再自动生成角色 RotationLambdaRoleArn: !GetAtt rHostedLambdaExecutionRole.Arn RotationRules: AutomaticallyAfterDays: 60
备选方案:通过自定义资源获取自动生成角色的ARN
如果必须使用AWS自动生成的Lambda角色,可以添加一个Lambda-backed自定义资源,调用lambda:GetFunction接口查询目标Lambda的执行角色ARN,再把返回值填入你的托管策略的Roles参数中:
# 自定义资源执行角色,允许调用Lambda查询接口 rGetLambdaRoleCustomResourceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AllowGetLambdaFunction PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: lambda:GetFunction Resource: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:SecretsManager-research-creds-rotation-lambda # 自定义资源逻辑,返回目标Lambda的角色ARN rGetLambdaRoleFunction: Type: AWS::Lambda::Function Properties: Runtime: python3.9 Code: ZipFile: | import boto3 import cfnresponse lambda_client = boto3.client('lambda') def handler(event, context): if event['RequestType'] in ['Create', 'Update']: try: lambda_arn = event['ResourceProperties']['LambdaArn'] resp = lambda_client.get_function(FunctionName=lambda_arn) role_arn = resp['Configuration']['Role'] cfnresponse.send(event, context, cfnresponse.SUCCESS, {'RoleArn': role_arn}) except Exception as e: cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)}) else: cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) Handler: index.handler Role: !GetAtt rGetLambdaRoleCustomResourceRole.Arn Timeout: 30 # 调用自定义资源获取角色ARN rGetLambdaRole: Type: Custom::GetLambdaRole DependsOn: rSecretRotationSchedule Properties: ServiceToken: !GetAtt rGetLambdaRoleFunction.Arn LambdaArn: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:SecretsManager-research-creds-rotation-lambda
修改你的托管策略配置,直接引用自定义资源返回的ARN即可:
rRotationLambdaDecryptPolicy: Type: AWS::IAM::ManagedPolicy # 依赖调整为自定义资源,确保Lambda生成后再创建策略 DependsOn: rGetLambdaRole Properties: Description: "Providing access to HostedLambda for decrypting KMS" ManagedPolicyName: CustomedHostedLambdaKmsUserRolePolicy PolicyDocument: Version: '2012-10-17' Statement: - Sid: AllowLambdaDecryptKMS Effect: Allow Action: - kms:Decrypt - kms:CreateGrant Resource: - !Sub arn:aws:kms:*:${AWS::AccountId}:key/* Condition: ForAnyValue:StringLike: kms:ResourceAliases: alias/SecretsManager_KMSKey Roles: - !GetAtt rGetLambdaRole.RoleArn
内容的提问来源于stack exchange,提问作者Zack_Coder
相关产品推荐
相关产品推荐

