Skip to content

Commit

Permalink
Add a dlq for the Event Rule
Browse files Browse the repository at this point in the history
  • Loading branch information
biffgaut committed Jan 29, 2025
1 parent 6529df7 commit 4613c8e
Show file tree
Hide file tree
Showing 40 changed files with 1,519 additions and 224 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import * as sqs from 'aws-cdk-lib/aws-sqs';
import * as events from 'aws-cdk-lib/aws-events';
import * as eventtargets from 'aws-cdk-lib/aws-events-targets';
import * as kms from 'aws-cdk-lib/aws-kms';
import * as defaults from '@aws-solutions-constructs/core';
import { ServicePrincipal } from 'aws-cdk-lib/aws-iam';
Expand Down Expand Up @@ -42,6 +43,15 @@ export interface EventbridgeToSqsProps {
* @default - None
*/
readonly eventRuleProps: events.RuleProps;
/**
* Whether to deploy a DLQ for the Rule itself
* (this DLQ is would receive messages that can't be delivered to
* the target SQS queue))
*
* This is new, so defaulting to false to avoid surprising existing clients
* @default - false
*/
readonly deployRuleDlq?: boolean;
/**
* Existing instance of SQS queue object, providing both this and queueProps will cause an error.
*
Expand Down Expand Up @@ -105,6 +115,7 @@ export class EventbridgeToSqs extends Construct {
public readonly eventBus?: events.IEventBus;
public readonly eventsRule: events.Rule;
public readonly encryptionKey?: kms.IKey;
public readonly eventRuleDlq?: sqs.Queue;

/**
* @summary Constructs a new instance of the EventbridgeToSqs class.
Expand Down Expand Up @@ -140,12 +151,19 @@ export class EventbridgeToSqs extends Construct {
this.encryptionKey = buildQueueResponse.key;
this.deadLetterQueue = buildQueueResponse.dlq;

const sqsEventTarget: events.IRuleTarget = {
bind: () => ({
id: this.sqsQueue.queueName,
arn: this.sqsQueue.queueArn
})
};
let sqsEventTargetProps: eventtargets.SqsQueueProps = {};

if (defaults.CheckBooleanWithDefault(props.deployRuleDlq, false)) {
this.eventRuleDlq = defaults.buildQueue(this, 'ruleDlq', {
deployDeadLetterQueue: false,
enableEncryptionWithCustomerManagedKey: enableEncryptionParam,
encryptionKey: this.encryptionKey,
}).queue;

sqsEventTargetProps = defaults.consolidateProps(sqsEventTargetProps, { deadLetterQueue: this.eventRuleDlq });
}

const sqsEventTarget = new eventtargets.SqsQueue(this.sqsQueue, sqsEventTargetProps);

// build an event bus if existingEventBus is provided or eventBusProps are provided
this.eventBus = defaults.buildEventBus(this, {
Expand All @@ -163,7 +181,5 @@ export class EventbridgeToSqs extends Construct {
this.sqsQueue.grantPurge(new ServicePrincipal('events.amazonaws.com'));
}

// Policy for event to be able to send messages to the queue and Grant Event Bridge service access to the SQS queue encryption key
this.sqsQueue.grantSendMessages(new ServicePrincipal('events.amazonaws.com'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import * as cdk from 'aws-cdk-lib';
import { EventbridgeToSqs, EventbridgeToSqsProps } from '../lib';
import * as events from "aws-cdk-lib/aws-events";
import * as sqs from "aws-cdk-lib/aws-sqs";
import { Template } from 'aws-cdk-lib/assertions';
import { Match, Template } from 'aws-cdk-lib/assertions';
import * as defaults from '@aws-solutions-constructs/core';

function deployNewStack(stack: cdk.Stack) {
Expand Down Expand Up @@ -495,7 +495,7 @@ test('Queue purging flag grants correct permissions', () => {
},
{
Action: [
"sqs:PurgeQueue",
"sqs:SendMessage",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl"
],
Expand All @@ -512,7 +512,7 @@ test('Queue purging flag grants correct permissions', () => {
},
{
Action: [
"sqs:SendMessage",
"sqs:PurgeQueue",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl"
],
Expand Down Expand Up @@ -559,3 +559,51 @@ test('check that CheckSqsProps is being called', () => {
};
expect(app).toThrowError("Error - Either provide queueProps or existingQueueObj, but not both.\n");
});

test.only('Check that rule dlq is not created by default', () => {
const stack = new cdk.Stack();
const props: EventbridgeToSqsProps = {
eventRuleProps: {
schedule: events.Schedule.rate(cdk.Duration.minutes(5))
}
};
new EventbridgeToSqs(stack, 'test-eventbridge-sqs', props);
const template = Template.fromStack(stack);
template.resourceCountIs("AWS::SQS::Queue", 2);
template.hasResourceProperties("AWS::Events::Rule", {
Targets: [
{
Id: "Target0",
DeadLetterConfig: Match.absent(),
}
]
});
});

test.only('Check that rule dlq is created when requested', () => {
const stack = new cdk.Stack();
const props: EventbridgeToSqsProps = {
eventRuleProps: {
schedule: events.Schedule.rate(cdk.Duration.minutes(5))
},
deployRuleDlq: true
};
new EventbridgeToSqs(stack, 'test-eventbridge-sqs', props);
const template = Template.fromStack(stack);
template.resourceCountIs("AWS::SQS::Queue", 3);
template.hasResourceProperties("AWS::Events::Rule", {
Targets: [
{
Id: "Target0",
DeadLetterConfig: {
Arn: {
"Fn::GetAtt": [
Match.stringLikeRegexp("testeventbridgesqsruleDlq.*"),
"Arn"
]
}
},
}
]
});
});
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"36.0.0"}
{"version":"39.0.0"}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"version": "36.0.0",
"version": "39.0.0",
"files": {
"7af5ea5f919ee11dba0f3d6b1c862aaeb33516536f0772e7558e77a6bf765846": {
"9acaa89ceee5e5b8ab6d77a48e9ba3aaa89df75c8f22ffdbeccaf7ef4ef6a3fd": {
"source": {
"path": "evtsqs-exist-bus.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "7af5ea5f919ee11dba0f3d6b1c862aaeb33516536f0772e7558e77a6bf765846.json",
"objectKey": "9acaa89ceee5e5b8ab6d77a48e9ba3aaa89df75c8f22ffdbeccaf7ef4ef6a3fd.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
"kms:GenerateDataKey*",
"kms:ReEncrypt*"
],
"Condition": {
"StringEquals": {
"aws:SourceAccount": {
"Ref": "AWS::AccountId"
}
}
},
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
Expand Down Expand Up @@ -73,6 +80,13 @@
"sqs:GetQueueUrl",
"sqs:SendMessage"
],
"Condition": {
"StringEquals": {
"aws:SourceAccount": {
"Ref": "AWS::AccountId"
}
}
},
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
Expand Down Expand Up @@ -120,12 +134,7 @@
"Arn"
]
},
"Id": {
"Fn::GetAtt": [
"MyQueueE6CA6235",
"QueueName"
]
}
"Id": "Target0"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "36.0.0",
"version": "39.0.0",
"files": {
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
"source": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "36.0.0",
"version": "39.0.0",
"testCases": {
"evtsqs-exist-bus/Integ/DefaultTest": {
"stacks": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "36.0.0",
"version": "39.0.0",
"artifacts": {
"evtsqsexistbusIntegDefaultTestDeployAssertD6166996.assets": {
"type": "cdk:asset-manifest",
Expand Down Expand Up @@ -66,7 +66,7 @@
"validateOnSynth": false,
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/7af5ea5f919ee11dba0f3d6b1c862aaeb33516536f0772e7558e77a6bf765846.json",
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9acaa89ceee5e5b8ab6d77a48e9ba3aaa89df75c8f22ffdbeccaf7ef4ef6a3fd.json",
"requiresBootstrapStackVersion": 6,
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
"additionalDependencies": [
Expand Down
Loading

0 comments on commit 4613c8e

Please sign in to comment.