globaldatanetmenu

.Deploying CloudFormation StackSets with AWS CDK

Jul 19th 2023-5 min read

AWS Cloud Development Kit (CDK) is a powerful framework that allows developers to define cloud infrastructure as code using familiar programming languages. With CDK, you can easily provision and manage AWS resources in a consistent and automated manner. In this blog post, we'll walk you through the process of creating a StackSet using AWS CDK.

Before we dive into the details, let's take a quick look at what a StackSet is and how it can help you manage your AWS infrastructure.

StackSets are containers for CloudFormation stacks that enable simultaneous creation, update, and deletion across multiple AWS accounts and regions. With StacksSets, you can ensure that all environments are consistent and compliant with the policies you have in place.

The native support for StackSet in CDK is somewhat rudimentary, due to the fact that it is more common in CDK to use CDK pipelines to roll out stacks to multiple accounts and regions.

Therefore, in order to use StackSet in CDK, a few things need to be considered. In this blogpost, we will show steps on how to deploy StackSets via CDK.

Let’s see how this works.

Prerequisites

To follow this tutorial, make sure you have the following prerequisites

Bootstrap AWS Account

Bootstrapping is the process of providing resources for the AWS CDK before you can deploy AWS CDK applications in an AWS environment. Normally you could use the default

cdk bootstrap aws://ACCOUNT-NUMBER-1/REGION-1 command. However, we need to customise the template to make the assets available to the entire AWS Organization, as we want to use this CDK environment to deploy StackSets. To get the latest version of the CDK bootstrap template, do the following:

cdk bootstrap --show-template > bootstrap-template.yaml

ℹ️ The CDK boostrap template contains an S3 bucket for files and an ECR repository for container images. It also creates few IAM roles.

Blog Content

After that, we need to modify two resources in this template. The s3 bucket for Assets and the KMS Key that will be used to encrypt the assets.

Add the following Part to the Parameters Section of the template:

  PrincipalOrgID:
    Description: >-
      The identifier of your AWS organization. Used in the KMS key policy and S3 bucket to
      share the key with all accounts under your organization
    Type: String

We will reference this Parameter in the Resource section.

Add this CodeSnippet to the FileAssetsBucketEncryptionKey Resource in to the Key Policy Section. This will

        KeyPolicy:
        Statement:
          - Action:
          ....
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
            Effect: Allow
            Principal:
              AWS: "*"
            Resource: "*"
            Condition:
              StringEquals:
                kms:ViaService:
                  - Fn::Sub: s3.${AWS::Region}.amazonaws.com
              ForAnyValue:StringLike:
                aws:PrincipalOrgID:
                - !Ref PrincipalOrgID

Extend the PolicyDocument of the StagingBucketPolicy with the following CodeSnippet. This will ensure that all Accounts of the Organization get access to the objects in the Asset Bucket.

      PolicyDocument:
        Id: AccessControl
        Version: "2012-10-17"
        Statement:
        ...
          - Sid: ''
            Effect: Allow
            Principal: '*'
            Action:
            - s3:Get*

            Resource: !Sub '${StagingBucket.Arn}/*'
            Condition:
              ForAnyValue:StringLike:
                aws:PrincipalOrgID:
                - !Ref PrincipalOrgID
          - Sid: ''
            Effect: Allow
            Principal: '*'
            Action: s3:ListBucket
            Resource: !Sub '${StagingBucket.Arn}'
            Condition:
              ForAnyValue:StringLike:
                aws:PrincipalOrgID:
                - !Ref PrincipalOrgID

After all the adjustments we need to deploy the template.

aws cloudformation create-stack \
  --stack-name CDKToolkit \
  --template-body file://bootstrap-template.yaml
Blog Content

Set Up Your CDK Project

After bootstrapping our Account we are ready to Initialize a new CDK project. We will do that in a new directory. The initialisation creates a new CDK project structure with a sample lib/stackset-cdk-demo-stack.ts file, which we will modify to create our StackSet.

#Create new directory
mkdir stackset-cdk-demo
cd stackset-cdk-demo

#Init new CDK Project
cdk init app --language typescript

Define the StackSet

Open lib/stackset-cdk-demo-stack.ts and remove the example stack definition. We'll define our stackset instead:

import * as cdk from 'aws-cdk-lib';
import * as servicecatalog from 'aws-cdk-lib/aws-servicecatalog';
import { StackSetTemplate } from "./stackSetTemplate";
import * as s3 from "aws-cdk-lib/aws-s3";

export class StackSetCdkDemoStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);


    const stackSetTemplateSandbox = new StackSetTemplate(this, "stacksettemplate", {
      Config: props.stacksetProps,
      assetBucket: s3.Bucket.fromBucketName(this, "assetbucket", "myCDKAssetBucket")
    });

    new cdk.CfnStackSet(this, "TESTSTACKSET", {
      permissionModel: "SELF_MANAGED",
      stackSetName: "TEST-STACKSET",
      description:
        "example of StackSet with CDK",
      capabilities: ["CAPABILITY_NAMED_IAM"],
      templateUrl: servicecatalog.CloudFormationTemplate.fromProductStack(stackSetTemplateSandbox).bind(this).httpUrl,
      operationPreferences: {
        failureToleranceCount: 30,
        maxConcurrentCount: 30,
      }
    });
  }
}

⚠️ Ensure to adjust the myCDKAssetBucket to your AWS Account Assets Bucket.

🚨 Using the servicecatalog ProductStack construct we get rid of the PseudoParameter for the assets bucket in lambdas in the template.

❌ Without using the servicatalog ProductStack:

!sub cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}

✅ Using the servicatalog ProductStack:

cdk-hnb659fds-assets-123456789012-eu-central-1

This workaround will ensure that all AWS accounts can access the assets in our CDK app.

Create StackSet template

In the lib directory create a new file called stackSetTemplate.ts and add the following code to the file:

Example Lambda Code

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as servicecatalog from "aws-cdk-lib/aws-servicecatalog";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import * as lambda from "aws-cdk-lib/aws-lambda";


//Standardstackdefinition
export class StackSetTemplate extends servicecatalog.ProductStack {
// export class CdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    /**
     * Dummy Node JS Lambda Function
     */
      const lambdaFunction = new NodejsFunction(this, "testFunction", {
        memorySize: 128,
        timeout: cdk.Duration.seconds(60),
        runtime: lambda.Runtime.NODEJS_18_X,
        handler: "handler",
        entry: path.join(__dirname, "lambda/index.ts"),
        bundling: {
          minify: true,
          externalModules: ["aws-sdk"]
        }
      });
      lambdaFunction.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN);
    }
  }
}

Create a new directory lambda in the lib directory. In the new lambda directory create a new file called index.ts and add the following code:

import { Handler } from 'aws-lambda';

export const handler: Handler = async (event, context) => {
    console.log('EVENT: \n' + JSON.stringify(event, null, 2));
    return context.logStreamName;
};

Deploy the StackSet

Run cdk deploy
in a terminal to deploy the StackSet and associated CloudFormation stacks.

ℹ️ CDK will ask you to confirm that you want to deploy the changes. Type y and press Enter to continue.

Conclusion

In this blog post, we've explored how to create a StackSet using AWS CDK. We also learned how to share the CDK Assets to the whole AWS Organization. StackSets are an essential tool for managing infrastructure at scale across multiple AWS accounts and regions. Using CDK, you can easily define and deploy complex cloud infrastructure as code, and leverage the full power of AWS CloudFormation to ensure consistency, compliance, and efficiency across your organisation's cloud resources.

globaldatanetCloud Development, Optimization & Automation

.Navigation

.Social

  • follow globaldatanet on instagram
  • follow globaldatanet on facebook
  • follow globaldatanet on twitter
  • follow globaldatanet on linkendin
  • follow globaldatanet on twitch
  •  listen to our serverless world podcast
  • follow globaldatanet's tech rss feed
  • follow globaldatanet at github
© 2024 by globaldatanet. All Right Reserved
Your privacy is important to us!

We use cookies on our website. Some of them are essential,while others help us to improve our online offer.
You can find more information in our Privacy policy