Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a Cloudfront distribution an AWS KMS key to GET an S3 image encrypted at rest?

I would like to use AWS's Server Side Encryption (SSE) with the AWS Key Management Service (KMS) to encrypt data at rest in S3. (See this AWS blog post detailing SSE-KMS.)

However, I also have the requirement that I use Cloudfront Presigned URLs.

How can I set up a Cloudfront distribution to use a key in AWS KMS to decrypt and use S3 objects encrypted at rest?

(This Boto3 issue seems to be from someone looking for the same answers as me, but with no results).

like image 204
Chris W. Avatar asked May 04 '18 03:05

Chris W.


People also ask

Do I need to specify the AWS KMS key when I download a KMS encrypted object from Amazon S3?

You don't need to specify the AWS KMS key ID when you download an SSE-KMS-encrypted object from an S3 bucket. Instead, you need the permission to decrypt the AWS KMS key.

How does S3 KMS encryption work?

AWS KMS generates a data key, encrypts it under the KMS key, and sends both the plaintext data key and the encrypted data key to Amazon S3. Amazon S3 encrypts the data using the data key and removes the plaintext key from memory as soon as possible after use.

Does CloudFront support KMS?

@LaurentJalbertSimard I haven't tested it, but I found this on the official forum: "CloudFront currently does not support KMS server-side encryption for S3. The reason this does not work is that viewer requests through CloudFront does not have access to the KMS credentials used to encrypt the s3 objects.

Is KMS encrypted at rest?

AWS Key Management Service (AWS KMS) allows you to use keys under your control to encrypt data at rest stored in Amazon S3. The two primary methods for implementing this encryption are server-side encryption (SSE) and client-side encryption (CSE). Each method offers multiple interfaces and API options to choose from.


2 Answers

This was previously not possible because CloudFront didn't support it and because (as I mentioned in comments on John's answer -- which was on the right track) there was no way to roll-your-own solution with Lambda@Edge because the X-Amz-Cf-Id request header --generated on the back side of CloudFront and visible only to S3, not to the trigger invocation -- would invalidate any signature you tried to add to the request inside a Lambda@Edge trigger, because signing of all X-Amz-* headers is mandatory.

But the X-Amz-Cf-Id header value is now exposed to a Lambda@Edge trigger function in the event structure -- not with the other request headers, but as a simple string attribute -- at event.Records[0].cf.config.requestId.

With that value in hand, you can use the execution role credentials and the built-in SDK in the Lambda@Edge environment to generate a signature and and add the necessary headers (including an Authorization header with the derived credential identifier and freshly-generated signature) to the request.

This setup does not use an Origin Access Identifier (OAI) because the Lambda@Edge trigger's IAM Execution Role is used instead of an OAI to persuade S3 that the request is authorized.

Achraf Souk has published an official AWS blog post explaining the solution from start to finish.

https://aws.amazon.com/blogs/networking-and-content-delivery/serving-sse-kms-encrypted-content-from-s3-using-cloudfront/

like image 139
Michael - sqlbot Avatar answered Sep 21 '22 00:09

Michael - sqlbot


Use S3 Presigned URLs. This AWS article discusses how to generate urls using Java, but this is easily ported to another language.

Server-Side Encryption with AWS Key Management Service (SSE-KMS)

like image 21
John Hanley Avatar answered Sep 21 '22 00:09

John Hanley