AWS Database Blog

How to encrypt Amazon Aurora using AWS KMS and your own CMK

When selecting a relational database engine, customers look at many different aspects, including management, performance, reliability, automation, and more recently, the ability to natively encrypt data at rest. Amazon Aurora provides a highly available, optimal, and scalable relational database engine that supports both MySQL and PostgreSQL. Amazon Aurora also supports native encryption of data at rest and uses AWS Key Management Service (AWS KMS) to store and manage the keys used for this encryption.

You can use AWS KMS to create, store, and manage your encryption keys. It’s backed by a hardware security module (HSM), which gives you confidence that your keys are stored securely.

AWS KMS is also compliant with many different compliance schemes, including the following:

A feature of AWS KMS is to use customer-managed customer master keys, or CMKs. By using a CMK in AWS KMS, you gain the ability to rotate the key according to your own policies, delete the key, and control access to the key via KMS policies and IAM policies. You can choose to have AWS KMS generate a master key on your behalf, or you can import your own key material using the Import Key feature. By importing your own key material, you can keep a copy under your control and re-import it in the future as needed.

It is important to note that when you import your own key material, you become responsible for the availability and durability of your key. You are allowed only one key per CMK, and ciphertext is not portable between CMKs. For more information, see Considerations for Imported Key Material in the AWS KMS Developer Guide.

Solution diagram and explanation

The following diagram illustrates the solution in this post:

At a high level, the Amazon Aurora database (1) uses a customer master key (2) stored in AWS KMS (3) to encrypt the data (4) at rest in the database (1).

In more detail, Aurora gets a unique 256-bit data encryption key (DEK) from AWS KMS for each Aurora database instance. That DEK is provisioned into memory on Aurora hosts while the database instance is running. A copy of the DEK that is encrypted under the CMK is stored by Amazon RDS so that it can launch future snapshots of the database.

It’s important to note that although multiple keys are stored in memory, none of these keys are written to disk without being encrypted first. The ability to decrypt any keys and to decrypt Aurora snapshots at rest always requires an authenticated call to AWS KMS. This is how we help prevent unauthorized access to encrypted data at rest.

Solution overview

The first step in this process is to generate a new CMK with your imported key material. The overall steps are as follows:

  1. Create a CMK container in AWS KMS with key origin as external.
  2. Download the public wrapping key.
  3. Encrypt the key material with this wrapping key.
  4. Import encrypted key material into the CMK container in AWS KMS.

Next, you configure Amazon Aurora to use the imported CMK to encrypt the data at rest in the database. And finally, you rotate the CMK in AWS KMS by using the UpdateAlias function.

Although I cover AWS KMS policies briefly, this post does not focus on them. For more information about AWS KMS key policies, see Using Key Policies in AWS KMS in the AWS KMS Developer Guide.

Creating a new CMK

First, create a new CMK in AWS KMS:

  1. Sign in to the AWS Management Console and open the IAM console.
  2. In the left navigation pane, choose Encryption keys.
  3. You now need to choose which AWS Region to create the new key in. This Region must be the same as the one in which you will create the Amazon Aurora database instance. This example uses the EU (London) Region.
  4. Choose Create key.
  5. Choose a relevant alias and description for your key. Under Advanced Options, choose External for Key Material Origin. Select the check box and choose Next Step.
  6. Select any key-value pair tags that you want to use for your key. Tags help you identify this key. They can be used to identify the cost center, project code, or owner of the key. Then choose Next Step.
  7. Select the user or role with which you want to administer the key. Administrators cannot use the key to perform encrypt or decrypt operations, but they can modify the key policy to give themselves these permissions. In this example, choose the Admin role, and give the role the ability to delete the key. Then choose Next Step.
  8. Select the user or role to which you want to give key usage permissions. These permissions provide the ability to perform encrypt or decrypt operations, but not manage the key. This example uses AWSServiceRoleForRDS. This role is predefined by AWS and is the service role in which Amazon RDS runs. When you add this role as a key user, it allows the Amazon Aurora database to use the CMK. Then choose Next Step.
  9. Finally, get a summary of the key policy shown as a JSON policy. It is always recommended that you review this to ensure that you are granting the appropriate roles and users to administer and use the key.

You have now created a CMK with relevant permissions into which you can import your key material.

Importing key material

The new CMK is ready to receive your imported key material. In this example, you use OpenSSL to generate a 256-bit symmetric key, and then encrypt this key for import into AWS KMS. For information and instructions on how to download and install OpenSSL, see the OpenSSL website. AWS recommends that you use a more secure method of generating and storing your key material, such as an HSM or other key management system.

AWS KMS provides three different encryption schemes that you can use:

  • RSAES_OAEP_SHA_256 – RSA encryption with OAEP and SHA-256 hash
  • RSAES_OAEP_SHA_1 – RSA encryption with OAEP and SHA-1 hash
  • RSAES_PKCS1_V1_5 – RSA encryption with PKCS#1 v1.5

Because this example is using OpenSSL, I will use RSAES_OAEP_SHA_1. AWS recommends that you use RSAES_OAEP_SHA_256 if it is supported by the HSM or key management system that is being used.

AWS KMS creates a wrapping key and an import token to use for importing the key material. The wrapping key is the public key that is used to encrypt the raw key material before upload. The import token contains metadata to ensure that the material is imported correctly.

For more information, see Importing Key Material in AWS KMS.

  1. This example uses RSAES_OAEP_SHA_1. Choose it in the drop-down list, and then choose Download wrapping key and import token.
  2. This step downloads a file named ImportParameters.zip. Extract the README, ImportToken, and WrappingKey
  3. Use the rand function in OpenSSL as follows to generate a pseudo-random 32-byte, or 256-bit, string and output it to a file named bin. For more information, see The OpenSSL Documentation.
    $ openssl rand -out PlaintextKeyMaterial.bin 32
  4. Next, take the bin file and encrypt it using the WrappingKey downloaded from the console. To do this, use the rsautl function in OpenSSL with the following command. Replace the value of -in with the key material that was generated in step 3. Replace the value of -inkey with the wrapping key extracted in step 2. For more information, see the OpenSSL documentation.
    $ openssl rsautl -encrypt \
                     -in PlaintextKeyMaterial.bin \
                     -oaep \
                     -inkey WrappingKey.bin \
                     -keyform DER \
                     -pubin \
                     -out EncryptedKeyMaterial.bin
  5. Now that you have the key material that is encrypted with the public key, return to the console. Select the I am ready to upload my exported key material check box, and choose Next.
  6. Next, choose the Encrypted key material file that was generated with the OpenSSL rsautl function, and the Import token that was downloaded from the console. Also, choose the option to not have this key automatically expire. Then choose Finish.

You have now completed the import process, and you have created a new CMK that contains the encrypted imported key material.

Encrypting an Aurora database with the imported CMK

You will now create an Amazon Aurora MySQL cluster, and use the CMK to encrypt the data at rest.

For this post, you will use the smallest instance class, db.t2.small, which has 1 vCPU and 2 GiB of RAM. Other instance classes are available with different vCPU and RAM allocations.

  1. On the AWS Management Console, choose Relational Database Service or RDS.
  2. I always double check that I am in the same Region, (EU) London, as the CMK I created. Choose Get started now.
  3. Choose Amazon Aurora as the engine and choose the MySQL 5.6-compatible edition. Then choose Next.
  4. For the DB details, choose the smallest instance class, t2.small. You can also select Multi-AZ deployment if you need the database to be highly available. For more information about instance classes, see DB Instance Class. For information about Multi-AZ deployments, see High Availability (Multi-AZ).
  5. Scroll down to the instance settings. Here you specify your DB instance identifier, a user name, and a password for master access to the database. Then choose Next.
  6. You now need to fill out your networking configuration. Use the default virtual private cloud (VPC) and create a new subnet group. Don’t make your DB accessible to the public, and don’t specify any preference for the Availability Zone. Choose Create new VPC security group. For more information about networking and VPCs for Amazon Aurora, see Working with an Amazon RDS DB Instance in a VPC.
  7. Scrolling down, you can now specify your cluster identifier, database name, and port. Optionally, you can also set the parameter group for the DB and the cluster. Parameter groups control the configuration settings that are applied to the DB instance and cluster. For more information, see Working with DB Parameter Groups.
  8. Scrolling down, you can now specify the encryption key that you want to use. Here you can enable encryption and choose the CMK that you created earlier. To verify, you can check that the KMS key ID matches what was created earlier. For failover priority, leave the preference at default. For more information, see Fault Tolerance for an Aurora DB Cluster.
  9. Scroll down, and choose the backup retention that you want, and whether you want enhanced or standard monitoring. For more information, see Enhanced Monitoring in the Amazon RDS documentation.
  10. Finally, choose Launch DB instance.

You have now created a new, highly available Amazon Aurora cluster. You have specified the CMK that you created earlier to be used to encrypt data at rest.

To verify this, follow these steps:

  1. Go back to the Amazon RDS console and choose Instances in the left navigation pane.
  2. Wait until the instance status is available. if it is not yet available, wait for a few minutes and refresh the page. Then choose one of the database instances that you created.
  3. Scroll down to the Details On the lower-right side, you can see that the database is encrypted, and which key is being used for this encryption.

Key rotation

You might have compliance requirements that make it necessary to periodically rotate keys. AWS KMS provides a couple of options to rotate the CMK. In this post, I am using a CMK with imported key material, and I can’t use the AWS KMS automatic key rotation feature. For more information about automatic key rotation, see Rotating Customer Master Keys.

A recommended approach to manual key rotation is to use key aliases within AWS KMS. This allows users to always select the same key alias when configuring databases, while the key administrator rotates the underlying CMK. By keeping the old CMK, you allow any applications that currently use this key to still decrypt any data that was encrypted by it, as long as the CMK key policy still gives the AWSServiceRoleForRDS role permission as a Key User. It also allows for any new data to be encrypted with the new CMK.

To perform key rotation by updating the alias, you must use the AWS CLI because you can’t perform these steps in the console. For more information, see AWS Command Line Interface.

In this example with Aurora, the database continues to use the old CMK to perform encrypt and decrypt operations. However, any new Amazon RDS instances that are created will use the new CMK.

Next I will go through the steps of creating a new CMK with imported material and then updating the alias.

Follow the same steps in the “Creating a new CMK” and “Importing key material” sections in this post, in which you created a new CMK placeholder and then imported the material. Be sure to choose a different alias. The first CMK you created is MyRDSKey, and the second CMK is MyRDSKeyNew.

  1. After following these steps, you now have two CMKs in AWS KMS: MyRDSKey, which you originally created, and MyRDSKeyNew, which is the key you just created. Note that the Key IDs are different.
  2. You now need to get a list of all the aliases used by the AWS KMS keys. To do this, use the aws kms list-aliases command from the AWS CLI. For more information about this command, see ListAliases.
    $ aws kms list-aliases
    {
      "Aliases": [{
          "AliasArn": "arn:aws:kms:eu-west-2: 111122223333:alias/MyRDSKey",
          "AliasName": "alias/MyRDSKey",
          "TargetKeyId": "641bc676-b15e-461f-8857-a3e8bc7145fb"
          },
          {
          "AliasArn": "arn:aws:kms:eu-west-2: 111122223333:alias/MyRDSKeyNew",
          "AliasName": "alias/MyRDSKeyNew",
          "TargetKeyId": "17f2b4c1-1871-40d2-aaf6-6c020d4b7164"
          }
          ]
    }
  3. Next, change the alias on the key using the aws kms update-alias command from the AWS CLI, which changes the alias on the newly created key. For more information about this command, see UpdateAliases
    $ aws kms update-alias --alias-name alias/MyRDSKey --target-key-id 17f2b4c1-1871-40d2-aaf6-6c020d4b7164
  4. To confirm this change, you can go back to the console and view your KMS keys. Here you can see that the alias of the newly created CMK has changed to MyRDSKey. The alias of the old CMK is now blank.

You have now successfully changed the alias on the CMK. Any databases that use the old CMK still continue to do so for encrypt and decrypt operations by referring to the key ID. Any new databases that are created use the new key with the MyRDSKey alias. The benefit of using the alias here is that any automated provisioning process, scripts, and applications can still call the key via its alias, without having to update them.

Conclusion

In this post, I walked through creating a new CMK with imported material, and then used it to encrypt an Amazon Aurora database. Finally, I created another CMK with different material and rotated the alias of this key.

If you have any questions, comments, or suggestions, please leave a comment below. You can also visit the AWS Forums for Amazon RDS and AWS KMS.

If you want more information about cryptography on AWS, we have documentation available on Cryptography Basics, and a whitepaper on AWS Key Management Service Cryptographic Details.


About the Author

Andrew Robinson is a solutions architect at Amazon Web Services. He works with the AWS customers to provide guidance and technical assistance on database projects, helping them improve the value of their solutions when using AWS.