-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
bootstrap-environment.ts
161 lines (146 loc) · 5.25 KB
/
bootstrap-environment.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import * as fs from 'fs-extra';
import * as os from 'os';
import * as path from 'path';
import { Tag } from '../cdk-toolkit';
import { Mode, SdkProvider } from './aws-auth';
import { deployStack, DeployStackResult } from './deploy-stack';
// tslint:disable:max-line-length
/** @experimental */
export const BUCKET_NAME_OUTPUT = 'BucketName';
/** @experimental */
export const REPOSITORY_NAME_OUTPUT = 'RepositoryName';
/** @experimental */
export const BUCKET_DOMAIN_NAME_OUTPUT = 'BucketDomainName';
export interface BootstrapEnvironmentProps {
/**
* The name to be given to the CDK Bootstrap bucket.
*
* @default - a name is generated by CloudFormation.
*/
readonly bucketName?: string;
/**
* The ID of an existing KMS key to be used for encrypting items in the bucket.
*
* @default - the default KMS key for S3 will be used.
*/
readonly kmsKeyId?: string;
/**
* Tags for cdktoolkit stack.
*
* @default - None.
*/
readonly tags?: Tag[];
/**
* Whether to execute the changeset or only create it and leave it in review.
* @default true
*/
readonly execute?: boolean;
/**
* The list of AWS account IDs that are trusted to deploy into the environment being bootstrapped.
*
* @default - only the bootstrapped account can deploy into this environment
*/
readonly trustedAccounts?: string[];
/**
* The ARNs of the IAM managed policies that should be attached to the role performing CloudFormation deployments.
* In most cases, this will be the AdministratorAccess policy.
* At least one policy is required if {@link trustedAccounts} were passed.
*
* @default - the role will have no policies attached
*/
readonly cloudFormationExecutionPolicies?: string[];
}
/** @experimental */
export async function bootstrapEnvironment(environment: cxapi.Environment, sdkProvider: SdkProvider, toolkitStackName: string, roleArn: string | undefined, props: BootstrapEnvironmentProps = {}): Promise<DeployStackResult> {
if (props.trustedAccounts?.length) {
throw new Error('--trust can only be passed for the new bootstrap experience!');
}
if (props.cloudFormationExecutionPolicies?.length) {
throw new Error('--cloudformation-execution-policies can only be passed for the new bootstrap experience!');
}
const template = {
Description: 'The CDK Toolkit Stack. It was created by `cdk bootstrap` and manages resources necessary for managing your Cloud Applications with AWS CDK.',
Resources: {
StagingBucket: {
Type: 'AWS::S3::Bucket',
Properties: {
BucketName: props.bucketName,
AccessControl: 'Private',
BucketEncryption: {
ServerSideEncryptionConfiguration: [{
ServerSideEncryptionByDefault: {
SSEAlgorithm: 'aws:kms',
KMSMasterKeyID: props.kmsKeyId,
},
}],
},
PublicAccessBlockConfiguration: {
BlockPublicAcls: true,
BlockPublicPolicy: true,
IgnorePublicAcls: true,
RestrictPublicBuckets: true,
},
},
},
StagingBucketPolicy: {
Type: 'AWS::S3::BucketPolicy',
Properties: {
Bucket: { Ref: 'StagingBucket' },
PolicyDocument: {
Id: 'AccessControl',
Version: '2012-10-17',
Statement: [
{
Sid: 'AllowSSLRequestsOnly',
Action: 's3:*',
Effect: 'Deny',
Resource: [
{ 'Fn::Sub': '${StagingBucket.Arn}' },
{ 'Fn::Sub': '${StagingBucket.Arn}/*' },
],
Condition: {
Bool: { 'aws:SecureTransport': 'false' },
},
Principal: '*',
},
],
},
},
},
},
Outputs: {
[BUCKET_NAME_OUTPUT]: {
Description: 'The name of the S3 bucket owned by the CDK toolkit stack',
Value: { Ref: 'StagingBucket' },
},
[BUCKET_DOMAIN_NAME_OUTPUT]: {
Description: 'The domain name of the S3 bucket owned by the CDK toolkit stack',
Value: { 'Fn::GetAtt': ['StagingBucket', 'RegionalDomainName'] },
},
},
};
const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap'));
const builder = new cxapi.CloudAssemblyBuilder(outdir);
const templateFile = `${toolkitStackName}.template.json`;
await fs.writeJson(path.join(builder.outdir, templateFile), template, { spaces: 2 });
builder.addArtifact(toolkitStackName, {
type: cxschema.ArtifactType.AWS_CLOUDFORMATION_STACK,
environment: cxapi.EnvironmentUtils.format(environment.account, environment.region),
properties: {
templateFile,
},
});
const assembly = builder.buildAssembly();
const resolvedEnvironment = await sdkProvider.resolveEnvironment(environment.account, environment.region);
return await deployStack({
stack: assembly.getStackByName(toolkitStackName),
resolvedEnvironment,
sdk: await sdkProvider.forEnvironment(environment.account, environment.region, Mode.ForWriting),
sdkProvider,
roleArn,
tags: props.tags,
execute: props.execute,
});
}