From 312235a2b0a7bf24b26ff3318f619a738cb58e2b Mon Sep 17 00:00:00 2001 From: GZ Date: Thu, 6 Jun 2024 12:57:36 -0700 Subject: [PATCH 1/5] chore(apigatewayv2): add apigatewayv2 integrations and authorizers to jsiirc (#30461) ### Issue # (if applicable) Closes https://github.com/aws/aws-cdk/issues/28348 ### Reason for this change When we promote apigatewayv2 from experimental to stable module, we did not add `jsiirc.json` file, thus no documentation is created and the namespace for import is incorrect. ### Description of changes We cannot fix the namespace now as this is stable modules and there're customers using it. Fixing this would be a breaking change to users who use apigatewayv2 in `aws-cdk-lib`. ### Description of how you validated changes N/A ### Checklist - [ ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-apigatewayv2-authorizers/.jsiirc.json | 13 +++++++++ .../aws-apigatewayv2-authorizers/README.md | 26 +++++++++++++++++ .../.jsiirc.json | 13 +++++++++ .../aws-apigatewayv2-integrations/README.md | 28 ++++++++++++++++++- 4 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 packages/aws-cdk-lib/aws-apigatewayv2-authorizers/.jsiirc.json create mode 100644 packages/aws-cdk-lib/aws-apigatewayv2-integrations/.jsiirc.json diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-authorizers/.jsiirc.json b/packages/aws-cdk-lib/aws-apigatewayv2-authorizers/.jsiirc.json new file mode 100644 index 0000000000000..9fbccc2314fc9 --- /dev/null +++ b/packages/aws-cdk-lib/aws-apigatewayv2-authorizers/.jsiirc.json @@ -0,0 +1,13 @@ +{ + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AwsApigatewayv2Authorizers" + }, + "java": { + "package": "software.amazon.awscdk.aws_apigatewayv2_authorizers" + }, + "python": { + "module": "aws_cdk.aws_apigatewayv2_authorizers" + } + } +} diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-authorizers/README.md b/packages/aws-cdk-lib/aws-apigatewayv2-authorizers/README.md index 2cef622ea1381..a633d395ce08a 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2-authorizers/README.md +++ b/packages/aws-cdk-lib/aws-apigatewayv2-authorizers/README.md @@ -13,6 +13,9 @@ - [WebSocket APIs](#websocket-apis) - [Lambda Authorizer](#lambda-authorizer) - [IAM Authorizers](#iam-authorizer) +- [Import Issues](#import-issues) + - [DotNet Namespace](#dotnet-namespace) + - [Java Package](#java-package) ## Introduction @@ -280,3 +283,26 @@ user.attachInlinePolicy(new iam.Policy(this, 'AllowInvoke', { })); ``` + +## Import Issues + +`jsiirc.json` file is missing during the stablization process of this module, which caused import issues for DotNet and Java users who attempt to use this module. Unfortunately, to guarantee backward compatibility, we cannot simply correct the namespace for DotNet or package for Java. The following outlines the workaround. + +### DotNet Namespace + +Instead of the conventional namespace `Amazon.CDK.AWS.Apigatewayv2.Authorizers`, you would need to use the following namespace: + +```cs +using Amazon.CDK.AwsApigatewayv2Authorizers;; +``` + +### Java Package + +Instead of conventional package `import software.amazon.awscdk.services.apigatewayv2_authorizers.*`, you would need to use the following package: + +```java +import software.amazon.awscdk.aws_apigatewayv2_authorizers.*; + +// If you want to import a specific construct +import software.amazon.awscdk.aws_apigatewayv2_authorizers.WebSocketIamAuthorizer; +``` diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/.jsiirc.json b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/.jsiirc.json new file mode 100644 index 0000000000000..6ad7dc9b48919 --- /dev/null +++ b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/.jsiirc.json @@ -0,0 +1,13 @@ +{ + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AwsApigatewayv2Integrations" + }, + "java": { + "package": "software.amazon.awscdk.aws_apigatewayv2_integrations" + }, + "python": { + "module": "aws_cdk.aws_apigatewayv2_integrations" + } + } +} diff --git a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md index 4df90c5836218..9fd07172268e6 100644 --- a/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md +++ b/packages/aws-cdk-lib/aws-apigatewayv2-integrations/README.md @@ -11,6 +11,9 @@ - [WebSocket APIs](#websocket-apis) - [Lambda WebSocket Integration](#lambda-websocket-integration) - [AWS WebSocket Integration](#aws-websocket-integration) +- [Import Issues](#import-issues) + - [DotNet Namespace](#dotnet-namespace) + - [Java Package](#java-package) ## HTTP APIs @@ -307,4 +310,27 @@ webSocketApi.addRoute('$connect', { ``` You can also set additional properties to change the behavior of your integration, such as `contentHandling`. -See [Working with binary media types for WebSocket APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-develop-binary-media-types.html). \ No newline at end of file +See [Working with binary media types for WebSocket APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-develop-binary-media-types.html). + +## Import Issues + +`jsiirc.json` file is missing during the stablization process of this module, which caused import issues for DotNet and Java users who attempt to use this module. Unfortunately, to guarantee backward compatibility, we cannot simply correct the namespace for DotNet or package for Java. The following outlines the workaround. + +### DotNet Namespace + +Instead of the conventional namespace `Amazon.CDK.AWS.Apigatewayv2.Integrations`, you would need to use the following namespace: + +```cs +using Amazon.CDK.AwsApigatewayv2Integrations; +``` + +### Java Package + +Instead of conventional package `import software.amazon.awscdk.services.apigatewayv2_integrations.*`, you would need to use the following package: + +```java +import software.amazon.awscdk.aws_apigatewayv2_integrations.*; + +// If you want to import a specific construct +import software.amazon.awscdk.aws_apigatewayv2_integrations.WebSocketAwsIntegration; +``` From a05591d34b234f92e57448ff8e15b9f74cc56da8 Mon Sep 17 00:00:00 2001 From: Burak Aktas Date: Fri, 7 Jun 2024 00:24:57 +0300 Subject: [PATCH 2/5] chore(events): rule cannot have more than 5 targets (#30470) ### Issue # (if applicable) Closes #. ### Reason for this change This is a minor refactor for preventing an Event Rule to have at most 5 associated targets defined during a synth. This is the main limit set by EventBridge https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-quota.html#eb-limits ### Description of changes This is a very simple change in `aws-events` module to check if the `targets` array length of an `Event` is greater than 5. If it is then it throws an Error during build time. ### Description of how you validated changes Added a unit test by in `rule.test.ts` by verifying an Error is being thrown when a Rule has more than 5 associated targets. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-events/lib/rule.ts | 4 ++++ .../aws-cdk-lib/aws-events/test/rule.test.ts | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/aws-cdk-lib/aws-events/lib/rule.ts b/packages/aws-cdk-lib/aws-events/lib/rule.ts index b96347e20ba2b..bbac64b14e63a 100644 --- a/packages/aws-cdk-lib/aws-events/lib/rule.ts +++ b/packages/aws-cdk-lib/aws-events/lib/rule.ts @@ -314,6 +314,10 @@ export class Rule extends Resource implements IRule { errors.push('Either \'eventPattern\' or \'schedule\' must be defined'); } + if (this.targets.length > 5) { + errors.push('Event rule cannot have more than 5 targets.'); + } + return errors; } diff --git a/packages/aws-cdk-lib/aws-events/test/rule.test.ts b/packages/aws-cdk-lib/aws-events/test/rule.test.ts index 80f3c5cbe53d6..dbcf5ad9bd01c 100644 --- a/packages/aws-cdk-lib/aws-events/test/rule.test.ts +++ b/packages/aws-cdk-lib/aws-events/test/rule.test.ts @@ -72,6 +72,25 @@ describe('rule', () => { }); }); + test('rule cannot have more than 5 targets', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app); + const resource = new Construct(stack, 'Resource'); + const rule = new Rule(stack, 'MyRule', { + schedule: Schedule.rate(cdk.Duration.minutes(10)), + targets: [ + new SomeTarget('T1', resource), + new SomeTarget('T2', resource), + new SomeTarget('T3', resource), + new SomeTarget('T4', resource), + new SomeTarget('T5', resource), + new SomeTarget('T6', resource), + ], + }); + + expect(() => app.synth()).toThrow(/Event rule cannot have more than 5 targets./); + }); + test('get rate as token', () => { const app = new cdk.App(); const stack = new cdk.Stack(app, 'MyScheduledStack'); From 448b441379209b21fe12311e7a7ff6383460b2fb Mon Sep 17 00:00:00 2001 From: Parker Scanlon <69879391+scanlonp@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:53:34 -0700 Subject: [PATCH 3/5] chore(lambda): match enum value to property (#30472) Looks like we are comparing `LogFormat` to the `LoggingFormat` enum. This is not technically a problem for us because `LogFormat` is a string. We deprecated it and created `LoggingFormat` to enforce the enum. This conditional works because all the enums collapse to strings, but it is best if we sync up the properties with their correct enums. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-lambda/lib/function.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-lambda/lib/function.ts b/packages/aws-cdk-lib/aws-lambda/lib/function.ts index 32e477f81f86b..45c67d9ea3d4b 100644 --- a/packages/aws-cdk-lib/aws-lambda/lib/function.ts +++ b/packages/aws-cdk-lib/aws-lambda/lib/function.ts @@ -1179,7 +1179,7 @@ export class Function extends FunctionBase { } if (props.applicationLogLevel || props.applicationLogLevelV2 || props.systemLogLevel || props.systemLogLevelV2) { - if (props.logFormat !== LoggingFormat.JSON && props.loggingFormat === undefined) { + if (props.logFormat !== LogFormat.JSON && props.loggingFormat === undefined) { throw new Error(`To use ApplicationLogLevel and/or SystemLogLevel you must set LogFormat to '${LogFormat.JSON}', got '${props.logFormat}'.`); } From 516ecef9a5504c19558367c360a2791559b929eb Mon Sep 17 00:00:00 2001 From: kazuho cryer-shinozuka Date: Fri, 7 Jun 2024 07:24:36 +0900 Subject: [PATCH 4/5] feat(config): proactive evaluation mode (#30174) ### Issue # (if applicable) Closes #30172. ### Reason for this change AWS Config supports for proactive evaluation mode but L2 construct cannot configure it. ### Description of changes - Define `EvaluationMode` class - Add `evaluationModes` prop to `RuleProps` ```ts new config.ManagedRule(stack, 'ManagedRule', { identifier: config.ManagedRuleIdentifiers.API_GW_XRAY_ENABLED, evaluationModes: config.EvaluationMode.DETECTIVE_AND_PROACTIVE, // add }); ``` ### Description of how you validated changes Add both unit and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../ConfigRuleEvaluationMode.assets.json | 19 + .../ConfigRuleEvaluationMode.template.json | 201 ++++++++++ ...efaultTestDeployAssert7587D529.assets.json | 19 + ...aultTestDeployAssert7587D529.template.json | 36 ++ .../cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 143 +++++++ .../tree.json | 362 ++++++++++++++++++ .../test/integ.rule-evaluation-mode.ts | 55 +++ packages/aws-cdk-lib/aws-config/README.md | 28 ++ packages/aws-cdk-lib/aws-config/lib/rule.ts | 39 ++ .../aws-cdk-lib/aws-config/test/rule.test.ts | 31 +- 12 files changed, 944 insertions(+), 2 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.assets.json new file mode 100644 index 0000000000000..0cb794a558431 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "cd5d1281320457bd3bdf9cec55c92e3a307cde74cabf41ffc7b171bdd983a792": { + "source": { + "path": "ConfigRuleEvaluationMode.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "cd5d1281320457bd3bdf9cec55c92e3a307cde74cabf41ffc7b171bdd983a792.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.template.json new file mode 100644 index 0000000000000..a9c7aade54f1b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationMode.template.json @@ -0,0 +1,201 @@ +{ + "Resources": { + "CustomFunctionServiceRoleD3F73B79": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSConfigRulesExecutionRole" + ] + ] + } + ] + } + }, + "CustomFunctionBADD59E7": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = (event) => console.log(event);" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "CustomFunctionServiceRoleD3F73B79", + "Arn" + ] + }, + "Runtime": "nodejs18.x" + }, + "DependsOn": [ + "CustomFunctionServiceRoleD3F73B79" + ] + }, + "CustomFunctionCustomRulePermissionbM1jVaicvRO9SDCiAbsQcYrOlESEtMwrrF9ZQQRvd5QED54A3F8": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "CustomFunctionBADD59E7", + "Arn" + ] + }, + "Principal": "config.amazonaws.com", + "SourceAccount": { + "Ref": "AWS::AccountId" + } + } + }, + "CustomRuleB1CBBADE": { + "Type": "AWS::Config::ConfigRule", + "Properties": { + "EvaluationModes": [ + { + "Mode": "PROACTIVE" + } + ], + "Scope": { + "ComplianceResourceTypes": [ + "AWS::EC2::Instance" + ] + }, + "Source": { + "Owner": "CUSTOM_LAMBDA", + "SourceDetails": [ + { + "EventSource": "aws.config", + "MessageType": "ScheduledNotification" + } + ], + "SourceIdentifier": { + "Fn::GetAtt": [ + "CustomFunctionBADD59E7", + "Arn" + ] + } + } + }, + "DependsOn": [ + "CustomFunctionCustomRulePermissionbM1jVaicvRO9SDCiAbsQcYrOlESEtMwrrF9ZQQRvd5QED54A3F8", + "CustomFunctionBADD59E7", + "CustomFunctionServiceRoleD3F73B79" + ] + }, + "ManagedRule7126A2A0": { + "Type": "AWS::Config::ConfigRule", + "Properties": { + "EvaluationModes": [ + { + "Mode": "DETECTIVE" + }, + { + "Mode": "PROACTIVE" + } + ], + "Source": { + "Owner": "AWS", + "SourceIdentifier": "API_GW_XRAY_ENABLED" + } + } + }, + "CustomPolicy6CB3FDA5": { + "Type": "AWS::Config::ConfigRule", + "Properties": { + "EvaluationModes": [ + { + "Mode": "DETECTIVE" + } + ], + "Scope": { + "ComplianceResourceTypes": [ + "AWS::DynamoDB::Table" + ] + }, + "Source": { + "CustomPolicyDetails": { + "EnableDebugLogDelivery": true, + "PolicyRuntime": "guard-2.x.x", + "PolicyText": "\n# This rule checks if point in time recovery (PITR) is enabled on active Amazon DynamoDB tables\nlet status = ['ACTIVE']\n\nrule tableisactive when\n resourceType == \"AWS::DynamoDB::Table\" {\n configuration.tableStatus == %status\n}\n\nrule checkcompliance when\n resourceType == \"AWS::DynamoDB::Table\"\n tableisactive {\n let pitr = supplementaryConfiguration.ContinuousBackupsDescription.pointInTimeRecoveryDescription.pointInTimeRecoveryStatus\n %pitr == \"ENABLED\"\n}\n" + }, + "Owner": "CUSTOM_POLICY", + "SourceDetails": [ + { + "EventSource": "aws.config", + "MessageType": "ConfigurationItemChangeNotification" + }, + { + "EventSource": "aws.config", + "MessageType": "OversizedConfigurationItemChangeNotification" + } + ] + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets.json new file mode 100644 index 0000000000000..c3053254108a7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/integ.json new file mode 100644 index 0000000000000..83ee605a31b7f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "ConfigRuleEvaluationModeTest/DefaultTest": { + "stacks": [ + "ConfigRuleEvaluationMode" + ], + "assertionStack": "ConfigRuleEvaluationModeTest/DefaultTest/DeployAssert", + "assertionStackName": "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/manifest.json new file mode 100644 index 0000000000000..286127ff887ca --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/manifest.json @@ -0,0 +1,143 @@ +{ + "version": "36.0.0", + "artifacts": { + "ConfigRuleEvaluationMode.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ConfigRuleEvaluationMode.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ConfigRuleEvaluationMode": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ConfigRuleEvaluationMode.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/cd5d1281320457bd3bdf9cec55c92e3a307cde74cabf41ffc7b171bdd983a792.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ConfigRuleEvaluationMode.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ConfigRuleEvaluationMode.assets" + ], + "metadata": { + "/ConfigRuleEvaluationMode/CustomFunction/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomFunctionServiceRoleD3F73B79" + } + ], + "/ConfigRuleEvaluationMode/CustomFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomFunctionBADD59E7" + } + ], + "/ConfigRuleEvaluationMode/CustomFunction/CustomRulePermissionbM1jVaicvRO9SDCiAbsQcYrOlESEtMwrrF9ZQQRvd5Q=": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomFunctionCustomRulePermissionbM1jVaicvRO9SDCiAbsQcYrOlESEtMwrrF9ZQQRvd5QED54A3F8" + } + ], + "/ConfigRuleEvaluationMode/CustomRule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomRuleB1CBBADE" + } + ], + "/ConfigRuleEvaluationMode/ManagedRule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ManagedRule7126A2A0" + } + ], + "/ConfigRuleEvaluationMode/CustomPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "CustomPolicy6CB3FDA5" + } + ], + "/ConfigRuleEvaluationMode/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ConfigRuleEvaluationMode/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ConfigRuleEvaluationMode" + }, + "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ConfigRuleEvaluationModeTestDefaultTestDeployAssert7587D529.assets" + ], + "metadata": { + "/ConfigRuleEvaluationModeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ConfigRuleEvaluationModeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ConfigRuleEvaluationModeTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/tree.json new file mode 100644 index 0000000000000..c7daf55976d19 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.js.snapshot/tree.json @@ -0,0 +1,362 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "ConfigRuleEvaluationMode": { + "id": "ConfigRuleEvaluationMode", + "path": "ConfigRuleEvaluationMode", + "children": { + "CustomFunction": { + "id": "CustomFunction", + "path": "ConfigRuleEvaluationMode/CustomFunction", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "ConfigRuleEvaluationMode/CustomFunction/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "ConfigRuleEvaluationMode/CustomFunction/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "ConfigRuleEvaluationMode/CustomFunction/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSConfigRulesExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "ConfigRuleEvaluationMode/CustomFunction/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = (event) => console.log(event);" + }, + "handler": "index.handler", + "role": { + "Fn::GetAtt": [ + "CustomFunctionServiceRoleD3F73B79", + "Arn" + ] + }, + "runtime": "nodejs18.x" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", + "version": "0.0.0" + } + }, + "CustomRulePermissionbM1jVaicvRO9SDCiAbsQcYrOlESEtMwrrF9ZQQRvd5Q=": { + "id": "CustomRulePermissionbM1jVaicvRO9SDCiAbsQcYrOlESEtMwrrF9ZQQRvd5Q=", + "path": "ConfigRuleEvaluationMode/CustomFunction/CustomRulePermissionbM1jVaicvRO9SDCiAbsQcYrOlESEtMwrrF9ZQQRvd5Q=", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Permission", + "aws:cdk:cloudformation:props": { + "action": "lambda:InvokeFunction", + "functionName": { + "Fn::GetAtt": [ + "CustomFunctionBADD59E7", + "Arn" + ] + }, + "principal": "config.amazonaws.com", + "sourceAccount": { + "Ref": "AWS::AccountId" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnPermission", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.Function", + "version": "0.0.0" + } + }, + "CustomRule": { + "id": "CustomRule", + "path": "ConfigRuleEvaluationMode/CustomRule", + "children": { + "Resource": { + "id": "Resource", + "path": "ConfigRuleEvaluationMode/CustomRule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Config::ConfigRule", + "aws:cdk:cloudformation:props": { + "evaluationModes": [ + { + "mode": "PROACTIVE" + } + ], + "scope": { + "complianceResourceTypes": [ + "AWS::EC2::Instance" + ] + }, + "source": { + "owner": "CUSTOM_LAMBDA", + "sourceDetails": [ + { + "eventSource": "aws.config", + "messageType": "ScheduledNotification" + } + ], + "sourceIdentifier": { + "Fn::GetAtt": [ + "CustomFunctionBADD59E7", + "Arn" + ] + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_config.CfnConfigRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_config.CustomRule", + "version": "0.0.0" + } + }, + "ManagedRule": { + "id": "ManagedRule", + "path": "ConfigRuleEvaluationMode/ManagedRule", + "children": { + "Resource": { + "id": "Resource", + "path": "ConfigRuleEvaluationMode/ManagedRule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Config::ConfigRule", + "aws:cdk:cloudformation:props": { + "evaluationModes": [ + { + "mode": "DETECTIVE" + }, + { + "mode": "PROACTIVE" + } + ], + "source": { + "owner": "AWS", + "sourceIdentifier": "API_GW_XRAY_ENABLED" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_config.CfnConfigRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_config.ManagedRule", + "version": "0.0.0" + } + }, + "CustomPolicy": { + "id": "CustomPolicy", + "path": "ConfigRuleEvaluationMode/CustomPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "ConfigRuleEvaluationMode/CustomPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Config::ConfigRule", + "aws:cdk:cloudformation:props": { + "evaluationModes": [ + { + "mode": "DETECTIVE" + } + ], + "scope": { + "complianceResourceTypes": [ + "AWS::DynamoDB::Table" + ] + }, + "source": { + "owner": "CUSTOM_POLICY", + "sourceDetails": [ + { + "eventSource": "aws.config", + "messageType": "ConfigurationItemChangeNotification" + }, + { + "eventSource": "aws.config", + "messageType": "OversizedConfigurationItemChangeNotification" + } + ], + "customPolicyDetails": { + "enableDebugLogDelivery": true, + "policyRuntime": "guard-2.x.x", + "policyText": "\n# This rule checks if point in time recovery (PITR) is enabled on active Amazon DynamoDB tables\nlet status = ['ACTIVE']\n\nrule tableisactive when\n resourceType == \"AWS::DynamoDB::Table\" {\n configuration.tableStatus == %status\n}\n\nrule checkcompliance when\n resourceType == \"AWS::DynamoDB::Table\"\n tableisactive {\n let pitr = supplementaryConfiguration.ContinuousBackupsDescription.pointInTimeRecoveryDescription.pointInTimeRecoveryStatus\n %pitr == \"ENABLED\"\n}\n" + } + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_config.CfnConfigRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_config.CustomPolicy", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ConfigRuleEvaluationMode/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ConfigRuleEvaluationMode/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "ConfigRuleEvaluationModeTest": { + "id": "ConfigRuleEvaluationModeTest", + "path": "ConfigRuleEvaluationModeTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "ConfigRuleEvaluationModeTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "ConfigRuleEvaluationModeTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "ConfigRuleEvaluationModeTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ConfigRuleEvaluationModeTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ConfigRuleEvaluationModeTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.ts new file mode 100644 index 0000000000000..3e83e114ee6c7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-config/test/integ.rule-evaluation-mode.ts @@ -0,0 +1,55 @@ +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as cdk from 'aws-cdk-lib'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as config from 'aws-cdk-lib/aws-config'; +import { STANDARD_NODEJS_RUNTIME } from '../../config'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'ConfigRuleEvaluationMode'); + +const fn = new lambda.Function(stack, 'CustomFunction', { + code: lambda.AssetCode.fromInline('exports.handler = (event) => console.log(event);'), + handler: 'index.handler', + runtime: STANDARD_NODEJS_RUNTIME, +}); + +new config.CustomRule(stack, 'CustomRule', { + lambdaFunction: fn, + periodic: true, + ruleScope: config.RuleScope.fromResources([config.ResourceType.EC2_INSTANCE]), + evaluationModes: config.EvaluationMode.PROACTIVE, +}); + +new config.ManagedRule(stack, 'ManagedRule', { + identifier: config.ManagedRuleIdentifiers.API_GW_XRAY_ENABLED, + evaluationModes: config.EvaluationMode.DETECTIVE_AND_PROACTIVE, +}); + +const samplePolicyText = ` +# This rule checks if point in time recovery (PITR) is enabled on active Amazon DynamoDB tables +let status = ['ACTIVE'] + +rule tableisactive when + resourceType == "AWS::DynamoDB::Table" { + configuration.tableStatus == %status +} + +rule checkcompliance when + resourceType == "AWS::DynamoDB::Table" + tableisactive { + let pitr = supplementaryConfiguration.ContinuousBackupsDescription.pointInTimeRecoveryDescription.pointInTimeRecoveryStatus + %pitr == "ENABLED" +} +`; + +new config.CustomPolicy(stack, 'CustomPolicy', { + policyText: samplePolicyText, + enableDebugLog: true, + ruleScope: config.RuleScope.fromResources([config.ResourceType.DYNAMODB_TABLE]), + evaluationModes: config.EvaluationMode.DETECTIVE, +}); + +new integ.IntegTest(app, 'ConfigRuleEvaluationModeTest', { + testCases: [stack], +}); diff --git a/packages/aws-cdk-lib/aws-config/README.md b/packages/aws-cdk-lib/aws-config/README.md index 68e35b0eb6526..b970845135f78 100644 --- a/packages/aws-cdk-lib/aws-config/README.md +++ b/packages/aws-cdk-lib/aws-config/README.md @@ -206,6 +206,34 @@ const tagRule = new config.CustomRule(this, 'CostCenterTagRule', { }); ``` +### Evaluation Mode + +You can specify the [evaluation mode](https://docs.aws.amazon.com/config/latest/developerguide/evaluate-config-rules.html) for a rule to determine when AWS Config runs evaluations. + +Use the `evaluationModes` property to specify the evaluation mode: + +```ts +declare const fn: lambda.Function; +declare const samplePolicyText: string; + +new config.ManagedRule(this, 'ManagedRule', { + identifier: config.ManagedRuleIdentifiers.API_GW_XRAY_ENABLED, + evaluationModes: config.EvaluationMode.DETECTIVE_AND_PROACTIVE, +}); + +new config.CustomRule(this, 'CustomRule', { + lambdaFunction: fn, + evaluationModes: config.EvaluationMode.PROACTIVE, +}); + +new config.CustomPolicy(this, 'CustomPolicy', { + policyText: samplePolicyText, + evaluationModes: config.EvaluationMode.DETECTIVE, +}); +``` + +**Note**: Proactive evaluation mode is not supported for all rules. See [AWS Config documentation](https://docs.aws.amazon.com/config/latest/developerguide/evaluate-config-rules.html#aws-config-rules-evaluation-modes) for more information. + ### Events You can define Amazon EventBridge event rules which trigger when a compliance check fails diff --git a/packages/aws-cdk-lib/aws-config/lib/rule.ts b/packages/aws-cdk-lib/aws-config/lib/rule.ts index e3af326672a57..81285ebb87d12 100644 --- a/packages/aws-cdk-lib/aws-config/lib/rule.ts +++ b/packages/aws-cdk-lib/aws-config/lib/rule.ts @@ -34,6 +34,29 @@ export interface IRule extends IResource { onReEvaluationStatus(id: string, options?: events.OnEventOptions): events.Rule; } +/** + * The mode of evaluation for the rule. + */ +export class EvaluationMode { + /** + * Evaluate resources that have already been deployed + */ + public static readonly DETECTIVE = new EvaluationMode(['DETECTIVE']); + /** + * Evaluate resources before they have been deployed + */ + public static readonly PROACTIVE = new EvaluationMode(['PROACTIVE']); + /** + * Evaluate resources that have already been deployed and before they have been deployed + */ + public static readonly DETECTIVE_AND_PROACTIVE = new EvaluationMode(['DETECTIVE', 'PROACTIVE']); + + /** + * @param modes The modes of evaluation for the rule + */ + protected constructor(public readonly modes: string[]) {} +} + /** * A new or imported rule. */ @@ -222,6 +245,13 @@ export interface RuleProps { * @default - evaluations for the rule are triggered when any resource in the recording group changes. */ readonly ruleScope?: RuleScope; + + /** + * The modes the AWS Config rule can be evaluated in. The valid values are distinct objects. + * + * @default - Detective evaluation mode only + */ + readonly evaluationModes?: EvaluationMode; } /** @@ -271,6 +301,9 @@ export class ManagedRule extends RuleNew { owner: 'AWS', sourceIdentifier: props.identifier, }, + evaluationModes: props.evaluationModes?.modes.map((mode) => ({ + mode, + })), }); this.configRuleName = rule.ref; @@ -444,6 +477,9 @@ export class CustomRule extends RuleNew { sourceDetails, sourceIdentifier: props.lambdaFunction.functionArn, }, + evaluationModes: props.evaluationModes?.modes.map((mode) => ({ + mode, + })), }); this.configRuleName = rule.ref; @@ -529,6 +565,9 @@ export class CustomPolicy extends RuleNew { policyText: props.policyText, }, }, + evaluationModes: props.evaluationModes?.modes.map((mode) => ({ + mode, + })), }); this.configRuleName = rule.ref; diff --git a/packages/aws-cdk-lib/aws-config/test/rule.test.ts b/packages/aws-cdk-lib/aws-config/test/rule.test.ts index d1da74a11ae4d..8715729856b06 100644 --- a/packages/aws-cdk-lib/aws-config/test/rule.test.ts +++ b/packages/aws-cdk-lib/aws-config/test/rule.test.ts @@ -18,6 +18,7 @@ describe('rule', () => { }, maximumExecutionFrequency: config.MaximumExecutionFrequency.THREE_HOURS, configRuleName: 'cool rule', + evaluationModes: config.EvaluationMode.DETECTIVE_AND_PROACTIVE, }); // THEN @@ -32,6 +33,14 @@ describe('rule', () => { key: 'value', }, MaximumExecutionFrequency: 'Three_Hours', + EvaluationModes: [ + { + Mode: 'DETECTIVE', + }, + { + Mode: 'PROACTIVE', + }, + ], }); }); @@ -55,6 +64,7 @@ describe('rule', () => { maximumExecutionFrequency: config.MaximumExecutionFrequency.SIX_HOURS, configRuleName: 'cool rule', periodic: true, + evaluationModes: config.EvaluationMode.DETECTIVE_AND_PROACTIVE, }); // THEN @@ -90,6 +100,14 @@ describe('rule', () => { key: 'value', }, MaximumExecutionFrequency: 'Six_Hours', + EvaluationModes: [ + { + Mode: 'DETECTIVE', + }, + { + Mode: 'PROACTIVE', + }, + ], }, }); @@ -419,12 +437,12 @@ describe('rule', () => { new config.CustomPolicy(stack, 'Rule', { policyText: ` let status = ['ACTIVE'] - + rule tableisactive when resourceType == "AWS::DynamoDB::Table" { configuration.tableStatus == %status } - + rule checkcompliance when resourceType == "AWS::DynamoDB::Table" tableisactive { @@ -433,6 +451,7 @@ describe('rule', () => { }`, description: 'really cool rule', configRuleName: 'cool rule', + evaluationModes: config.EvaluationMode.DETECTIVE_AND_PROACTIVE, }); // THEN @@ -452,6 +471,14 @@ describe('rule', () => { }, ConfigRuleName: 'cool rule', Description: 'really cool rule', + EvaluationModes: [ + { + Mode: 'DETECTIVE', + }, + { + Mode: 'PROACTIVE', + }, + ], }); }); From 8f4d4d75df7adf994f97de633de3da2fc32c7eee Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Thu, 6 Jun 2024 19:49:29 -0400 Subject: [PATCH 5/5] chore(stepfunction-tasks): eventbridge aws. event source prefix check is more strict than it should be (#30237) 1. fix the event source validation 2. move the validation from renderEntries() to validateEntries() 3. add unit tests ### Issue # (if applicable) Closes #30191 ### Reason for this change ### Description of changes ### Description of how you validated changes ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/eventbridge/put-events.ts | 20 ++++++++-------- .../test/eventbridge/put-events.test.ts | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/eventbridge/put-events.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/eventbridge/put-events.ts index cb0f08bb9a311..dfb8694d801c6 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/eventbridge/put-events.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/eventbridge/put-events.ts @@ -132,17 +132,14 @@ export class EventBridgePutEvents extends sfn.TaskStateBase { } private renderEntries(): Object[] { + // we should have validated all entries in validateEntries() return this.props.entries.map(entry => { - if (entry.source?.startsWith('aws')) { - throw new Error('Event source cannot start with "aws."'); - } else { - return { - Detail: entry.detail?.value, - DetailType: entry.detailType, - EventBusName: entry.eventBus?.eventBusArn, - Source: entry.source, - }; - } + return { + Detail: entry.detail?.value, + DetailType: entry.detailType, + EventBusName: entry.eventBus?.eventBusArn, + Source: entry.source, + }; }); } @@ -150,5 +147,8 @@ export class EventBridgePutEvents extends sfn.TaskStateBase { if (this.props.entries.length <= 0) { throw new Error('Value for property `entries` must be a non-empty array.'); } + if (this.props.entries.some(e => e.source.startsWith('aws.'))) { + throw new Error('Event source cannot start with "aws."'); + } } } \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/eventbridge/put-events.test.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/eventbridge/put-events.test.ts index 67e98c798d32e..5a4a63221b504 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/eventbridge/put-events.test.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/eventbridge/put-events.test.ts @@ -161,6 +161,30 @@ describe('Put Events', () => { }).toThrowError('Unsupported service integration pattern'); }); + test('event source cannot start with "aws."', () => { + expect(() => { + new EventBridgePutEvents(stack, 'PutEvents', { + entries: [{ + detail: sfn.TaskInput.fromText('MyDetail'), + detailType: 'MyDetailType', + source: 'aws.source', + }], + }); + }).toThrow(/Event source cannot start with "aws."/); + }); + + test('event source can start with "aws" without trailing dot', () => { + expect(() => { + new EventBridgePutEvents(stack, 'PutEvents', { + entries: [{ + detail: sfn.TaskInput.fromText('MyDetail'), + detailType: 'MyDetailType', + source: 'awssource', + }], + }); + }).not.toThrow(/Event source cannot start with "aws."/); + }); + test('provided EventBus', () => { // GIVEN const eventBus = new events.EventBus(stack, 'EventBus');