diff --git a/design/cdk-bootstrap.md b/design/cdk-bootstrap.md index 2dbc0ce5985f8..718f475b51426 100644 --- a/design/cdk-bootstrap.md +++ b/design/cdk-bootstrap.md @@ -323,4 +323,4 @@ This should make sure the CFN update succeeds. ## Bootstrap template The bootstrap template used by the CLI command can be found in the -[aws-cdk package](../packages/aws-cdk/lib/api/bootstrap/bootstrap-template.json). +[aws-cdk package](../packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml). diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment2.ts b/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment2.ts index 8d4b9b5159716..d65ccc8c56072 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment2.ts +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment2.ts @@ -3,6 +3,7 @@ import * as fs from 'fs-extra'; import * as os from 'os'; import * as path from 'path'; import { BootstrapEnvironmentProps, deployStack, DeployStackResult } from '..'; +import { loadStructuredFile } from '../../serialize'; import { SdkProvider } from '../aws-auth'; export async function bootstrapEnvironment2(environment: cxapi.Environment, sdk: SdkProvider, @@ -14,11 +15,14 @@ export async function bootstrapEnvironment2(environment: cxapi.Environment, sdk: const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap-new')); const builder = new cxapi.CloudAssemblyBuilder(outdir); - const templateFile = `${toolkitStackName}.template.json`; - await fs.copy( - path.join(__dirname, 'bootstrap-template.json'), - path.join(builder.outdir, templateFile)); + // convert from YAML to JSON (which the Cloud Assembly uses) + const templateFile = `${toolkitStackName}.template.json`; + const bootstrapTemplatePath = path.join(__dirname, 'bootstrap-template.yaml'); + const bootstrapTemplateObject = loadStructuredFile(bootstrapTemplatePath); + await fs.writeJson( + path.join(builder.outdir, templateFile), + bootstrapTemplateObject); builder.addArtifact(toolkitStackName, { type: cxapi.ArtifactType.AWS_CLOUDFORMATION_STACK, diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.json b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.json deleted file mode 100644 index 38c95a3b58ecf..0000000000000 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.json +++ /dev/null @@ -1,427 +0,0 @@ -{ - "Description": "This stack includes resources needed to deploy AWS CDK apps into this environment", - "Parameters": { - "TrustedAccounts": { - "Description": "List of AWS accounts that are trusted to publish assets and deploy stacks to this environment", - "Default": "", - "Type": "CommaDelimitedList" - }, - "CloudFormationExecutionPolicies": { - "Description": "List of the ManagedPolicy ARN(s) to attach to the CloudFormation deployment role", - "Default": "", - "Type": "CommaDelimitedList" - }, - "FileAssetsBucketName": { - "Description": "The name of the S3 bucket used for file assets", - "Default": "", - "Type": "String" - }, - "FileAssetsBucketKmsKeyId": { - "Description": "Custom KMS key ID to use for encrypting file assets (by default a KMS key will be automatically defined)", - "Default": "", - "Type": "String" - }, - "ContainerAssetsRepositoryName": { - "Description": "A user-provided custom name to use for the container assets ECR repository", - "Default": "", - "Type": "String" - } - }, - "Conditions": { - "HasTrustedAccounts": { - "Fn::Not": [ - { - "Fn::Equals": [ - "", - { - "Fn::Join": [ - "", - { - "Ref": "TrustedAccounts" - } - ] - } - ] - } - ] - }, - "HasCloudFormationExecutionPolicies": { - "Fn::Not": [ - { - "Fn::Equals": [ - "", - { - "Fn::Join": [ - "", - { - "Ref": "CloudFormationExecutionPolicies" - } - ] - } - ] - } - ] - }, - "HasCustomFileAssetsBucketName": { - "Fn::Not": [ - { - "Fn::Equals": [ - "", - { - "Ref": "FileAssetsBucketName" - } - ] - } - ] - }, - "CreateNewKey": { - "Fn::Equals": [ - "", - { - "Ref": "FileAssetsBucketKmsKeyId" - } - ] - }, - "HasCustomContainerAssetsRepositoryName": { - "Fn::Not": [ - { - "Fn::Equals": [ - "", - { - "Ref": "ContainerAssetsRepositoryName" - } - ] - } - ] - } - }, - "Resources": { - "FileAssetsBucketEncryptionKey": { - "Type": "AWS::KMS::Key", - "Properties": { - "KeyPolicy": { - "Statement": [ - { - "Action": [ - "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", - "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", - "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion", "kms:GenerateDataKey" - ], - "Effect": "Allow", - "Principal": { - "AWS": { - "Ref": "AWS::AccountId" - } - }, - "Resource": "*" - }, - { - "Action": [ - "kms:Decrypt", "kms:DescribeKey", "kms:Encrypt", - "kms:ReEncrypt*", "kms:GenerateDataKey*" - ], - "Effect": "Allow", - "Principal": { - "AWS": { - "Ref": "AWS::AccountId" - } - }, - "Resource": "*", - "Condition": { - "StringEquals": { - "kms:ViaService": [ - { "Fn::Sub": "s3.${AWS::Region}.amazonaws.com" } - ] - } - } - }, - { - "Action": [ - "kms:Decrypt", "kms:DescribeKey", "kms:Encrypt", - "kms:ReEncrypt*", "kms:GenerateDataKey*" - ], - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Sub": "${PublishingRole.Arn}" - } - }, - "Resource": "*" - } - ] - } - }, - "Condition": "CreateNewKey" - }, - "StagingBucket": { - "Type": "AWS::S3::Bucket", - "Properties": { - "BucketName": { - "Fn::If": [ - "HasCustomFileAssetsBucketName", - { "Fn::Sub": "${FileAssetsBucketName}" }, - { "Fn::Sub": "cdk-bootstrap-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" } - ] - }, - "AccessControl": "Private", - "BucketEncryption": { - "ServerSideEncryptionConfiguration": [{ - "ServerSideEncryptionByDefault": { - "SSEAlgorithm": "aws:kms", - "KMSMasterKeyID": { - "Fn::If": [ - "CreateNewKey", - { "Fn::Sub": "${FileAssetsBucketEncryptionKey.Arn}" }, - { "Fn::Sub": "${FileAssetsBucketKmsKeyId}" } - ] - } - } - }] - }, - "PublicAccessBlockConfiguration": { - "BlockPublicAcls": true, - "BlockPublicPolicy": true, - "IgnorePublicAcls": true, - "RestrictPublicBuckets": true - } - }, - "UpdateReplacePolicy": "Retain" - }, - "ContainerAssetsRepository": { - "Type": "AWS::ECR::Repository", - "Properties": { - "RepositoryName": { - "Fn::If": [ - "HasCustomContainerAssetsRepositoryName", - { "Fn::Sub": "${ContainerAssetsRepositoryName}" }, - { "Fn::Sub": "cdk-bootstrap-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}" } - ] - } - } - }, - "PublishingRole": { - "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" - } - ] - } - ] - }, - "RoleName": { - "Fn::Sub": "cdk-bootstrap-publishing-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "PublishingRoleDefaultPolicy": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "s3:GetObject*", "s3:GetBucket*", "s3:List*", - "s3:DeleteObject*", "s3:PutObject*", "s3:Abort*" - ], - "Resource": [ - { - "Fn::Sub": "${StagingBucket.Arn}" - }, - { - "Fn::Sub": "${StagingBucket.Arn}/*" - } - ], - "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}" } - ] - } - }, - { - "Action": [ - "ecr:PutImage", "ecr:InitiateLayerUpload", - "ecr:UploadLayerPart", "ecr:CompleteLayerUpload", - "ecr:BatchCheckLayerAvailability", - "ecr:DescribeRepositories", "ecr:DescribeImages" - ], - "Resource": { - "Fn::Sub": "${ContainerAssetsRepository.Arn}" - }, - "Effect": "Allow" - }, - { - "Action": ["ecr:GetAuthorizationToken"], - "Resource": "*", - "Effect": "Allow" - } - ], - "Version": "2012-10-17" - }, - "Roles": [ - { "Ref": "PublishingRole" } - ], - "PolicyName": { - "Fn::Sub": "cdk-bootstrap-hnb659fds-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "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": [ - { - "Action": [ - "cloudformation:CreateChangeSet", "cloudformation:DeleteChangeSet", - "cloudformation:DescribeChangeSet", "cloudformation:DescribeStacks", - "cloudformation:ExecuteChangeSet", - "s3:GetObject*", "s3:GetBucket*", - "s3:List*", "s3:Abort*", - "s3:DeleteObject*", "s3:PutObject*", - "kms:Decrypt", "kms:DescribeKey", "kms:Encrypt", - "kms:ReEncrypt*", "kms:GenerateDataKey*" - ], - "Resource": "*", - "Effect": "Allow" - }, - { - "Action": "iam:PassRole", - "Resource": { - "Fn::Sub": "${CloudFormationExecutionRole.Arn}" - }, - "Effect": "Allow" - }, - { - "Sid": "CliPermissions", - "Action": [ - "cloudformation:DescribeStackEvents", - "cloudformation:GetTemplate", - "cloudformation:DeleteStack", - "sts:GetCallerIdentity" - ], - "Resource": "*", - "Effect": "Allow" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "default" - } - ], - "RoleName": { - "Fn::Sub": "cdk-bootstrap-deploy-action-role-${AWS::AccountId}-${AWS::Region}" - } - } - }, - "CloudFormationExecutionRole": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "cloudformation.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "ManagedPolicyArns": { - "Fn::If": [ - "HasCloudFormationExecutionPolicies", - { "Ref": "CloudFormationExecutionPolicies" }, - { "Ref": "AWS::NoValue" } - ] - }, - "RoleName": { - "Fn::Sub": "cdk-bootstrap-cfn-exec-role-${AWS::AccountId}-${AWS::Region}" - } - } - } - }, - "Outputs": { - "BucketName": { - "Description": "The name of the S3 bucket owned by the CDK toolkit stack", - "Value": { "Fn::Sub": "${StagingBucket}" } - }, - "BucketDomainName": { - "Description": "The domain name of the S3 bucket owned by the CDK toolkit stack", - "Value": { "Fn::Sub": "${StagingBucket.RegionalDomainName}" } - }, - "BootstrapVersion": { - "Description": "The version of the bootstrap resources that are currently mastered in this stack", - "Value": "1", - "Export": { - "Name": { "Fn::Sub": "AwsCdkBootstrapVersion" } - } - } - } -} diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml new file mode 100644 index 0000000000000..18dfc1216708c --- /dev/null +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml @@ -0,0 +1,305 @@ +Description: This stack includes resources needed to deploy AWS CDK apps into this + environment +Parameters: + TrustedAccounts: + Description: List of AWS accounts that are trusted to publish assets and deploy + stacks to this environment + Default: '' + Type: CommaDelimitedList + CloudFormationExecutionPolicies: + Description: List of the ManagedPolicy ARN(s) to attach to the CloudFormation + deployment role + Default: '' + Type: CommaDelimitedList + FileAssetsBucketName: + Description: The name of the S3 bucket used for file assets + Default: '' + Type: String + FileAssetsBucketKmsKeyId: + Description: Custom KMS key ID to use for encrypting file assets (by default a + KMS key will be automatically defined) + Default: '' + Type: String + ContainerAssetsRepositoryName: + Description: A user-provided custom name to use for the container assets ECR repository + Default: '' + Type: String +Conditions: + HasTrustedAccounts: + Fn::Not: + - Fn::Equals: + - '' + - Fn::Join: + - '' + - Ref: TrustedAccounts + HasCloudFormationExecutionPolicies: + Fn::Not: + - Fn::Equals: + - '' + - Fn::Join: + - '' + - Ref: CloudFormationExecutionPolicies + HasCustomFileAssetsBucketName: + Fn::Not: + - Fn::Equals: + - '' + - Ref: FileAssetsBucketName + CreateNewKey: + Fn::Equals: + - '' + - Ref: FileAssetsBucketKmsKeyId + HasCustomContainerAssetsRepositoryName: + Fn::Not: + - Fn::Equals: + - '' + - Ref: ContainerAssetsRepositoryName +Resources: + FileAssetsBucketEncryptionKey: + Type: AWS::KMS::Key + Properties: + KeyPolicy: + Statement: + - Action: + - kms:Create* + - kms:Describe* + - kms:Enable* + - kms:List* + - kms:Put* + - kms:Update* + - kms:Revoke* + - kms:Disable* + - kms:Get* + - kms:Delete* + - kms:ScheduleKeyDeletion + - kms:CancelKeyDeletion + - kms:GenerateDataKey + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + Resource: "*" + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Ref: AWS::AccountId + Resource: "*" + Condition: + StringEquals: + kms:ViaService: + - Fn::Sub: s3.${AWS::Region}.amazonaws.com + - Action: + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Effect: Allow + Principal: + AWS: + Fn::Sub: "${PublishingRole.Arn}" + Resource: "*" + Condition: CreateNewKey + StagingBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: + Fn::If: + - HasCustomFileAssetsBucketName + - Fn::Sub: "${FileAssetsBucketName}" + - Fn::Sub: cdk-bootstrap-hnb659fds-assets-${AWS::AccountId}-${AWS::Region} + AccessControl: Private + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: aws:kms + KMSMasterKeyID: + Fn::If: + - CreateNewKey + - Fn::Sub: "${FileAssetsBucketEncryptionKey.Arn}" + - Fn::Sub: "${FileAssetsBucketKmsKeyId}" + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + UpdateReplacePolicy: Retain + ContainerAssetsRepository: + Type: AWS::ECR::Repository + Properties: + RepositoryName: + Fn::If: + - HasCustomContainerAssetsRepositoryName + - Fn::Sub: "${ContainerAssetsRepositoryName}" + - Fn::Sub: cdk-bootstrap-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region} + PublishingRole: + 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 + RoleName: + Fn::Sub: cdk-bootstrap-publishing-role-${AWS::AccountId}-${AWS::Region} + PublishingRoleDefaultPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyDocument: + Statement: + - Action: + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:DeleteObject* + - s3:PutObject* + - s3:Abort* + Resource: + - Fn::Sub: "${StagingBucket.Arn}" + - Fn::Sub: "${StagingBucket.Arn}/*" + 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} + - Action: + - ecr:PutImage + - ecr:InitiateLayerUpload + - ecr:UploadLayerPart + - ecr:CompleteLayerUpload + - ecr:BatchCheckLayerAvailability + - ecr:DescribeRepositories + - ecr:DescribeImages + Resource: + Fn::Sub: "${ContainerAssetsRepository.Arn}" + Effect: Allow + - Action: + - ecr:GetAuthorizationToken + Resource: "*" + Effect: Allow + Version: '2012-10-17' + Roles: + - Ref: PublishingRole + PolicyName: + Fn::Sub: cdk-bootstrap-hnb659fds-publishing-role-default-policy-${AWS::AccountId}-${AWS::Region} + 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: + - Action: + # Permissions needed in CodePipeline. + # S3 and KMS are needed on '*', + # as we don't know the IDs of the CodePipeline's bucket and key in advance + - cloudformation:CreateChangeSet + - cloudformation:DeleteChangeSet + - cloudformation:DescribeChangeSet + - cloudformation:DescribeStacks + - cloudformation:ExecuteChangeSet + - s3:GetObject* + - s3:GetBucket* + - s3:List* + - s3:Abort* + - s3:DeleteObject* + - s3:PutObject* + # Necessary to write to the cross-region artifact replication bucket + # https://aws.amazon.com/premiumsupport/knowledge-center/codepipeline-deploy-cloudformation/. + - kms:Decrypt + - kms:DescribeKey + - kms:Encrypt + - kms:ReEncrypt* + - kms:GenerateDataKey* + Resource: "*" + Effect: Allow + - Action: iam:PassRole + Resource: + Fn::Sub: "${CloudFormationExecutionRole.Arn}" + Effect: Allow + - Sid: CliPermissions + Action: + # Permissions needed by the CLI when doing `cdk deploy`. + # Our CI/CD does not need DeleteStack, + # but we also want to use this role from the CLI, + # and there you can call `cdk destroy` + - cloudformation:DescribeStackEvents + - cloudformation:GetTemplate + - cloudformation:DeleteStack + - sts:GetCallerIdentity + Resource: "*" + Effect: Allow + Version: '2012-10-17' + PolicyName: default + RoleName: + Fn::Sub: cdk-bootstrap-deploy-action-role-${AWS::AccountId}-${AWS::Region} + CloudFormationExecutionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: sts:AssumeRole + Effect: Allow + Principal: + Service: cloudformation.amazonaws.com + Version: '2012-10-17' + ManagedPolicyArns: + Fn::If: + - HasCloudFormationExecutionPolicies + - Ref: CloudFormationExecutionPolicies + - Ref: AWS::NoValue + RoleName: + Fn::Sub: cdk-bootstrap-cfn-exec-role-${AWS::AccountId}-${AWS::Region} +Outputs: + BucketName: + Description: The name of the S3 bucket owned by the CDK toolkit stack + Value: + Fn::Sub: "${StagingBucket}" + BucketDomainName: + Description: The domain name of the S3 bucket owned by the CDK toolkit stack + Value: + Fn::Sub: "${StagingBucket.RegionalDomainName}" + BootstrapVersion: + Description: The version of the bootstrap resources that are currently mastered + in this stack + Value: '1' + Export: + Name: + Fn::Sub: AwsCdkBootstrapVersion diff --git a/packages/aws-cdk/lib/serialize.ts b/packages/aws-cdk/lib/serialize.ts index 7f68927753703..41e8f842c69c1 100644 --- a/packages/aws-cdk/lib/serialize.ts +++ b/packages/aws-cdk/lib/serialize.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs-extra'; import * as YAML from 'yaml'; /* eslint-disable @typescript-eslint/no-require-imports */ @@ -47,3 +48,11 @@ export function serializeStructure(object: any, json: boolean) { return toYAML(object); } } + +/** + * Load a YAML or JSON file from disk + */ +export async function loadStructuredFile(fileName: string) { + const contents = await fs.readFile(fileName, { encoding: 'utf-8' }); + return deserializeStructure(contents); +} \ No newline at end of file diff --git a/packages/aws-cdk/test/integ/bootstrap/bootstrap.integ-test.ts b/packages/aws-cdk/test/integ/bootstrap/bootstrap.integ-test.ts index 1fc02d6de1d23..9272e47d32429 100644 --- a/packages/aws-cdk/test/integ/bootstrap/bootstrap.integ-test.ts +++ b/packages/aws-cdk/test/integ/bootstrap/bootstrap.integ-test.ts @@ -53,6 +53,7 @@ describe('Bootstrapping', () => { testStack = await deployCdkApp(outdir, env, sdk, bootstrapStackName, (app) => { new MyTestCdkStack(app, exampleAppStack, { assetType: ExampleAsset.ASSET_1, + env, }); }); }); @@ -75,6 +76,7 @@ describe('Bootstrapping', () => { await deployCdkApp(outdir, env, sdk, bootstrapStackName, (app) => { new MyTestCdkStack(app, exampleAppStack, { assetType: ExampleAsset.ASSET_2, + env, }); }); }); diff --git a/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.d.ts b/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.d.ts index 621b5f816e607..ba790fd1502b5 100644 --- a/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.d.ts +++ b/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.d.ts @@ -1,4 +1,5 @@ import { Construct, Stack, StackProps } from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; export declare enum ExampleAsset { ASSET_1 = "asset1.txt", @@ -7,6 +8,8 @@ export declare enum ExampleAsset { export interface MyTestCdkStackProps extends StackProps { readonly assetType: ExampleAsset; + + readonly env: cxapi.Environment; } export declare class MyTestCdkStack extends Stack { diff --git a/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.js b/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.js index f175127b3414b..cf2d671f0716f 100644 --- a/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.js +++ b/packages/aws-cdk/test/integ/bootstrap/example-cdk-app/my-test-cdk-stack.js @@ -17,7 +17,13 @@ exports.ExampleAsset = ExampleAsset; */ class MyTestCdkStack extends core.Stack { constructor(scope, id, props) { - super(scope, id, props); + super(scope, id, { + ...props, + env: { + account: props.env.account, + region: props.env.region, + }, + }); // we need to have at least one resource // make it different based on the asset,