konokenj.cdk-api-mcp-server 0.40.0__py3-none-any.whl → 0.42.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.
- cdk_api_mcp_server/__about__.py +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-bedrock-alpha/README.md +540 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-eks-v2-alpha/README.md +44 -46
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-lambda-python-alpha/README.md +6 -6
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/aws-s3tables-alpha/README.md +28 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/README.md/README.md +364 -16
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/README.md +144 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api-dualstack.ts +3 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api.ts +2 -4
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.stage.ts +7 -20
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.usage-plan.ts +80 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.iam.ts +34 -38
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.sqs.ts +58 -71
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codepipeline-actions/integ.pipeline-elastic-beanstalk-deploy.ts +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cognito/README.md +11 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cognito/integ.user-pool-client-explicit-props.ts +1 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/README.md +38 -13
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb-v2.cci.ts +49 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.cci.ts +27 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.dynamodb.contirubtor-insights-for-gsi.ts +6 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.table-v2-global.ts +9 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/README.md +3 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs/integ.ebs-volume-initialization-rate.ts +80 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs-patterns/README.md +2 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ecs-patterns/integ.alb-fargate-service-smart-defaults.ts +143 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/README.md +25 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-events/integ.archive-customer-managed-key.ts +23 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/README.md +2 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-route53/integ.delete-existing-record-set.ts +0 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/README.md +18 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-deployment/integ.bucket-deployment-cross-stack-ssm-source.ts +91 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-signer/integ.signing-profile.ts +5 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-sns/README.md +2 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-sns-subscriptions/integ.sns-sqs-subscription-filter.ts +75 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-sns-subscriptions/integ.sns-sqs.ts +21 -40
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/README.md +9 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke-jsonata.ts +87 -80
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.invoke.ts +87 -69
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.start-job-run.ts +102 -104
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/core/README.md +2 -1893
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +52 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/README.md +24 -1
- {konokenj_cdk_api_mcp_server-0.40.0.dist-info → konokenj_cdk_api_mcp_server-0.42.0.dist-info}/METADATA +2 -2
- {konokenj_cdk_api_mcp_server-0.40.0.dist-info → konokenj_cdk_api_mcp_server-0.42.0.dist-info}/RECORD +47 -39
- {konokenj_cdk_api_mcp_server-0.40.0.dist-info → konokenj_cdk_api_mcp_server-0.42.0.dist-info}/WHEEL +0 -0
- {konokenj_cdk_api_mcp_server-0.40.0.dist-info → konokenj_cdk_api_mcp_server-0.42.0.dist-info}/entry_points.txt +0 -0
- {konokenj_cdk_api_mcp_server-0.40.0.dist-info → konokenj_cdk_api_mcp_server-0.42.0.dist-info}/licenses/LICENSE.txt +0 -0
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-dynamodb/integ.table-v2-global.ts
CHANGED
|
@@ -19,7 +19,9 @@ class TestStack extends Stack {
|
|
|
19
19
|
writeCapacity: Capacity.autoscaled({ maxCapacity: 20, targetUtilizationPercent: 60, seedCapacity: 10 }),
|
|
20
20
|
}),
|
|
21
21
|
encryption: TableEncryptionV2.awsManagedKey(),
|
|
22
|
-
|
|
22
|
+
contributorInsightsSpecification: {
|
|
23
|
+
enabled: true,
|
|
24
|
+
},
|
|
23
25
|
pointInTimeRecovery: true,
|
|
24
26
|
tableClass: TableClass.STANDARD_INFREQUENT_ACCESS,
|
|
25
27
|
timeToLiveAttribute: 'attr',
|
|
@@ -49,7 +51,9 @@ class TestStack extends Stack {
|
|
|
49
51
|
readCapacity: Capacity.autoscaled({ minCapacity: 5, maxCapacity: 25 }),
|
|
50
52
|
globalSecondaryIndexOptions: {
|
|
51
53
|
gsi2: {
|
|
52
|
-
|
|
54
|
+
contributorInsightsSpecification: {
|
|
55
|
+
enabled: false,
|
|
56
|
+
},
|
|
53
57
|
},
|
|
54
58
|
},
|
|
55
59
|
tags: [{ key: 'USE2ReplicaTagKey', value: 'USE2ReplicaTagValue' }],
|
|
@@ -57,7 +61,9 @@ class TestStack extends Stack {
|
|
|
57
61
|
{
|
|
58
62
|
region: 'us-west-2',
|
|
59
63
|
tableClass: TableClass.STANDARD,
|
|
60
|
-
|
|
64
|
+
contributorInsightsSpecification: {
|
|
65
|
+
enabled: false,
|
|
66
|
+
},
|
|
61
67
|
globalSecondaryIndexOptions: {
|
|
62
68
|
gsi1: {
|
|
63
69
|
readCapacity: Capacity.fixed(15),
|
|
@@ -1970,6 +1970,9 @@ const volumeFromSnapshot = new ecs.ServiceManagedVolume(this, 'EBSVolume', {
|
|
|
1970
1970
|
snapShotId: 'snap-066877671789bd71b',
|
|
1971
1971
|
volumeType: ec2.EbsDeviceVolumeType.GP3,
|
|
1972
1972
|
fileSystemType: ecs.FileSystemType.XFS,
|
|
1973
|
+
// Specifies the Amazon EBS Provisioned Rate for Volume Initialization.
|
|
1974
|
+
// Valid range is between 100 and 300 MiB/s.
|
|
1975
|
+
volumeInitializationRate: Size.mebibytes(200),
|
|
1973
1976
|
},
|
|
1974
1977
|
});
|
|
1975
1978
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import * as cdk from 'aws-cdk-lib';
|
|
3
|
+
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
4
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
5
|
+
import { Construct } from 'constructs';
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* This integration test demonstrates how to use EBS volume initialization rate
|
|
9
|
+
* with Service Managed Volumes.
|
|
10
|
+
*
|
|
11
|
+
* To run this test with a real EBS snapshot:
|
|
12
|
+
* 1. Create an EBS volume:
|
|
13
|
+
* aws ec2 create-volume --size 1 --volume-type gp3 --availability-zone us-east-1a
|
|
14
|
+
* 2. Create a snapshot from the volume:
|
|
15
|
+
* aws ec2 create-snapshot --volume-id vol-xxxxxxxxx --description "Test snapshot"
|
|
16
|
+
* 3. Wait for snapshot completion:
|
|
17
|
+
* aws ec2 wait snapshot-completed --snapshot-ids snap-xxxxxxxxx
|
|
18
|
+
* 4. Set the environment variable SNAPSHOT_ID to the snapshot ID:
|
|
19
|
+
* export SNAPSHOT_ID=snap-xxxxxxxxx
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const snapShotId = process.env.SNAPSHOT_ID ?? 'snap-123456789abcdef0';
|
|
23
|
+
|
|
24
|
+
class TestStack extends cdk.Stack {
|
|
25
|
+
constructor(scope: Construct, id: string) {
|
|
26
|
+
super(scope, id);
|
|
27
|
+
|
|
28
|
+
const vpc = new ec2.Vpc(this, 'Vpc', {
|
|
29
|
+
maxAzs: 1,
|
|
30
|
+
restrictDefaultSecurityGroup: false,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const cluster = new ecs.Cluster(this, 'FargateCluster', {
|
|
34
|
+
vpc,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef');
|
|
38
|
+
|
|
39
|
+
const container = taskDefinition.addContainer('web', {
|
|
40
|
+
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
41
|
+
portMappings: [{
|
|
42
|
+
containerPort: 80,
|
|
43
|
+
protocol: ecs.Protocol.TCP,
|
|
44
|
+
}],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const volume = new ecs.ServiceManagedVolume(this, 'EBSVolume', {
|
|
48
|
+
name: 'ebs1',
|
|
49
|
+
managedEBSVolume: {
|
|
50
|
+
volumeType: ec2.EbsDeviceVolumeType.GP3,
|
|
51
|
+
size: cdk.Size.gibibytes(1),
|
|
52
|
+
fileSystemType: ecs.FileSystemType.EXT4,
|
|
53
|
+
volumeInitializationRate: cdk.Size.mebibytes(200),
|
|
54
|
+
snapShotId: snapShotId,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
volume.mountIn(container, {
|
|
59
|
+
containerPath: '/var/lib',
|
|
60
|
+
readOnly: false,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
taskDefinition.addVolume(volume);
|
|
64
|
+
|
|
65
|
+
const service = new ecs.FargateService(this, 'FargateService', {
|
|
66
|
+
cluster,
|
|
67
|
+
taskDefinition,
|
|
68
|
+
desiredCount: 1,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
service.addVolume(volume);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const app = new cdk.App();
|
|
76
|
+
const stack = new TestStack(app, 'integ-aws-ecs-ebs-volume-initialization-rate');
|
|
77
|
+
|
|
78
|
+
new integ.IntegTest(app, 'EBSVolumeInitializationRate', {
|
|
79
|
+
testCases: [stack],
|
|
80
|
+
});
|
|
@@ -70,6 +70,8 @@ Fargate services will use the `LATEST` platform version by default, but you can
|
|
|
70
70
|
|
|
71
71
|
Fargate services use the default VPC Security Group unless one or more are provided using the `securityGroups` property in the constructor.
|
|
72
72
|
|
|
73
|
+
**Security Considerations**: When using custom security groups on your load balancer, the `openListener` property controls whether the load balancer listener allows traffic from anywhere on the internet (0.0.0.0/0). By default, `openListener` is `true`, but it will automatically default to `false` when custom security groups are detected, preventing unintended internet exposure. You can always explicitly set `openListener: true` to override this behavior if needed.
|
|
74
|
+
|
|
73
75
|
By setting `redirectHTTP` to true, CDK will automatically create a listener on port 80 that redirects HTTP traffic to the HTTPS port.
|
|
74
76
|
|
|
75
77
|
If you specify the option `recordType` you can decide if you want the construct to use CNAME or Route53-Aliases as record sets.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test for the conditional openListener behavior in ApplicationLoadBalancedFargateService.
|
|
3
|
+
*
|
|
4
|
+
* This test validates the security feature that automatically sets openListener to false when custom
|
|
5
|
+
* security groups are detected on the load balancer, preventing unintended internet exposure.
|
|
6
|
+
*
|
|
7
|
+
* Test scenarios:
|
|
8
|
+
* 1. DefaultService: No custom security groups provided
|
|
9
|
+
* - Expected: openListener defaults to true, creates 0.0.0.0/0 ingress rules
|
|
10
|
+
* - Validates: Default behavior when CDK manages all security groups
|
|
11
|
+
*
|
|
12
|
+
* 2. ExplicitOpenService: Explicit openListener: true
|
|
13
|
+
* - Expected: Creates 0.0.0.0/0 ingress rules regardless of other settings
|
|
14
|
+
* - Validates: Explicit override functionality works correctly
|
|
15
|
+
*
|
|
16
|
+
* 3. ExplicitClosedService: Explicit openListener: false
|
|
17
|
+
* - Expected: Does NOT create 0.0.0.0/0 ingress rules
|
|
18
|
+
* - Validates: Explicit closed listener prevents internet access
|
|
19
|
+
*
|
|
20
|
+
* 4. ConditionalWithCustomSG: Custom security groups + no explicit openListener
|
|
21
|
+
* - Expected: Conditional behavior kicks in, openListener defaults to false
|
|
22
|
+
* - Validates: Core feature - prevents 0.0.0.0/0 rules when custom SGs detected
|
|
23
|
+
*
|
|
24
|
+
* The test uses AWS SDK calls to verify actual security group configurations in deployed resources,
|
|
25
|
+
* ensuring the feature works correctly in real AWS environments.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { Vpc, SecurityGroup, Port } from 'aws-cdk-lib/aws-ec2';
|
|
29
|
+
import { Cluster, ContainerImage } from 'aws-cdk-lib/aws-ecs';
|
|
30
|
+
import { ApplicationLoadBalancer } from 'aws-cdk-lib/aws-elasticloadbalancingv2';
|
|
31
|
+
import { App, Stack, Duration } from 'aws-cdk-lib';
|
|
32
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
33
|
+
import { ApplicationLoadBalancedFargateService } from 'aws-cdk-lib/aws-ecs-patterns';
|
|
34
|
+
|
|
35
|
+
const app = new App({
|
|
36
|
+
postCliContext: {
|
|
37
|
+
// Enable the feature flag for this test
|
|
38
|
+
'@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener': true,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const stack = new Stack(app, 'aws-ecs-integ-alb-fg-smart-defaults');
|
|
43
|
+
const vpc = new Vpc(stack, 'Vpc', { maxAzs: 3, natGateways: 1, restrictDefaultSecurityGroup: false });
|
|
44
|
+
const cluster = new Cluster(stack, 'Cluster', { vpc });
|
|
45
|
+
|
|
46
|
+
// Test case 1: Service with conditional default (no openListener specified)
|
|
47
|
+
// CDK creates load balancer, should default to openListener: true (no custom security groups)
|
|
48
|
+
new ApplicationLoadBalancedFargateService(stack, 'SmartDefaultService', {
|
|
49
|
+
cluster,
|
|
50
|
+
memoryLimitMiB: 512,
|
|
51
|
+
taskImageOptions: {
|
|
52
|
+
image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
53
|
+
},
|
|
54
|
+
// No openListener specified - should default to true since no custom security groups
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Test case 2: Service with explicit openListener: true
|
|
58
|
+
new ApplicationLoadBalancedFargateService(stack, 'ExplicitOpenService', {
|
|
59
|
+
cluster,
|
|
60
|
+
memoryLimitMiB: 512,
|
|
61
|
+
taskImageOptions: {
|
|
62
|
+
image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
63
|
+
},
|
|
64
|
+
openListener: true, // Should create 0.0.0.0/0 rules
|
|
65
|
+
listenerPort: 8080,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Test case 3: Service with explicit openListener: false
|
|
69
|
+
new ApplicationLoadBalancedFargateService(stack, 'ExplicitClosedService', {
|
|
70
|
+
cluster,
|
|
71
|
+
memoryLimitMiB: 512,
|
|
72
|
+
taskImageOptions: {
|
|
73
|
+
image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
74
|
+
},
|
|
75
|
+
openListener: false, // Should NOT create 0.0.0.0/0 rules
|
|
76
|
+
listenerPort: 9090,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Test case 4: Service with custom security groups (conditional default should apply)
|
|
80
|
+
const customSecurityGroup = new SecurityGroup(stack, 'CustomSecurityGroup', {
|
|
81
|
+
vpc,
|
|
82
|
+
description: 'Custom security group for load balancer',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Add a custom rule to the security group
|
|
86
|
+
customSecurityGroup.addIngressRule(
|
|
87
|
+
customSecurityGroup,
|
|
88
|
+
Port.tcp(80),
|
|
89
|
+
'Allow HTTP from custom security group',
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const customLoadBalancer = new ApplicationLoadBalancer(stack, 'CustomLoadBalancer', {
|
|
93
|
+
vpc,
|
|
94
|
+
internetFacing: true,
|
|
95
|
+
securityGroup: customSecurityGroup,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// This should use conditional default (openListener: false) because custom security groups are detected
|
|
99
|
+
new ApplicationLoadBalancedFargateService(stack, 'SmartDefaultWithCustomSG', {
|
|
100
|
+
cluster,
|
|
101
|
+
memoryLimitMiB: 512,
|
|
102
|
+
taskImageOptions: {
|
|
103
|
+
image: ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
|
|
104
|
+
},
|
|
105
|
+
loadBalancer: customLoadBalancer,
|
|
106
|
+
// No openListener specified - should default to false due to custom security groups
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const integTest = new integ.IntegTest(app, 'albFargateServiceSmartDefaultsTest', {
|
|
110
|
+
testCases: [stack],
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Validate the core conditional behavior by checking the custom security group
|
|
114
|
+
// This confirms that when custom security groups are provided, the conditional default prevents
|
|
115
|
+
// creating overly permissive 0.0.0.0/0 ingress rules
|
|
116
|
+
// Assert that the custom security group only contains self-referencing rules (no 0.0.0.0/0)
|
|
117
|
+
// This validates the feature prevents unintended internet exposure
|
|
118
|
+
integTest.assertions.awsApiCall('EC2', 'describeSecurityGroups', {
|
|
119
|
+
GroupIds: [customSecurityGroup.securityGroupId],
|
|
120
|
+
}).expect(integ.ExpectedResult.objectLike({
|
|
121
|
+
SecurityGroups: [
|
|
122
|
+
{
|
|
123
|
+
IpPermissions: integ.Match.arrayWith([
|
|
124
|
+
integ.Match.objectLike({
|
|
125
|
+
FromPort: 80,
|
|
126
|
+
ToPort: 80,
|
|
127
|
+
// Verify only security group references exist, no public internet access (0.0.0.0/0)
|
|
128
|
+
UserIdGroupPairs: integ.Match.arrayWith([
|
|
129
|
+
integ.Match.objectLike({
|
|
130
|
+
GroupId: customSecurityGroup.securityGroupId,
|
|
131
|
+
}),
|
|
132
|
+
]),
|
|
133
|
+
// Ensure no IpRanges with 0.0.0.0/0 are present
|
|
134
|
+
IpRanges: [],
|
|
135
|
+
}),
|
|
136
|
+
]),
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
})).waitForAssertions({
|
|
140
|
+
totalTimeout: Duration.minutes(5),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
app.synth();
|
|
@@ -332,6 +332,28 @@ new events.EventBus(this, 'Bus', {
|
|
|
332
332
|
});
|
|
333
333
|
```
|
|
334
334
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
335
|
+
To use a customer managed key for an archive, use the `kmsKey` attribute.
|
|
336
|
+
|
|
337
|
+
Note: When you attach a customer managed key to either an EventBus or an Archive, a policy that allows EventBridge to interact with your resource will be added.
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
import * as kms from 'aws-cdk-lib/aws-kms';
|
|
341
|
+
import { Archive, EventBus } from 'aws-cdk-lib/aws-events';
|
|
342
|
+
|
|
343
|
+
const stack = new Stack();
|
|
344
|
+
|
|
345
|
+
declare const kmsKey: kms.IKey;
|
|
346
|
+
|
|
347
|
+
const eventBus = new EventBus(stack, 'Bus');
|
|
348
|
+
|
|
349
|
+
const archive = new Archive(stack, 'Archive', {
|
|
350
|
+
kmsKey: kmsKey,
|
|
351
|
+
sourceEventBus: eventBus,
|
|
352
|
+
eventPattern: {
|
|
353
|
+
source: ['aws.ec2']
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
To enable archives or schema discovery on an event bus, customers has the choice of using either an AWS owned key or a customer managed key.
|
|
359
|
+
For more information, see [KMS key options for event bus encryption](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-encryption-at-rest-key-options.html).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as kms from 'aws-cdk-lib/aws-kms';
|
|
2
|
+
import { App, RemovalPolicy, Stack } from 'aws-cdk-lib';
|
|
3
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
4
|
+
import { Archive, EventBus } from 'aws-cdk-lib/aws-events';
|
|
5
|
+
|
|
6
|
+
const app = new App();
|
|
7
|
+
const stack = new Stack(app, 'archive-customer-managed-key');
|
|
8
|
+
|
|
9
|
+
const kmsKey = new kms.Key(stack, 'KmsKey', {
|
|
10
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
new Archive(stack, 'Archive', {
|
|
14
|
+
kmsKey: kmsKey,
|
|
15
|
+
sourceEventBus: EventBus.fromEventBusName(stack, 'DefaultEventBus', 'default'),
|
|
16
|
+
eventPattern: {
|
|
17
|
+
source: ['test'],
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
new IntegTest(app, 'archive-customer-managed-key-test', {
|
|
22
|
+
testCases: [stack],
|
|
23
|
+
});
|
|
@@ -1177,7 +1177,7 @@ const version = fn.currentVersion;
|
|
|
1177
1177
|
You can use Application AutoScaling to automatically configure the provisioned concurrency for your functions. AutoScaling can be set to track utilization or be based on a schedule. To configure AutoScaling on a function alias:
|
|
1178
1178
|
|
|
1179
1179
|
```ts
|
|
1180
|
-
import * as
|
|
1180
|
+
import * as appscaling from 'aws-cdk-lib/aws-applicationautoscaling';
|
|
1181
1181
|
|
|
1182
1182
|
declare const fn: lambda.Function;
|
|
1183
1183
|
const alias = fn.addAlias('prod');
|
|
@@ -1192,7 +1192,7 @@ as.scaleOnUtilization({
|
|
|
1192
1192
|
|
|
1193
1193
|
// Configure Scheduled Scaling
|
|
1194
1194
|
as.scaleOnSchedule('ScaleUpInTheMorning', {
|
|
1195
|
-
schedule:
|
|
1195
|
+
schedule: appscaling.Schedule.cron({ hour: '8', minute: '0'}),
|
|
1196
1196
|
minCapacity: 20,
|
|
1197
1197
|
});
|
|
1198
1198
|
```
|
|
@@ -325,6 +325,24 @@ new s3deploy.BucketDeployment(this, 'DeployWithInvalidation', {
|
|
|
325
325
|
});
|
|
326
326
|
```
|
|
327
327
|
|
|
328
|
+
By default, the deployment will wait for invalidation to succeed to complete. This will poll Cloudfront for a maximum of 13 minutes to check for a successful invalidation. The drawback to this is that the deployment will fail if invalidation fails or if it takes longer than 13 minutes. As a workaround, there is the option `waitForDistributionInvalidation`, which can be set to false to skip waiting for the invalidation, but this can be risky as invalidation errors will not be reported.
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
|
|
332
|
+
|
|
333
|
+
declare const bucket: s3.IBucket;
|
|
334
|
+
declare const distribution: cloudfront.IDistribution;
|
|
335
|
+
|
|
336
|
+
new s3deploy.BucketDeployment(this, 'DeployWithInvalidation', {
|
|
337
|
+
sources: [s3deploy.Source.asset('./website-dist')],
|
|
338
|
+
destinationBucket: bucket,
|
|
339
|
+
distribution,
|
|
340
|
+
distributionPaths: ['/images/*.png'],
|
|
341
|
+
// Invalidate cache but don't wait or verify that invalidation has completed successfully.
|
|
342
|
+
waitForDistributionInvalidation: false
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
328
346
|
## Signed Content Payloads
|
|
329
347
|
|
|
330
348
|
By default, deployment uses streaming uploads which set the `x-amz-content-sha256`
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import { Construct } from 'constructs';
|
|
3
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
4
|
+
import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
|
|
5
|
+
import * as ssm from 'aws-cdk-lib/aws-ssm';
|
|
6
|
+
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
7
|
+
|
|
8
|
+
class SsmStack extends cdk.NestedStack {
|
|
9
|
+
public readonly ssmParam: ssm.StringListParameter;
|
|
10
|
+
|
|
11
|
+
constructor(scope: Construct, id: string, props?: cdk.NestedStackProps) {
|
|
12
|
+
super(scope, id, props);
|
|
13
|
+
|
|
14
|
+
const testSubnets = ['subnet-12345', 'subnet-67890'];
|
|
15
|
+
|
|
16
|
+
this.ssmParam = new ssm.StringListParameter(this, 'TestParam', {
|
|
17
|
+
parameterName: '/repro/subnets',
|
|
18
|
+
stringListValue: testSubnets,
|
|
19
|
+
description: 'Test parameter for reproduction',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class S3Stack extends cdk.NestedStack {
|
|
25
|
+
public readonly bucket: s3.Bucket;
|
|
26
|
+
|
|
27
|
+
constructor(scope: Construct, id: string, props?: cdk.NestedStackProps) {
|
|
28
|
+
super(scope, id, props);
|
|
29
|
+
|
|
30
|
+
const readParam = ssm.StringListParameter.fromStringListParameterName(
|
|
31
|
+
this,
|
|
32
|
+
'ReadParam',
|
|
33
|
+
'/repro/subnets',
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
this.bucket = new s3.Bucket(this, 'ReproBucket', {
|
|
37
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
38
|
+
autoDeleteObjects: true,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
new s3deploy.BucketDeployment(this, 'ReproDeployment', {
|
|
42
|
+
sources: [
|
|
43
|
+
s3deploy.Source.jsonData('config.json', {
|
|
44
|
+
subnets: readParam.stringListValue,
|
|
45
|
+
expectedValues: ['subnet-12345', 'subnet-67890'],
|
|
46
|
+
version: '2.207.0',
|
|
47
|
+
issue: 'StringListParameter tokens not resolved in Source.jsonData',
|
|
48
|
+
timestamp: new Date().toISOString(),
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
destinationBucket: this.bucket,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class MainStack extends cdk.Stack {
|
|
57
|
+
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
|
58
|
+
super(scope, id, props);
|
|
59
|
+
|
|
60
|
+
const ssmStack = new SsmStack(this, 'SsmStack');
|
|
61
|
+
const s3Stack = new S3Stack(this, 'S3Stack');
|
|
62
|
+
s3Stack.addDependency(ssmStack);
|
|
63
|
+
|
|
64
|
+
new cdk.CfnOutput(this, 'BucketName', {
|
|
65
|
+
value: s3Stack.bucket.bucketName,
|
|
66
|
+
description: 'Check config.json in this bucket',
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
new cdk.CfnOutput(this, 'ParameterName', {
|
|
70
|
+
value: ssmStack.ssmParam.parameterName,
|
|
71
|
+
description: 'SSM parameter name',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
new cdk.CfnOutput(this, 'ExpectedValues', {
|
|
75
|
+
value: JSON.stringify(['subnet-12345', 'subnet-67890']),
|
|
76
|
+
description: 'Expected subnet values in config.json',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
new cdk.CfnOutput(this, 'VerificationCommand', {
|
|
80
|
+
value: `aws s3 cp s3://${s3Stack.bucket.bucketName}/config.json - | jq .`,
|
|
81
|
+
description: 'Command to check the deployed JSON',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const app = new cdk.App();
|
|
87
|
+
const stack = new MainStack(app, 'integ-bucket-deployment-cross-stack-ssm');
|
|
88
|
+
|
|
89
|
+
new integ.IntegTest(app, 'integ-bucket-deployment-cross-stack-ssm-source', {
|
|
90
|
+
testCases: [stack],
|
|
91
|
+
});
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-signer/integ.signing-profile.ts
CHANGED
|
@@ -16,6 +16,11 @@ new signer.SigningProfile(stack, 'SigningProfileOCI', {
|
|
|
16
16
|
signatureValidity: cdk.Duration.days(60),
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
new signer.SigningProfile(stack, 'SigningProfileWithName', {
|
|
20
|
+
platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA,
|
|
21
|
+
signingProfileName: 'test-signing-profile-name',
|
|
22
|
+
});
|
|
23
|
+
|
|
19
24
|
new IntegTest(app, 'cdk-integ-signer-signing-profile', {
|
|
20
25
|
testCases: [stack],
|
|
21
26
|
});
|
|
@@ -121,6 +121,7 @@ declare const fn: lambda.Function;
|
|
|
121
121
|
|
|
122
122
|
// Lambda should receive only message matching the following conditions on message body:
|
|
123
123
|
// color: 'red' or 'orange'
|
|
124
|
+
// store: property must not be present
|
|
124
125
|
myTopic.addSubscription(new subscriptions.LambdaSubscription(fn, {
|
|
125
126
|
filterPolicyWithMessageBody: {
|
|
126
127
|
background: sns.FilterOrPolicy.policy({
|
|
@@ -128,6 +129,7 @@ myTopic.addSubscription(new subscriptions.LambdaSubscription(fn, {
|
|
|
128
129
|
allowlist: ['red', 'orange'],
|
|
129
130
|
})),
|
|
130
131
|
}),
|
|
132
|
+
store: sns.FilterOrPolicy.filter(sns.SubscriptionFilter.notExistsFilter()),
|
|
131
133
|
},
|
|
132
134
|
}));
|
|
133
135
|
```
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as sns from 'aws-cdk-lib/aws-sns';
|
|
2
|
+
import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
3
|
+
import * as cdk from 'aws-cdk-lib';
|
|
4
|
+
import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests-alpha';
|
|
5
|
+
import * as subs from 'aws-cdk-lib/aws-sns-subscriptions';
|
|
6
|
+
|
|
7
|
+
const app = new cdk.App();
|
|
8
|
+
|
|
9
|
+
const stack = new cdk.Stack(app, 'sns-sqs-subscription-filter');
|
|
10
|
+
|
|
11
|
+
const topic = new sns.Topic(stack, 'MyTopic');
|
|
12
|
+
|
|
13
|
+
const queue1 = new sqs.Queue(stack, 'MyQueue1');
|
|
14
|
+
const queue2 = new sqs.Queue(stack, 'MyQueue2');
|
|
15
|
+
|
|
16
|
+
topic.addSubscription(new subs.SqsSubscription(queue1, {
|
|
17
|
+
filterPolicyWithMessageBody: {
|
|
18
|
+
background: sns.Policy.policy({
|
|
19
|
+
color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({
|
|
20
|
+
allowlist: ['red', 'green'],
|
|
21
|
+
})),
|
|
22
|
+
}),
|
|
23
|
+
price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({
|
|
24
|
+
allowlist: [100, 200],
|
|
25
|
+
})),
|
|
26
|
+
store: sns.Filter.filter(sns.SubscriptionFilter.existsFilter()),
|
|
27
|
+
},
|
|
28
|
+
rawMessageDelivery: true,
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
topic.addSubscription(new subs.SqsSubscription(queue2, {
|
|
32
|
+
filterPolicyWithMessageBody: {
|
|
33
|
+
background: sns.Policy.policy({
|
|
34
|
+
color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({
|
|
35
|
+
denylist: ['red', 'green'],
|
|
36
|
+
})),
|
|
37
|
+
}),
|
|
38
|
+
price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({
|
|
39
|
+
betweenStrict: { start: 100, stop: 200 },
|
|
40
|
+
})),
|
|
41
|
+
store: sns.Filter.filter(sns.SubscriptionFilter.notExistsFilter()),
|
|
42
|
+
},
|
|
43
|
+
rawMessageDelivery: true,
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
const integTest = new IntegTest(app, 'SNS Subscription filters', {
|
|
47
|
+
testCases: [stack],
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const message1 = JSON.stringify({ background: { color: 'green' }, price: 200, store: 'fans' }); // matches queue1 subscription filter
|
|
51
|
+
const message2 = JSON.stringify({ background: { color: 'blue' }, price: 150 }); // matches queue2 subscription filter
|
|
52
|
+
|
|
53
|
+
// publish messages to SNS topic
|
|
54
|
+
integTest.assertions.awsApiCall('SNS', 'publish', {
|
|
55
|
+
Message: message1,
|
|
56
|
+
TopicArn: topic.topicArn,
|
|
57
|
+
});
|
|
58
|
+
integTest.assertions.awsApiCall('SNS', 'publish', {
|
|
59
|
+
Message: message2,
|
|
60
|
+
TopicArn: topic.topicArn,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// check messages arrived at expected destination queue
|
|
64
|
+
integTest.assertions.awsApiCall('SQS', 'receiveMessage', {
|
|
65
|
+
QueueUrl: queue1.queueUrl,
|
|
66
|
+
WaitTimeSeconds: 20,
|
|
67
|
+
}).expect(ExpectedResult.objectLike({
|
|
68
|
+
Messages: [{ Body: message1 }],
|
|
69
|
+
}));
|
|
70
|
+
integTest.assertions.awsApiCall('SQS', 'receiveMessage', {
|
|
71
|
+
QueueUrl: queue2.queueUrl,
|
|
72
|
+
WaitTimeSeconds: 20,
|
|
73
|
+
}).expect(ExpectedResult.objectLike({
|
|
74
|
+
Messages: [{ Body: message2 }],
|
|
75
|
+
}));
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-sns-subscriptions/integ.sns-sqs.ts
CHANGED
|
@@ -3,50 +3,31 @@ import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
|
3
3
|
import * as cdk from 'aws-cdk-lib';
|
|
4
4
|
import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests-alpha';
|
|
5
5
|
import * as subs from 'aws-cdk-lib/aws-sns-subscriptions';
|
|
6
|
-
|
|
7
|
-
topic: sns.Topic;
|
|
8
|
-
queue: sqs.Queue;
|
|
9
|
-
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
|
|
10
|
-
super(scope, id, props);
|
|
11
|
-
this.topic = new sns.Topic(this, 'MyTopic');
|
|
12
|
-
const queueStack = new cdk.Stack(app, 'QueueStack');
|
|
13
|
-
this.queue = new sqs.Queue(queueStack, 'MyQueue');
|
|
14
|
-
this.topic.addSubscription(new subs.SqsSubscription(this.queue, {
|
|
15
|
-
filterPolicyWithMessageBody: {
|
|
16
|
-
background: sns.Policy.policy({
|
|
17
|
-
color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({
|
|
18
|
-
allowlist: ['red', 'green'],
|
|
19
|
-
denylist: ['white', 'orange'],
|
|
20
|
-
})),
|
|
21
|
-
}),
|
|
22
|
-
price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({
|
|
23
|
-
allowlist: [100, 200],
|
|
24
|
-
between: { start: 300, stop: 350 },
|
|
25
|
-
greaterThan: 500,
|
|
26
|
-
lessThan: 1000,
|
|
27
|
-
betweenStrict: { start: 2000, stop: 3000 },
|
|
28
|
-
})),
|
|
29
|
-
},
|
|
30
|
-
}));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
// Beginning of the test suite
|
|
6
|
+
|
|
34
7
|
const app = new cdk.App();
|
|
35
|
-
|
|
8
|
+
|
|
9
|
+
const stack = new cdk.Stack(app, 'SnsToSqsStack');
|
|
10
|
+
|
|
11
|
+
const topic = new sns.Topic(stack, 'MyTopic');
|
|
12
|
+
|
|
13
|
+
const queue = new sqs.Queue(stack, 'MyQueue');
|
|
14
|
+
|
|
15
|
+
topic.addSubscription(new subs.SqsSubscription(queue, { rawMessageDelivery: true }));
|
|
16
|
+
|
|
36
17
|
const integTest = new IntegTest(app, 'SNS Subscriptions', {
|
|
37
|
-
testCases: [
|
|
38
|
-
stack,
|
|
39
|
-
],
|
|
18
|
+
testCases: [stack],
|
|
40
19
|
});
|
|
20
|
+
|
|
21
|
+
const message = JSON.stringify({ color: 'green', price: 200 });
|
|
22
|
+
|
|
41
23
|
integTest.assertions.awsApiCall('SNS', 'publish', {
|
|
42
|
-
Message:
|
|
43
|
-
TopicArn:
|
|
24
|
+
Message: message,
|
|
25
|
+
TopicArn: topic.topicArn,
|
|
44
26
|
});
|
|
45
|
-
|
|
46
|
-
|
|
27
|
+
|
|
28
|
+
integTest.assertions.awsApiCall('SQS', 'receiveMessage', {
|
|
29
|
+
QueueUrl: queue.queueUrl,
|
|
47
30
|
WaitTimeSeconds: 20,
|
|
48
|
-
})
|
|
49
|
-
message
|
|
50
|
-
Messages: [{ Body: '{color: "green", price: 200}' }],
|
|
31
|
+
}).expect(ExpectedResult.objectLike({
|
|
32
|
+
Messages: [{ Body: message }],
|
|
51
33
|
}));
|
|
52
|
-
app.synth();
|