Security

SNS/SQS KMS Access Denied: Cross-Service-Verschlüsselungsberechtigungen beheben

2026-05-03 · 7 Min. Lesezeit

Sie haben gerade die serverseitige Verschlüsselung für Ihre SQS-Queue aktiviert. Ein verantwortungsvoller Schritt — Daten sollten immer verschlüsselt gespeichert werden. Aber jetzt kann Ihr SNS-Topic keine Nachrichten mehr an die Queue zustellen. Die Nachrichten verschwinden lautlos, und wenn Sie die SNS-Zustellungsprotokolle prüfen, sehen Sie Folgendes:

{
  "notification": {
    "messageId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE",
    "topicArn": "arn:aws:sns:us-east-1:123456789012:order-events"
  },
  "delivery": {
    "statusCode": 403,
    "providerResponse": "{\"ErrorCode\":\"KMS.AccessDeniedException\",\"ErrorMessage\":\"User: arn:aws:iam::123456789012:root is not authorized to perform: kms:GenerateDataKey on resource: arn:aws:kms:us-east-1:123456789012:key/abc123-def456\",\"sqsRequestId\":\"xxx\"}"
  }
}

Oder vielleicht scheitert Ihre Lambda-Funktion beim Lesen einer verschlüsselten SQS-Queue:

[ERROR] KMSAccessDeniedException: The ciphertext refers to a customer master
key that does not exist, does not exist in this region, or you are not allowed
to access.

Diese Fehler sind frustrierend, weil die Verschlüsselungskonfiguration korrekt aussieht — die Queue ist verschlüsselt, der Schlüssel existiert und die IAM-Policies scheinen in Ordnung. Das Problem liegt darin, dass KMS-Key-Policies nach einem anderen Berechtigungsmodell funktionieren als die meisten AWS-Dienste, und Cross-Service-Verschlüsselung Berechtigungen erfordert, die nicht offensichtlich sind.

Das Problem verstehen: Warum Cross-Service-KMS fehlschlägt

Wenn Sie eine SQS-Queue mit einem KMS-Schlüssel verschlüsseln, benötigt jeder Dienst, der in die Queue schreibt oder daraus liest, die Berechtigung, diesen Schlüssel zu verwenden. Das ist ein wichtiger Unterschied zu unverschlüsselten Queues:

  • SNS benötigt kms:GenerateDataKey und kms:Decrypt zum Publizieren von Nachrichten
  • Lambda benötigt kms:Decrypt zum Abrufen und Lesen von Nachrichten
  • S3-Event-Benachrichtigungen benötigen kms:GenerateDataKey zum Publizieren an verschlüsselte SNS-Topics
  • EventBridge benötigt ähnliche Berechtigungen bei verschlüsselten Ziel-Queues

Die Berechtigungen müssen an zwei Stellen gewährt werden: in der IAM-Policy des aufrufenden Principals und in der KMS-Key-Policy selbst. Fehlt eine davon, kommt es zur AccessDeniedException.

Ursache 1: AWS-Managed Key (aws/sqs) bei Cross-Service-Kommunikation

Dies ist der häufigste Fehler, den ich in der Praxis sehe. Wenn Sie die Verschlüsselung einer SQS-Queue über die Konsole aktivieren, ist die Standardoption der AWS-verwaltete Schlüssel alias/aws/sqs. Dieser Schlüssel funktioniert einwandfrei für direkte API-Aufrufe von IAM-Benutzern und -Rollen, aber er kann nicht von AWS-Service-Principals wie sns.amazonaws.com verwendet werden.

Prüfen Sie, welchen Schlüssel Ihre Queue verwendet:

aws sqs get-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-queue \
  --attribute-names KmsMasterKeyId \
  --query 'Attributes.KmsMasterKeyId' \
  --output text

Wenn dies alias/aws/sqs oder einen ARN mit alias/aws/sqs zurückgibt, ist das Ihr Problem. Sie müssen zu einem kundenverwalteten KMS-Schlüssel (CMK) wechseln, damit Sie die Key-Policy anpassen können, um anderen AWS-Diensten Zugriff zu gewähren.

Die Lösung: Kundenverwalteten Schlüssel erstellen und verwenden

# Kundenverwalteten Schlüssel erstellen
aws kms create-key \
  --description "Schluessel fuer Order-Queue-Verschluesselung" \
  --query 'KeyMetadata.KeyId' \
  --output text

Speichern Sie die Key-ID und erstellen Sie einen Alias für einfache Referenzierung:

aws kms create-alias \
  --alias-name alias/order-queue-key \
  --target-key-id YOUR_KEY_ID

Aktualisieren Sie die SQS-Queue mit dem neuen Schlüssel:

aws sqs set-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-queue \
  --attributes '{"KmsMasterKeyId":"YOUR_KEY_ID"}'

Ursache 2: KMS-Key-Policy ohne Service-Principal-Berechtigungen

Selbst mit einem kundenverwalteten Schlüssel muss die KMS-Key-Policy den AWS-Service-Principals, die mit der verschlüsselten Queue interagieren müssen, explizit Berechtigungen erteilen. Standardmäßig vertraut ein neuer KMS-Schlüssel nur dem Account-Root und den Key-Administratoren.

Prüfen Sie die aktuelle Key-Policy:

aws kms get-key-policy \
  --key-id YOUR_KEY_ID \
  --policy-name default \
  --output text

Die Lösung: SNS-Service-Principal zur Key-Policy hinzufügen

Fügen Sie der Key-Policy ein Statement hinzu, das dem SNS-Service-Principal die Nutzung des Schlüssels erlaubt:

{
  "Sid": "AllowSNSToUseKey",
  "Effect": "Allow",
  "Principal": {
    "Service": "sns.amazonaws.com"
  },
  "Action": [
    "kms:GenerateDataKey",
    "kms:Decrypt"
  ],
  "Resource": "*",
  "Condition": {
    "ArnLike": {
      "aws:SourceArn": "arn:aws:sns:us-east-1:123456789012:order-events"
    }
  }
}

Wenden Sie die aktualisierte Key-Policy an:

aws kms put-key-policy \
  --key-id YOUR_KEY_ID \
  --policy-name default \
  --policy file://key-policy.json

Der Condition-Block ist sicherheitskritisch. Ohne ihn könnte jedes SNS-Topic in jedem Account Ihren Schlüssel verwenden. Begrenzen Sie die Condition immer auf spezifische Source-ARNs.

S3-Service-Principal hinzufügen (für S3-Event-Benachrichtigungen)

Wenn S3-Event-Benachrichtigungen an ein verschlüsseltes SNS-Topic oder eine SQS-Queue publizieren, fügen Sie auch den S3-Service-Principal hinzu:

{
  "Sid": "AllowS3ToUseKey",
  "Effect": "Allow",
  "Principal": {
    "Service": "s3.amazonaws.com"
  },
  "Action": [
    "kms:GenerateDataKey",
    "kms:Decrypt"
  ],
  "Resource": "*",
  "Condition": {
    "ArnLike": {
      "aws:SourceArn": "arn:aws:s3:::my-bucket"
    }
  }
}

Ursache 3: Lambda-Ausführungsrolle ohne kms:Decrypt

Wenn Lambda eine verschlüsselte SQS-Queue pollt, muss die Lambda-Ausführungsrolle die Berechtigung kms:Decrypt für den KMS-Schlüssel haben. Das ist unabhängig von den SQS-Berechtigungen — sqs:ReceiveMessage allein reicht nicht aus.

Prüfen Sie die Lambda-Ausführungsrolle:

# Ausführungsrollen-ARN abrufen
aws lambda get-function-configuration \
  --function-name order-processor \
  --query 'Role' \
  --output text

# Angehängte Policies auflisten
aws iam list-attached-role-policies \
  --role-name order-processor-role

# Inline-Policies prüfen
aws iam list-role-policies \
  --role-name order-processor-role

Die Lösung: KMS-Berechtigungen zur Lambda-Rolle hinzufügen

Fügen Sie diese Policy zur Lambda-Ausführungsrolle hinzu:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:DescribeKey"
      ],
      "Resource": "arn:aws:kms:us-east-1:123456789012:key/YOUR_KEY_ID"
    }
  ]
}
aws iam put-role-policy \
  --role-name order-processor-role \
  --policy-name KMSDecryptForSQS \
  --policy-document file://kms-decrypt-policy.json

Stellen Sie außerdem sicher, dass die KMS-Key-Policy ein Statement enthält, das die Lambda-Ausführungsrolle erlaubt:

{
  "Sid": "AllowLambdaRoleToDecrypt",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::123456789012:role/order-processor-role"
  },
  "Action": [
    "kms:Decrypt",
    "kms:DescribeKey"
  ],
  "Resource": "*"
}

Ursache 4: Cross-Account verschlüsselte Queue-Subscriptions

Cross-Account-Setups fügen eine weitere Komplexitätsebene hinzu. Wenn ein SNS-Topic in Account A an eine verschlüsselte SQS-Queue in Account B publiziert, benötigen Sie Berechtigungen an drei Stellen: der SNS-Topic-Policy, der SQS-Queue-Policy und der KMS-Key-Policy in Account B.

Die KMS-Key-Policy in Account B muss dem SNS-Service-Principal Zugriff gewähren, eingeschränkt durch den Source-Topic-ARN aus Account A:

{
  "Sid": "AllowCrossAccountSNS",
  "Effect": "Allow",
  "Principal": {
    "Service": "sns.amazonaws.com"
  },
  "Action": [
    "kms:GenerateDataKey",
    "kms:Decrypt"
  ],
  "Resource": "*",
  "Condition": {
    "ArnLike": {
      "aws:SourceArn": "arn:aws:sns:us-east-1:111111111111:order-events"
    }
  }
}

Verifizieren Sie, dass die SQS-Queue-Policy auch dem SNS-Topic aus Account A das Senden von Nachrichten erlaubt:

aws sqs get-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/222222222222/order-queue \
  --attribute-names Policy \
  --query 'Attributes.Policy' \
  --output text | python3 -m json.tool

Ursache 5: KMS-Schlüssel in einer anderen Region

KMS-Schlüssel sind regional. Wenn Ihre SQS-Queue in us-east-1 liegt, aber der KMS-Schlüssel-ARN auf einen Schlüssel in eu-west-1 verweist, wird die Verschlüsselung fehlschlagen. Dies kann passieren, wenn Infrastrukturkonfigurationen zwischen Regionen kopiert werden.

Verifizieren Sie, dass die Schlüssel-Region mit der Queue-Region übereinstimmt:

# Region aus dem Key-ARN prüfen
aws sqs get-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-queue \
  --attribute-names KmsMasterKeyId \
  --output text

Das Key-ARN-Format ist arn:aws:kms:REGION:ACCOUNT:key/KEY_ID. Stellen Sie sicher, dass REGION mit der Region der SQS-Queue übereinstimmt.

Schritt-für-Schritt-Diagnose

Wenn Sie auf einen KMS-Access-Denied-Fehler mit SNS/SQS stoßen, folgen Sie dieser systematischen Checkliste:

  1. KMS-Schlüssel identifizieren, der von der Queue oder dem Topic verwendet wird
  2. Prüfen, ob es ein AWS-verwalteter Schlüssel ist — wenn ja, zu einem kundenverwalteten Schlüssel wechseln
  3. KMS-Key-Policy lesen und sicherstellen, dass die erforderlichen Service-Principals aufgeführt sind
  4. IAM-Policies prüfen auf der publizierenden/konsumierenden Rolle für kms:GenerateDataKey und kms:Decrypt
  5. Mit manuellem Publish testen, um die Lösung zu bestätigen
# SNS-Publish an die Queue testen
aws sns publish \
  --topic-arn arn:aws:sns:us-east-1:123456789012:order-events \
  --message '{"test": "kms-permissions-check"}' \
  --output text
# Prüfen, ob die Nachricht in der Queue ankommt
aws sqs receive-message \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-queue \
  --max-number-of-messages 1 \
  --wait-time-seconds 5

Prävention: Best Practices für verschlüsselte Queues

  1. Verwenden Sie immer kundenverwaltete Schlüssel für Queues, die Nachrichten von anderen AWS-Diensten empfangen. AWS-verwaltete Schlüssel sind einfacher, können aber keine Cross-Service-Berechtigungen gewähren.

  2. Nutzen Sie CloudTrail zur KMS-Überwachung. Aktivieren Sie CloudTrail-Logging für KMS-API-Aufrufe, damit Sie genau sehen können, welche Principals abgelehnt werden:

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=Decrypt \
  --start-time 2026-05-03T00:00:00Z \
  --max-results 20 \
  --query 'Events[*].{Time:EventTime,User:Username,Error:CloudTrailEvent}' \
  --output table
  1. Conditions eng eingrenzen. Verwenden Sie immer aws:SourceArn oder aws:SourceAccount Conditions in Key-Policies, um unbeabsichtigten Zugriff zu verhindern.

  2. Infrastructure as Code verwenden. Definieren Sie KMS-Key-Policies zusammen mit den Queues und Topics in CloudFormation oder CDK. So werden die Berechtigungen immer gemeinsam deployt und in Pull Requests überprüft.

  3. Verschlüsselung End-to-End testen in Ihrer CI/CD-Pipeline, bevor Sie in die Produktion deployen. Ein einfacher Integrationstest, der eine Nachricht publiziert und aus der verschlüsselten Queue empfängt, erkennt Berechtigungsprobleme, bevor sie die Produktion erreichen.

Hilfe bei KMS-Berechtigungen nötig?

Cross-Service-Verschlüsselung in AWS ist leistungsfähig, aber das Berechtigungsmodell ist wirklich komplex. Wenn Sie Stunden mit dem Debugging von KMS-Access-Denied-Fehlern verbringen oder sicherstellen möchten, dass Ihre Verschlüsselungsarchitektur von Anfang an den AWS-Best-Practices folgt, können wir helfen. Kontaktieren Sie uns für eine kostenlose AWS-Beratung — wir haben Hunderte dieser Berechtigungskonfigurationen entwirrt und können das Problem typischerweise bereits im ersten Gespräch identifizieren.

Brauchen Sie Hilfe mit Ihrer AWS-Infrastruktur?

Buchen Sie ein kostenloses 30-Minuten-Gespräch.