diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/IntegTestBatchDefaultEnvVarsStackDefaultTestDeployAssertC15EFFF2.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/IntegTestBatchDefaultEnvVarsStackDefaultTestDeployAssertC15EFFF2.assets.json index 0ee3c895dea43..729e582cb3fac 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/IntegTestBatchDefaultEnvVarsStackDefaultTestDeployAssertC15EFFF2.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/IntegTestBatchDefaultEnvVarsStackDefaultTestDeployAssertC15EFFF2.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "38.0.1", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.assets.json index 21e208bc4a0a6..fcaa8d81d24aa 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.assets.json @@ -1,7 +1,7 @@ { - "version": "21.0.0", + "version": "38.0.1", "files": { - "f9728b2d2c64ff638563c8cc4a3e8eb9ddf3074e2ae01d68fde11aeda0968fb1": { + "48862253eb1fed012c1b274795624b9ddc15444520044ea09a9ecd3ed2f4c300": { "source": { "path": "RuleStack.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f9728b2d2c64ff638563c8cc4a3e8eb9ddf3074e2ae01d68fde11aeda0968fb1.json", + "objectKey": "48862253eb1fed012c1b274795624b9ddc15444520044ea09a9ecd3ed2f4c300.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.template.json index 5025f8b2c914b..51d42081980bd 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/RuleStack.template.json @@ -148,6 +148,112 @@ }, "State": "ENABLED" } + }, + "MyWildcardRule477FB0F9": { + "Type": "AWS::Events::Rule", + "Properties": { + "EventPattern": { + "account": [ + { + "wildcard": "account*" + } + ] + }, + "State": "ENABLED" + } + }, + "MyAnythingButPrefixRule756FC7C6": { + "Type": "AWS::Events::Rule", + "Properties": { + "EventPattern": { + "account": [ + { + "anything-but": { + "prefix": "prefix-" + } + } + ] + }, + "State": "ENABLED" + } + }, + "MyAnythingButSuffixRuleB1E496DF": { + "Type": "AWS::Events::Rule", + "Properties": { + "EventPattern": { + "account": [ + { + "anything-but": { + "suffix": "-suffix" + } + } + ] + }, + "State": "ENABLED" + } + }, + "MyAnythingButWildcardRuleEED7F44B": { + "Type": "AWS::Events::Rule", + "Properties": { + "EventPattern": { + "account": [ + { + "anything-but": { + "wildcard": "account*" + } + } + ] + }, + "State": "ENABLED" + } + }, + "MyAnythingButEqualsIgnoreCaseEBE7F91F": { + "Type": "AWS::Events::Rule", + "Properties": { + "EventPattern": { + "account": [ + { + "anything-but": { + "equals-ignore-case": [ + "account1", + "account2" + ] + } + } + ] + }, + "State": "ENABLED" + } + }, + "MyPrefixEqualsIgnoreCaseC9726B40": { + "Type": "AWS::Events::Rule", + "Properties": { + "EventPattern": { + "account": [ + { + "prefix": { + "equals-ignore-case": "prefix-" + } + } + ] + }, + "State": "ENABLED" + } + }, + "MySuffixEqualsIgnoreCaseBE2DDE03": { + "Type": "AWS::Events::Rule", + "Properties": { + "EventPattern": { + "account": [ + { + "suffix": { + "equals-ignore-case": "-suffix" + } + } + ] + }, + "State": "ENABLED" + } } }, "Parameters": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/cdk.out index 8ecc185e9dbee..c6e612584e352 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/integ.json index 3716c914b03f1..6b1bd909d381f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "38.0.1", "testCases": { "IntegTest-BatchDefaultEnvVarsStack/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/manifest.json index 4117383bdd483..0db2d9480cad8 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "38.0.1", "artifacts": { "RuleStack.assets": { "type": "cdk:asset-manifest", @@ -14,10 +14,12 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "RuleStack.template.json", + "terminationProtection": false, "validateOnSynth": false, + "notificationArns": [], "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}/f9728b2d2c64ff638563c8cc4a3e8eb9ddf3074e2ae01d68fde11aeda0968fb1.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/48862253eb1fed012c1b274795624b9ddc15444520044ea09a9ecd3ed2f4c300.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -39,6 +41,48 @@ "data": "MyRuleA44AB831" } ], + "/RuleStack/MyWildcardRule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyWildcardRule477FB0F9" + } + ], + "/RuleStack/MyAnythingButPrefixRule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyAnythingButPrefixRule756FC7C6" + } + ], + "/RuleStack/MyAnythingButSuffixRule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyAnythingButSuffixRuleB1E496DF" + } + ], + "/RuleStack/MyAnythingButWildcardRule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyAnythingButWildcardRuleEED7F44B" + } + ], + "/RuleStack/MyAnythingButEqualsIgnoreCase/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyAnythingButEqualsIgnoreCaseEBE7F91F" + } + ], + "/RuleStack/MyPrefixEqualsIgnoreCase/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyPrefixEqualsIgnoreCaseC9726B40" + } + ], + "/RuleStack/MySuffixEqualsIgnoreCase/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MySuffixEqualsIgnoreCaseBE2DDE03" + } + ], "/RuleStack/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -67,7 +111,9 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "IntegTestBatchDefaultEnvVarsStackDefaultTestDeployAssertC15EFFF2.template.json", + "terminationProtection": false, "validateOnSynth": false, + "notificationArns": [], "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", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/tree.json index f68ebe1fc832e..137538f70ceab 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.js.snapshot/tree.json @@ -165,36 +165,268 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/aws-events.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-events.Rule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "MyWildcardRule": { + "id": "MyWildcardRule", + "path": "RuleStack/MyWildcardRule", + "children": { + "Resource": { + "id": "Resource", + "path": "RuleStack/MyWildcardRule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "eventPattern": { + "account": [ + { + "wildcard": "account*" + } + ] + }, + "state": "ENABLED" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "MyAnythingButPrefixRule": { + "id": "MyAnythingButPrefixRule", + "path": "RuleStack/MyAnythingButPrefixRule", + "children": { + "Resource": { + "id": "Resource", + "path": "RuleStack/MyAnythingButPrefixRule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "eventPattern": { + "account": [ + { + "anything-but": { + "prefix": "prefix-" + } + } + ] + }, + "state": "ENABLED" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "MyAnythingButSuffixRule": { + "id": "MyAnythingButSuffixRule", + "path": "RuleStack/MyAnythingButSuffixRule", + "children": { + "Resource": { + "id": "Resource", + "path": "RuleStack/MyAnythingButSuffixRule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "eventPattern": { + "account": [ + { + "anything-but": { + "suffix": "-suffix" + } + } + ] + }, + "state": "ENABLED" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "MyAnythingButWildcardRule": { + "id": "MyAnythingButWildcardRule", + "path": "RuleStack/MyAnythingButWildcardRule", + "children": { + "Resource": { + "id": "Resource", + "path": "RuleStack/MyAnythingButWildcardRule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "eventPattern": { + "account": [ + { + "anything-but": { + "wildcard": "account*" + } + } + ] + }, + "state": "ENABLED" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "MyAnythingButEqualsIgnoreCase": { + "id": "MyAnythingButEqualsIgnoreCase", + "path": "RuleStack/MyAnythingButEqualsIgnoreCase", + "children": { + "Resource": { + "id": "Resource", + "path": "RuleStack/MyAnythingButEqualsIgnoreCase/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "eventPattern": { + "account": [ + { + "anything-but": { + "equals-ignore-case": [ + "account1", + "account2" + ] + } + } + ] + }, + "state": "ENABLED" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "MyPrefixEqualsIgnoreCase": { + "id": "MyPrefixEqualsIgnoreCase", + "path": "RuleStack/MyPrefixEqualsIgnoreCase", + "children": { + "Resource": { + "id": "Resource", + "path": "RuleStack/MyPrefixEqualsIgnoreCase/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "eventPattern": { + "account": [ + { + "prefix": { + "equals-ignore-case": "prefix-" + } + } + ] + }, + "state": "ENABLED" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "MySuffixEqualsIgnoreCase": { + "id": "MySuffixEqualsIgnoreCase", + "path": "RuleStack/MySuffixEqualsIgnoreCase", + "children": { + "Resource": { + "id": "Resource", + "path": "RuleStack/MySuffixEqualsIgnoreCase/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "eventPattern": { + "account": [ + { + "suffix": { + "equals-ignore-case": "-suffix" + } + } + ] + }, + "state": "ENABLED" + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" } }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "RuleStack/BootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "RuleStack/CheckBootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } }, "IntegTest-BatchDefaultEnvVarsStack": { @@ -210,7 +442,7 @@ "path": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.154" + "version": "10.4.2" } }, "DeployAssert": { @@ -221,33 +453,33 @@ "id": "BootstrapVersion", "path": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert/BootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } }, "CheckBootstrapVersion": { "id": "CheckBootstrapVersion", "path": "IntegTest-BatchDefaultEnvVarsStack/DefaultTest/DeployAssert/CheckBootstrapVersion", "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } } }, "constructInfo": { - "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/integ-tests.IntegTest", + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", "version": "0.0.0" } }, @@ -256,13 +488,13 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.154" + "version": "10.4.2" } } }, "constructInfo": { - "fqn": "@aws-cdk/core.App", - "version": "0.0.0" + "fqn": "constructs.Construct", + "version": "10.4.2" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.ts index 958e3d9d1694b..64a6fa77ddb51 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events/test/integ.rule.ts @@ -41,6 +41,48 @@ new Rule(stack, 'MyRule', { }, }); +new Rule(stack, 'MyWildcardRule', { + eventPattern: { + account: Match.wildcard('account*'), + }, +}); + +new Rule(stack, 'MyAnythingButPrefixRule', { + eventPattern: { + account: Match.anythingButPrefix('prefix-'), + }, +}); + +new Rule(stack, 'MyAnythingButSuffixRule', { + eventPattern: { + account: Match.anythingButSuffix('-suffix'), + }, +}); + +new Rule(stack, 'MyAnythingButWildcardRule', { + eventPattern: { + account: Match.anythingButWildcard('account*'), + }, +}); + +new Rule(stack, 'MyAnythingButEqualsIgnoreCase', { + eventPattern: { + account: Match.anythingButEqualsIgnoreCase('account1', 'account2'), + }, +}); + +new Rule(stack, 'MyPrefixEqualsIgnoreCase', { + eventPattern: { + account: Match.prefixEqualsIgnoreCase('prefix-'), + }, +}); + +new Rule(stack, 'MySuffixEqualsIgnoreCase', { + eventPattern: { + account: Match.suffixEqualsIgnoreCase('-suffix'), + }, +}); + new IntegTest(app, 'IntegTest-BatchDefaultEnvVarsStack', { testCases: [stack], }); diff --git a/packages/aws-cdk-lib/aws-events/README.md b/packages/aws-cdk-lib/aws-events/README.md index 9a8af87acee4c..a4bc633b94b2f 100644 --- a/packages/aws-cdk-lib/aws-events/README.md +++ b/packages/aws-cdk-lib/aws-events/README.md @@ -91,7 +91,12 @@ onCommitRule.addTarget(new targets.SnsTopic(topic, { })); ``` -To define a pattern, use the matcher API, which provides a number of factory methods to declare different logical predicates. For example, to match all S3 events for objects larger than 1024 bytes, stored using one of the storage classes Glacier, Glacier IR or Deep Archive and coming from any region other than the AWS GovCloud ones: +### Matchers + +To define a pattern, use the `Match` class, which provides a number of factory methods to declare +different logical predicates. For example, to match all S3 events for objects larger than 1024 +bytes, stored using one of the storage classes Glacier, Glacier IR or Deep Archive and coming from +any region other than the AWS GovCloud ones: ```ts const rule = new events.Rule(this, 'rule', { @@ -104,11 +109,10 @@ const rule = new events.Rule(this, 'rule', { // 'OR' condition 'source-storage-class': events.Match.anyOf( - events.Match.prefix("GLACIER"), + events.Match.prefix('GLACIER'), events.Match.exactString('DEEP_ARCHIVE'), ), }, - detailType: events.Match.equalsIgnoreCase('object created'), // If you prefer, you can use a low level array of strings, as directly consumed by EventBridge source: ['aws.s3'], @@ -118,6 +122,52 @@ const rule = new events.Rule(this, 'rule', { }); ``` +Matches can also be made case-insensitive, or make use of wildcard matches. For example, to match +object create events for buckets whose name starts with `raw-`, for objects with key matching +the pattern `path/to/object/*.txt` and the requester ends with `.AMAZONAWS.COM`: + +```ts +const rule = new events.Rule(this, 'rule', { + eventPattern: { + detail: { + bucket: { + name: events.Match.prefixEqualsIgnoreCase('raw-'), + }, + + object: { + key: events.Match.wildcard('path/to/object/*.txt'), + }, + + requester: events.Match.suffixEqualsIgnoreCase('.AMAZONAWS.COM'), + }, + detailType: events.Match.equalsIgnoreCase('object created'), + }, +}); +``` + +The "anything but" matchers allow you to specify multiple arguments. For example: + +```ts +const rule = new events.Rule(this, 'rule', { + eventPattern: { + region: events.Match.anythingBut('us-east-1', 'us-east-2', 'us-west-1', 'us-west-2'), + + detail: { + bucket: { + name: events.Match.anythingButPrefix('foo', 'bar', 'baz'), + }, + + object: { + key: events.Match.anythingButSuffix('.gif', '.png', '.jpg'), + }, + + requester: events.Match.anythingButWildcard('*.amazonaws.com', '123456789012'), + }, + detailType: events.Match.anythingButEqualsIgnoreCase('object created', 'object deleted'), + }, +}); +``` + ## Scheduling You can configure a Rule to run on a schedule (cron or rate). @@ -271,4 +321,3 @@ new events.EventBus(this, 'Bus', { **Note**: Archives and schema discovery are not supported for event buses encrypted using a customer managed key. To enable archives or schema discovery on an event bus, choose to use an AWS owned key. 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). - diff --git a/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts b/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts index c4f37bdffe055..c9e6750814909 100644 --- a/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts +++ b/packages/aws-cdk-lib/aws-events/lib/event-pattern.ts @@ -65,6 +65,27 @@ export class Match implements IResolvable { return this.fromObjects([{ suffix: value }]); } + /** + * Matches strings with the given prefix in the JSON of the event regardless of the casing + */ + public static prefixEqualsIgnoreCase(value: string): string[] { + return this.fromObjects([{ prefix: { 'equals-ignore-case': value } }]); + } + + /** + * Matches strings with the given suffix in the JSON of the event regardless of the casing + */ + public static suffixEqualsIgnoreCase(value: string): string[] { + return this.fromObjects([{ suffix: { 'equals-ignore-case': value } }]); + } + + /** + * Matches strings with the given wildcard pattern in the JSON of the event + */ + public static wildcard(value: string): string[] { + return this.fromObjects([{ wildcard: value }]); + } + /** * Matches IPv4 and IPv6 network addresses using the Classless Inter-Domain Routing (CIDR) format */ @@ -109,8 +130,29 @@ export class Match implements IResolvable { /** * Matches any string that doesn't start with the given prefix. */ - public static anythingButPrefix(prefix: string): string[] { - return this.fromObjects([{ 'anything-but': { prefix: prefix } }]); + public static anythingButPrefix(...values: string[]): string[] { + return this.anythingButConjunction('prefix', values); + } + + /** + * Matches any string that doesn't end with the given suffix. + */ + public static anythingButSuffix(...values: string[]): string[] { + return this.anythingButConjunction('suffix', values); + } + + /** + * Matches any string that doesn't match with the given wildcard pattern. + */ + public static anythingButWildcard(...values: string[]): string[] { + return this.anythingButConjunction('wildcard', values); + } + + /** + * Matches any string that doesn't match with the given value regardless of character casing. + */ + public static anythingButEqualsIgnoreCase(...values: string[]): string[] { + return this.anythingButConjunction('equals-ignore-case', values); } /** @@ -185,6 +227,17 @@ export class Match implements IResolvable { return this.fromObjects(matchers); } + private static anythingButConjunction(filterKey: string, values: string[]): string[] { + if (values.length === 0) { + throw new Error('anythingBut matchers must be non-empty lists'); + } + + // When there is a single value return it, otherwise return the array + const filterValue = values.length === 1 ? values[0] : values; + + return this.fromObjects([{ 'anything-but': { [filterKey]: filterValue } }]); + } + private static numeric(operator: ComparisonOperator, value: number): string[] { return this.fromObjects([{ numeric: [operator, value] }]); } diff --git a/packages/aws-cdk-lib/aws-events/test/matchers.test.ts b/packages/aws-cdk-lib/aws-events/test/matchers.test.ts index cdda43b3c1a1a..b9f9fe24a8403 100644 --- a/packages/aws-cdk-lib/aws-events/test/matchers.test.ts +++ b/packages/aws-cdk-lib/aws-events/test/matchers.test.ts @@ -23,6 +23,48 @@ describe(Match, () => { expect(stack.resolve(Match.anythingButPrefix('foo'))).toEqual([ { 'anything-but': { prefix: 'foo' } }, ]); + + expect(stack.resolve(Match.anythingButPrefix('foo', 'bar'))).toEqual([ + { 'anything-but': { prefix: ['foo', 'bar'] } }, + ]); + + expect(() => stack.resolve(Match.anythingButPrefix())).toThrowError(/must be non-empty lists/); + }); + + test('anythingButSuffix', () => { + expect(stack.resolve(Match.anythingButSuffix('foo'))).toEqual([ + { 'anything-but': { suffix: 'foo' } }, + ]); + + expect(stack.resolve(Match.anythingButSuffix('foo', 'bar'))).toEqual([ + { 'anything-but': { suffix: ['foo', 'bar'] } }, + ]); + + expect(() => stack.resolve(Match.anythingButPrefix())).toThrowError(/must be non-empty lists/); + }); + + test('anythingButWildcard', () => { + expect(stack.resolve(Match.anythingButWildcard('*.txt'))).toEqual([ + { 'anything-but': { wildcard: '*.txt' } }, + ]); + + expect(stack.resolve(Match.anythingButWildcard('*.txt', '*.json'))).toEqual([ + { 'anything-but': { wildcard: ['*.txt', '*.json'] } }, + ]); + + expect(() => stack.resolve(Match.anythingButPrefix())).toThrowError(/must be non-empty lists/); + }); + + test('anythingButEqualsIgnoreCase', () => { + expect(stack.resolve(Match.anythingButEqualsIgnoreCase('foo'))).toEqual([ + { 'anything-but': { 'equals-ignore-case': 'foo' } }, + ]); + + expect(stack.resolve(Match.anythingButEqualsIgnoreCase('foo', 'bar'))).toEqual([ + { 'anything-but': { 'equals-ignore-case': ['foo', 'bar'] } }, + ]); + + expect(() => stack.resolve(Match.anythingButPrefix())).toThrowError(/must be non-empty lists/); }); test('numeric', () => { @@ -77,6 +119,24 @@ describe(Match, () => { ]); }); + test('prefixEqualsIgnoreCase', () => { + expect(stack.resolve(Match.prefixEqualsIgnoreCase('foo'))).toEqual([ + { prefix: { 'equals-ignore-case': 'foo' } }, + ]); + }); + + test('suffixEqualsIgnoreCase', () => { + expect(stack.resolve(Match.suffixEqualsIgnoreCase('foo'))).toEqual([ + { suffix: { 'equals-ignore-case': 'foo' } }, + ]); + }); + + test('wildcard', () => { + expect(stack.resolve(Match.wildcard('*.json'))).toEqual([ + { wildcard: '*.json' }, + ]); + }); + test('equalsIgnoreCase', () => { expect(stack.resolve(Match.equalsIgnoreCase('foo'))).toEqual([ { 'equals-ignore-case': 'foo' },