From 16820d7c0bb389a48bd0dee8aff042f87b890fe0 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Wed, 30 Sep 2020 07:21:36 +0000 Subject: [PATCH 01/14] feat(aws-events-targets): add CloudWatch LogGroup Target --- .../@aws-cdk/aws-events-targets/README.md | 26 ++++++++ .../@aws-cdk/aws-events-targets/lib/index.ts | 1 + .../aws-events-targets/lib/log-group.ts | 34 ++++++++++ .../@aws-cdk/aws-events-targets/package.json | 12 ++-- .../test/logs/integ.log-group.expected.json | 54 ++++++++++++++++ .../test/logs/integ.log-group.ts | 27 ++++++++ .../test/logs/log-group.test.ts | 64 +++++++++++++++++++ packages/@aws-cdk/aws-events/README.md | 2 +- 8 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 packages/@aws-cdk/aws-events-targets/lib/log-group.ts create mode 100644 packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json create mode 100644 packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts create mode 100644 packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index 686c26c270bbc..d3ef65a2a6809 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -23,7 +23,33 @@ Currently supported are: * Queue a Batch job * Make an AWS API call * Put a record to a Kinesis stream +* Log an event into a LogGroup See the README of the `@aws-cdk/aws-events` library for more information on EventBridge. +## LogGroup + +Use the `LogGroup` target to log your events in a CloudWatch LogGroup. + +```ts +const rule = new Rule(this, 'rule'); + +const logGroup = new LogGroup(this, 'logGroup'); + +rule.addTarget(targets.LogGroup(logGroup)); +``` + +You can also use an [InputTransformer](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_InputTransformer.html). + +```ts +const rule = new Rule(this, 'rule'); + +const logGroup = new LogGroup(this, 'logGroup'); + +rule.addTarget(targets.LogGroup(logGroup, { + event: events.RuleTargetInput.fromObject({ + data: events.EventField.fromPath('$.detail.data'), + }) +})); +``` \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/lib/index.ts b/packages/@aws-cdk/aws-events-targets/lib/index.ts index 7031423e6b739..ebebfe3a3058b 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/index.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/index.ts @@ -9,3 +9,4 @@ export * from './ecs-task-properties'; export * from './ecs-task'; export * from './state-machine'; export * from './kinesis-stream'; +export * from './log-group'; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts new file mode 100644 index 0000000000000..8427c1f90f1f2 --- /dev/null +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -0,0 +1,34 @@ +import * as events from '@aws-cdk/aws-events'; +import * as logs from '@aws-cdk/aws-logs'; +/** + * Customize the CloudWatch LogGroup Event Target + */ +export interface LogGroupProps { + /** + * The event to send to the CloudWatch LogGroup + * + * This will be the event logged into the CloudWatch LogGroup + * + * @default - the entire EventBridge event + */ + readonly event?: events.RuleTargetInput; +} + +/** + * Use an AWS CloudWatch LogGroup as an event rule target + */ +export class LogGroup implements events.IRuleTarget { + constructor(private readonly handler: logs.ILogGroup, private readonly props: LogGroupProps = {}) {} + + /** + * Returns a RuleTarget that can be used to log an event into a CloudWatch LogGroup + */ + public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig { + return { + id: '', + arn: this.handler.logGroupArn, + input: this.props.event, + targetResource: this.handler, + }; + } +} diff --git a/packages/@aws-cdk/aws-events-targets/package.json b/packages/@aws-cdk/aws-events-targets/package.json index 80a1d52f9240b..3859c8514e58c 100644 --- a/packages/@aws-cdk/aws-events-targets/package.json +++ b/packages/@aws-cdk/aws-events-targets/package.json @@ -77,39 +77,41 @@ "pkglint": "0.0.0" }, "dependencies": { + "@aws-cdk/aws-batch": "0.0.0", "@aws-cdk/aws-codebuild": "0.0.0", "@aws-cdk/aws-codepipeline": "0.0.0", "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-ecs": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sns-subscriptions": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/aws-stepfunctions": "0.0.0", - "@aws-cdk/aws-batch": "0.0.0", - "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/core": "0.0.0", "constructs": "^3.0.4" }, "homepage": "https://github.com/aws/aws-cdk", "peerDependencies": { + "@aws-cdk/aws-batch": "0.0.0", "@aws-cdk/aws-codebuild": "0.0.0", "@aws-cdk/aws-codepipeline": "0.0.0", "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/aws-ecs": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sns-subscriptions": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/aws-stepfunctions": "0.0.0", - "@aws-cdk/aws-batch": "0.0.0", "@aws-cdk/core": "0.0.0", - "constructs": "^3.0.4", - "@aws-cdk/aws-kinesis": "0.0.0" + "constructs": "^3.0.4" }, "engines": { "node": ">= 10.13.0 <13 || >=13.7.0" diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json new file mode 100644 index 0000000000000..520bb9b53d744 --- /dev/null +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json @@ -0,0 +1,54 @@ +{ + "Resources": { + "loggroupB02AAEB1": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "RetentionInDays": 731 + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "TimerBF6F831F": { + "Type": "AWS::Events::Rule", + "Properties": { + "ScheduleExpression": "rate(1 minute)", + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "loggroupB02AAEB1", + "Arn" + ] + }, + "Id": "Target0" + } + ] + } + }, + "Timer2B6F162E9": { + "Type": "AWS::Events::Rule", + "Properties": { + "ScheduleExpression": "rate(2 minutes)", + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "loggroupB02AAEB1", + "Arn" + ] + }, + "Id": "Target0", + "InputTransformer": { + "InputPathsMap": { + "f1": "$" + }, + "InputTemplate": "{\"data\":}" + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts new file mode 100644 index 0000000000000..65934941ae6dd --- /dev/null +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts @@ -0,0 +1,27 @@ +import * as events from '@aws-cdk/aws-events'; +import * as logs from '@aws-cdk/aws-logs'; +import * as cdk from '@aws-cdk/core'; +import * as targets from '../../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'log-group-events'); + +const logGroup = new logs.LogGroup(stack, 'log-group'); + +const timer = new events.Rule(stack, 'Timer', { + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), +}); +timer.addTarget(new targets.LogGroup(logGroup)); + +const timer2 = new events.Rule(stack, 'Timer2', { + schedule: events.Schedule.rate(cdk.Duration.minutes(2)), +}); +timer2.addTarget(new targets.LogGroup(logGroup, { + event: events.RuleTargetInput.fromObject({ + data: events.EventField.fromPath('$'), + }), +})); + +app.synth(); + diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts new file mode 100644 index 0000000000000..ffe7abda24162 --- /dev/null +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts @@ -0,0 +1,64 @@ +import { expect, haveResource } from '@aws-cdk/assert'; +import * as events from '@aws-cdk/aws-events'; +import * as logs from '@aws-cdk/aws-logs'; +import * as cdk from '@aws-cdk/core'; +import * as targets from '../../lib'; + + +test('use log group as an event rule target', () => { + // GIVEN + const stack = new cdk.Stack(); + const logGroup = new logs.LogGroup(stack, 'MyLogGroup'); + const rule1 = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), + }); + + // WHEN + rule1.addTarget(new targets.LogGroup(logGroup)); + + // THEN + expect(stack).to(haveResource('AWS::Events::Rule', { + ScheduleExpression: 'rate(1 minute)', + State: 'ENABLED', + Targets: [ + { + Arn: { 'Fn::GetAtt': ['MyLogGroup5C0DAD85', 'Arn'] }, + Id: 'Target0', + }, + ], + })); +}); + +test('use log group as an event rule target with rule target input', () => { + // GIVEN + const stack = new cdk.Stack(); + const logGroup = new logs.LogGroup(stack, 'MyLogGroup'); + const rule1 = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), + }); + + // WHEN + rule1.addTarget(new targets.LogGroup(logGroup, { + event: events.RuleTargetInput.fromObject({ + data: events.EventField.fromPath('$'), + }), + })); + + // THEN + expect(stack).to(haveResource('AWS::Events::Rule', { + ScheduleExpression: 'rate(1 minute)', + State: 'ENABLED', + Targets: [ + { + Arn: { 'Fn::GetAtt': ['MyLogGroup5C0DAD85', 'Arn'] }, + Id: 'Target0', + InputTransformer: { + InputPathsMap: { + f1: '$', + }, + InputTemplate: '{"data":}', + }, + }, + ], + })); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events/README.md b/packages/@aws-cdk/aws-events/README.md index 3c0782339b665..77263d685eb67 100644 --- a/packages/@aws-cdk/aws-events/README.md +++ b/packages/@aws-cdk/aws-events/README.md @@ -28,7 +28,7 @@ event when the pipeline changes it's state. Service](https://docs.aws.amazon.com/eventbridge/latest/userguide/event-types.html). * __Targets__: A target processes events. Targets can include Amazon EC2 instances, AWS Lambda functions, Kinesis streams, Amazon ECS tasks, Step - Functions state machines, Amazon SNS topics, Amazon SQS queues, and built-in + Functions state machines, Amazon SNS topics, Amazon SQS queues, Amazon CloudWatch LogGroups, and built-in targets. A target receives events in JSON format. * __Rules__: A rule matches incoming events and routes them to targets for processing. A single rule can route to multiple targets, all of which are From 1ebf625e75c23f6010b0b6193ada952dd761fee5 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Thu, 1 Oct 2020 02:01:27 +0000 Subject: [PATCH 02/14] Rename handler prop to logGroup and add documentation about LogGroup name required prefix --- .../@aws-cdk/aws-events-targets/README.md | 13 +++-- .../aws-events-targets/lib/log-group.ts | 9 ++-- .../test/logs/integ.log-group.expected.json | 39 ++++++++++++--- .../test/logs/integ.log-group.ts | 4 +- .../test/logs/log-group.test.ts | 48 +++++++++++++++++-- 5 files changed, 95 insertions(+), 18 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index d3ef65a2a6809..65a77d550c58d 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -32,10 +32,14 @@ EventBridge. Use the `LogGroup` target to log your events in a CloudWatch LogGroup. +The LogGroup name must start with `/aws/events/`. + ```ts const rule = new Rule(this, 'rule'); -const logGroup = new LogGroup(this, 'logGroup'); +const logGroup = new LogGroup(this, 'MyLogGroup', { + logGroupName: '/aws/events/MyLogGroup', +}); rule.addTarget(targets.LogGroup(logGroup)); ``` @@ -45,11 +49,14 @@ You can also use an [InputTransformer](https://docs.aws.amazon.com/eventbridge/l ```ts const rule = new Rule(this, 'rule'); -const logGroup = new LogGroup(this, 'logGroup'); +const logGroup = new LogGroup(this, 'MyLogGroup', { + logGroupName: '/aws/events/MyLogGroup', +}); rule.addTarget(targets.LogGroup(logGroup, { event: events.RuleTargetInput.fromObject({ - data: events.EventField.fromPath('$.detail.data'), + status: events.EventField.fromPath('$.detail.status'), + instanceId: events.EventField.fromPath('$.detail.instance-id'), }) })); ``` \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts index 8427c1f90f1f2..99789688346a1 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -15,10 +15,12 @@ export interface LogGroupProps { } /** - * Use an AWS CloudWatch LogGroup as an event rule target + * Use an AWS CloudWatch LogGroup as an event rule target. + * + * The LogGroup name must start with /aws/events/. */ export class LogGroup implements events.IRuleTarget { - constructor(private readonly handler: logs.ILogGroup, private readonly props: LogGroupProps = {}) {} + constructor(private readonly logGroup: logs.ILogGroup, private readonly props: LogGroupProps = {}) {} /** * Returns a RuleTarget that can be used to log an event into a CloudWatch LogGroup @@ -26,9 +28,8 @@ export class LogGroup implements events.IRuleTarget { public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig { return { id: '', - arn: this.handler.logGroupArn, + arn: `arn:aws:logs:${this.logGroup.stack.region}:${this.logGroup.stack.account}:log-group:${this.logGroup.logGroupName}`, input: this.props.event, - targetResource: this.handler, }; } } diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json index 520bb9b53d744..95297d0c0f623 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json @@ -3,6 +3,7 @@ "loggroupB02AAEB1": { "Type": "AWS::Logs::LogGroup", "Properties": { + "LogGroupName": "/aws/events/MyLogGroupName", "RetentionInDays": 731 }, "UpdateReplacePolicy": "Retain", @@ -16,9 +17,22 @@ "Targets": [ { "Arn": { - "Fn::GetAtt": [ - "loggroupB02AAEB1", - "Arn" + "Fn::Join": [ + "", + [ + "arn:aws:logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:", + { + "Ref": "loggroupB02AAEB1" + } + ] ] }, "Id": "Target0" @@ -34,9 +48,22 @@ "Targets": [ { "Arn": { - "Fn::GetAtt": [ - "loggroupB02AAEB1", - "Arn" + "Fn::Join": [ + "", + [ + "arn:aws:logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:", + { + "Ref": "loggroupB02AAEB1" + } + ] ] }, "Id": "Target0", diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts index 65934941ae6dd..a9c363b39e294 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts @@ -7,7 +7,9 @@ const app = new cdk.App(); const stack = new cdk.Stack(app, 'log-group-events'); -const logGroup = new logs.LogGroup(stack, 'log-group'); +const logGroup = new logs.LogGroup(stack, 'log-group', { + logGroupName: '/aws/events/MyLogGroupName', +}); const timer = new events.Rule(stack, 'Timer', { schedule: events.Schedule.rate(cdk.Duration.minutes(1)), diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts index ffe7abda24162..acc56f994072e 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts @@ -8,7 +8,9 @@ import * as targets from '../../lib'; test('use log group as an event rule target', () => { // GIVEN const stack = new cdk.Stack(); - const logGroup = new logs.LogGroup(stack, 'MyLogGroup'); + const logGroup = new logs.LogGroup(stack, 'MyLogGroup', { + logGroupName: '/aws/events/MyLogGroup', + }); const rule1 = new events.Rule(stack, 'Rule', { schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); @@ -22,7 +24,25 @@ test('use log group as an event rule target', () => { State: 'ENABLED', Targets: [ { - Arn: { 'Fn::GetAtt': ['MyLogGroup5C0DAD85', 'Arn'] }, + Arn: { + 'Fn::Join': [ + '', + [ + 'arn:aws:logs:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':log-group:', + { + Ref: 'MyLogGroup5C0DAD85', + }, + ], + ], + }, Id: 'Target0', }, ], @@ -32,7 +52,9 @@ test('use log group as an event rule target', () => { test('use log group as an event rule target with rule target input', () => { // GIVEN const stack = new cdk.Stack(); - const logGroup = new logs.LogGroup(stack, 'MyLogGroup'); + const logGroup = new logs.LogGroup(stack, 'MyLogGroup', { + logGroupName: '/aws/events/MyLogGroup', + }); const rule1 = new events.Rule(stack, 'Rule', { schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); @@ -50,7 +72,25 @@ test('use log group as an event rule target with rule target input', () => { State: 'ENABLED', Targets: [ { - Arn: { 'Fn::GetAtt': ['MyLogGroup5C0DAD85', 'Arn'] }, + Arn: { + 'Fn::Join': [ + '', + [ + 'arn:aws:logs:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':log-group:', + { + Ref: 'MyLogGroup5C0DAD85', + }, + ], + ], + }, Id: 'Target0', InputTransformer: { InputPathsMap: { From ba11ea0e51c3c7ae93b756f32713d93f3eafbe01 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Fri, 9 Oct 2020 00:22:33 -0700 Subject: [PATCH 03/14] Add log group name validation --- .../aws-events-targets/lib/log-group.ts | 5 +++ .../test/logs/log-group.test.ts | 31 +++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts index 99789688346a1..729cec88c7229 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -1,5 +1,6 @@ import * as events from '@aws-cdk/aws-events'; import * as logs from '@aws-cdk/aws-logs'; +import { Token } from '@aws-cdk/core'; /** * Customize the CloudWatch LogGroup Event Target */ @@ -26,6 +27,10 @@ export class LogGroup implements events.IRuleTarget { * Returns a RuleTarget that can be used to log an event into a CloudWatch LogGroup */ public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig { + if (!Token.isUnresolved(this.logGroup.logGroupName) && !this.logGroup.logGroupName.startsWith('/aws/events/')) { + throw new Error('Target LogGroup name must start with "/aws/events/"'); + } + return { id: '', arn: `arn:aws:logs:${this.logGroup.stack.region}:${this.logGroup.stack.account}:log-group:${this.logGroup.logGroupName}`, diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts index acc56f994072e..8033e21419cfc 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts @@ -1,4 +1,4 @@ -import { expect, haveResource } from '@aws-cdk/assert'; +import '@aws-cdk/assert/jest'; import * as events from '@aws-cdk/aws-events'; import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; @@ -19,7 +19,7 @@ test('use log group as an event rule target', () => { rule1.addTarget(new targets.LogGroup(logGroup)); // THEN - expect(stack).to(haveResource('AWS::Events::Rule', { + expect(stack).toHaveResource('AWS::Events::Rule', { ScheduleExpression: 'rate(1 minute)', State: 'ENABLED', Targets: [ @@ -46,7 +46,26 @@ test('use log group as an event rule target', () => { Id: 'Target0', }, ], - })); + }); +}); + + +test.only('log group used as an event rule target must have a name starting with "/aws/events/"', () => { + // GIVEN + const logGroupName = '/awdss/events/MyLogGroup'; + const stack = new cdk.Stack(); + + const rule1 = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), + }); + + // WHEN + let addTargetWrapper = () => { + rule1.addTarget(new targets.LogGroup(logs.LogGroup.fromLogGroupName(stack, 'MyLogGroupImported', logGroupName))); + }; + + // THEN + expect(addTargetWrapper).toThrowError('Target LogGroup name must start with "/aws/events/"'); }); test('use log group as an event rule target with rule target input', () => { @@ -67,7 +86,7 @@ test('use log group as an event rule target with rule target input', () => { })); // THEN - expect(stack).to(haveResource('AWS::Events::Rule', { + expect(stack).toHaveResource('AWS::Events::Rule', { ScheduleExpression: 'rate(1 minute)', State: 'ENABLED', Targets: [ @@ -100,5 +119,5 @@ test('use log group as an event rule target with rule target input', () => { }, }, ], - })); -}); \ No newline at end of file + }); +}); From 30c045ac44d820e9efd50d3510dbfd8f367babca Mon Sep 17 00:00:00 2001 From: DaWyz Date: Fri, 9 Oct 2020 11:18:57 -0700 Subject: [PATCH 04/14] Fixing documentation --- packages/@aws-cdk/aws-events-targets/README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index 65a77d550c58d..0f25bb810eaa4 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -35,7 +35,11 @@ Use the `LogGroup` target to log your events in a CloudWatch LogGroup. The LogGroup name must start with `/aws/events/`. ```ts -const rule = new Rule(this, 'rule'); +const rule = new Rule(this, 'rule', { + eventPattern: { + source: [stack.account], + }, +}); const logGroup = new LogGroup(this, 'MyLogGroup', { logGroupName: '/aws/events/MyLogGroup', @@ -47,16 +51,20 @@ rule.addTarget(targets.LogGroup(logGroup)); You can also use an [InputTransformer](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_InputTransformer.html). ```ts -const rule = new Rule(this, 'rule'); +const rule = new Rule(this, 'rule', { + eventPattern: { + source: [stack.account], + }, +}); const logGroup = new LogGroup(this, 'MyLogGroup', { logGroupName: '/aws/events/MyLogGroup', }); -rule.addTarget(targets.LogGroup(logGroup, { +rule.addTarget(new targets.LogGroup(logGroup, { event: events.RuleTargetInput.fromObject({ status: events.EventField.fromPath('$.detail.status'), instanceId: events.EventField.fromPath('$.detail.instance-id'), }) })); -``` \ No newline at end of file +``` From b970107a44eac5a57c7e19debbed7a2e5f5adb84 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sun, 25 Oct 2020 15:08:09 -0700 Subject: [PATCH 05/14] Add support for resource policy for LogGroup --- .../@aws-cdk/aws-events-targets/README.md | 6 +- .../lib/log-group-resource-policy.ts | 50 +++ .../aws-events-targets/lib/log-group.ts | 22 +- .../@aws-cdk/aws-events-targets/package.json | 2 + .../test/logs/integ.log-group.expected.json | 379 +++++++++++++++++- .../test/logs/integ.log-group.ts | 12 +- .../logs/log-group-resource-policy.test.ts | 65 +++ .../test/logs/log-group.test.ts | 19 - 8 files changed, 520 insertions(+), 35 deletions(-) create mode 100644 packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts create mode 100644 packages/@aws-cdk/aws-events-targets/test/logs/log-group-resource-policy.test.ts diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index 5d5ca536460d1..2cdf880d56cb1 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -33,8 +33,6 @@ EventBridge. Use the `LogGroup` target to log your events in a CloudWatch LogGroup. -The LogGroup name must start with `/aws/events/`. - ```ts const rule = new Rule(this, 'rule', { eventPattern: { @@ -43,7 +41,7 @@ const rule = new Rule(this, 'rule', { }); const logGroup = new LogGroup(this, 'MyLogGroup', { - logGroupName: '/aws/events/MyLogGroup', + logGroupName: 'MyLogGroup', }); rule.addTarget(targets.LogGroup(logGroup)); @@ -59,7 +57,7 @@ const rule = new Rule(this, 'rule', { }); const logGroup = new LogGroup(this, 'MyLogGroup', { - logGroupName: '/aws/events/MyLogGroup', + logGroupName: 'MyLogGroup', }); rule.addTarget(new targets.LogGroup(logGroup, { diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts new file mode 100644 index 0000000000000..949f03aa61baa --- /dev/null +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts @@ -0,0 +1,50 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as cdk from '@aws-cdk/core'; +import * as cr from '@aws-cdk/custom-resources'; + +/** + * Construction properties for LogGroupResourcePolicy + */ +export interface LogGroupResourcePolicyProps { + /** + * The log group resource policy name + */ + readonly policyName: string; + /** + * The policy statements for the log group resource logs + */ + readonly policyStatements: [iam.PolicyStatement]; +} + +/** + * Creates LogGroup resource policies. + */ +export class LogGroupResourcePolicy extends cr.AwsCustomResource { + constructor(scope: cdk.Construct, id: string, props: LogGroupResourcePolicyProps) { + const policyDocument = new iam.PolicyDocument({ + statements: props.policyStatements, + }); + + super(scope, id, { + resourceType: 'Custom::CloudwatchLogResourcePolicy', + onUpdate: { + service: 'CloudWatchLogs', + action: 'putResourcePolicy', + parameters: { + policyName: props.policyName, + policyDocument: JSON.stringify(policyDocument), + }, + physicalResourceId: cr.PhysicalResourceId.of(id), + }, + onDelete: { + service: 'CloudWatchLogs', + action: 'deleteResourcePolicy', + parameters: { + policyName: props.policyName, + }, + ignoreErrorCodesMatching: '400', + }, + policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: ['*'] }), + }); + } +} diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts index 729cec88c7229..d2c2a6e04b11a 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -1,6 +1,8 @@ import * as events from '@aws-cdk/aws-events'; +import * as iam from '@aws-cdk/aws-iam'; import * as logs from '@aws-cdk/aws-logs'; -import { Token } from '@aws-cdk/core'; +import * as cdk from '@aws-cdk/core'; +import { LogGroupResourcePolicy } from './log-group-resource-policy'; /** * Customize the CloudWatch LogGroup Event Target */ @@ -17,8 +19,6 @@ export interface LogGroupProps { /** * Use an AWS CloudWatch LogGroup as an event rule target. - * - * The LogGroup name must start with /aws/events/. */ export class LogGroup implements events.IRuleTarget { constructor(private readonly logGroup: logs.ILogGroup, private readonly props: LogGroupProps = {}) {} @@ -27,14 +27,26 @@ export class LogGroup implements events.IRuleTarget { * Returns a RuleTarget that can be used to log an event into a CloudWatch LogGroup */ public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig { - if (!Token.isUnresolved(this.logGroup.logGroupName) && !this.logGroup.logGroupName.startsWith('/aws/events/')) { - throw new Error('Target LogGroup name must start with "/aws/events/"'); + // Use a custom resource to set the log group resource policy since it is not supported by CDK and cfn. + // https://github.com/aws/aws-cdk/issues/5343 + const resourcePolicyId = `EventsLogGroupPolicy${_rule.node.uniqueId}`; + if (!this.logGroup.node.tryFindChild(resourcePolicyId)) { + new LogGroupResourcePolicy(cdk.Stack.of(this.logGroup), resourcePolicyId, { + policyName: `${this.logGroup.logGroupName}EventsLogPolicy`, + policyStatements: [new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['logs:PutLogEvents', 'logs:CreateLogStream'], + resources: [this.logGroup.logGroupArn], + principals: [new iam.ServicePrincipal('events.amazonaws.com')], + })], + }); } return { id: '', arn: `arn:aws:logs:${this.logGroup.stack.region}:${this.logGroup.stack.account}:log-group:${this.logGroup.logGroupName}`, input: this.props.event, + targetResource: this.logGroup, }; } } diff --git a/packages/@aws-cdk/aws-events-targets/package.json b/packages/@aws-cdk/aws-events-targets/package.json index 56fadd34d4f1f..2cdeeea56339a 100644 --- a/packages/@aws-cdk/aws-events-targets/package.json +++ b/packages/@aws-cdk/aws-events-targets/package.json @@ -99,6 +99,7 @@ "@aws-cdk/aws-sns-subscriptions": "0.0.0", "@aws-cdk/aws-stepfunctions": "0.0.0", "@aws-cdk/core": "0.0.0", + "@aws-cdk/custom-resources": "0.0.0", "constructs": "^3.0.4" }, "homepage": "https://github.com/aws/aws-cdk", @@ -119,6 +120,7 @@ "@aws-cdk/aws-sns-subscriptions": "0.0.0", "@aws-cdk/aws-stepfunctions": "0.0.0", "@aws-cdk/core": "0.0.0", + "@aws-cdk/custom-resources": "0.0.0", "constructs": "^3.0.4" }, "engines": { diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json index 95297d0c0f623..735469195af0d 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json @@ -3,11 +3,20 @@ "loggroupB02AAEB1": { "Type": "AWS::Logs::LogGroup", "Properties": { - "LogGroupName": "/aws/events/MyLogGroupName", + "LogGroupName": "MyLogGroupName", "RetentionInDays": 731 }, - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "loggroup2F19C5C9B": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "MyLogGroupName2", + "RetentionInDays": 731 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" }, "TimerBF6F831F": { "Type": "AWS::Events::Rule", @@ -40,6 +49,223 @@ ] } }, + "EventsLogGroupPolicyloggroupeventsTimerC63340B0CustomResourcePolicy67B796AA": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "logs:PutResourcePolicy", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "logs:DeleteResourcePolicy", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "EventsLogGroupPolicyloggroupeventsTimerC63340B0CustomResourcePolicy67B796AA", + "Roles": [ + { + "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" + } + ] + } + }, + "EventsLogGroupPolicyloggroupeventsTimerC63340B0C92153CD": { + "Type": "Custom::CloudwatchLogResourcePolicy", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "AWS679f53fac002430cb0da5b7982bd22872D164C4C", + "Arn" + ] + }, + "Create": { + "service": "CloudWatchLogs", + "action": "putResourcePolicy", + "parameters": { + "policyName": { + "Fn::Join": [ + "", + [ + { + "Ref": "loggroupB02AAEB1" + }, + "EventsLogPolicy" + ] + ] + }, + "policyDocument": { + "Fn::Join": [ + "", + [ + "{\"Statement\":[{\"Action\":[\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Resource\":\"", + { + "Fn::GetAtt": [ + "loggroupB02AAEB1", + "Arn" + ] + }, + "\"}],\"Version\":\"2012-10-17\"}" + ] + ] + } + }, + "physicalResourceId": { + "id": "EventsLogGroupPolicyloggroupeventsTimerC63340B0" + } + }, + "Update": { + "service": "CloudWatchLogs", + "action": "putResourcePolicy", + "parameters": { + "policyName": { + "Fn::Join": [ + "", + [ + { + "Ref": "loggroupB02AAEB1" + }, + "EventsLogPolicy" + ] + ] + }, + "policyDocument": { + "Fn::Join": [ + "", + [ + "{\"Statement\":[{\"Action\":[\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Resource\":\"", + { + "Fn::GetAtt": [ + "loggroupB02AAEB1", + "Arn" + ] + }, + "\"}],\"Version\":\"2012-10-17\"}" + ] + ] + } + }, + "physicalResourceId": { + "id": "EventsLogGroupPolicyloggroupeventsTimerC63340B0" + } + }, + "Delete": { + "service": "CloudWatchLogs", + "action": "deleteResourcePolicy", + "parameters": { + "policyName": { + "Fn::Join": [ + "", + [ + { + "Ref": "loggroupB02AAEB1" + }, + "EventsLogPolicy" + ] + ] + } + }, + "ignoreErrorCodesMatching": "400" + }, + "InstallLatestAwsSdk": true + }, + "DependsOn": [ + "EventsLogGroupPolicyloggroupeventsTimerC63340B0CustomResourcePolicy67B796AA" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2": { + "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" + ] + ] + } + ] + } + }, + "AWS679f53fac002430cb0da5b7982bd22872D164C4C": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Ref": "AssetParametersb64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94S3Bucket38F1BB8E" + }, + "S3Key": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 0, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersb64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94S3VersionKeyCCDC67C0" + } + ] + } + ] + }, + { + "Fn::Select": [ + 1, + { + "Fn::Split": [ + "||", + { + "Ref": "AssetParametersb64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94S3VersionKeyCCDC67C0" + } + ] + } + ] + } + ] + ] + } + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Timeout": 120 + }, + "DependsOn": [ + "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" + ] + }, "Timer2B6F162E9": { "Type": "AWS::Events::Rule", "Properties": { @@ -61,7 +287,7 @@ }, ":log-group:", { - "Ref": "loggroupB02AAEB1" + "Ref": "loggroup2F19C5C9B" } ] ] @@ -76,6 +302,151 @@ } ] } + }, + "EventsLogGroupPolicyloggroupeventsTimer289E3527ECustomResourcePolicy24E754C4": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "logs:PutResourcePolicy", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "logs:DeleteResourcePolicy", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "EventsLogGroupPolicyloggroupeventsTimer289E3527ECustomResourcePolicy24E754C4", + "Roles": [ + { + "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" + } + ] + } + }, + "EventsLogGroupPolicyloggroupeventsTimer289E3527E78608648": { + "Type": "Custom::CloudwatchLogResourcePolicy", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "AWS679f53fac002430cb0da5b7982bd22872D164C4C", + "Arn" + ] + }, + "Create": { + "service": "CloudWatchLogs", + "action": "putResourcePolicy", + "parameters": { + "policyName": { + "Fn::Join": [ + "", + [ + { + "Ref": "loggroup2F19C5C9B" + }, + "EventsLogPolicy" + ] + ] + }, + "policyDocument": { + "Fn::Join": [ + "", + [ + "{\"Statement\":[{\"Action\":[\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Resource\":\"", + { + "Fn::GetAtt": [ + "loggroup2F19C5C9B", + "Arn" + ] + }, + "\"}],\"Version\":\"2012-10-17\"}" + ] + ] + } + }, + "physicalResourceId": { + "id": "EventsLogGroupPolicyloggroupeventsTimer289E3527E" + } + }, + "Update": { + "service": "CloudWatchLogs", + "action": "putResourcePolicy", + "parameters": { + "policyName": { + "Fn::Join": [ + "", + [ + { + "Ref": "loggroup2F19C5C9B" + }, + "EventsLogPolicy" + ] + ] + }, + "policyDocument": { + "Fn::Join": [ + "", + [ + "{\"Statement\":[{\"Action\":[\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Resource\":\"", + { + "Fn::GetAtt": [ + "loggroup2F19C5C9B", + "Arn" + ] + }, + "\"}],\"Version\":\"2012-10-17\"}" + ] + ] + } + }, + "physicalResourceId": { + "id": "EventsLogGroupPolicyloggroupeventsTimer289E3527E" + } + }, + "Delete": { + "service": "CloudWatchLogs", + "action": "deleteResourcePolicy", + "parameters": { + "policyName": { + "Fn::Join": [ + "", + [ + { + "Ref": "loggroup2F19C5C9B" + }, + "EventsLogPolicy" + ] + ] + } + }, + "ignoreErrorCodesMatching": "400" + }, + "InstallLatestAwsSdk": true + }, + "DependsOn": [ + "EventsLogGroupPolicyloggroupeventsTimer289E3527ECustomResourcePolicy24E754C4" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "AssetParametersb64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94S3Bucket38F1BB8E": { + "Type": "String", + "Description": "S3 bucket for asset \"b64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94\"" + }, + "AssetParametersb64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94S3VersionKeyCCDC67C0": { + "Type": "String", + "Description": "S3 key for asset version \"b64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94\"" + }, + "AssetParametersb64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94ArtifactHash782948FC": { + "Type": "String", + "Description": "Artifact hash for asset \"b64b129569a5ac7a9abf88a18ac0b504d1fb1208872460476ed3fd435830eb94\"" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts index a9c363b39e294..06fa29a96a015 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts @@ -8,7 +8,13 @@ const app = new cdk.App(); const stack = new cdk.Stack(app, 'log-group-events'); const logGroup = new logs.LogGroup(stack, 'log-group', { - logGroupName: '/aws/events/MyLogGroupName', + logGroupName: 'MyLogGroupName', + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +const logGroup2 = new logs.LogGroup(stack, 'log-group2', { + logGroupName: 'MyLogGroupName2', + removalPolicy: cdk.RemovalPolicy.DESTROY, }); const timer = new events.Rule(stack, 'Timer', { @@ -19,9 +25,9 @@ timer.addTarget(new targets.LogGroup(logGroup)); const timer2 = new events.Rule(stack, 'Timer2', { schedule: events.Schedule.rate(cdk.Duration.minutes(2)), }); -timer2.addTarget(new targets.LogGroup(logGroup, { +timer2.addTarget(new targets.LogGroup(logGroup2, { event: events.RuleTargetInput.fromObject({ - data: events.EventField.fromPath('$'), + data: events.EventField.fromPath('$.detail-type'), }), })); diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group-resource-policy.test.ts b/packages/@aws-cdk/aws-events-targets/test/logs/log-group-resource-policy.test.ts new file mode 100644 index 0000000000000..999d813105baf --- /dev/null +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group-resource-policy.test.ts @@ -0,0 +1,65 @@ +import '@aws-cdk/assert/jest'; +import * as iam from '@aws-cdk/aws-iam'; +import { App, Stack } from '@aws-cdk/core'; +import { LogGroupResourcePolicy } from '../../lib/log-group-resource-policy'; + +let app: App; +let stack: Stack; + +beforeEach(() => { + app = new App(); + stack = new Stack(app, 'Stack', { + env: { account: '1234', region: 'testregion' }, + }); +}); + +test('minimal example renders correctly', () => { + new LogGroupResourcePolicy(stack, 'LogGroupResourcePolicy', { + policyName: 'TestPolicy', + policyStatements: [new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['logs:PutLogEvents', 'logs:CreateLogStream'], + resources: ['*'], + principals: [new iam.ServicePrincipal('es.amazonaws.com')], + })], + }); + + expect(stack).toHaveResource('Custom::CloudwatchLogResourcePolicy', { + ServiceToken: { + 'Fn::GetAtt': [ + 'AWS679f53fac002430cb0da5b7982bd22872D164C4C', + 'Arn', + ], + }, + Create: { + service: 'CloudWatchLogs', + action: 'putResourcePolicy', + parameters: { + policyName: 'TestPolicy', + policyDocument: '{"Statement":[{"Action":["logs:PutLogEvents","logs:CreateLogStream"],"Effect":"Allow","Principal":{"Service":"es.amazonaws.com"},"Resource":"*"}],"Version":"2012-10-17"}', + }, + physicalResourceId: { + id: 'LogGroupResourcePolicy', + }, + }, + Update: { + service: 'CloudWatchLogs', + action: 'putResourcePolicy', + parameters: { + policyName: 'TestPolicy', + policyDocument: '{"Statement":[{"Action":["logs:PutLogEvents","logs:CreateLogStream"],"Effect":"Allow","Principal":{"Service":"es.amazonaws.com"},"Resource":"*"}],"Version":"2012-10-17"}', + }, + physicalResourceId: { + id: 'LogGroupResourcePolicy', + }, + }, + Delete: { + service: 'CloudWatchLogs', + action: 'deleteResourcePolicy', + parameters: { + policyName: 'TestPolicy', + }, + ignoreErrorCodesMatching: '400', + }, + }); +}); diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts index 8033e21419cfc..e9c579b49b0fe 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts @@ -49,25 +49,6 @@ test('use log group as an event rule target', () => { }); }); - -test.only('log group used as an event rule target must have a name starting with "/aws/events/"', () => { - // GIVEN - const logGroupName = '/awdss/events/MyLogGroup'; - const stack = new cdk.Stack(); - - const rule1 = new events.Rule(stack, 'Rule', { - schedule: events.Schedule.rate(cdk.Duration.minutes(1)), - }); - - // WHEN - let addTargetWrapper = () => { - rule1.addTarget(new targets.LogGroup(logs.LogGroup.fromLogGroupName(stack, 'MyLogGroupImported', logGroupName))); - }; - - // THEN - expect(addTargetWrapper).toThrowError('Target LogGroup name must start with "/aws/events/"'); -}); - test('use log group as an event rule target with rule target input', () => { // GIVEN const stack = new cdk.Stack(); From 4c71270a1e884032e65ddadaca6306dac47d12e8 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sun, 25 Oct 2020 17:58:28 -0700 Subject: [PATCH 06/14] fix integ json for loggroup target --- .../test/logs/integ.log-group.expected.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json index 735469195af0d..4b90c40edabd2 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json @@ -295,9 +295,9 @@ "Id": "Target0", "InputTransformer": { "InputPathsMap": { - "f1": "$" + "detail-type": "$.detail-type" }, - "InputTemplate": "{\"data\":}" + "InputTemplate": "{\"data\":}" } } ] From 3b59ec3963c8ec5a056187e75043f9e2ac2e46c8 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Tue, 27 Oct 2020 23:13:38 -0700 Subject: [PATCH 07/14] Improve code and fix nits --- .../lib/log-group-resource-policy.ts | 8 +- .../aws-events-targets/lib/log-group.ts | 14 +- .../test/logs/integ.log-group.expected.json | 164 +++++++++++++++++- .../test/logs/integ.log-group.ts | 16 +- .../test/logs/log-group.test.ts | 16 +- 5 files changed, 205 insertions(+), 13 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts index 949f03aa61baa..46423373b37ca 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts @@ -3,7 +3,7 @@ import * as cdk from '@aws-cdk/core'; import * as cr from '@aws-cdk/custom-resources'; /** - * Construction properties for LogGroupResourcePolicy + * Properties to configure a log group resource policy */ export interface LogGroupResourcePolicyProps { /** @@ -44,7 +44,11 @@ export class LogGroupResourcePolicy extends cr.AwsCustomResource { }, ignoreErrorCodesMatching: '400', }, - policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: ['*'] }), + policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ + // putResourcePolicy and deleteResourcePolicy don't support resource-level permissions. We must specify all resources ("*"). + // https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazoncloudwatchlogs.html + resources: ['*'], + }), }); } } diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts index d2c2a6e04b11a..f9fa5e3945e94 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -20,7 +20,7 @@ export interface LogGroupProps { /** * Use an AWS CloudWatch LogGroup as an event rule target. */ -export class LogGroup implements events.IRuleTarget { +export class CloudWatchLogGroup implements events.IRuleTarget { constructor(private readonly logGroup: logs.ILogGroup, private readonly props: LogGroupProps = {}) {} /** @@ -30,8 +30,11 @@ export class LogGroup implements events.IRuleTarget { // Use a custom resource to set the log group resource policy since it is not supported by CDK and cfn. // https://github.com/aws/aws-cdk/issues/5343 const resourcePolicyId = `EventsLogGroupPolicy${_rule.node.uniqueId}`; + + const logGroupStack = cdk.Stack.of(this.logGroup); + if (!this.logGroup.node.tryFindChild(resourcePolicyId)) { - new LogGroupResourcePolicy(cdk.Stack.of(this.logGroup), resourcePolicyId, { + new LogGroupResourcePolicy(logGroupStack, resourcePolicyId, { policyName: `${this.logGroup.logGroupName}EventsLogPolicy`, policyStatements: [new iam.PolicyStatement({ effect: iam.Effect.ALLOW, @@ -44,7 +47,12 @@ export class LogGroup implements events.IRuleTarget { return { id: '', - arn: `arn:aws:logs:${this.logGroup.stack.region}:${this.logGroup.stack.account}:log-group:${this.logGroup.logGroupName}`, + arn: logGroupStack.formatArn({ + service: 'logs', + resource: 'log-group', + sep: ':', + resourceName: this.logGroup.logGroupName, + }), input: this.props.event, targetResource: this.logGroup, }; diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json index 4b90c40edabd2..515fcd6d4e0ed 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json @@ -18,6 +18,15 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "loggroupimportedD91682B5": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "MyLogGroupNameToBeImported", + "RetentionInDays": 731 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "TimerBF6F831F": { "Type": "AWS::Events::Rule", "Properties": { @@ -29,7 +38,11 @@ "Fn::Join": [ "", [ - "arn:aws:logs:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", { "Ref": "AWS::Region" }, @@ -277,7 +290,11 @@ "Fn::Join": [ "", [ - "arn:aws:logs:", + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", { "Ref": "AWS::Region" }, @@ -433,6 +450,149 @@ ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" + }, + "Timer30894E3BB": { + "Type": "AWS::Events::Rule", + "Properties": { + "ScheduleExpression": "rate(1 minute)", + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:MyLogGroupNameToBeImported" + ] + ] + }, + "Id": "Target0" + } + ] + } + }, + "EventsLogGroupPolicyloggroupeventsTimer37DF74C17CustomResourcePolicyAE930E1E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "logs:PutResourcePolicy", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "logs:DeleteResourcePolicy", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "EventsLogGroupPolicyloggroupeventsTimer37DF74C17CustomResourcePolicyAE930E1E", + "Roles": [ + { + "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" + } + ] + } + }, + "EventsLogGroupPolicyloggroupeventsTimer37DF74C174B3D705D": { + "Type": "Custom::CloudwatchLogResourcePolicy", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "AWS679f53fac002430cb0da5b7982bd22872D164C4C", + "Arn" + ] + }, + "Create": { + "service": "CloudWatchLogs", + "action": "putResourcePolicy", + "parameters": { + "policyName": "MyLogGroupNameToBeImportedEventsLogPolicy", + "policyDocument": { + "Fn::Join": [ + "", + [ + "{\"Statement\":[{\"Action\":[\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Resource\":\"arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:MyLogGroupNameToBeImported:*\"}],\"Version\":\"2012-10-17\"}" + ] + ] + } + }, + "physicalResourceId": { + "id": "EventsLogGroupPolicyloggroupeventsTimer37DF74C17" + } + }, + "Update": { + "service": "CloudWatchLogs", + "action": "putResourcePolicy", + "parameters": { + "policyName": "MyLogGroupNameToBeImportedEventsLogPolicy", + "policyDocument": { + "Fn::Join": [ + "", + [ + "{\"Statement\":[{\"Action\":[\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Resource\":\"arn:", + { + "Ref": "AWS::Partition" + }, + ":logs:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":log-group:MyLogGroupNameToBeImported:*\"}],\"Version\":\"2012-10-17\"}" + ] + ] + } + }, + "physicalResourceId": { + "id": "EventsLogGroupPolicyloggroupeventsTimer37DF74C17" + } + }, + "Delete": { + "service": "CloudWatchLogs", + "action": "deleteResourcePolicy", + "parameters": { + "policyName": "MyLogGroupNameToBeImportedEventsLogPolicy" + }, + "ignoreErrorCodesMatching": "400" + }, + "InstallLatestAwsSdk": true + }, + "DependsOn": [ + "EventsLogGroupPolicyloggroupeventsTimer37DF74C17CustomResourcePolicyAE930E1E" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts index 06fa29a96a015..6d813dd3df3dd 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts @@ -17,19 +17,31 @@ const logGroup2 = new logs.LogGroup(stack, 'log-group2', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); +new logs.LogGroup(stack, 'log-group-imported', { + logGroupName: 'MyLogGroupNameToBeImported', + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +const importedLogGroup = logs.LogGroup.fromLogGroupName(stack, 'imported-log-group', 'MyLogGroupNameToBeImported'); + const timer = new events.Rule(stack, 'Timer', { schedule: events.Schedule.rate(cdk.Duration.minutes(1)), }); -timer.addTarget(new targets.LogGroup(logGroup)); +timer.addTarget(new targets.CloudWatchLogGroup(logGroup)); const timer2 = new events.Rule(stack, 'Timer2', { schedule: events.Schedule.rate(cdk.Duration.minutes(2)), }); -timer2.addTarget(new targets.LogGroup(logGroup2, { +timer2.addTarget(new targets.CloudWatchLogGroup(logGroup2, { event: events.RuleTargetInput.fromObject({ data: events.EventField.fromPath('$.detail-type'), }), })); +const timer3 = new events.Rule(stack, 'Timer3', { + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), +}); +timer3.addTarget(new targets.CloudWatchLogGroup(importedLogGroup)); + app.synth(); diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts index e9c579b49b0fe..6df5ad191770a 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/log-group.test.ts @@ -16,7 +16,7 @@ test('use log group as an event rule target', () => { }); // WHEN - rule1.addTarget(new targets.LogGroup(logGroup)); + rule1.addTarget(new targets.CloudWatchLogGroup(logGroup)); // THEN expect(stack).toHaveResource('AWS::Events::Rule', { @@ -28,7 +28,11 @@ test('use log group as an event rule target', () => { 'Fn::Join': [ '', [ - 'arn:aws:logs:', + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':logs:', { Ref: 'AWS::Region', }, @@ -60,7 +64,7 @@ test('use log group as an event rule target with rule target input', () => { }); // WHEN - rule1.addTarget(new targets.LogGroup(logGroup, { + rule1.addTarget(new targets.CloudWatchLogGroup(logGroup, { event: events.RuleTargetInput.fromObject({ data: events.EventField.fromPath('$'), }), @@ -76,7 +80,11 @@ test('use log group as an event rule target with rule target input', () => { 'Fn::Join': [ '', [ - 'arn:aws:logs:', + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':logs:', { Ref: 'AWS::Region', }, From 9e9e4258d42e57bb4fed97daa3fcd4270909870b Mon Sep 17 00:00:00 2001 From: DaWyz Date: Tue, 27 Oct 2020 23:23:56 -0700 Subject: [PATCH 08/14] Remove like to issue as it's not related to events targets --- packages/@aws-cdk/aws-events-targets/lib/log-group.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts index f9fa5e3945e94..b372b731a41d2 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -28,7 +28,6 @@ export class CloudWatchLogGroup implements events.IRuleTarget { */ public bind(_rule: events.IRule, _id?: string): events.RuleTargetConfig { // Use a custom resource to set the log group resource policy since it is not supported by CDK and cfn. - // https://github.com/aws/aws-cdk/issues/5343 const resourcePolicyId = `EventsLogGroupPolicy${_rule.node.uniqueId}`; const logGroupStack = cdk.Stack.of(this.logGroup); From d1bf75b0fb9ff3a8d7fc64cbfd3106f53a226761 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sat, 14 Nov 2020 17:23:14 -0800 Subject: [PATCH 09/14] Fix nits and udpate aws-events-targets README.md --- .../@aws-cdk/aws-events-targets/README.md | 34 ++++++------------- .../lib/log-group-resource-policy.ts | 2 +- .../aws-events-targets/lib/log-group.ts | 1 + 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index 2cdf880d56cb1..047734c8fc892 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -33,37 +33,23 @@ EventBridge. Use the `LogGroup` target to log your events in a CloudWatch LogGroup. +For example, the following code snippet creates an event rule with a CloudWatch LogGroup as a target. +Every events sent from the `aws.ec2` source will be sent to the CloudWatch LogGroup. + ```ts -const rule = new Rule(this, 'rule', { - eventPattern: { - source: [stack.account], - }, -}); +import * as logs from "@aws-cdk/aws-logs"; +import * as events from "@aws-cdk/aws-events"; +import * as targets from "@aws-cdk/aws-events-targets"; -const logGroup = new LogGroup(this, 'MyLogGroup', { +const logGroup = new log.LogGroup(this, 'MyLogGroup', { logGroupName: 'MyLogGroup', }); -rule.addTarget(targets.LogGroup(logGroup)); -``` - -You can also use an [InputTransformer](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_InputTransformer.html). - -```ts -const rule = new Rule(this, 'rule', { +const rule = new events.Rule(this, 'rule', { eventPattern: { - source: [stack.account], + source: ["aws.ec2"], }, }); -const logGroup = new LogGroup(this, 'MyLogGroup', { - logGroupName: 'MyLogGroup', -}); - -rule.addTarget(new targets.LogGroup(logGroup, { - event: events.RuleTargetInput.fromObject({ - status: events.EventField.fromPath('$.detail.status'), - instanceId: events.EventField.fromPath('$.detail.instance-id'), - }) -})); +rule.addTarget(new targets.LogGroup(logGroup)); ``` diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts index 46423373b37ca..5435c271e0df4 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts @@ -47,7 +47,7 @@ export class LogGroupResourcePolicy extends cr.AwsCustomResource { policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ // putResourcePolicy and deleteResourcePolicy don't support resource-level permissions. We must specify all resources ("*"). // https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazoncloudwatchlogs.html - resources: ['*'], + resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE, }), }); } diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts index b372b731a41d2..17577b42aa753 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -3,6 +3,7 @@ import * as iam from '@aws-cdk/aws-iam'; import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; import { LogGroupResourcePolicy } from './log-group-resource-policy'; + /** * Customize the CloudWatch LogGroup Event Target */ From 90c19bb3654852046dc4360268b1e5b73ff9e50e Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sat, 14 Nov 2020 19:01:20 -0800 Subject: [PATCH 10/14] fix readme --- packages/@aws-cdk/aws-events-targets/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index 047734c8fc892..c99441f05d32a 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -41,7 +41,7 @@ import * as logs from "@aws-cdk/aws-logs"; import * as events from "@aws-cdk/aws-events"; import * as targets from "@aws-cdk/aws-events-targets"; -const logGroup = new log.LogGroup(this, 'MyLogGroup', { +const logGroup = new logs.LogGroup(this, 'MyLogGroup', { logGroupName: 'MyLogGroup', }); @@ -51,5 +51,5 @@ const rule = new events.Rule(this, 'rule', { }, }); -rule.addTarget(new targets.LogGroup(logGroup)); +rule.addTarget(new targets.CloudWatchLogGroup(logGroup)); ``` From b334fda4ee7c984f06c3ede69340f702077bac3e Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sat, 14 Nov 2020 22:18:30 -0800 Subject: [PATCH 11/14] use node.addr for log-group-resource policyName --- .../lib/log-group-resource-policy.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts index 5435c271e0df4..73ffff1fd0716 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts @@ -8,8 +8,10 @@ import * as cr from '@aws-cdk/custom-resources'; export interface LogGroupResourcePolicyProps { /** * The log group resource policy name + * + * @default: an opaque tree-unique address for this construct (node.addr). */ - readonly policyName: string; + readonly policyName?: string; /** * The policy statements for the log group resource logs */ @@ -25,13 +27,15 @@ export class LogGroupResourcePolicy extends cr.AwsCustomResource { statements: props.policyStatements, }); + let policyName = props.policyName || cdk.Lazy.stringValue({ produce: () => this.node.addr }); + super(scope, id, { resourceType: 'Custom::CloudwatchLogResourcePolicy', onUpdate: { service: 'CloudWatchLogs', action: 'putResourcePolicy', parameters: { - policyName: props.policyName, + policyName: policyName, policyDocument: JSON.stringify(policyDocument), }, physicalResourceId: cr.PhysicalResourceId.of(id), @@ -40,7 +44,7 @@ export class LogGroupResourcePolicy extends cr.AwsCustomResource { service: 'CloudWatchLogs', action: 'deleteResourcePolicy', parameters: { - policyName: props.policyName, + policyName: policyName, }, ignoreErrorCodesMatching: '400', }, From 9f0da1b297471f7eae24615215eb8ecea3de455f Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sat, 14 Nov 2020 22:25:51 -0800 Subject: [PATCH 12/14] default PolicyName to use cdk.Names.uniqueId() instead of node.addr() --- .../aws-events-targets/lib/log-group-resource-policy.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts index 73ffff1fd0716..d0bbaca87f689 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group-resource-policy.ts @@ -8,8 +8,6 @@ import * as cr from '@aws-cdk/custom-resources'; export interface LogGroupResourcePolicyProps { /** * The log group resource policy name - * - * @default: an opaque tree-unique address for this construct (node.addr). */ readonly policyName?: string; /** @@ -27,7 +25,7 @@ export class LogGroupResourcePolicy extends cr.AwsCustomResource { statements: props.policyStatements, }); - let policyName = props.policyName || cdk.Lazy.stringValue({ produce: () => this.node.addr }); + let policyName = props.policyName || cdk.Lazy.stringValue({ produce: () => cdk.Names.uniqueId(this) }); super(scope, id, { resourceType: 'Custom::CloudwatchLogResourcePolicy', From 5cfa80771670b643f217a0d0743454f48b1a43f8 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sat, 14 Nov 2020 22:29:35 -0800 Subject: [PATCH 13/14] Removing policyName value in favor of the uniqueId --- packages/@aws-cdk/aws-events-targets/lib/log-group.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts index 17577b42aa753..ac6e3f7917da4 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/log-group.ts @@ -35,7 +35,6 @@ export class CloudWatchLogGroup implements events.IRuleTarget { if (!this.logGroup.node.tryFindChild(resourcePolicyId)) { new LogGroupResourcePolicy(logGroupStack, resourcePolicyId, { - policyName: `${this.logGroup.logGroupName}EventsLogPolicy`, policyStatements: [new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['logs:PutLogEvents', 'logs:CreateLogStream'], From 3251d58e88d3fa8891640dea1106d925dc5d5b72 Mon Sep 17 00:00:00 2001 From: DaWyz Date: Sun, 15 Nov 2020 10:00:25 -0800 Subject: [PATCH 14/14] update integration test expectation --- .../test/logs/integ.log-group.expected.json | 78 +++---------------- 1 file changed, 9 insertions(+), 69 deletions(-) diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json index 515fcd6d4e0ed..1f4e086b51607 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.expected.json @@ -101,17 +101,7 @@ "service": "CloudWatchLogs", "action": "putResourcePolicy", "parameters": { - "policyName": { - "Fn::Join": [ - "", - [ - { - "Ref": "loggroupB02AAEB1" - }, - "EventsLogPolicy" - ] - ] - }, + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimerC63340B025F606BE", "policyDocument": { "Fn::Join": [ "", @@ -136,17 +126,7 @@ "service": "CloudWatchLogs", "action": "putResourcePolicy", "parameters": { - "policyName": { - "Fn::Join": [ - "", - [ - { - "Ref": "loggroupB02AAEB1" - }, - "EventsLogPolicy" - ] - ] - }, + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimerC63340B025F606BE", "policyDocument": { "Fn::Join": [ "", @@ -171,17 +151,7 @@ "service": "CloudWatchLogs", "action": "deleteResourcePolicy", "parameters": { - "policyName": { - "Fn::Join": [ - "", - [ - { - "Ref": "loggroupB02AAEB1" - }, - "EventsLogPolicy" - ] - ] - } + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimerC63340B025F606BE" }, "ignoreErrorCodesMatching": "400" }, @@ -359,17 +329,7 @@ "service": "CloudWatchLogs", "action": "putResourcePolicy", "parameters": { - "policyName": { - "Fn::Join": [ - "", - [ - { - "Ref": "loggroup2F19C5C9B" - }, - "EventsLogPolicy" - ] - ] - }, + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimer289E3527EF8F6205F", "policyDocument": { "Fn::Join": [ "", @@ -394,17 +354,7 @@ "service": "CloudWatchLogs", "action": "putResourcePolicy", "parameters": { - "policyName": { - "Fn::Join": [ - "", - [ - { - "Ref": "loggroup2F19C5C9B" - }, - "EventsLogPolicy" - ] - ] - }, + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimer289E3527EF8F6205F", "policyDocument": { "Fn::Join": [ "", @@ -429,17 +379,7 @@ "service": "CloudWatchLogs", "action": "deleteResourcePolicy", "parameters": { - "policyName": { - "Fn::Join": [ - "", - [ - { - "Ref": "loggroup2F19C5C9B" - }, - "EventsLogPolicy" - ] - ] - } + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimer289E3527EF8F6205F" }, "ignoreErrorCodesMatching": "400" }, @@ -522,7 +462,7 @@ "service": "CloudWatchLogs", "action": "putResourcePolicy", "parameters": { - "policyName": "MyLogGroupNameToBeImportedEventsLogPolicy", + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimer37DF74C17EF314A8E", "policyDocument": { "Fn::Join": [ "", @@ -552,7 +492,7 @@ "service": "CloudWatchLogs", "action": "putResourcePolicy", "parameters": { - "policyName": "MyLogGroupNameToBeImportedEventsLogPolicy", + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimer37DF74C17EF314A8E", "policyDocument": { "Fn::Join": [ "", @@ -582,7 +522,7 @@ "service": "CloudWatchLogs", "action": "deleteResourcePolicy", "parameters": { - "policyName": "MyLogGroupNameToBeImportedEventsLogPolicy" + "policyName": "loggroupeventsEventsLogGroupPolicyloggroupeventsTimer37DF74C17EF314A8E" }, "ignoreErrorCodesMatching": "400" },