konokenj.cdk-api-mcp-server 0.28.0__py3-none-any.whl → 0.30.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-amplify-alpha/README.md +71 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/@aws-cdk/integ-tests-alpha/README.md +1 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api-dualstack.ts +4 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.api.ts +4 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2/integ.stage.ts +20 -7
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-authorizers/integ.iam.ts +38 -34
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-apigatewayv2-integrations/integ.sqs.ts +71 -58
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-backup/README.md +2 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-backup/integ.backup.ts +12 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudfront/README.md +18 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/README.md +32 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/integ.alarm-and-dashboard.ts +1 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-cloudwatch/integ.math-alarm-and-dashboard.ts +4 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-config.ts +4 -15
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-codedeploy/integ.deployment-group.ts +218 -40
- 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-ec2/README.md +13 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-ec2/integ.client-vpn-endpoint-client-route-enforcement.ts +68 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/README.md +83 -83
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.eks-al2023-nodegroup.ts +1 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.fargate-cluster.ts +1 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-eks/integ.helm-chart-logging.ts +55 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-kms/README.md +4 -3
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-kms/integ.alias-from-alias-name.ts +26 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/README.md +15 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.log-retention.ts +8 -2
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-event-sources/README.md +68 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-event-sources/integ.kafka-schema-registry.ts +186 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/README.md +23 -13
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.cluster-snapshot.ts +3 -71
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.instance-engine-lifecycle-support.ts +53 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3/README.md +16 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-s3-notifications/integ.bucket-notifications.ts +42 -80
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.call-aws-service-cross-region-lambda.ts +97 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-stepfunctions-tasks/integ.start-job-run.ts +51 -106
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +21 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/cx-api/README.md +14 -0
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/pipelines/README.md +7 -1
- cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/pipelines/integ.newpipeline-single-publisher.ts +53 -0
- {konokenj_cdk_api_mcp_server-0.28.0.dist-info → konokenj_cdk_api_mcp_server-0.30.0.dist-info}/METADATA +2 -2
- {konokenj_cdk_api_mcp_server-0.28.0.dist-info → konokenj_cdk_api_mcp_server-0.30.0.dist-info}/RECORD +45 -38
- {konokenj_cdk_api_mcp_server-0.28.0.dist-info → konokenj_cdk_api_mcp_server-0.30.0.dist-info}/WHEEL +0 -0
- {konokenj_cdk_api_mcp_server-0.28.0.dist-info → konokenj_cdk_api_mcp_server-0.30.0.dist-info}/entry_points.txt +0 -0
- {konokenj_cdk_api_mcp_server-0.28.0.dist-info → konokenj_cdk_api_mcp_server-0.30.0.dist-info}/licenses/LICENSE.txt +0 -0
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda/integ.log-retention.ts
CHANGED
|
@@ -4,7 +4,11 @@ import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
|
4
4
|
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
5
5
|
import { STANDARD_NODEJS_RUNTIME } from '../../config';
|
|
6
6
|
|
|
7
|
-
const app = new cdk.App(
|
|
7
|
+
const app = new cdk.App({
|
|
8
|
+
postCliContext: {
|
|
9
|
+
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
|
|
10
|
+
},
|
|
11
|
+
});
|
|
8
12
|
|
|
9
13
|
const stack = new cdk.Stack(app, 'aws-cdk-lambda-log-retention');
|
|
10
14
|
|
|
@@ -13,6 +17,7 @@ new lambda.Function(stack, 'OneWeek', {
|
|
|
13
17
|
handler: 'index.handler',
|
|
14
18
|
runtime: STANDARD_NODEJS_RUNTIME,
|
|
15
19
|
logRetention: logs.RetentionDays.ONE_WEEK,
|
|
20
|
+
logRemovalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
16
21
|
});
|
|
17
22
|
|
|
18
23
|
new lambda.Function(stack, 'OneMonth', {
|
|
@@ -20,6 +25,7 @@ new lambda.Function(stack, 'OneMonth', {
|
|
|
20
25
|
handler: 'index.handler',
|
|
21
26
|
runtime: STANDARD_NODEJS_RUNTIME,
|
|
22
27
|
logRetention: logs.RetentionDays.ONE_MONTH,
|
|
28
|
+
logRemovalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
23
29
|
});
|
|
24
30
|
|
|
25
31
|
new lambda.Function(stack, 'OneYear', {
|
|
@@ -27,10 +33,10 @@ new lambda.Function(stack, 'OneYear', {
|
|
|
27
33
|
handler: 'index.handler',
|
|
28
34
|
runtime: STANDARD_NODEJS_RUNTIME,
|
|
29
35
|
logRetention: logs.RetentionDays.ONE_YEAR,
|
|
36
|
+
logRemovalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
30
37
|
});
|
|
31
38
|
|
|
32
39
|
new IntegTest(app, 'LambdaLogRetentionInteg', {
|
|
33
40
|
testCases: [stack],
|
|
34
41
|
diffAssets: true,
|
|
35
42
|
});
|
|
36
|
-
app.synth();
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-lambda-event-sources/README.md
CHANGED
|
@@ -445,6 +445,74 @@ myFunction.addEventSource(new ManagedKafkaEventSource({
|
|
|
445
445
|
}));
|
|
446
446
|
```
|
|
447
447
|
|
|
448
|
+
Set a confluent or self-managed schema registry to de-serialize events from the event source. Note, this will similarly work for `SelfManagedKafkaEventSource` but the example only shows setup for `ManagedKafkaEventSource`.
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
import { ManagedKafkaEventSource, ConfluentSchemaRegistry } from 'aws-cdk-lib/aws-lambda-event-sources';
|
|
452
|
+
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
|
|
453
|
+
|
|
454
|
+
// Your MSK cluster arn
|
|
455
|
+
declare const clusterArn: string;
|
|
456
|
+
|
|
457
|
+
// The Kafka topic you want to subscribe to
|
|
458
|
+
const topic = 'some-cool-topic';
|
|
459
|
+
|
|
460
|
+
const secret = new Secret(this, 'Secret', { secretName: 'AmazonMSK_KafkaSecret' });
|
|
461
|
+
|
|
462
|
+
declare const myFunction: lambda.Function;
|
|
463
|
+
myFunction.addEventSource(new ManagedKafkaEventSource({
|
|
464
|
+
clusterArn,
|
|
465
|
+
topic,
|
|
466
|
+
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
|
|
467
|
+
provisionedPollerConfig: {
|
|
468
|
+
minimumPollers: 1,
|
|
469
|
+
maximumPollers: 3,
|
|
470
|
+
},
|
|
471
|
+
schemaRegistryConfig: new ConfluentSchemaRegistry({
|
|
472
|
+
schemaRegistryUri: 'https://example.com',
|
|
473
|
+
eventRecordFormat: lambda.EventRecordFormat.JSON,
|
|
474
|
+
authenticationType: lambda.KafkaSchemaRegistryAccessConfigType.BASIC_AUTH,
|
|
475
|
+
secret: secret,
|
|
476
|
+
schemaValidationConfigs: [{ attribute: lambda.KafkaSchemaValidationAttribute.KEY }],
|
|
477
|
+
}),
|
|
478
|
+
}));
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Set Glue schema registry to de-serialize events from the event source. Note, this will similarly work for `SelfManagedKafkaEventSource` but the example only shows setup for `ManagedKafkaEventSource`.
|
|
482
|
+
|
|
483
|
+
```ts
|
|
484
|
+
import { CfnRegistry } from 'aws-cdk-lib/aws-glue';
|
|
485
|
+
import { ManagedKafkaEventSource, GlueSchemaRegistry } from 'aws-cdk-lib/aws-lambda-event-sources';
|
|
486
|
+
|
|
487
|
+
// Your MSK cluster arn
|
|
488
|
+
declare const clusterArn: string;
|
|
489
|
+
|
|
490
|
+
// The Kafka topic you want to subscribe to
|
|
491
|
+
const topic = 'some-cool-topic';
|
|
492
|
+
|
|
493
|
+
// Your Glue Schema Registry
|
|
494
|
+
const glueRegistry = new CfnRegistry(this, 'Registry', {
|
|
495
|
+
name: 'schema-registry',
|
|
496
|
+
description: 'Schema registry for event source',
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
declare const myFunction: lambda.Function;
|
|
500
|
+
myFunction.addEventSource(new ManagedKafkaEventSource({
|
|
501
|
+
clusterArn,
|
|
502
|
+
topic,
|
|
503
|
+
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
|
|
504
|
+
provisionedPollerConfig: {
|
|
505
|
+
minimumPollers: 1,
|
|
506
|
+
maximumPollers: 3,
|
|
507
|
+
},
|
|
508
|
+
schemaRegistryConfig: new GlueSchemaRegistry({
|
|
509
|
+
schemaRegistry: glueRegistry,
|
|
510
|
+
eventRecordFormat: lambda.EventRecordFormat.JSON,
|
|
511
|
+
schemaValidationConfigs: [{ attribute: lambda.KafkaSchemaValidationAttribute.KEY }],
|
|
512
|
+
}),
|
|
513
|
+
}));
|
|
514
|
+
```
|
|
515
|
+
|
|
448
516
|
## Roadmap
|
|
449
517
|
|
|
450
518
|
Eventually, this module will support all the event sources described under
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { TestFunction } from './test-function';
|
|
2
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
3
|
+
import {
|
|
4
|
+
SelfManagedKafkaEventSource,
|
|
5
|
+
AuthenticationMethod,
|
|
6
|
+
GlueSchemaRegistry,
|
|
7
|
+
ConfluentSchemaRegistry,
|
|
8
|
+
} from 'aws-cdk-lib/aws-lambda-event-sources';
|
|
9
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
10
|
+
import { App, StackProps, Stack, SecretValue } from 'aws-cdk-lib';
|
|
11
|
+
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
|
12
|
+
import { CfnRegistry } from 'aws-cdk-lib/aws-glue';
|
|
13
|
+
|
|
14
|
+
// Self-Managed Kafka Stack with Schema Registry
|
|
15
|
+
export class SmkGlueSchemaRegistryStack extends Stack {
|
|
16
|
+
constructor(scope: App, id: string, props?: StackProps) {
|
|
17
|
+
super(scope, id, props);
|
|
18
|
+
|
|
19
|
+
// Create a Lambda function
|
|
20
|
+
const testLambdaFunction = new TestFunction(this, 'GlueFunction');
|
|
21
|
+
|
|
22
|
+
// Create dummy certificates for authentication
|
|
23
|
+
const dummyCertString = `-----BEGIN CERTIFICATE-----
|
|
24
|
+
MIIE5DCCAsygAwIBAgIRAPJdwaFaNRrytHBto0j5BA0wDQYJKoZIhvcNAQELBQAw
|
|
25
|
+
cmUuiAii9R0=
|
|
26
|
+
-----END CERTIFICATE-----
|
|
27
|
+
-----BEGIN CERTIFICATE-----
|
|
28
|
+
MIIFgjCCA2qgAwIBAgIQdjNZd6uFf9hbNC5RdfmHrzANBgkqhkiG9w0BAQsFADBb
|
|
29
|
+
c8PH3PSoAaRwMMgOSA2ALJvbRz8mpg==
|
|
30
|
+
-----END CERTIFICATE-----"
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
const dummyPrivateKey = `-----BEGIN ENCRYPTED PRIVATE KEY-----
|
|
34
|
+
zp2mwJn2NYB7AZ7+imp0azDZb+8YG2aUCiyqb6PnnA==
|
|
35
|
+
-----END ENCRYPTED PRIVATE KEY-----`;
|
|
36
|
+
|
|
37
|
+
// Create secrets for Kafka authentication
|
|
38
|
+
const rootCASecret = new secretsmanager.Secret(this, 'GlueRootCASecret', {
|
|
39
|
+
secretObjectValue: {
|
|
40
|
+
certificate: SecretValue.unsafePlainText(dummyCertString),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const clientCertificatesSecret = new secretsmanager.Secret(this, 'GlueClientCertSecret', {
|
|
45
|
+
secretObjectValue: {
|
|
46
|
+
certificate: SecretValue.unsafePlainText(dummyCertString),
|
|
47
|
+
privateKey: SecretValue.unsafePlainText(dummyPrivateKey),
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Grant read permissions to the Lambda function
|
|
52
|
+
rootCASecret.grantRead(testLambdaFunction);
|
|
53
|
+
clientCertificatesSecret.grantRead(testLambdaFunction);
|
|
54
|
+
|
|
55
|
+
// Create a Glue Schema Registry
|
|
56
|
+
const glueRegistry = new CfnRegistry(this, 'SchemaRegistry', {
|
|
57
|
+
name: 'smk-glue-test-schema-registry',
|
|
58
|
+
description: 'Schema registry for SMK integration tests',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Define Kafka bootstrap servers
|
|
62
|
+
const bootstrapServers = [
|
|
63
|
+
'kafka-broker-1:9092',
|
|
64
|
+
'kafka-broker-2:9092',
|
|
65
|
+
'kafka-broker-3:9092',
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
// Common configuration for SMK event sources
|
|
69
|
+
const commonConfig = {
|
|
70
|
+
bootstrapServers,
|
|
71
|
+
secret: clientCertificatesSecret,
|
|
72
|
+
authenticationMethod: AuthenticationMethod.CLIENT_CERTIFICATE_TLS_AUTH,
|
|
73
|
+
rootCACertificate: rootCASecret,
|
|
74
|
+
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// SMK with Glue Schema Registry
|
|
78
|
+
testLambdaFunction.addEventSource(new SelfManagedKafkaEventSource({
|
|
79
|
+
...commonConfig,
|
|
80
|
+
topic: 'test-topic-smk-glue',
|
|
81
|
+
consumerGroupId: 'test-consumer-group-smk-glue',
|
|
82
|
+
provisionedPollerConfig: {
|
|
83
|
+
minimumPollers: 1,
|
|
84
|
+
maximumPollers: 3,
|
|
85
|
+
},
|
|
86
|
+
schemaRegistryConfig: new GlueSchemaRegistry({
|
|
87
|
+
schemaRegistry: glueRegistry,
|
|
88
|
+
eventRecordFormat: lambda.EventRecordFormat.JSON,
|
|
89
|
+
schemaValidationConfigs: [{ attribute: lambda.KafkaSchemaValidationAttribute.KEY }],
|
|
90
|
+
}),
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Self-Managed Kafka Stack with Schema Registry
|
|
96
|
+
export class SmkConfluentSchemaRegistryStack extends Stack {
|
|
97
|
+
constructor(scope: App, id: string, props?: StackProps) {
|
|
98
|
+
super(scope, id, props);
|
|
99
|
+
|
|
100
|
+
// Create a Lambda function
|
|
101
|
+
const testLambdaFunction = new TestFunction(this, 'ConfluentFunction');
|
|
102
|
+
|
|
103
|
+
// Create dummy certificates for authentication
|
|
104
|
+
const dummyCertString = `-----BEGIN CERTIFICATE-----
|
|
105
|
+
MIIE5DCCAsygAwIBAgIRAPJdwaFaNRrytHBto0j5BA0wDQYJKoZIhvcNAQELBQAw
|
|
106
|
+
cmUuiAii9R0=
|
|
107
|
+
-----END CERTIFICATE-----
|
|
108
|
+
-----BEGIN CERTIFICATE-----
|
|
109
|
+
MIIFgjCCA2qgAwIBAgIQdjNZd6uFf9hbNC5RdfmHrzANBgkqhkiG9w0BAQsFADBb
|
|
110
|
+
c8PH3PSoAaRwMMgOSA2ALJvbRz8mpg==
|
|
111
|
+
-----END CERTIFICATE-----"
|
|
112
|
+
`;
|
|
113
|
+
|
|
114
|
+
const dummyPrivateKey = `-----BEGIN ENCRYPTED PRIVATE KEY-----
|
|
115
|
+
zp2mwJn2NYB7AZ7+imp0azDZb+8YG2aUCiyqb6PnnA==
|
|
116
|
+
-----END ENCRYPTED PRIVATE KEY-----`;
|
|
117
|
+
|
|
118
|
+
// Create secrets for Kafka authentication
|
|
119
|
+
const rootCASecret = new secretsmanager.Secret(this, 'ConfluentRootCASecret', {
|
|
120
|
+
secretObjectValue: {
|
|
121
|
+
certificate: SecretValue.unsafePlainText(dummyCertString),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const clientCertificatesSecret = new secretsmanager.Secret(this, 'ConfluentClientCertSecret', {
|
|
126
|
+
secretObjectValue: {
|
|
127
|
+
certificate: SecretValue.unsafePlainText(dummyCertString),
|
|
128
|
+
privateKey: SecretValue.unsafePlainText(dummyPrivateKey),
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Grant read permissions to the Lambda function
|
|
133
|
+
rootCASecret.grantRead(testLambdaFunction);
|
|
134
|
+
clientCertificatesSecret.grantRead(testLambdaFunction);
|
|
135
|
+
|
|
136
|
+
// Define Kafka bootstrap servers
|
|
137
|
+
const bootstrapServers = [
|
|
138
|
+
'kafka-broker-1:9092',
|
|
139
|
+
'kafka-broker-2:9092',
|
|
140
|
+
'kafka-broker-3:9092',
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
// Common configuration for SMK event sources
|
|
144
|
+
const commonConfig = {
|
|
145
|
+
bootstrapServers,
|
|
146
|
+
secret: clientCertificatesSecret,
|
|
147
|
+
authenticationMethod: AuthenticationMethod.CLIENT_CERTIFICATE_TLS_AUTH,
|
|
148
|
+
rootCACertificate: rootCASecret,
|
|
149
|
+
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// SMK with Confluent Schema Registry
|
|
153
|
+
testLambdaFunction.addEventSource(new SelfManagedKafkaEventSource({
|
|
154
|
+
...commonConfig,
|
|
155
|
+
topic: 'test-topic-smk-confluent',
|
|
156
|
+
consumerGroupId: 'test-consumer-group-smk-confluent',
|
|
157
|
+
provisionedPollerConfig: {
|
|
158
|
+
minimumPollers: 1,
|
|
159
|
+
maximumPollers: 3,
|
|
160
|
+
},
|
|
161
|
+
schemaRegistryConfig: new ConfluentSchemaRegistry({
|
|
162
|
+
schemaRegistryUri: 'https://schema-registry.example.com',
|
|
163
|
+
eventRecordFormat: lambda.EventRecordFormat.JSON,
|
|
164
|
+
authenticationType: lambda.KafkaSchemaRegistryAccessConfigType.BASIC_AUTH,
|
|
165
|
+
secret: clientCertificatesSecret,
|
|
166
|
+
schemaValidationConfigs: [{ attribute: lambda.KafkaSchemaValidationAttribute.KEY }],
|
|
167
|
+
}),
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Create the app and stacks
|
|
173
|
+
const app = new App({
|
|
174
|
+
postCliContext: {
|
|
175
|
+
'@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy': false,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
const glueStack = new SmkGlueSchemaRegistryStack(app, 'lambda-event-source-glue-schema-registry');
|
|
179
|
+
const confluentStack = new SmkConfluentSchemaRegistryStack(app, 'lambda-event-source-confluent-schema-registry');
|
|
180
|
+
|
|
181
|
+
// Create the integration tests
|
|
182
|
+
new IntegTest(app, 'SchemaRegistryInteg', {
|
|
183
|
+
testCases: [glueStack, confluentStack],
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
app.synth();
|
|
@@ -147,19 +147,6 @@ new rds.DatabaseCluster(this, 'DatabaseCluster', {
|
|
|
147
147
|
});
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
To configure [the life cycle type of the cluster](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/extended-support.html), use the `engineLifecycleSupport` property:
|
|
151
|
-
|
|
152
|
-
```ts
|
|
153
|
-
declare const vpc: ec2.IVpc;
|
|
154
|
-
|
|
155
|
-
new rds.DatabaseCluster(this, 'DatabaseCluster', {
|
|
156
|
-
engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_07_0 }),
|
|
157
|
-
writer: rds.ClusterInstance.serverlessV2('writerInstance'),
|
|
158
|
-
vpc,
|
|
159
|
-
engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT,
|
|
160
|
-
});
|
|
161
|
-
```
|
|
162
|
-
|
|
163
150
|
### Updating the database instances in a cluster
|
|
164
151
|
|
|
165
152
|
Database cluster instances may be updated in bulk or on a rolling basis.
|
|
@@ -1576,6 +1563,29 @@ new rds.DatabaseCluster(this, 'Cluster', {
|
|
|
1576
1563
|
});
|
|
1577
1564
|
```
|
|
1578
1565
|
|
|
1566
|
+
## Extended Support
|
|
1567
|
+
|
|
1568
|
+
With Amazon RDS Extended Support, you can continue running your database on a major engine version past the RDS end of
|
|
1569
|
+
standard support date for an additional cost. To configure the life cycle type, use the `engineLifecycleSupport` property:
|
|
1570
|
+
|
|
1571
|
+
```ts
|
|
1572
|
+
declare const vpc: ec2.IVpc;
|
|
1573
|
+
|
|
1574
|
+
new rds.DatabaseCluster(this, 'DatabaseCluster', {
|
|
1575
|
+
engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_07_0 }),
|
|
1576
|
+
writer: rds.ClusterInstance.serverlessV2('writerInstance'),
|
|
1577
|
+
vpc,
|
|
1578
|
+
engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT,
|
|
1579
|
+
});
|
|
1580
|
+
|
|
1581
|
+
new rds.DatabaseInstance(this, 'DatabaseInstance', {
|
|
1582
|
+
engine: rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_0_39 }),
|
|
1583
|
+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.R7G, ec2.InstanceSize.LARGE),
|
|
1584
|
+
vpc,
|
|
1585
|
+
engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT_DISABLED,
|
|
1586
|
+
});
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1579
1589
|
## Importing existing DatabaseInstance
|
|
1580
1590
|
|
|
1581
1591
|
### Lookup DatabaseInstance by instanceIdentifier
|
cdk_api_mcp_server/resources/aws-cdk/constructs/aws-cdk-lib/aws-rds/integ.cluster-snapshot.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
1
|
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
3
|
-
import
|
|
4
|
-
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
5
|
-
import { App, ArnFormat, CustomResource, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
|
|
6
|
-
import * as cr from 'aws-cdk-lib/custom-resources';
|
|
2
|
+
import { App, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib';
|
|
7
3
|
import { Construct } from 'constructs';
|
|
8
4
|
import * as rds from 'aws-cdk-lib/aws-rds';
|
|
9
5
|
import { ClusterInstance } from 'aws-cdk-lib/aws-rds';
|
|
10
6
|
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
11
|
-
import {
|
|
7
|
+
import { ClusterSnapshoter } from './snapshoter';
|
|
12
8
|
|
|
13
9
|
class TestStack extends Stack {
|
|
14
10
|
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
@@ -34,7 +30,7 @@ class TestStack extends Stack {
|
|
|
34
30
|
removalPolicy: RemovalPolicy.DESTROY,
|
|
35
31
|
});
|
|
36
32
|
|
|
37
|
-
const snapshoter = new
|
|
33
|
+
const snapshoter = new ClusterSnapshoter(this, 'Snapshoter', {
|
|
38
34
|
cluster,
|
|
39
35
|
snapshotIdentifier: 'cdk-integ-cluster-snapshot',
|
|
40
36
|
});
|
|
@@ -58,69 +54,6 @@ class TestStack extends Stack {
|
|
|
58
54
|
}
|
|
59
55
|
}
|
|
60
56
|
|
|
61
|
-
interface SnapshoterProps {
|
|
62
|
-
readonly cluster: rds.IDatabaseCluster;
|
|
63
|
-
readonly snapshotIdentifier: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
class Snapshoter extends Construct {
|
|
67
|
-
public readonly snapshotArn: string;
|
|
68
|
-
|
|
69
|
-
constructor(scope: Construct, id: string, props: SnapshoterProps) {
|
|
70
|
-
super(scope, id);
|
|
71
|
-
|
|
72
|
-
const clusterArn = Stack.of(this).formatArn({
|
|
73
|
-
service: 'rds',
|
|
74
|
-
resource: 'cluster',
|
|
75
|
-
resourceName: props.cluster.clusterIdentifier,
|
|
76
|
-
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const snapshotArn = Stack.of(this).formatArn({
|
|
80
|
-
service: 'rds',
|
|
81
|
-
resource: 'cluster-snapshot',
|
|
82
|
-
resourceName: props.snapshotIdentifier,
|
|
83
|
-
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const code = lambda.Code.fromAsset(path.join(__dirname, 'snapshot-handler'), { exclude: ['*.ts'] });
|
|
87
|
-
const onEventHandler = new lambda.Function(this, 'OnEventHandler', {
|
|
88
|
-
code,
|
|
89
|
-
runtime: STANDARD_NODEJS_RUNTIME,
|
|
90
|
-
handler: 'index.onEventHandler',
|
|
91
|
-
});
|
|
92
|
-
onEventHandler.addToRolePolicy(new iam.PolicyStatement({
|
|
93
|
-
actions: ['rds:CreateDBClusterSnapshot', 'rds:DeleteDBClusterSnapshot'],
|
|
94
|
-
resources: [clusterArn, snapshotArn],
|
|
95
|
-
}));
|
|
96
|
-
|
|
97
|
-
const isCompleteHandler = new lambda.Function(this, 'IsCompleteHandler', {
|
|
98
|
-
code,
|
|
99
|
-
runtime: STANDARD_NODEJS_RUNTIME,
|
|
100
|
-
handler: 'index.isCompleteHandler',
|
|
101
|
-
});
|
|
102
|
-
isCompleteHandler.addToRolePolicy(new iam.PolicyStatement({
|
|
103
|
-
actions: ['rds:DescribeDBClusterSnapshots'],
|
|
104
|
-
resources: [clusterArn, snapshotArn],
|
|
105
|
-
}));
|
|
106
|
-
|
|
107
|
-
const provider = new cr.Provider(this, 'SnapshotProvider', {
|
|
108
|
-
onEventHandler,
|
|
109
|
-
isCompleteHandler,
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const customResource = new CustomResource(this, 'Snapshot', {
|
|
113
|
-
resourceType: 'Custom::Snapshoter',
|
|
114
|
-
serviceToken: provider.serviceToken,
|
|
115
|
-
properties: {
|
|
116
|
-
DBClusterIdentifier: props.cluster.clusterIdentifier,
|
|
117
|
-
DBClusterSnapshotIdentifier: props.snapshotIdentifier,
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
this.snapshotArn = customResource.getAttString('DBClusterSnapshotArn');
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
57
|
const app = new App({
|
|
125
58
|
postCliContext: {
|
|
126
59
|
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
|
|
@@ -133,4 +66,3 @@ new IntegTest(app, 'ClusterSnapshotInteg', {
|
|
|
133
66
|
testCases: [stack],
|
|
134
67
|
diffAssets: true,
|
|
135
68
|
});
|
|
136
|
-
app.synth();
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
import { App, RemovalPolicy, Stack } from 'aws-cdk-lib';
|
|
3
|
+
import * as rds from 'aws-cdk-lib/aws-rds';
|
|
4
|
+
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
|
|
5
|
+
import { InstanceSnapshoter } from './snapshoter';
|
|
6
|
+
|
|
7
|
+
const app = new App({
|
|
8
|
+
postCliContext: {
|
|
9
|
+
'@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy': true,
|
|
10
|
+
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const stack = new Stack(app, 'cdk-instance-engine-lifecycle-support');
|
|
15
|
+
|
|
16
|
+
const vpc = new ec2.Vpc(stack, 'Vpc', { maxAzs: 2, natGateways: 1, restrictDefaultSecurityGroup: false });
|
|
17
|
+
|
|
18
|
+
const engine = rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_4_5 });
|
|
19
|
+
const instanceType = ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.SMALL);
|
|
20
|
+
|
|
21
|
+
const sourceInstance = new rds.DatabaseInstance(stack, 'Instance', {
|
|
22
|
+
engine,
|
|
23
|
+
instanceType,
|
|
24
|
+
vpc,
|
|
25
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
26
|
+
engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const snapshoter = new InstanceSnapshoter(stack, 'Snapshoter', {
|
|
30
|
+
instance: sourceInstance,
|
|
31
|
+
snapshotIdentifier: 'cdk-instance-engine-lifecycle-support-snapshot',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const restoredInstance = new rds.DatabaseInstanceFromSnapshot(stack, 'FromSnapshot', {
|
|
35
|
+
snapshotIdentifier: snapshoter.snapshotArn,
|
|
36
|
+
engine,
|
|
37
|
+
instanceType,
|
|
38
|
+
vpc,
|
|
39
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
40
|
+
engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT_DISABLED,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
new rds.DatabaseInstanceReadReplica(stack, 'ReadReplica', {
|
|
44
|
+
sourceDatabaseInstance: restoredInstance,
|
|
45
|
+
instanceType,
|
|
46
|
+
vpc,
|
|
47
|
+
removalPolicy: RemovalPolicy.DESTROY,
|
|
48
|
+
engineLifecycleSupport: rds.EngineLifecycleSupport.OPEN_SOURCE_RDS_EXTENDED_SUPPORT_DISABLED,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
new IntegTest(app, 'cdk-instance-engine-lifecycle-support-test', {
|
|
52
|
+
testCases: [stack],
|
|
53
|
+
});
|
|
@@ -156,6 +156,22 @@ bucket.grantReadWrite(myLambda);
|
|
|
156
156
|
Will give the Lambda's execution role permissions to read and write
|
|
157
157
|
from the bucket.
|
|
158
158
|
|
|
159
|
+
### Understanding "grant" Methods
|
|
160
|
+
|
|
161
|
+
The S3 construct library provides several grant methods for the `Bucket` resource, but two of them have a special behavior. This two accept an `objectsKeyPattern` parameter to restrict granted permissions to specific resources:
|
|
162
|
+
- `grantRead`
|
|
163
|
+
- `grantReadWrite`
|
|
164
|
+
|
|
165
|
+
When examining the synthesized policy, you'll notice it includes both your specified object key patterns and the bucket itself.
|
|
166
|
+
This is by design. Some permissions (like `s3:ListBucket`) apply at the bucket level, while others (like `s3:GetObject`) apply to specific objects.
|
|
167
|
+
|
|
168
|
+
Specifically, the [`s3:ListBucket` action operates on bucket resources](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazons3.html#amazons3-bucket)
|
|
169
|
+
and requires the bucket ARN to work properly. This might be seen as a bug, giving the impression that more permissions were granted than the ones you intended, but the reality is that the policy does not ignore your `objectsKeyPattern` - object-specific actions like `s3:GetObject`
|
|
170
|
+
will still be limited to the resources defined in your pattern.
|
|
171
|
+
|
|
172
|
+
If you need to restrict the `s3:ListBucket` action to specific paths, you can add a `Condition` to your policy that limits the `objectsKeyPattern` to specific folders. For more details and examples, see the [AWS documentation on bucket policies](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html#example-bucket-policies-folders).
|
|
173
|
+
|
|
174
|
+
|
|
159
175
|
## AWS Foundational Security Best Practices
|
|
160
176
|
|
|
161
177
|
### Enforcing SSL
|
|
@@ -1,106 +1,68 @@
|
|
|
1
|
-
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
2
1
|
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
2
|
+
import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
3
3
|
import * as cdk from 'aws-cdk-lib';
|
|
4
|
-
import * as s3n from 'aws-cdk-lib/aws-s3-notifications';
|
|
5
|
-
import { STANDARD_NODEJS_RUNTIME } from '../../../config';
|
|
6
|
-
import * as constructs from 'constructs';
|
|
7
4
|
import * as integ from '@aws-cdk/integ-tests-alpha';
|
|
5
|
+
import * as s3n from 'aws-cdk-lib/aws-s3-notifications';
|
|
8
6
|
|
|
9
7
|
const app = new cdk.App({
|
|
10
8
|
postCliContext: {
|
|
11
|
-
'@aws-cdk/aws-lambda:useCdkManagedLogGroup': false,
|
|
12
9
|
'@aws-cdk/aws-s3:keepNotificationInImportedBucket': false,
|
|
13
10
|
},
|
|
14
11
|
});
|
|
15
12
|
|
|
16
|
-
const stack = new cdk.Stack(app, '
|
|
13
|
+
const stack = new cdk.Stack(app, 'sqs-bucket-notifications');
|
|
17
14
|
|
|
18
|
-
const
|
|
15
|
+
const bucket1 = new s3.Bucket(stack, 'Bucket1', {
|
|
19
16
|
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
20
17
|
});
|
|
18
|
+
const queue = new sqs.Queue(stack, 'MyQueue');
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
runtime: STANDARD_NODEJS_RUNTIME,
|
|
24
|
-
handler: 'index.handler',
|
|
25
|
-
code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`),
|
|
26
|
-
});
|
|
20
|
+
bucket1.addObjectCreatedNotification(new s3n.SqsDestination(queue));
|
|
27
21
|
|
|
28
|
-
const
|
|
22
|
+
const bucket2 = new s3.Bucket(stack, 'Bucket2', {
|
|
29
23
|
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
24
|
+
autoDeleteObjects: true,
|
|
30
25
|
});
|
|
26
|
+
bucket2.addObjectCreatedNotification(new s3n.SqsDestination(queue), { suffix: '.png' });
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const c1 = new constructs.Construct(stack, 'Construct1');
|
|
35
|
-
const unmanagedBucket = s3.Bucket.fromBucketName(c1, 'IntegUnmanagedBucket1', bucketA.bucketName);
|
|
36
|
-
|
|
37
|
-
unmanagedBucket.addObjectCreatedNotification(new s3n.LambdaDestination(fn), { prefix: 'TEST1/', suffix: '.png' });
|
|
38
|
-
unmanagedBucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(fn), { prefix: 'TEST2/' });
|
|
28
|
+
const encryptedQueue = new sqs.Queue(stack, 'EncryptedQueue', { encryption: sqs.QueueEncryption.KMS });
|
|
29
|
+
bucket1.addObjectRemovedNotification(new s3n.SqsDestination(encryptedQueue));
|
|
39
30
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
const bucket3 = new s3.Bucket(stack, 'Bucket3WithSkipDestinationValidation', {
|
|
32
|
+
notificationsSkipDestinationValidation: true,
|
|
33
|
+
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
34
|
+
});
|
|
35
|
+
const queueWithIncorrectS3Permissions = new sqs.Queue(stack, 'MyQueueWithIncorrectS3Permissions');
|
|
36
|
+
queueWithIncorrectS3Permissions.addToResourcePolicy(
|
|
37
|
+
new cdk.aws_iam.PolicyStatement({
|
|
38
|
+
effect: cdk.aws_iam.Effect.DENY,
|
|
39
|
+
actions: ['sqs:SendMessage'],
|
|
40
|
+
principals: [new cdk.aws_iam.ServicePrincipal('s3.amazonaws.com')],
|
|
41
|
+
resources: [queueWithIncorrectS3Permissions.queueArn],
|
|
42
|
+
}));
|
|
43
|
+
bucket3.addEventNotification(s3.EventType.OBJECT_TAGGING_PUT, new s3n.SqsDestination(queueWithIncorrectS3Permissions));
|
|
45
44
|
|
|
46
|
-
const integTest = new integ.IntegTest(app, '
|
|
47
|
-
cdkCommandOptions: {
|
|
48
|
-
deploy: {
|
|
49
|
-
args: {
|
|
50
|
-
rollback: false,
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
},
|
|
45
|
+
const integTest = new integ.IntegTest(app, 'SQSBucketNotificationsTest', {
|
|
54
46
|
testCases: [stack],
|
|
55
47
|
diffAssets: true,
|
|
56
48
|
});
|
|
57
49
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
50
|
+
integTest.assertions
|
|
51
|
+
// First remove the test notifications
|
|
52
|
+
.awsApiCall('SQS', 'purgeQueue', {
|
|
53
|
+
QueueUrl: queue.queueUrl,
|
|
54
|
+
})
|
|
55
|
+
.next(integTest.assertions
|
|
56
|
+
.awsApiCall('S3', 'putObject', {
|
|
57
|
+
Bucket: bucket2.bucketName,
|
|
58
|
+
Key: 'image.png',
|
|
59
|
+
Body: 'Some content',
|
|
60
|
+
}))
|
|
61
|
+
.next(integTest.assertions
|
|
62
|
+
.awsApiCall('SQS', 'receiveMessage', {
|
|
63
|
+
QueueUrl: queue.queueUrl,
|
|
64
|
+
WaitTimeSeconds: 20,
|
|
65
|
+
})
|
|
66
|
+
.assertAtPath('Messages.0.Body.Records.0.s3.object.key', integ.ExpectedResult.stringLikeRegexp('image\\.png')));
|
|
67
67
|
|
|
68
|
-
getNotifications.expect(integ.ExpectedResult.objectLike({
|
|
69
|
-
LambdaFunctionConfigurations: [
|
|
70
|
-
{
|
|
71
|
-
Events: [
|
|
72
|
-
's3:ObjectCreated:*',
|
|
73
|
-
],
|
|
74
|
-
Filter: {
|
|
75
|
-
Key: {
|
|
76
|
-
FilterRules: [
|
|
77
|
-
{
|
|
78
|
-
Name: 'Prefix',
|
|
79
|
-
Value: 'TEST1/',
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
Name: 'Suffix',
|
|
83
|
-
Value: '.png',
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
Events: [
|
|
91
|
-
's3:ObjectCreated:*',
|
|
92
|
-
],
|
|
93
|
-
Filter: {
|
|
94
|
-
Key: {
|
|
95
|
-
FilterRules: [
|
|
96
|
-
{
|
|
97
|
-
Name: 'Prefix',
|
|
98
|
-
Value: 'TEST2/',
|
|
99
|
-
},
|
|
100
|
-
],
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
}));
|
|
106
68
|
app.synth();
|