首页 > 解决方案 > Cloudformation 模板 - IAM 角色和 Lambda 资源

问题描述

我想创建一个 cloudformation 堆栈集,其中包含不同区域的 IAM 和 lambda 等资源。当我尝试部署这些资源时,它失败了,因为 IAM 角色是全局的,它试图在第二个区域再次创建并且整个堆栈集失败。

无论如何我可以提到在一个区域部署全球资源和在所有其他区域部署 lambda 等资源的堆栈集吗?

标签: amazon-cloudformation

解决方案


我浏览了很多资源,终于找到了解决方案。如果我们将模板拆分为堆栈集,那么我的依赖资源将中断,因为在 cloudformation 中创建是并行的。即,在创建全局角色之前,lambda 将尝试部署并且它将失败,因为角色不可用(lambda 需要)。

因此,我们可以为每个全局资源添加一个条件,如下所示

    Conditions:
        RegionCheck: !Equals 
            - !Ref "AWS::Region"
            - us-east-1

并且,在资源部分添加条件如下,

    Resources:
        GlobalRolelambda:
            Type: 'AWS::IAM::Role'
            Condition: RegionCheck
            Properties:
                RoleName: !Ref LambdaExecutionRole
                ManagedPolicyArns:
                    - 'arn:aws:iam::aws:policy/ReadOnlyAccess'
                    - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
                Path: /
                AssumeRolePolicyDocument:
                    Version: 2012-10-17
                    Statement:
                        - Effect: Allow
                            Principal:
                                Service:
                                    - lambda.amazonaws.com
                            Action:
                                - 'sts:AssumeRole'
                Policies:
                    - PolicyName: lambda-policy
                        PolicyDocument:
                            Version: 2012-10-17
                            Statement:
                                - Effect: Allow
                                    Action:
                                        - 'glue:GetConnections'
                                        - 'mediastore:ListContainers'
                                        - 'mediastore:GetContainerPolicy'
                                    Resource: '*'

但是,在这样做之后,问题仍然存在,因为如果您添加具有依赖属性的 lambda 资源,角色将在一个区域创建但不在第二个区域创建,lambda 将无法在第二个区域创建。我们需要在模板中添加一个等待条件来处理这个,如下条件:

    CreateLambdaRole: !Equals [ !Ref LambdaRoleName, 'false' ]
    CreateLamdaRoleRegion: !And
        - !Condition RegionCheck
        - !Condition CreateLambdaRole

并且,在角色资源之后添加以下资源,

    CreateRoleWaitHandle: 
        Condition: CreateLamdaRoleRegion
        DependsOn: GlobalRolelambda
        Type: "AWS::CloudFormation::WaitConditionHandle"
#added, since DependsOn: !If is not possible, trigger by WaitCondition if CreateLamdaRoleRegion is false
    WaitHandle: 
        Type: "AWS::CloudFormation::WaitConditionHandle"
#added, since DependsOn: !If is not possible
    WaitCondition: 
        Type: "AWS::CloudFormation::WaitCondition"
        Properties: 
            Handle: !If [CreateLamdaRoleRegion, !Ref CreateRoleWaitHandle, !Ref WaitHandle]
            Timeout: "1"
            Count: 0

现在,在 lambda 资源中引用它,

    lambdaProcessorFunction:
        Type: AWS::Lambda::Function
        Properties:
            FunctionName: Lambda-processor
            Description: ''
            Handler: index.handler
            Role:
                Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/LambdaExecutionRole'
            Runtime: python3.6
            Timeout: 600
            MemorySize: 1024  
            Code:
                S3Bucket: !Ref SourceBucketName
                S3Key: !Ref SourceBucketKey
        DependsOn: WaitCondition

请参阅以下源链接,这可能会有所帮助

  1. https://garbe.io/blog/2017/07/17/cloudformation-hacks/

  2. CloudFormation,在 DependsOn 上应用条件


推荐阅读