Skip to content

Commit

Permalink
feat(events): dead letter queue for an Event Bus (#30628)
Browse files Browse the repository at this point in the history
### Issue # (if applicable)

Closes #30531.

### Reason for this change

EventBus L2 construct doesn't support for configuring dead letter queue.

### Description of changes

Add `deadLetterQueue` prop to `EventBusProps`

### Description of how you validated changes

Add both unit and integ test

### Checklist
- [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
badmintoncryer authored Oct 19, 2024
1 parent a32436a commit 318eae6
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 8 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
{
"Resources": {
"DLQ581697C4": {
"Type": "AWS::SQS::Queue",
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
},
"BusEA82B648": {
"Type": "AWS::Events::EventBus",
"Properties": {
"DeadLetterConfig": {
"Arn": {
"Fn::GetAtt": [
"DLQ581697C4",
"Arn"
]
}
},
"Description": "myEventBus",
"Name": "StackBusAA0A1E4B"
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import * as iam from 'aws-cdk-lib/aws-iam';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { App, Stack } from 'aws-cdk-lib';
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
import { EventBus } from 'aws-cdk-lib/aws-events';

const app = new App();
const stack = new Stack(app, 'Stack');

const dlq = new sqs.Queue(stack, 'DLQ');

const bus = new EventBus(stack, 'Bus', {
deadLetterQueue: dlq,
description: 'myEventBus',
});

Expand Down
16 changes: 16 additions & 0 deletions packages/aws-cdk-lib/aws-events/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,22 @@ bus.archive('MyArchive', {
});
```

## Dead-Letter Queue for EventBus

It is possible to configure a [Dead Letter Queue for an EventBus](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-event-delivery.html#eb-rule-dlq). This is useful when you want to capture events that could not be delivered to any of the targets.

To configure a Dead Letter Queue for an EventBus, you can use the `deadLetterQueue` property of the `EventBus` construct.

```ts
import * as sqs from 'aws-cdk-lib/aws-sqs';

const dlq = new sqs.Queue(this, 'DLQ');

const bus = new events.EventBus(this, 'Bus', {
deadLetterQueue: dlq,
});
```

## Granting PutEvents to an existing EventBus

To import an existing EventBus into your CDK application, use `EventBus.fromEventBusArn`, `EventBus.fromEventBusAttributes`
Expand Down
13 changes: 13 additions & 0 deletions packages/aws-cdk-lib/aws-events/lib/event-bus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Archive, BaseArchiveProps } from './archive';
import { CfnEventBus, CfnEventBusPolicy } from './events.generated';
import * as iam from '../../aws-iam';
import * as kms from '../../aws-kms';
import * as sqs from '../../aws-sqs';
import { ArnFormat, IResource, Lazy, Names, Resource, Stack, Token } from '../../core';

/**
Expand Down Expand Up @@ -80,6 +81,15 @@ export interface EventBusProps {
*/
readonly eventSourceName?: string;

/**
* Dead-letter queue for the event bus
*
* @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-event-delivery.html#eb-rule-dlq
*
* @default - no dead-letter queue
*/
readonly deadLetterQueue?: sqs.IQueue;

/**
* The event bus description.
*
Expand Down Expand Up @@ -343,6 +353,9 @@ export class EventBus extends EventBusBase {
const eventBus = new CfnEventBus(this, 'Resource', {
name: this.physicalName,
eventSourceName,
deadLetterConfig: props?.deadLetterQueue ? {
arn: props.deadLetterQueue.queueArn,
} : undefined,
description: props?.description,
kmsKeyIdentifier: props?.kmsKey?.keyArn,
});
Expand Down
26 changes: 21 additions & 5 deletions packages/aws-cdk-lib/aws-events/test/event-bus.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
import { Template } from '../../assertions';
import * as iam from '../../aws-iam';
import { Effect } from '../../aws-iam';
import * as kms from '../../aws-kms';
import * as sqs from '../../aws-sqs';
import { Aws, CfnResource, Stack, Arn, App, PhysicalName, CfnOutput } from '../../core';
import { EventBus } from '../lib';

Expand Down Expand Up @@ -568,7 +568,7 @@ describe('event bus', () => {

// WHEN
bus.addToResourcePolicy(new iam.PolicyStatement({
effect: Effect.ALLOW,
effect: iam.Effect.ALLOW,
principals: [new iam.AccountPrincipal('111111111111111')],
actions: ['events:PutEvents'],
sid: '123',
Expand Down Expand Up @@ -616,15 +616,15 @@ describe('event bus', () => {
const bus = new EventBus(stack, 'Bus');

const statement1 = new iam.PolicyStatement({
effect: Effect.ALLOW,
effect: iam.Effect.ALLOW,
principals: [new iam.ArnPrincipal('arn')],
actions: ['events:PutEvents'],
sid: 'statement1',
resources: [bus.eventBusArn],
});

const statement2 = new iam.PolicyStatement({
effect: Effect.ALLOW,
effect: iam.Effect.ALLOW,
principals: [new iam.ArnPrincipal('arn')],
actions: ['events:DeleteRule'],
sid: 'statement2',
Expand All @@ -649,12 +649,28 @@ describe('event bus', () => {

// THEN
expect(() => bus.addToResourcePolicy(new iam.PolicyStatement({
effect: Effect.ALLOW,
effect: iam.Effect.ALLOW,
principals: [new iam.ArnPrincipal('arn')],
actions: ['events:PutEvents'],
}))).toThrow('Event Bus policy statements must have a sid');
});

test('set dead letter queue', () => {
const app = new App();
const stack = new Stack(app, 'Stack');
const dlq = new sqs.Queue(stack, 'DLQ');
new EventBus(stack, 'Bus', {
deadLetterQueue: dlq,
});

Template.fromStack(stack).hasResourceProperties('AWS::Events::EventBus', {
DeadLetterConfig: {
Arn: {
'Fn::GetAtt': ['DLQ581697C4', 'Arn'],
},
},
});
});
test('Event Bus with a customer managed key', () => {
// GIVEN
const app = new App();
Expand Down

0 comments on commit 318eae6

Please sign in to comment.