6 min read

Understanding S3 Encryption

I think that there is enough confusion when talking about encryption in S3 that it’s worth a short overview to help you avoid mistakes and a false sense of security.

You may be looking at S3 encryption because you want to keep your data safe, or maybe to check off a few boxes with regulation, but at the end of the day, we all want private information to stay private.

S3 gives us a few options for encryption, and I hope that this post will help you pick the right one for your requirements. Each option has its own tradeoffs, but it should be pretty straightforward to secure your data for most use cases.

Some terminology and setting expectations

Before we dive into the specifics of S3, I think it’s important to go over a few terms to make sure we are all aligned.

If you are not sure what “Encryption at Rest” or “Encryption in Transit” means, I suggest that you take a few minutes to go over these terms:

Encryption in Transit and Rest

Server-side encryption

This is where S3 encrypts the data for you before storing it.

AWS provides you with three options for managing the encryption:

  • S3 Managed Keys
  • Customer managed keys with KMS
  • Customer provided keys

There is a slight difference between the first two options, and the third adds more complexity to the mix.

In most cases, I will see companies using S3 managed keys or customer-managed keys with KMS, as it is a quick way to secure your data without making drastic changes. But as mentioned before, there are tradeoffs, so I recommend evaluating all of the options before making a decision.

Friendly Warning

When you enable S3 server-side encryption on an existing bucket, only new objects will be encrypted.

S3 Managed Keys

With S3 managed keys, you delegate everything to AWS. You basically want to make sure that your data is encrypted and trust AWS to do the whole key management lifecycle:

  • Each object is encrypted with a unique key.
  • The key itself is encrypted with a master key.
  • AWS rotates the master key.
  • As of today, they use AES256.
  • Metadata is always in clear text.

Customer master keys with KMS

This option is similar to S3 managed keys, but with a few slight changes:

  • You control the encryption keys in KMS - for better and worse.
  • AWS keeps an audit trail of who did what and when.
  • You can set rotation for the master key if you wish to do so.

Every time you write an object, S3 will call KMS for creating the data keys (those in the middle) - which adds to KMS cost.

You can reduce that cost by selecting to use S3 Bucket Keys, that act as a temporary middle-man for creating the data keys.

Customer Provided Keys

If you don’t want AWS to manage your keys nor use KMS, you still have the option of providing your own keys to S3 to perform the encryption and decryption for you.

That means that in read and write requests, you will provide an encryption key for S3.

S3 will not save this key at any point.

Why would you do that?

One reason is if you want to provide the keys but don’t want to write or execute the code that does the actual encryption and decryption.

Oh, and don’t lose the keys.

Client Side Encryption

When you want to ensure that your data is encrypted end-to-end, and have trust issues, client-side encryption is your friend.

You may be concerned about:

  1. Trusting Amazon with the keys.
  2. Making sure that if someone hacks your AWS account, they will not have access to these objects (but remember that a key will be available in clear text somewhere).
  3. Even though you encrypt the traffic, you want to ensure data encryption at the source rather than at the destination (S3).

One thing to note with client-side encryption is that you are moving the heavy lifting of encryption and decryption, a taxing operation, to your own application.

At scale, this could have a significant effect on your architecture.

Using KMS

Even when you want to encrypt the objects at the application level, you must keep the keys somewhere. That somewhere could be KMS.

With this option for client-side encryption, you store the key in KMS and then use it to create Data Keys to encrypt the object.

  1. Your application asks KMS to create a Data Key.
  2. KMS returns the data key - once in clear text, and once in encrypted form.
  3. Your application uses the plain text version to encrypt the object.
  4. When uploading the object, your application also attaches the encrypted version of the data key to store in the metadata.
  5. When reading an object from S3, your application takes the encrypted data key from the object metadata and asks KMS for the clear text version of it for decryption.

As you can see, there is a lot of back and forth, and the application is still responsible for the encryption and decryption process.

Using Application Keys

When you want the whole process to happen inside your application, you can use your own master key and the S3 client for local encryption.

This means that AWS is not a part of the encryption and decryption process and only stores an encrypted data key in the S3 object metadata.

How does it work?

  1. Your application uses a local master key to interact with the S3 encryption client to create a data key.
  2. It then uses the data key to encrypt the file.
  3. When uploading the file, you also upload the encrypted data key.
  4. When downloading the file, the metadata indicates which data key to use.
  5. The application decrypts the data key.
  6. The application decrypts the data using the decrypted data key.

When selecting this option, you are responsible for the key rotation and storing the master key, so heavy is the burden.

Forcing Encryption in Transit

The last bit I want to talk about in this post is the Encryption in Transit portion, which in S3 is just HTTPS.

By default, S3 allows you access via HTTP (clear text) and HTTPS (encrypted).

You can force using HTTPS by setting a bucket policy:

{
  "Id": "ExamplePolicy",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSSLRequestsOnly",
      "Action": "s3:*",
      "Effect": "Deny",
      "Resource": [
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET",
        "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
      ],
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      },
      "Principal": "*"
    }
  ]
}

Wrapping up

I hope that this post helped you understand what encryption means in S3. It’s a confusing topic and a bit of a rabbit hole if you don’t know what you are looking for.

My advice is to do some backward planning, make sure you spec out what you need to encrypt and how, and only then select the appropriate S3 encryption scheme.

And remember that there is always a tradeoff between security, usability, and performance, so weigh in your risks accordingly.

Want to learn more about DevOps?

An email that dives deep into subjects that are all DevOps

    We won't send you spam. Unsubscribe at any time.
    Powered By ConvertKit