Skip to content

feat: Add check for rule AwsSolutions-SQS3 for a queue that is a DLQ for EventBridge Rule #1990

@emma-patterson-sonarsource

Description

Description

For the rule AwsSolutions-SQS3 it enforces every queue to have a dead letter queue unless it is already a DLQ itself or a DLQ for lambda.

We are missing the check for when a queue is a DLQ for an EventBridge rule.

Use Case

When adding a DLQ to an EventBridge Rule, e.g.:

        event_rule.add_target(
            aws_events_targets.LambdaFunction(
                handler=self.rule_props.target_function_handler,
                retry_attempts=2,
                dead_letter_queue=self._dlq_queue,
                event=self.rule_props.event_rule_target_input,
            )
        )

Currently we get the error that the queue is non-compliant because it does not have a DLQ but it is itself a DLQ.

Proposed Solution

Handle this in a similar way to the lambda DLQ check found here:

https://github.com/cdklabs/cdk-nag/blob/main/src/rules/sqs/SQSQueueDLQ.ts

We could go something like:

import { CfnRule } from 'aws-cdk-lib/aws-events';
import { Stack } from 'aws-cdk-lib';
import { flattenCfnReference } from './utils'; // Your helper to resolve Cfn references

/**
 * Helper function to check whether a given EventBridge Rule uses the target SQS queue as a DLQ
 * @param node the CfnRule to check
 * @param queueLogicalId the Cfn Logical ID of the target queue
 * @param queueName the name of the target queue
 * @returns whether the CfnRule uses the target SQS queue as a DLQ
 */
function isMatchingEventBridgeRuleDLQ(
  node: CfnRule,
  queueLogicalId: string,
  queueName: string | undefined
): boolean {
  const targets = Stack.of(node).resolve(node.targets) ?? [];

  for (const target of targets) {
    const dlqArn = flattenCfnReference(
      Stack.of(node).resolve(target?.deadLetterConfig?.arn) ?? ''
    );

    if (
      new RegExp(`${queueLogicalId}(?![\\w])`).test(dlqArn) ||
      (queueName !== undefined &&
        new RegExp(`:${queueName}(?![\\w\\-_\\.])`).test(dlqArn))
    ) {
      return true;
    }
  }

  return false;
}

and add a new branch for this:

 } else if (child instanceof CfnRule) {
         if (isMatchingEventBridgeRuleTarget(child, queueLogicalId, queueName)) {
              found = true;
              break;
         }
 }

Other information

No response

Acknowledge

  • I may be able to implement this feature request
  • This feature might incur a breaking change

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature-requestA feature should be added or improved.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions