Deploy into multiple AWS regions with Cloudformation

Andy BrunnerTechnik

Recently, we faced the challenge of creating a new S3 bucket in each of a number of specific regions. We have found that we can do this by using a Cloudformation Stack, that deploys a StackSet, that again deploys a Stack for each region.

Sounds confusing? Let me explain. We will create a StackSet that is going to deploy the same Stack template into multiple regions, and if you wish, to multiple AWS accounts as well. And the thing is, we will deploy the StackSet using a Stack.

Prerequisites

Before you start, make sure you set the permissions correctly. Check out the AWS Docs. If the resources you’d like to deploy should end up in the same AWS account as your primary deployment, create all the permissions in the same account. But even though, you have to.

The Cloudformation template

Actually, it’s not a big deal to create a template for a StackSet. There are several guides out there explaining how to do it. But what took us a little more time to figure out, is how to pass a parameter from the parent template through the stack to the child templates.

Here’s the template and how we made it work:

AWSTemplateFormatVersion: '2010-09-09'
Description: Stackset for multiple S3 buckets

Parameters:
  env:
    Type: String
    Description: Amplify environment
  deployRegions:
    Type: CommaDelimitedList
    Description: aws regions to deploy the S3 buckets to

Resources:
  StackSet:
    Type: AWS::CloudFormation::StackSet
    Properties:
      Description: Multiple S3 buckets in multiple regions
      PermissionModel: SELF_MANAGED
      Parameters:
        - ParameterKey: env
          ParameterValue: !Ref env

      StackInstancesGroup:
        - DeploymentTargets:
            Accounts:
              - !Ref "AWS::AccountId"
          Regions: !Ref deployRegions

      StackSetName: !Sub "s3Buckets-${env}"
      TemplateBody: |
        AWSTemplateFormatVersion: 2010-09-09
        Description: Create a S3 bucket
        Parameters:
          env:
            Type: String
        Resources:
          s3bucketInRegion:
            Type: AWS::S3::Bucket
            Properties:
              BucketName: !Sub myNewBucket-${env}-${AWS::Region}
              AccessControl: Private
              LifecycleConfiguration:
                Rules:
                - ExpirationInDays: 3
                  Id: "Remove files after 3 days"
                  Status: Enabled
                  Prefix: "upload/3d"
              CorsConfiguration:
                CorsRules:
                - AllowedHeaders:
                  - "*"
                  AllowedMethods:
                  - GET
                  - POST
                  AllowedOrigins:
                  - "*"
                  MaxAge: 3600
              Tags:
                - Key: Company
                  Value: myCompany

The parent template gets a parameter called env from the AWS Amplify framework. This one is passed to the Properties of the StackSet. This way the StackSet provides this parameter to its child Stacks.

As we are using AWS Amplify to deploy the StackSet, we’re providing the deployment regions as a parameter to the parent template. If you’d like to specify the regions within the template, edit the following part.

      StackInstancesGroup:
        - DeploymentTargets:
            Accounts:
              - !Ref "AWS::AccountId"
          Regions:
            - eu-west-1
            - eu-west-2
            - ap-northeast-1

And if you like to deploy your resources into multiple AWS accounts, just provide the corresponding account IDs.

We hope, we were able to help you with creating your Cloudformation template.

Best regards
Andy / cloudxs