avatarTeri Radichel

Summarize

Pausing to Consider Services vs. Users of KMS Keys

ACM.294 Refactoring our generic KMS Key policy. Is an AWS Service using the key, a user, or both?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

⚙️ Check out my series on Automating Cybersecurity Metrics | Code.

🔒 Related Stories: AWS Security | Application Security | KMS

💻 Free Content on Jobs in Cybersecurity | ✉️ Sign up for the Email List

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In a prior post I tried out a ForEach for a KMS KeyPolicy which was a royal waste of time on two accounts. First, it’s not possible and I didn’t understand the documentation. Secondly, it was overkill.

There’s a much simpler solution I think. Duh. Sometimes the answer is right in front of your face. In fact, the answer was in the template I already wrote and was modifying! I think I’ve hit brain overload at this point with all this infrastructure code, but I’m constantly trying to distill the verbose code down to far fewer lines of code when possible. And that’s what I’m going to do in this post (hopefully.)

This is why reading my blog is like a stream of consciousness, trial and error. Instead of just giving you the right answer like it was magic and I instantly knew it, you get to see how I troubleshoot, think, and work through problems. I guess that may be possibly different then some blogs you might be reading.

Although my attempt at a solution was not a success, it was interesting to take a look at AWS LanguageTransformations and ponder how they work and if I might want to use them for some other use case. Some thoughts about that in the last post.

So on to my much simpler solution. But first why I’m doing this. I started to realize as I struggled with my AWS KMS Key Policy template that I was trying to use the same service parameter (named ServiceParam in my template) passed into the template for services that a user uses the key with and services that need to use the key. I need two different statements to allow each of those things.

I started thinking about all the use cases. Should I have a separate key for users and AWS services? Are there use cases where both need access to a key?

What about CloudTrail — it creates logs and encrypts them with a key. Then the user needs to decrypt and view the logs. So yes.

Are there use cases where I want to use the key with multiple services? Yes. In my development environment, I don’t want to pay for a key for every single different service the developers are using. I may break out an application key that is storing data in systems we build from a key used by deployment systems. But already when deploying my static website code I’ve used a key with an S3 bucket, a key with Elastic Container Registry (ECR) and AWS Secrets Manager. What if I just want to create a key that works with all of that for development purposes or for use by a deployment system of some kind?

When I create the policy I have two different types of principals. I wrote about principals in IAM policies here:

If I’m granting permissions to a user then I need to add this permission:

Principal:
  AWS: [User or Role ARN]

If I’m adding permissions for a service then I need to use this format:

Principal:
  Service: [Service Name].amazonaws.com

Since policy statements are not a resource I can’t loop through them with a ForEach, but I can limit the number of statements I need to create by adding multiple principles to a statement and pass those principals in as a comma delimited string.

In fact, I am already doing that. This is where my duh moment comes into play. Just as I pass in the EncryptARNs and the DecryptARNs and use those in a statement, I can also pass in the EncryptServices and DecryptServices and use those in my services policy statements.

I already have code to do that for users. I can basically replicate that code for the services. I already started passing in parameters to handle this but I can remove some of my condition logic and make everything simpler.

First, I’m going to rename the comma delimited list parameters to match the Encrypt and Decrypt ARN parameters roughly:

I would like to rename ServiceParam but that will break many things so I’m going to leave that as is and add a comment. I’m going to default the value to an empty string and only take action based on this parameter if it is set, because there is too much inconsistency in KMS key implementations to make it worth including and using every time at this point.

If additional permissions and restrictions are required for Secrets Manager and that is the only service used by a particular key, then pass in secretsmanager into that parameter. Otherwise it can be left blank. If the CreateGrant permission is required, pass in ecr or ec2 as the service used with the key.

Recall that I have conditions for these services:

If you’re trying to use a key with ec2, ecr, and secrets manager then obviously you won’t get the necessary code. For backwards compatibility I’m going to leave the ecr and ec2 options in there. But I’m also going to add an AllowCreateGrantParam because that is more flexible for different use cases. If it is set, it too will set the CreateGrantAllowed condition to true.

Certain services require the CreateGrant permission:

You can add a condition to a policy for access only by Secrets Manager.

We may have other use cases for the service parameter in the future and I want to hopefully not break most of my prior scripts so leaving that as is.

I need to change the parameter names uses in these conditions to match what I renamed above:

Next I need to fix the code to work with the above. It seems to me that I can literally copy and paste my user permissions and change the principal tag to Service instead of AWS like so.

However, I think we can remove some of the above permissions. My prior template had less permission for services so hopefully this works. I’ll have to go back and retest all the keys I created. Unfortunately my test scripts have fallen behind, as is typical when you don’t have a lot of resources working on a project.

Here is the final code that deployed. I tested granting access to two services — but I’m not actually going to leave the key deployed that way. I’m only going to grant access to required services.

Key template

Once again it is too long so I will display it in pieces.

Parameters:

Conditions

Mappings:

Resources, with Key Policy Statements to follow

Administrators Statement:

Safety net for Root and to make CloudFormation work:

Statement for AWS principals

Just a reminder about Secrets Manager:

While testing I found that you need to allow encrypt and decrypt for your KMS Key Policy in conjunction with AWS Secrets Manager (unless that changed). To better protect your secrets only allow principals either read or write permission on the secret policy and in IAM policies as required. I don’t know if this applies to other services as well but I am just taking that defense in depth approach with all services until if and when that is fixed (if it ever is.)

Statement for AWS services that need permission to encrypt and decrypt:

Outputs:

Function:

Test deploy script (will not actually allow those services unless I need to later):

Well, that worked as far as deploying the key but I still need to make sure it works for all the services that need to use the key. I’ll test that as time allows.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2023

About Teri Radichel:
~~~~~~~~~~~~~~~~~~~~
⭐️ Author: Cybersecurity Books
⭐️ Presentations: Presentations by Teri Radichel
⭐️ Recognition: SANS Award, AWS Security Hero, IANS Faculty
⭐️ Certifications: SANS ~ GSE 240
⭐️ Education: BA Business, Master of Software Engineering, Master of Infosec
⭐️ Company: Penetration Tests, Assessments, Phone Consulting ~ 2nd Sight Lab
Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation
Follow for more stories like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
❤️ Sign Up my Medium Email List
❤️ Twitter: @teriradichel
❤️ LinkedIn: https://www.linkedin.com/in/teriradichel
❤️ Mastodon: @teriradichel@infosec.exchange
❤️ Facebook: 2nd Sight Lab
❤️ YouTube: @2ndsightlab
Kms
Key
Policy
Decrypt
Encrypt
Recommended from ReadMedium