Search code examples
amazon-web-servicesamazon-s3amazon-sqsaws-cdkamazon-kms

S3 Event notification to KMS_MANAGED encrypted SQS queue (in CDK) not working


I have an architecture developed with CDK with a S3 bucket and an event notification which will send a message to a SQS for each uploaded file to S3.

It works fine.

Now I'm trying to activate the encryption and I have the following:

  • for S3 -> I have activated the encryption using S3_MANAGED key and everything works fine
  • for SQS -> I have activated the encryption using KMS_MANAGED key and there is no message sent to SQS.

So I'm assuming some permissions are missing but I don't know how to fix it.

Do I need to add missing permissions to SQS to read from S3? Or permissions to S3 to send messages to a encrypted SQS?


Solution

  • TL;DR S3 Notifications don't work with sqs.QueueEncryption.KMS_MANAGED. Use a customer-managed key to encrypt the queue.

    AWS Knowledge Base: Why aren’t Amazon S3 event notifications delivered to an Amazon SQS queue that uses server-side encryption?:

    The default AWS managed KMS key can't be modified. You must use a customer managed key ... and add permissions to the KMS key to allow access to a specified service principal.

    Here's a minimal working example:

    // S3 Notifications to a Encrypted Queue
    export class S3SqsStack extends cdk.Stack {
      constructor(scope: Construct, id: string, props: cdk.StackProps) {
        super(scope, id, props);
    
        const bucket = new s3.Bucket(this, 'MyBucket', {
          encryption: s3.BucketEncryption.S3_MANAGED,
        });
    
        // https://aws.amazon.com/premiumsupport/knowledge-center/sqs-s3-event-notification-sse/
        const key = new kms.Key(this, 'MyCustomerKey', {
          policy: new iam.PolicyDocument({
            statements: [
              new iam.PolicyStatement({
                actions: ['kms:GenerateDataKey', 'kms:Decrypt'],
                resources: ['*'], // avoid circularity by not limiting the resource
                principals: [new iam.ServicePrincipal('s3.amazonaws.com')],
              }),
            ],
          }),
        });
    
        const queue = new sqs.Queue(this, 'MyQueue', {
          encryption: sqs.QueueEncryption.KMS,
          encryptionMasterKey: key,
        });
    
        bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.SqsDestination(queue));
      }
    }