Tools Resources

Understanding the Integration Between KMS and Secrets Manager on AWS

author_profile
Noga Yam Amitai
Wednesday, Mar 8th, 2023

Key Management Service (KMS), and Secrets Manager are easy to mix, not only because of the similarity in names but also because one might get confused over the purpose of each one. At a high level, KMS is a service that allows users to manage cryptographic keys for encryption, decryption, signing, and additional operations. We recommend that you read our technical blog on KMS to dive more deeply into the service and its features. Secrets Manager lets you store secrets – such as passwords and API keys, to avoid hard coding them in your applications. To better protect secrets, AWS Secrets Manager uses KMS to encrypt their content. In this post, we will cover the integration between the two services to better understand how they work.  

About Secrets Manager 
Secrets Manager is an AWS service that encrypts and stores your secrets, and transparently decrypts and returns them to you in plaintext. Secrets Manager enables you to replace hardcoded credentials in your code, with API calls to Secrets Manager to retrieve the secret’s value programmatically. This helps prevent credential compromise because it reduces the probability of exposing a secret value during the development lifecycle. 

Secrets Manager uses envelope encryption with AWS KMS keys and data keys to protect each secret value. In an envelope encryption the initial key is used to generate a data key (256-bit Advanced Encryption Standard (AES) symmetric data key), which is used to encrypt the secret value. 

The Integration between Secrets Manager and KMS 

The Secrets Manager service has its own KMS managed key named aws/secretsmanager. By examining this managed key policy, we can see that it allows any identity within the account to use the key through the Secrets Manager service. The diagram below shows that the end user cannot use the managed KMS Key aws/secretmanager directly (in red), but only through the AWS Secrets Manager service (in green). 

The Integration between Secrets Manager and KMS

Below is the key policy of the aws/secretsmanager managed KMS key: 

key policy of the aws/secretsmanager managed KMS key

This key policy contains the following statements:  

  1. The first and second statements allow users, groups, and roles in the account to use this KMS managed key for the specified actions. The kms:ViaService condition statement, restricts the use to requests that the Secrets Manager performs on the users’ behalf.
  2. As part of the first statement, permission to create a grant is given. Secrets Manager can create grants for the KMS key on the user's behalf, although it does not use grants to gain access to the KMS key.
  3. The key policy also allows the AWS account to create IAM policies that permit users to view KMS key properties and revoke grants.  

Creating a secret 

When creating a new secret, there are two options for choosing the encryption key (the KMS key):  

  1. Any symmetric encryption customer managed key in the same AWS account and Region.
  2. An AWS managed key for Secrets Manager - aws/secretsmanager 

There is no limitation on the number of secrets that can be encrypted with the same KMS key. In addition, you can change the encryption key of a secret after the creation (for more information, see modify a secret).  With both options the secret value encryption process will be the same. 

Encryption and decryption processes (from AWS’s documentation)  

To encrypt the secret value, Secrets Manager uses the following process:  

  1. Secrets Manager calls the AWS KMS GenerateDataKey operation with the ID of the KMS key for the secret and a request for a 256-bit Advanced Encryption Standard (AES) symmetric key. AWS KMS returns a plaintext data key and a copy of that data key encrypted under the KMS key.  
  2. Secrets Manager uses the plaintext data key and the AES algorithm to encrypt the secret value outside of AWS KMS. It removes the plaintext key from memory as soon as possible after using it.
  3. Secrets Manager stores the encrypted data key in the metadata of the secret, so it is available to decrypt the secret value. However, none of the Secrets Manager APIs return the encrypted secret or the encrypted data key.  

To decrypt an encrypted secret value:  

  1. Secrets Manager calls the AWS KMS Decrypt operation and passes on the encrypted data key.
  2. AWS KMS uses the KMS key for the secret to decrypt the data key. It returns the plaintext data key. 
  3. Secrets Manager uses the plaintext data key to decrypt the secret value. Then it removes the data key from memory as soon as possible. 

Who can decrypt a secret?  
Finally, we get to the main purpose of this research - who can decrypt a secret that was encrypted with a KMS key? As you can probably tell by now, it is not so easy to deduce if one has sufficient permissions for decrypting a secret stored in the Secrets Manager. There are a lot of factors to consider, so we will analyze the simplest cases and draw some conclusions about the rest. 

First Case – A secret encrypted with aws/secretsmanager key  
To check for the required permissions, let’s create a secret and choose to encrypt it with the aws/secretsmanager KMS managed key.  

aws/secretsmanager key policy

As mentioned above, the aws/secretsmanager key policy allows users, groups and roles from the same account to perform the action kms:Decrypt via the Secrets Manager service. After the secret was successfully created, we will create a policy that allows to perform the secretmanager:getSecretValue action on our new secret. 

The policy:  

perform the secretmanager:getSecretValue action

Next, we will create an IAM role and attach the policy above to it: 

IAM role

After creating the above role and attaching the policy, we can use the following command to assume the role:  <em>aws sts assume-role --role-arn ROLE-ARN --role-session-name SESSION-NAME</em>

Use the temporary credentials provided to act on the role’s behalf as described here.  Run the command bellow to validate that the role’s identity is in use: <em>aws sts get-caller-identity</em>

 Let's check if we can decrypt the secret:  
<em>aws secretsmanager get-secret-value --secret-id SECRET-ARN --region SECRET-REGION</em> 

Success, we got the secret value back!  

This means that assuming we know the secret’s ARN (if not, we will also need the secretsmanager:ListSecrets permission), the secretmanager:GetSecretValue is enough to decrypt a resource that was encrypted with aws/secretsmanager KMS managed key.  
 

External Cloud Attack Surface Now

Second Case – A secret encrypted with a custom-managed key  
First, we will create a KMS key without giving any permissions to our role (the one we have created in the previous section) in the key policy.  

A secret encrypted with a custom-managed key 

Now, let’s change the encryption key of our secret to the key we just created.  

Encryption key

Without adding any permissions to our policy, we will check if we can decrypt the secret:  
<em>aws secretsmanager get-secret-value --secret-id SECRET-ARN --region SECRET-REGION</em>  

Adding any permissions to our policy,

We got an Access Denied error and could not retrieve the secret’s value. The error message ”Access to KMS is not allowed” specifies that we miss permissions to use the KMS service.  
  
Let’s try to add the kms:Decrypt permission to our policy and specify the exact KMS key ”kms-demo” that we used to encrypt the secret as the resource in the policy statement. 

kms:Decrypt permission to our policy

Let’s try again to get the secret value we the updated policy permissions.  

Secret value we the updated policy permissions

This attempt was successful, meaning that the required permissions to decrypt a secret that is encrypted with a customer managed key are secretmanager:GetSecretValue, kms:Decrypt (assuming we know the secret’s ARN, otherwise the secretsmanager:ListSecrets permission is also required).  

An important thing to mention is that we have three options for giving the role the kms:Decrypt permission:  

  1. As demonstrated – Granting this permission through an IAM policy, only if the key policy allows the use of IAM permissions. 
  2. Using the key policy – We could add a statement to the key policy that allows our role to perform the action kms:Decrypt.  
  3. Creating a grant that gives the role permission to perform the decrypt operation. 

You can read the full details on each one of those methods in our technical blog about KMS.   

Conclusion 

AWS Key Management Service (KMS) and AWS Secrets Manager are two important services that work together to provide secure key management and secret storage. Understanding the integration between the two is crucial for ensuring the security of AWS resources and our data. By following best practices and implementing proper access controls, users can effectively manage their keys and secrets and prevent unauthorized access.

Popup Image