0

I want to create a cloudformation stackset with resources like IAM and lambda in different regions. when I tried to deploy these resources, it failed because IAM roles are global and it is trying to create again in second region and whole stackset is failed.

Is there anyway I can mention the stackset to deploy GLobal Resources in one region and resources like lambda in all other regions?

Prashanth
  • 93
  • 11

2 Answers2

0

Is there anyway I can mention the stackset to deploy GLobal Resources in one region and resources like lambda in all other regions?

Sadly there is not. You have to split your template, so that global resource are created as normal regional stacks.

Marcin
  • 215,873
  • 14
  • 235
  • 294
0

I went through many resources and finally found a solution. If we split the template in stacksets then my dependent resources will break because creation is parallel in cloudformation. i.e. before global role gets created, lambda will try to get deployed and it will fail because the role is not available(required by lambda).

Hence we can add a condition to each of the global resources like below

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

And, add the condition in the resources section as below,

    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: '*'

But, after doing this, the problem would still exist because, if you add lambda resource with depends on attribute, role would get created in one region but not in the second region, lambda will fail to create in second region. We need to add a wait condition in the template to handle this as below Conditions:

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

and, add below resources after Role Resource,

    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

and now, refer this in lambda resource,

    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

Refer to the below source links, which might help

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

  2. CloudFormation, apply Condition on DependsOn

Prashanth
  • 93
  • 11