Skip to content

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. The bootstrap action creates the resources that AWS CDK requires on the account.
An AWS CloudFormation template defines the resources and their configuration that the CDK uses.

The following are some use cases you can customize your bootstrap template for:

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

Resolution

Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshooting errors for the AWS CLI. Also, make sure that you're using the most recent AWS CLI version.

Use AWS CDK to deploy only the resources that you use

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

The CloudFormationExecutionRole has the arn:aws:iam::aws:policy/AdministratorAccess policy that grants full access to perform all actions.

Note: This policy goes against the least privilege principle. To restrict this policy, you must create a new policy and then bootstrap AWS CDK with the new custom policy.

Complete the following steps:

  1. To create a custom policy in AWS Identity and Access Management (IAM), run the following command:

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

    Note: Replace example-custom-Execution-policy-name.json with the filename of your JSON policy document. Replace cdkCFExecutionPolicy with your policy name**.**

  2. To use the newly created IAM policy to bootstrap the AWS CDK, run the following command:

    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 you have already bootstrapped the account, then rerun the cdk bootstrap command with the new custom policy.

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

Note: You can save only five policy versions in IAM. Delete earlier versions as required when you update your policy.

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

Complete the following steps:

  1. Run the cdk bootsrap command with additional flags for qualifier and bootstrap-bucket-name to bootstrap the account.
    cdk bootstrap --template bootstrap-template.yml --qualifier <example-custom-qualifier-value> --bootstrap-bucket-name <example-custom-bucket-name> --profile <example-profile-name>
    These flags create or update the CDKToolkit CloudFormation stack with new values for the resources.
  2. Update the app.py file with the following values:
    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 because of a resource that already exists, first identify and delete the resource if it's not needed. Then, perform the bootstrap from the CloudFormation stack again.

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

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

Complete the following steps:

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

    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 S3 bucket in the DeploymentActionRole and FilePublishingRoleDefaultPolicy resources of the bootstrap-template.yml.
    Example:

    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. This creates or updates the CDKToolkit CloudFormation stack with the preceding changes.

  4. To upload the file assets to your existing S3 bucket within your project, edit the stack synthesizer for CDK and include the following in your app.py file:

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

    Note: You can configure and customize additional parameters. For more information, see Customizing bootstrapping.