You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SNS绑定Dead-Letter Queue后权限报错:代码正常但提示不消

问题

配置SNS主题的死信队列时,持续收到以下报错:

Dead-letter queue (redrive policy) permissions
Couldn't check Amazon SQS queue permissions. Make sure that the queue exists and that your account has permission to read the attributes of the queue. To allow an Amazon SNS topic to send messages to an Amazon SQS queue, you must create an Amazon SQS queue policy.

代码能正常部署运行,但这条报错始终无法消除,该怎么解决?


相关代码
import { Duration, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as events from 'aws-cdk-lib/aws-events';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import * as sns from 'aws-cdk-lib/aws-sns';
import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { CdkStackProps } from '../cdk.stack';
import * as iam from 'aws-cdk-lib/aws-iam';
import { ServicePrincipal } from 'aws-cdk-lib/aws-iam';

export class EventBridgeSnsStack extends Stack {
  constructor(scope: Construct, id: string, props?: CdkStackProps) {
    super(scope, id, props);

    const dlQueue = new sqs.Queue(this, 'DeadLetterQueue', {
      queueName: `${props?.envProps.shortName}-xxxxSubscription_DLQ`,
      retentionPeriod: Duration.days(14),
    });

    // 创建SNS主题
    const topic = new sns.Topic(this, 'xxxxTopic', {
      displayName: 'xxxxTopic',
      topicName: `${props?.envProps.shortName}-xxxxTopic`,
    });
    // 为主题添加HTTP订阅
    const subscription = new subscriptions.UrlSubscription(
      `https://${props?.envProps.apiDomainAlias}/batch-job/update-xxxxx-statuses`,
      {
        deadLetterQueue: dlQueue,
        filterPolicy: {
          // 仅处理retryCount等于2的消息
          // 首次尝试失败后,retryCount会被设为2
          retryCount: sns.SubscriptionFilter.numericFilter({
            allowlist: [2],
          }),
        },
      },
    );
    topic.addSubscription(subscription);

    dlQueue.addToResourcePolicy(
      new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        principals: [new ServicePrincipal('sns.amazonaws.com')],
        actions: ['SQS:SendMessage'],
        resources: [dlQueue.queueArn],
        conditions: {
          ArnEquals: {
            'aws:SourceArn': topic.topicArn,
          },
        },
      }),
    );

    // 创建触发SNS主题的EventBridge规则
    const rule = new events.Rule(this, 'xxxxRule', {
      schedule: events.Schedule.cron({ minute: '0', hour: '0' }), // 每天午夜触发
      targets: [new targets.SnsTopic(topic)],
    });

    // 配置EventBridge规则触发SNS主题(注:此处重复添加了目标,可移除)
    rule.addTarget(new targets.SnsTopic(topic));
  }
}

解决方案

报错核心原因是SNS服务缺少读取死信队列属性的权限,结合代码中的小问题,按以下步骤修复:

  • 补充死信队列的读取权限
    当前队列策略仅允许SNS发送消息,但报错明确要求需要读取队列属性的权限。修改队列资源策略,添加SQS:GetQueueAttributes和SQS:GetQueueUrl动作:

    dlQueue.addToResourcePolicy(
      new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        principals: [new ServicePrincipal('sns.amazonaws.com')],
        actions: ['SQS:SendMessage', 'SQS:GetQueueAttributes', 'SQS:GetQueueUrl'],
        resources: [dlQueue.queueArn],
        conditions: {
          ArnEquals: {
            'aws:SourceArn': topic.topicArn,
          },
        },
      }),
    );
    
  • 显式声明权限依赖(可选)
    虽然CDK会自动处理资源依赖,但显式声明订阅对死信队列及其策略的依赖,可避免时序问题:

    subscription.node.addDependency(dlQueue);
    subscription.node.addDependency(dlQueue.resourcePolicy);
    
  • 移除重复的EventBridge目标
    代码中rule初始化时已添加SnsTopic作为目标,后续重复调用rule.addTarget会生成冗余配置,建议删除该行。

  • 重新部署验证
    部署修改后的栈,进入SNS控制台查看订阅的死信队列配置,报错应会消失。若仍存在,可手动检查队列资源策略是否正确应用,以及SNS服务是否能正常访问队列。


内容的提问来源于stack exchange,提问作者Ehsan Nissar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:12:51