Customer-Managed KMS Keys vs. AWS Managed Encryption | by Teri Radichel | Cloud Security | Nov, 2022
ACM.118 Why might you choose to use a customer-managed key to protect your cloud resources
This is a continuation of my series on Automating Cybersecurity Metrics.
Code in the last post automatically stops a VM after deploying it to help save money when resources are created before they are needed for use.
This post provides a summary of what has been covered in other posts to answer the following question:
Why would you want to use a customer-managed key instead of an AWS-managed key?
Applying encryption in and of itself does not protect your resources. Consider the following:
- Who has permission to use the encryption key that encrypted the resources. Anyone who has permission to use the key can decrypt and access the data. That includes anyone who steals the credentials.
- Who has permission to change or grant new permissions to use the key and access your encrypted resources.
I started thinking through how we might defend against those threats in this post on cloud architecture and KMS keys.
One of the benefits of using your own customer-managed key instead of an AWS-managed key is that you can create a key policy for a customer-managed key to limit who has permission to encrypt and decrypt data using that key. That limits your risk vs. granting anyone in your account permission to decrypt data encrypted with the default AWS encryption.
To understand the benefits of a KMS key policy you first need to understand the difference between IAM and Resource policies.
IAM vs. Trust vs. Resource Policies on AWS
The following post explains the difference between IAM, Resource, and Trust policies on AWS. In a nutshell, IAM Policies grant permission to a user to take actions. A resource policy adds access controls to a resource like a KMS key and defines who can access and take actions on the resource. A trust policy allows a user to assume a role that is allowed to take actions in the IAM Policy assigned to that role.
Why would you want to use both an IAM and a resource policy to limit access to use a KMS key? You can grant different people permission to change the IAM and resource policies to create separation of duties and multiple layers of protection. Keep reading for concrete examples of how to implement segregation of duties in your AWS account. It’s not exactly simple once you get into the weeds of how the different policies work together and nuances of policies you can create for different AWS services that can work with KMS keys.
By leveraging separation of duties you can limit the chance that one person makes a mistake and exposes your data. You can also ensure that a single malicious insider alone cannot expose your data. If one person’s credentials get stolen that will not be enough to access the data.
IAM Policies assign permissions to a principal
In order for a “principal” in AWS to use a KMS key to encrypt and decrypt data, an associated IAM policy needs to grant them permission to do so. (Principals are defined in the above post.) The policy defines the actions they can take and the resources on which the user can take the actions.
We granted users permissions to access the KMS service and specific Keys in IAM Policies throughout the series. We started by creating a KMS Administrator role and IAM Policy.
The KMS administrator has an IAM Policy that allows the user to administer KMS keys but not to use them to encrypt or decrypt data. So even if the KMS administrator grants themself permission to encrypt and decrypt their IAM policy won’t allow it. This is useful if you have separate IAM and KMS administrators.
Resource policies grant access to a resource
A KMS key policy is a resource policy. When you create a customer managed key on AWS you can associate a policy with it that defines who can take actions on a key.
You cannot modify a resource policy on an AWS managed key. From the AWS documentation:
You can view the key policy for an AWS managed key or a customer managed key, but you can only change the key policy for a customer managed key.
Why might you want to use a KMS key policy? I started addressing this question in the following post where we define requirements for separation of duties in our AWS account.
How can we meet the above requirements? We can use a combination of IAM and resource policies. In order to prevent policy mistakes we can try to create reusable templates and thoroughly test them.
A generic KMS Key CloudFormation template
I developed a generic CloudFormation template that would deploy and key and a key policy for all the keys in our account. My code also contains deployment scripts and common functions to reduce the lines of code we need to deploy our solution.
Here’s our starting point, though the code changes throughout the series to support additional use cases.
I refined the code here:
The CloudFormation template got many modifications in later posts an the current version can be found in GitHub here.
The related deployment scripts are in the parent folder. Key aliases are in a sibling folder. Common functions are in the root /Functions folder. You’ll need that for this template to work as designed.
Read all the posts to understand how the code works and any dependencies. I’m not re-explaining all that here.
Key Aliases for Customer-Managed Keys
You can name customer managed keys. This helps you more easily identify an encryption key and its purpose.
We created KMS Key Aliases in this post.
KMS and Systems Manager Parameter Store
AWS Systems Manager Parameter Store has a limited resource policy that doesn’t include access controls at the time of this writing. I wrote about using KMS with AWS SSM Parameter Store here:
Someone made an odd comment on this post. They said AWS cannot see your encryption key. Ok, but that wasn’t what this post was about. I revisited the post and not sure why the person made that comment. For the record, I never said AWS can see your encryption key or your data.
However, anyone who has kms encrypt and decrypt permissions in an IAM policy with no resource restrictions can encrypt and decrypt anything encrypted with AWS encryption. In other words, someone has kms.* and resource: * in an IAM Policy they can encrypt or decrypt anything in your account encrypted with AWS-managed encryption.
If you use a customer-managed key and add a resource policy to the key limiting who can use it, the person with full KMS permissions in their IAM Policy would not be able to use the key to encrypt or decrypt data with that key.
Parameter Store does not offer the same level of access control as AWS Secrets Manager and KMS. The latter two services offer resource policies that allow you to define access restrictions on the resources managed by that service, as well as IAM policy restrictions. SSM Parameter Store policies do not offer the same access controls. (at the time of this writing — that could change any minute now.)
Here’s what we have right now per the above documentation:
Parameter Store parameters cannot currently be shared across accounts as you can do with Secrets Manager.
KMS and Secrets Manager
A number of posts in the series cover how to use AWS Secrets Manager with KMS.
You can limit access to a KMS key only when using AWS Secrets Manager in your KMS key policy:
We later modified that policy to work with other services like EC2 and KMS directly. See the examples at the bottom of this post.
We moved the SSH key stored in SSM Parameter store in the above post to Secrets Manager protected with a KMS key here:
If you read through those posts you can see some of the detailed differences between AWS SSM Parameter Store and AWS Secrets Manager.
You can enforce separation of duties using IAM and Resource Policies
If you leverage IAM and Resource Policies you can create separation of duties within your cloud account to limit blast radius in the event of a security incident. I explain blast radius in my book at the bottom of this post. I present architectures in the examples below that attempt to create separation of duties to protect encrypted resources in your AWS account.
Example 1: Creating Automation Credentials Without Exposing Them to Users
We can overcome some KMS limitations with encrypt and decryption using Secrets Manager resource policies. Although we must grant encrypt and decrypt permissions unfortunately due to the way AWS works, in Secrets Manager we can use a resource policy to limit who can get or put a secret.
The above post also leverages the fact we can create a secret in CloudFormation — something that you cannot do the same way at the moment with Parameter Store (but again that may change any minute).
Example 2: Creating a User-Specific Secret
As a case study in segregation of duties for secrets I started exploring creating a user-specific secret that only a single user can access.
First we looked at the IAM Policies required to create the secret and get the secret.
I started pondering how we might go about implementing segregation of duties here but this wasn’t quite enough.
We looked at KMS encryption and MFA for the Developer user accessing the secret here:
In those post we looked at how we might create a separate user or role to manage the secret policies. We already had an IAM administrator to manage IAM policies an a KMS administrator to manage Key Policies.
Finally, we refined our policies to create a scenario where we have employed separation of duties in such a way that it would take a three-party collusion to obtain unauthorized access to a secret. No guarantees as I am not through testing, but hopefully it demonstrates the concept.
We granted a user access in the console to access a secret so we could enforce MFA with a user-specific policy.
If you read through all the posts you will find that there are limitations with MFA enforcement depending on what type of credentials are in use to perform an action. The AWS documentation on condition policies is a bit misleading. So we ended up with a user-specific policy and console access for the moment (until hopefully some of the above issues are resolved by AWS potentially.)
I didn’t spend too much longer on this because I also plan to move things into separate accounts which may make things easier. More on that later.
Example 3: Auto-generated passwords for Console Access
I explored auto-generating and storing passwords for console access.
This one came with some challenges that make it not an ideal solution due to AWS limitations. I might revisit this later and put this secret in Parameter Store as I plan to move IAM to it’s own account. No one in another account could access the secrets in the IAM account and the IAM users will not be able to login to the AWS console in other accounts. I need to implement and test that to verify it works as I think it will.
Example 4: Creating an EC2 instance only certain people can start
We created an EC2 instance with the latest Linux AMI.
We added an Encryption Key.
We granted the user access to use the key in a key policy. Without that permission they cannot start an encrypted EC2 instance. So one way to only allow certain users to start an EC2 instance is to limit access to who can use the encryption key.
Of course that is not the only way to restrict access but it can help you when designing separation of duties in your AWS account.
If you only check the box to encrypt your EC2 instance with the AWS-managed key, then anyone in the account with generic KMS encrypt and decrypt permissions can start the instance and access the data.
Control Key Rotation with Customer-Managed Keys
The other thing you can do with a customer managed key that you can’t do with a KMS managed key is control your key rotation policy.
AWS KMS automatically rotates AWS managed keys every year (approximately 365 days). You cannot enable or disable key rotation for AWS managed keys.
AWS-managed encryption keys do not count against your KMS quotas.
You can grant cross-account access to a customer-managed key.
This is something I have definitely found useful in the past and will be exploring more throughout this post.
Regional Access Limits with Customer Managed KMS keys
You can limit which keys a key may be used in or use keys in cross-region scenarios with KMS customer-managed keys.
You’ll have more granular control of exactly where a key is in use. This may be useful for organizations trying to comply with GDPR. If a KMS key cannot be used outside of a region then that can help limit data migrating to a region in AWS where it should not exist. It is certainly not the only control you will need but it may help.
Hopefully that gives you some ideas about why you might want to use a customer-managed key with a custom key policy on AWS.
In the next post I’ll summarize some of the differences we have uncovered so far between Secrets Manager and SSM Parameter Store.
Follow for updates.
If you liked this story please clap and follow:
Medium: Teri Radichel or Email List: Teri Radichel
Twitter: @teriradichel or @2ndSightLab
Requests services via LinkedIn: Teri Radichel or IANS Research
© 2nd Sight Lab 2022
All the posts in this series:
Cybersecurity for Executives in the Age of Cloud on Amazon
Need Cloud Security Training? 2nd Sight Lab Cloud Security Training
Is your cloud secure? Hire 2nd Sight Lab for a penetration test or security assessment.
Have a Cybersecurity or Cloud Security Question? Ask Teri Radichel by scheduling a call with IANS Research.
Cybersecurity & Cloud Security Resources by Teri Radichel: Cybersecurity and Cloud security classes, articles, white papers, presentations, and podcasts