Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(events-targets): replace custom resource with native grantWrite method for log group write permissions #30428

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions packages/aws-cdk-lib/aws-events-targets/lib/log-group.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { LogGroupResourcePolicy } from './log-group-resource-policy';
import { TargetBaseProps, bindBaseTargetConfig } from './util';
import * as events from '../../aws-events';
import { RuleTargetInputProperties, RuleTargetInput, EventField, IRule } from '../../aws-events';
Expand Down Expand Up @@ -78,30 +77,19 @@ export interface LogGroupProps extends TargetBaseProps {
* @default - the entire EventBridge event
*/
readonly logEvent?: LogGroupTargetInput;

/**
* Whether the custom resource created wll default to
* install latest AWS SDK
*
* @default - install latest AWS SDK
*/
readonly installLatestAwsSdk?: boolean;
}

/**
* Use an AWS CloudWatch LogGroup as an event rule target.
*/
export class CloudWatchLogGroup implements events.IRuleTarget {
private target?: RuleTargetInputProperties;
constructor(private readonly logGroup: logs.ILogGroup, private readonly props: LogGroupProps = {}) {}
constructor(public readonly logGroup: 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 {
// Use a custom resource to set the log group resource policy since it is not supported by CDK and cfn.
const resourcePolicyId = `EventsLogGroupPolicy${cdk.Names.nodeUniqueId(_rule.node)}`;

const logGroupStack = cdk.Stack.of(this.logGroup);

if (this.props.event && this.props.logEvent) {
Expand All @@ -115,17 +103,7 @@ export class CloudWatchLogGroup implements events.IRuleTarget {

_rule.node.addValidation({ validate: () => this.validateInputTemplate() });

if (!this.logGroup.node.tryFindChild(resourcePolicyId)) {
new LogGroupResourcePolicy(logGroupStack, resourcePolicyId, {
installLatestAwsSdk: this.props.installLatestAwsSdk,
policyStatements: [new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['logs:PutLogEvents', 'logs:CreateLogStream'],
resources: [this.logGroup.logGroupArn],
principals: [new iam.ServicePrincipal('events.amazonaws.com')],
})],
});
}
this.logGroup.grantWrite(new iam.ServicePrincipal('events.amazonaws.com'));

return {
...bindBaseTargetConfig(this.props),
Expand Down
68 changes: 28 additions & 40 deletions packages/aws-cdk-lib/aws-events-targets/test/logs/log-group.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,46 +158,6 @@ test('logEvent with defaults', () => {
});
});

test('can set install latest AWS SDK value to false', () => {
// GIVEN
const stack = new cdk.Stack();
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)),
});

// WHEN
rule1.addTarget(new targets.CloudWatchLogGroup(logGroup, {
installLatestAwsSdk: false,
}));

// THEN
Template.fromStack(stack).hasResourceProperties('Custom::CloudwatchLogResourcePolicy', {
InstallLatestAwsSdk: false,
});
});

test('default install latest AWS SDK is true', () => {
// GIVEN
const stack = new cdk.Stack();
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)),
});

// WHEN
rule1.addTarget(new targets.CloudWatchLogGroup(logGroup));

// THEN
Template.fromStack(stack).hasResourceProperties('Custom::CloudwatchLogResourcePolicy', {
InstallLatestAwsSdk: true,
});
});

test('can use logEvent', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down Expand Up @@ -398,3 +358,31 @@ testDeprecated('specifying retry policy with 0 retryAttempts', () => {
],
});
});

test('grant write permissions to log group', () => {
// GIVEN
const stack = new cdk.Stack();
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)),
});

// WHEN
rule1.addTarget(new targets.CloudWatchLogGroup(logGroup));

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Logs::ResourcePolicy', {
PolicyDocument: {
Statement: [
{
Action: ['logs:CreateLogStream', 'logs:PutLogEvents'],
Effect: 'Allow',
Principal: { Service: 'events.amazonaws.com' },
Resource: { 'Fn::GetAtt': ['MyLogGroup5C0DAD85', 'Arn'] },
},
],
},
});
});
Loading