How do I customize my AWS CDK bootstrap and deploy the CFNToolkit CloudFormation stack?

5 minute read
0

I want to customize my AWS Cloud Development Kit (AWS CDK) bootstrap and deploy the CFN AWS CloudFormation stack.

Short description

To use AWS CDK, you must bootstrap your AWS account. Bootstrapping creates the resources required by AWS CDK on the account. Your bootstrap template is able to be customized in accordance with compliance and security requirements such as the following:

  • Add tags to resources.
  • Add encryption for Amazon Simple Storage Service (Amazon S3) buckets.
  • Use custom Amazon S3 bucket names.
  • Use existing Amazon S3 buckets or apply the least privileged principal on the AWS Identity and Access Management (IAM) roles generated by the bootstrap template.

The cdk bootstrap command creates an AWS CloudFormation stack with the name CDKToolkit. The resources that are deployed in the CDKToolkit AWS CloudFormation stack come from the template.

Run the following command to show your bootstrap template:

cdk boostrap --show-template > bootstrap-template.yml

The preceding bootstrap template has the following resources:

  • resources such as the Amazon S3 bucket
  • AWS Key Management Service (AWS KMS) key
  • IAM roles
  • SSM parameter for versioning

For more information, see AWS CDK Bootstrap Template for Custom Bootstrapping on the GitHub website.

The following use cases allow your bootstrap template to be customized:

  • Use AWS CDK to deploy only the resources that you use.
  • Update or create a custom qualifier and name for an Amazon S3 bucket to store AWS CDK app file assets.
  • Use an existing Amazon S3 bucket to hold AWS CDK app file assets.

Resolution

To customize your bootstrap template, complete one of the following methods:

Use AWS CDK to deploy only the resources that you use

AWS CDK bootstrap creates a role CloudFormationExecutionRole that AWS CloudFormation assumes to deploy your stack. AWS CloudFormation uses this role to deploy from your local machine with the cdk deploy command or to deploy through AWS CDK pipelines for CI/CD.

To allow resources to be created with AWS CDK, the CloudFormationExecutionRole has the arn:aws:iam:aws:policy/AdministratorAccess policy that grants full access to perform all actions. This policy goes against the least privilege principle. To restrict this policy, you must create a new policy and bootstrap AWS CDK with the new custom policy.

Note: Make sure to review all commands and replace all instances of example strings with your required values.

1.    Create a custom policy in IAM:

aws iam create-policy \
  --policy-name cdkCFExecutionPolicy \
  --policy-document file://example-custom-Execution-Policy-name.json

2.    Use the newly created IAM policy to bootstrap the AWS CDK:

ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
cdk bootstrap aws://$ACCOUNT_ID/example-Region \
  --cloudformation-execution-policies "arn:aws:iam::$ACCOUNT_ID:policy/example-custom-Execution-Policy-name"

3.    (Optional) if the account has already been bootstrapped, then re-run the cdk bootstrap command with the new custom policy.

4.    (Optional) Update your policy as required by the AWS CDK application create a new policy version. New policy versions can be set as the default policy.

Note: Only five policy versions can be saved in IAM. Make sure to delete older versions as required when you make updates to your policy.

Update or create a custom qualifier and name for an Amazon S3 bucket to store AWS CDK app file assets

1.    Pass additional flags for qualifier and bootstrap-bucket-name to bootstrap the account. This updates or creates the CDKToolkit AWS CloudFormation stack with new values for the resources.

cdk bootstrap --template bootstrap-template.yml --qualifier <example-custom-qualifier-value> --bootstrap-bucket-name <example-custom-bucket-name> --profile <example-profile-name>

2.    Run the following commands to update the app.py to make the preceding changes:

import os
import aws_cdk as cdk
from myproject.myproject_stack import MyprojectStack
app = cdk.App()
MyprojectStack(app, "MyprojectStack", synthesizer=cdk.DefaultStackSynthesizer(qualifier="<example-custom-qualifier-value>", file_assets_bucket_name="<example-custom-bucket-name>"))
app.synth()

Note: If the CDKToolkit stack fails to deploy due to a resource that already exists, then identify and delete the resource if it's not needed. Then, perform the bootstrap from the AWS CloudFormation stack again.

Use an existing Amazon S3 bucket to hold AWS CDK app file assets

AWS CDK applications use the Amazon S3 bucket name and location from the CDKToolkit AWS CloudFormation Stack > Outputs section. To use an existing Amazon S3 bucket, you must modify the bootstrap-template.yml:

1.    Modify the Outputs value for BucketName and BucketDomainName with your existing Amazon S3 bucket details:

Outputs:
    BucketName:
        Description: The name of S3 bucket owned by the CDK toolkit stack
        Value: <example-existing-bucket-name>
    BucketDomainName:
        Description: The domain name of the S3 bucket owned by the CDK toolkit stack
        Value: <example-existing-bucket-name>.s3.<example-Region>.amazonaws.com

2.    Add the ARN of the existing Amazon S3 bucket in the DeploymentActionRole and FilePublishingRoleDefaultPolicy resources of the bootstrap-template.yml:

Resources:
    DeploymentActionRole:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Statement:
              - Action: sts:AssumeRole
                Effect: Allow
                Principal:
                  AWS:
                    Ref: AWS::AccountId
              - Fn::If:
                  - HasTrustedAccounts
                  - Action: sts:AssumeRole
                    Effect: Allow
                    Principal:
                      AWS:
                        Ref: TrustedAccounts
                  - Ref: AWS::NoValue
          Policies:
            - PolicyDocument:
                Statement:
                  - Sid: CliStagingBucket
                    Effect: Allow
                    Action:
                      - s3:GetObject*
                      - s3:GetBucket*
                      - s3:List*
                    Resource:
                      - Fn::Sub: ${StagingBucket.Arn}
                      - Fn::Sub: ${StagingBucket.Arn}/*
                      - arn:aws:s3:::<example-existing-bucket-name>
                      - arn:aws:s3:::<example-existing-bucket-name>/
                Version: "example-version"
              PolicyName: default
          RoleName:
            Fn::Sub: cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}
          Tags:
            - Key: aws-cdk:bootstrap-role
              Value: deploy
    FilePublishingRoleDefaultPolicy:
        Type: AWS::IAM::Policy
        Properties:
          PolicyDocument:
            Statement:
              - Action:
                  - s3:GetObject*
                  - s3:GetBucket*
                  - s3:GetEncryptionConfiguration
                  - s3:List*
                  - s3:DeleteObject*
                  - s3:PutObject*
                  - s3:Abort*
                Resource:
                  - Fn::Sub: ${StagingBucket.Arn}
                  - Fn::Sub: ${StagingBucket.Arn}/*
                  - arn:aws:s3:::<example-existing-bucket-name>/
                  - arn:aws:s3:::<example-existing-bucket-name>
                Effect: Allow
              - Action:
                  - kms:Decrypt
                  - kms:DescribeKey
                  - kms:Encrypt
                  - kms:ReEncrypt*
                  - kms:GenerateDataKey*
                Effect: Allow
                Resource:
                  Fn::If:
                    - CreateNewKey
                    - Fn::Sub: ${FileAssetsBucketEncryptionKey.Arn}
                    - Fn::Sub: arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/${FileAssetsBucketKmsKeyId}
            Version: "example-version"
          Roles:
            - Ref: FilePublishingRole
          PolicyName:
            Fn::Sub: cdk-${Qualifier}-file-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region}

3.    Run the cdk bootstrap command and the CDKToolkit AWS CloudFormation stack creates or updates with the preceding changes.

4.    To store file assets, run the following command:

MyprojectStack(app, "MyprojectStack", synthesizer=cdk.DefaultStackSynthesizer(file_assets_bucket_name="<example-existing-bucket-name>"))

Note: Additional parameters can be configured and customized. For more information, see Customizing bootstrapping.

AWS OFFICIAL
AWS OFFICIALUpdated 8 months ago