konokenj.cdk-api-mcp-server 0.52.0__py3-none-any.whl → 0.54.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.
Files changed (58) hide show
  1. cdk_api_mcp_server/__about__.py +1 -1
  2. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-eks-v2-alpha/README.md +45 -45
  3. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-imagebuilder-alpha/README.md +94 -0
  4. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-lambda-go-alpha/README.md +102 -4
  5. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-sagemaker-alpha/README.md +32 -0
  6. cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/mixins-preview/README.md +151 -5
  7. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/README.md/README.md +2 -0
  8. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigateway/README.md +25 -0
  9. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigateway/integ.lambda-permission-consolidation.ts +55 -0
  10. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/README.md +35 -0
  11. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.lambda-permission-consolidation.ts +45 -0
  12. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codebuild/README.md +0 -1
  13. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/README.md +26 -0
  14. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.add-to-resource-policy.ts +17 -0
  15. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.placement-strategies.ts +32 -8
  16. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/README.md +86 -86
  17. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.eks-al2023-nodegroup.ts +1 -1
  18. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.fargate-cluster.ts +1 -1
  19. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.runtime.inlinecode.ts +7 -0
  20. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/README.md +65 -4
  21. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-big-response.ts +13 -6
  22. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cloudfront.ts +20 -18
  23. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-nested-stack-source.ts +7 -1
  24. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-source.ts +6 -1
  25. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-ssm-source.ts +7 -1
  26. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-data.ts +83 -62
  27. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-deployed-bucket.ts +10 -4
  28. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-large-file.ts +20 -12
  29. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-loggroup.ts +7 -2
  30. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-efs.ts +77 -0
  31. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-empty.ts +69 -0
  32. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-multiple.ts +89 -0
  33. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-security-groups-single.ts +77 -0
  34. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-signcontent.ts +11 -7
  35. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution-with-destination-key.ts +15 -8
  36. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution-with-role.ts +29 -14
  37. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-substitution.ts +16 -8
  38. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-basic.ts +65 -0
  39. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-config.ts +66 -0
  40. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-custom-subnets.ts +66 -0
  41. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-efs.ts +66 -0
  42. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-security-groups.ts +72 -0
  43. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-vpc-subnet-selection.ts +70 -0
  44. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment.ts +47 -69
  45. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-secretsmanager/integ.secret.dynamic-reference-key.ts +38 -0
  46. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions/integ.sm-jsonpath-with-distributed-map-jsonata.ts +105 -0
  47. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/README.md +14 -3
  48. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.evaluate-expression-arm64.ts +27 -0
  49. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.evaluate-expression-default.ts +25 -0
  50. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.evaluate-expression-mixed-arch.ts +35 -0
  51. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.evaluate-expression-x86.ts +27 -0
  52. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +2 -2
  53. cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/interfaces/README.md +33 -0
  54. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.54.0.dist-info}/METADATA +2 -2
  55. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.54.0.dist-info}/RECORD +58 -38
  56. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.54.0.dist-info}/WHEEL +0 -0
  57. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.54.0.dist-info}/entry_points.txt +0 -0
  58. {konokenj_cdk_api_mcp_server-0.52.0.dist-info → konokenj_cdk_api_mcp_server-0.54.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,16 +1,162 @@
1
- # CDK Mixins: Composable Abstractions for AWS Resources
2
-
1
+ # CDK Mixins (Preview)
3
2
  <!--BEGIN STABILITY BANNER-->
4
3
 
5
4
  ---
6
5
 
7
6
  ![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)
8
7
 
9
- > The APIs of higher level constructs in this module are experimental and under active development. They are subject to non-backward compatible changes or removal in any future version. These are not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be announced in the release notes. This means that while you may use them, you may need to update your source code when upgrading to a newer version of this package.
8
+ > The APIs of higher level constructs in this module are experimental and under active development.
9
+ > They are subject to non-backward compatible changes or removal in any future version. These are
10
+ > not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be
11
+ > announced in the release notes. This means that while you may use them, you may need to update
12
+ > your source code when upgrading to a newer version of this package.
10
13
 
11
14
  ---
12
15
 
13
16
  <!--END STABILITY BANNER-->
14
17
 
15
- Implementation of the CDK Mixins proposal.
16
- See <https://github.com/aws/aws-cdk-rfcs/pull/824> for details.
18
+ CDK Mixins provide a new, advanced way to add functionality through composable abstractions.
19
+ Unlike traditional L2 constructs that bundle all features together, Mixins allow you to pick and choose exactly the capabilities you need for constructs.
20
+
21
+ ## Key Benefits
22
+
23
+ * **Universal Compatibility**: Apply the same abstractions to L1 constructs, L2 constructs, or custom constructs
24
+ * **Composable Design**: Mix and match features without being locked into specific implementations
25
+ * **Cross-Service Abstractions**: Use common patterns like encryption across different AWS services
26
+ * **Escape Hatch Freedom**: Customize resources in a safe, typed way while keeping the abstractions you want
27
+
28
+ ## Basic Usage
29
+
30
+ Mixins use `Mixins.of()` as the fundamental API for applying abstractions to constructs:
31
+
32
+ ```typescript
33
+ // Base form: apply mixins to any construct
34
+ const bucket = new s3.CfnBucket(scope, "MyBucket");
35
+ Mixins.of(bucket)
36
+ .apply(new EncryptionAtRest())
37
+ .apply(new AutoDeleteObjects());
38
+ ```
39
+
40
+ ## Creating Custom Mixins
41
+
42
+ Mixins are simple classes that implement the `IMixin` interface:
43
+
44
+ ```typescript
45
+ // Simple mixin that enables versioning
46
+ class CustomVersioningMixin implements IMixin {
47
+ supports(construct: any): boolean {
48
+ return construct instanceof s3.CfnBucket;
49
+ }
50
+
51
+ applyTo(bucket: any): any {
52
+ bucket.versioningConfiguration = {
53
+ status: "Enabled"
54
+ };
55
+ return bucket;
56
+ }
57
+ }
58
+
59
+ // Usage
60
+ const bucket = new s3.CfnBucket(scope, "MyBucket");
61
+ Mixins.of(bucket).apply(new CustomVersioningMixin());
62
+ ```
63
+
64
+ ## Construct Selection
65
+
66
+ Mixins operate on construct trees and can be applied selectively:
67
+
68
+ ```typescript
69
+ // Apply to all constructs in a scope
70
+ Mixins.of(scope).apply(new EncryptionAtRest());
71
+
72
+ // Apply to specific resource types
73
+ Mixins.of(scope, ConstructSelector.resourcesOfType(s3.CfnBucket))
74
+ .apply(new EncryptionAtRest());
75
+
76
+ // Apply to constructs matching a pattern
77
+ Mixins.of(scope, ConstructSelector.byId(/.*-prod-.*/))
78
+ .apply(new ProductionSecurityMixin());
79
+ ```
80
+
81
+ ## Built-in Mixins
82
+
83
+ ### Cross-Service Mixins
84
+
85
+ **EncryptionAtRest**: Applies encryption to supported AWS resources
86
+
87
+ ```typescript
88
+ // Works across different resource types
89
+ const bucket = new s3.CfnBucket(scope, "Bucket");
90
+ Mixins.of(bucket).apply(new EncryptionAtRest());
91
+
92
+ const logGroup = new logs.CfnLogGroup(scope, "LogGroup");
93
+ Mixins.of(logGroup).apply(new EncryptionAtRest());
94
+ ```
95
+
96
+ ### S3-Specific Mixins
97
+
98
+ **AutoDeleteObjects**: Configures automatic object deletion for S3 buckets
99
+
100
+ ```typescript
101
+ const bucket = new s3.CfnBucket(scope, "Bucket");
102
+ Mixins.of(bucket).apply(new AutoDeleteObjects());
103
+ ```
104
+
105
+ **EnableVersioning**: Enables versioning on S3 buckets
106
+
107
+ ```typescript
108
+ const bucket = new s3.CfnBucket(scope, "Bucket");
109
+ Mixins.of(bucket).apply(new EnableVersioning());
110
+ ```
111
+
112
+ ### Generic Mixins
113
+
114
+ **CfnPropertiesMixin**: Applies arbitrary CloudFormation properties
115
+
116
+ ```typescript
117
+ const bucket = new s3.CfnBucket(scope, "Bucket");
118
+ Mixins.of(bucket).apply(new CfnPropertiesMixin({
119
+ customProperty: { enabled: true }
120
+ }));
121
+ ```
122
+
123
+ ## Error Handling
124
+
125
+ Mixins provide comprehensive error handling:
126
+
127
+ ```typescript
128
+ // Graceful handling of unsupported constructs
129
+ Mixins.of(scope)
130
+ .apply(new EncryptionAtRest()); // Skips unsupported constructs
131
+
132
+ // Strict application that requires all constructs to match
133
+ Mixins.of(scope)
134
+ .mustApply(new EncryptionAtRest()); // Throws if no constructs support the mixin
135
+ ```
136
+
137
+ ## API Reference
138
+
139
+ ### Core Interfaces
140
+
141
+ * `IMixin` - Interface that all mixins must implement
142
+ * `Mixins` - Main entry point for applying mixins
143
+ * `ConstructSelector` - Selects constructs from a tree based on criteria
144
+ * `MixinApplicator` - Applies mixins to selected constructs
145
+
146
+ ### Mixins
147
+
148
+ * `EncryptionAtRest` - Cross-service encryption mixin
149
+ * `AutoDeleteObjects` - S3 auto-delete objects mixin
150
+ * `EnableVersioning` - S3 versioning mixin
151
+ * `CfnPropertiesMixin` - Generic CloudFormation properties mixin
152
+
153
+ ### Selectors
154
+
155
+ * `ConstructSelector.all()` - Select all constructs
156
+ * `ConstructSelector.cfnResource()` - Select CfnResource constructs
157
+ * `ConstructSelector.resourcesOfType()` - Select by type
158
+ * `ConstructSelector.byId()` - Select by ID pattern
159
+
160
+ ## License
161
+
162
+ This project is licensed under the Apache-2.0 License.
@@ -480,6 +480,8 @@ CloudFormation to re-read the secret.
480
480
  `SecretValue.ssmSecure()` is only supported for a limited set of resources.
481
481
  [Click here for a list of supported resources and properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#template-parameters-dynamic-patterns-resources).
482
482
 
483
+ `SecretValue.cfnDynamicReferenceKey` takes the same parameters as `SecretValue.secretsManager` and returns a key which can be used within a [dynamic reference](#dynamic-references) to dynamically load a secret from AWS Secrets Manager.
484
+
483
485
  ## ARN manipulation
484
486
 
485
487
  Sometimes you will need to put together or pick apart Amazon Resource Names
@@ -334,6 +334,31 @@ const getMessageIntegration = new apigateway.AwsIntegration({
334
334
  });
335
335
  ```
336
336
 
337
+ ### Lambda Integration Permissions
338
+
339
+ By default, creating a `LambdaIntegration` will add a permission for API Gateway to invoke your AWS Lambda function, scoped to the specific method which uses the integration.
340
+
341
+ If you reuse the same AWS Lambda function for many integrations, the AWS Lambda permission policy size can be exceeded by adding a separate policy statement for each method which invokes the AWS Lambda function. To avoid this, you can opt to scope permissions to any method on the API by setting `scopePermissionToMethod` to `false`, and this will ensure only a single policy statement is added to the AWS Lambda permission policy.
342
+
343
+ ```ts
344
+ declare const book: apigateway.Resource;
345
+ declare const backend: lambda.Function;
346
+
347
+ const getBookIntegration = new apigateway.LambdaIntegration(backend, {
348
+ scopePermissionToMethod: false,
349
+ });
350
+ const createBookIntegration = new apigateway.LambdaIntegration(backend, {
351
+ scopePermissionToMethod: false,
352
+ });
353
+
354
+ book.addMethod('GET', getBookIntegration);
355
+ book.addMethod('POST', createBookIntegration);
356
+ ```
357
+
358
+ In the above example, a single permission is added, shared by both `getBookIntegration` and `createBookIntegration`.
359
+
360
+ Note that setting `scopePermissionToMethod` to `false` will always allow test invocations, no matter the value specified for `allowTestInvoke`.
361
+
337
362
  ## Usage Plan & API Keys
338
363
 
339
364
  A usage plan specifies who can access one or more deployed API stages and methods, and the rate at which they can be
@@ -0,0 +1,55 @@
1
+ import { Code, Function, Runtime } from 'aws-cdk-lib/aws-lambda';
2
+ import { App, Stack } from 'aws-cdk-lib';
3
+ import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
4
+ import { Construct } from 'constructs';
5
+ import { LambdaIntegration, RestApi } from 'aws-cdk-lib/aws-apigateway';
6
+
7
+ class LambdaPermissionConsolidationStack extends Stack {
8
+ public readonly api: RestApi;
9
+ constructor(scope: Construct) {
10
+ super(scope, 'LambdaPermissionConsolidationStack');
11
+
12
+ const fn = new Function(this, 'Handler', {
13
+ code: Code.fromInline(`exports.handler = async function(event) {
14
+ return {
15
+ body: JSON.stringify({
16
+ message: 'Hello from ' + event.httpMethod,
17
+ }),
18
+ statusCode: 200,
19
+ headers: { 'Content-Type': 'application/json' }
20
+ };
21
+ }`),
22
+ runtime: Runtime.NODEJS_18_X,
23
+ handler: 'index.handler',
24
+ });
25
+
26
+ this.api = new RestApi(this, 'Api', {
27
+ cloudWatchRole: true,
28
+ });
29
+
30
+ const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
31
+ methods.forEach(method => {
32
+ this.api.root.addMethod(method, new LambdaIntegration(fn, {
33
+ scopePermissionToMethod: false,
34
+ }));
35
+ });
36
+ }
37
+ }
38
+
39
+ const app = new App({
40
+ postCliContext: {
41
+ '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
42
+ },
43
+ });
44
+ const testCase = new LambdaPermissionConsolidationStack(app);
45
+ const integ = new IntegTest(app, 'lambda-permission-consolidation', {
46
+ testCases: [testCase],
47
+ });
48
+
49
+ // Test that all methods work after consolidation
50
+ const call = integ.assertions.httpApiCall(testCase.api.deploymentStage.urlForPath('/'), {
51
+ method: 'GET',
52
+ });
53
+ call.expect(ExpectedResult.objectLike({
54
+ body: { message: 'Hello from GET' },
55
+ }));
@@ -47,6 +47,41 @@ httpApi.addRoutes({
47
47
  });
48
48
  ```
49
49
 
50
+ #### Lambda Integration Permissions
51
+
52
+ By default, creating a `HttpLambdaIntegration` will add a permission for API Gateway to invoke your AWS Lambda function, scoped to the specific route which uses the integration.
53
+
54
+ If you reuse the same AWS Lambda function for many integrations, the AWS Lambda permission policy size can be exceeded by adding a separate policy statement for each route which invokes the AWS Lambda function. To avoid this, you can opt to scope permissions to any route on the API by setting `scopePermissionToRoute` to `false`, and this will ensure only a single policy statement is added to the AWS Lambda permission policy.
55
+
56
+ ```ts
57
+ import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
58
+
59
+ declare const booksDefaultFn: lambda.Function;
60
+
61
+ const httpApi = new apigwv2.HttpApi(this, 'HttpApi');
62
+
63
+ const getBooksIntegration = new HttpLambdaIntegration('GetBooksIntegration', booksDefaultFn, {
64
+ scopePermissionToRoute: false,
65
+ });
66
+ const createBookIntegration = new HttpLambdaIntegration('CreateBookIntegration', booksDefaultFn, {
67
+ scopePermissionToRoute: false,
68
+ });
69
+
70
+ httpApi.addRoutes({
71
+ path: '/books',
72
+ methods: [ apigwv2.HttpMethod.GET ],
73
+ integration: getBooksIntegration,
74
+ });
75
+
76
+ httpApi.addRoutes({
77
+ path: '/books',
78
+ methods: [ apigwv2.HttpMethod.POST ],
79
+ integration: createBookIntegration,
80
+ });
81
+ ```
82
+
83
+ In the above example, a single permission is added, shared by both `getBookIntegration` and `createBookIntegration`.
84
+
50
85
  ### HTTP Proxy
51
86
 
52
87
  HTTP Proxy integrations enables connecting an HTTP API route to a publicly routable HTTP endpoint. When a client
@@ -0,0 +1,45 @@
1
+ import { HttpApi, HttpMethod, HttpRoute, HttpRouteKey } from 'aws-cdk-lib/aws-apigatewayv2';
2
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
3
+ import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
4
+ import { App, Stack } from 'aws-cdk-lib';
5
+ import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
6
+
7
+ const app = new App({
8
+ postCliContext: {
9
+ '@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
10
+ },
11
+ });
12
+ const stack = new Stack(app, 'integ-lambda-permission-consolidation');
13
+
14
+ const httpApi = new HttpApi(stack, 'HttpApi');
15
+
16
+ const lambdaHandler = new lambda.Function(stack, 'Handler', {
17
+ runtime: lambda.Runtime.NODEJS_18_X,
18
+ handler: 'index.handler',
19
+ code: new lambda.InlineCode('exports.handler = async function(event, context) { return { statusCode: 200, body: JSON.stringify({ message: \'Hello from \' + event.requestContext.http.path }) }; };'),
20
+ });
21
+
22
+ // Add several routes
23
+ for (let i = 1; i <= 10; i++) {
24
+ new HttpRoute(stack, `Route${i}`, {
25
+ httpApi: httpApi,
26
+ integration: new HttpLambdaIntegration(`Integration${i}`, lambdaHandler, {
27
+ scopePermissionToRoute: false,
28
+ }),
29
+ routeKey: HttpRouteKey.with(`/path${i}`, HttpMethod.GET),
30
+ });
31
+ }
32
+
33
+ // Integ Test Assertions
34
+ const integ = new IntegTest(app, 'Integ', { testCases: [stack] });
35
+
36
+ // Test that routes work after consolidation
37
+ integ.assertions.httpApiCall(httpApi.apiEndpoint + '/path1').expect(ExpectedResult.objectLike({
38
+ body: { message: 'Hello from /path1' },
39
+ status: 200,
40
+ }));
41
+
42
+ integ.assertions.httpApiCall(httpApi.apiEndpoint + '/path12').expect(ExpectedResult.objectLike({
43
+ body: { message: 'Hello from /path10' },
44
+ status: 200,
45
+ }));
@@ -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
 
@@ -872,6 +872,32 @@ table.addToResourcePolicy(new iam.PolicyStatement({
872
872
  TableV2 doesn’t support creating a replica and adding a resource-based policy to that replica in the same stack update in Regions other than the Region where you deploy the stack update.
873
873
  To incorporate a resource-based policy into a replica, you'll need to initially deploy the replica without the policy, followed by a subsequent update to include the desired policy.
874
874
 
875
+ ### Grant Methods and Resource Policies
876
+
877
+ Grant methods like `grantReadData()`, `grantWriteData()`, and `grantReadWriteData()` automatically add permissions to resource policies when used with same-account principals (like `AccountRootPrincipal`). This happens transparently:
878
+
879
+ ```ts
880
+ const table = new dynamodb.TableV2(this, 'Table', {
881
+ partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING },
882
+ });
883
+
884
+ // Automatically adds to table's resource policy (same account)
885
+ table.grantReadData(new iam.AccountRootPrincipal());
886
+
887
+ // Adds to IAM user's policy (not resource policy)
888
+ declare const user: iam.User;
889
+ table.grantReadData(user);
890
+ ```
891
+
892
+ **How it works:**
893
+ - **Same-account principals** (AccountRootPrincipal, AccountPrincipal): Grant adds statement to table's resource policy
894
+ - **IAM identities** (User, Role, Group): Grant adds statement to the identity's IAM policy
895
+ - **Resource policy statements**: Automatically use wildcard resources (`*`) to avoid circular dependencies
896
+
897
+ This behavior follows the same pattern as other AWS services like KMS and S3, where grants intelligently choose between resource policies and identity policies based on the principal type.
898
+
899
+ **To avoid wildcards in resource policies:** If you need scoped resource ARNs instead of wildcards, use `addToResourcePolicy()` directly with an explicit table name instead of grant methods. See the "Scoped Resource Policies (Advanced)" section above for details.
900
+
875
901
  ## Grants
876
902
 
877
903
  Using any of the `grant*` methods on an instance of the `TableV2` construct will only apply to the primary table, its indexes, and any associated `encryptionKey`. As an example, `grantReadData` used below will only apply the table in `us-west-2`:
@@ -26,6 +26,7 @@ import { IntegTest } from '@aws-cdk/integ-tests-alpha';
26
26
  export class TestStack extends Stack {
27
27
  public readonly wildcardTable: dynamodb.Table;
28
28
  public readonly scopedTable: dynamodb.Table;
29
+ public readonly grantTable: dynamodb.Table;
29
30
 
30
31
  constructor(scope: Construct, id: string, props?: StackProps) {
31
32
  super(scope, id, props);
@@ -66,6 +67,22 @@ export class TestStack extends Stack {
66
67
  // Use CloudFormation intrinsic function to construct table ARN with known table name
67
68
  resources: [Fn.sub('arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/my-explicit-scoped-table')],
68
69
  }));
70
+
71
+ // TEST 3: Table using grant methods with AccountRootPrincipal
72
+ // This validates the fix for issue #35967: circular dependency when using grant methods
73
+ // Before fix: grant methods with AccountRootPrincipal caused circular dependency
74
+ // After fix: grant methods use resourceSelfArns: ['*'] to avoid circular dependency
75
+ this.grantTable = new dynamodb.Table(this, 'GrantTable', {
76
+ partitionKey: {
77
+ name: 'id',
78
+ type: dynamodb.AttributeType.STRING,
79
+ },
80
+ removalPolicy: RemovalPolicy.DESTROY,
81
+ });
82
+
83
+ // This should NOT cause circular dependency - validates fix for #35967
84
+ // Using grantWriteData because it has simpler actions valid for resource policies
85
+ this.grantTable.grantWriteData(new iam.AccountRootPrincipal());
69
86
  }
70
87
  }
71
88
 
@@ -2,6 +2,7 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
2
  import * as cdk from 'aws-cdk-lib';
3
3
  import { Construct } from 'constructs';
4
4
  import * as ecs from 'aws-cdk-lib/aws-ecs';
5
+ import * as integ from '@aws-cdk/integ-tests-alpha';
5
6
 
6
7
  const app = new cdk.App({
7
8
  postCliContext: {
@@ -12,24 +13,29 @@ const app = new cdk.App({
12
13
  },
13
14
  });
14
15
 
15
- class EcsStack extends cdk.Stack {
16
- constructor(scope: Construct, id: string, props?: cdk.StackProps) {
17
- super(scope, id, props);
18
-
16
+ class BaseEcsStack extends cdk.Stack {
17
+ protected createBaseResources() {
19
18
  const vpc = new ec2.Vpc(this, 'VPC', { restrictDefaultSecurityGroup: false });
20
-
21
19
  const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc });
22
20
  cluster.addCapacity('DefaultAutoScalingGroup', {
23
21
  instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
24
22
  });
25
-
26
23
  const taskDefinition = new ecs.Ec2TaskDefinition(this, 'TaskDef');
27
24
  taskDefinition.addContainer('web', {
28
25
  image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
29
26
  memoryLimitMiB: 256,
30
27
  });
28
+ return { vpc, cluster, taskDefinition };
29
+ }
30
+ }
31
+
32
+ // Test service with multiple placement strategies
33
+ class EcsWithStrategiesStack extends BaseEcsStack {
34
+ constructor(scope: Construct, id: string, props?: cdk.StackProps) {
35
+ super(scope, id, props);
36
+ const { cluster, taskDefinition } = this.createBaseResources();
31
37
 
32
- new ecs.Ec2Service(this, 'Test_Stack', {
38
+ new ecs.Ec2Service(this, 'Service', {
33
39
  cluster,
34
40
  taskDefinition,
35
41
  placementStrategies: [
@@ -40,6 +46,24 @@ class EcsStack extends cdk.Stack {
40
46
  }
41
47
  }
42
48
 
43
- new EcsStack(app, 'aws-cdk-ecs-integration-test-stack');
49
+ // Test service with empty placement strategies
50
+ class EcsWithEmptyStrategiesStack extends BaseEcsStack {
51
+ constructor(scope: Construct, id: string, props?: cdk.StackProps) {
52
+ super(scope, id, props);
53
+ const { cluster, taskDefinition } = this.createBaseResources();
54
+
55
+ new ecs.Ec2Service(this, 'Service', {
56
+ cluster,
57
+ taskDefinition,
58
+ placementStrategies: [],
59
+ });
60
+ }
61
+ }
62
+ new integ.IntegTest(app, 'LambdaTest', {
63
+ testCases: [
64
+ new EcsWithStrategiesStack(app, 'ecs-placement-strategies-with-strategies'),
65
+ new EcsWithEmptyStrategiesStack(app, 'ecs-placement-strategies-empty'),
66
+ ],
67
+ });
44
68
 
45
69
  app.synth();