avatarTeri Radichel

Summary

The provided content outlines a process for deploying an AWS KMS key with a CloudFormation template, incorporating roles for encryption, decryption, and administration, and discusses troubleshooting key policy update errors.

Abstract

The content is a technical guide that walks through the deployment of an AWS KMS key using a CloudFormation template, which includes roles for encrypting, decrypting, and administering the key. It references previous articles that detail the creation of these roles and a key policy. The author encounters an error during deployment, which suggests that the user deploying the key will be locked out from updating the key policy. The guide explores various solutions, such as adding the deploying user's ARN to the key policy and considering the necessity of including the root user in the policy. The author ultimately resolves the issue, which seemed to stem from a bug in CloudFormation's error messaging or parsing logic, and provides insights into the correct policy configuration. The post concludes with the author's intention to refine the permissions and a note about upcoming content on executing the code with AWS CLI profiles using MFA.

Opinions

  • The author emphasizes the importance of careful testing of deployments to avoid security issues or downtime.
  • There is an opinion that the error message provided by CloudFormation may be incorrect or misleading, suggesting a potential bug in the system.
  • The author advocates for explicit permission granting in IAM policies rather than relying on broader principals like 'root'.
  • The author expresses frustration with the time-consuming nature of configuring AWS policies but acknowledges the necessity of getting the system's security aspects correct.
  • There is a mention of the potential for 'not-so-zero-trust' policies to be implemented due to the complexity and time required for proper configuration.
  • The author plans to update the code and explain the process in future posts, indicating a commitment to continuous improvement and knowledge sharing.

Deploy A KMS Key and Key Policy with CloudFormation

ACM.27 Testing our generic KMS Key template with the roles we created for encrypt, decryption, and administration

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

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

🔒 Related Stories: AWS Security | KMS | Cloud Governance

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

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

In the last post, I covered testing deployments — something far too often overlooked and can lead to security problems or downtime.

In this post I’m going to deploy a KMS key with a CloudFormation template using the ARNS for the roles we created earlier. We wrote some initial code for our key and policy but now we’re going to test it out.

Let’s review what we thought about and created up to this point which we’ll be using to deploy our KMS key and Key Policy.

A generic KMS Key template:

A role that will be allowed to encrypt data:

A role that will be allowed to decrypt data:

A KMS administrator role that can administer our key:

A key policy restricting key use to Secrets Manager:

The IAM scripts in the above posts moved to a single folder with the exception of our IAM batch job policies:

Now we will test the template with the ARNs for the roles we created above and will fix any issues with the code we initially wrote.

Role ARNs — template parameters or exports?

We could do what we’ve done before and use exports from all our other CloudFormation stacks to pass in the ARNs used by our key template. The problem is that in the end, some of the users may be in a different account than the one we are using to create the key. For testing purposes we have everything in a single account but ultimately the admin role will be in the same account as the keys but the encryption and decryption user roles will likely be in a separate account.

Based on those requirements, we’ll use an output for the admin role ARN since we can expect that the CloudFormation stack used to deploy it is in the same account as the key itself. However, we’ll pass in the user ARNs allowed to encrypt and decrypt the data since those are likely coming from external accounts. If we needed to we could share secrets across accounts later to get around this dilemma but for our current testing we’ll simply pass in the ARNS.

Deploy Script

Alright now we can try to deploy our key. We can use a deploy script like before and pass in the two ARNs we need. We can pass in a hard coded description since this particular script is, at the moment, specific to our credential encryption key. What you’ll notice if you run that script is that you’ll get an error like this:

It’s telling us that if we run this script, the user creating the script won’t be able to update the key policy in the future. Hmm, we have key a key administrator. Maybe the error message means that the user deploying the key cannot update the key in the future.

I could temporarily test that theory by adding the user that is running the deployment script (note this was only for testing purposes and has been removed):

We can get the ARN of the current user with the following command:

aws sts get-caller-identity

Run that command and one of the values it returns is the current role used to run the command. I presume you are following my prior instructions to run these commands from an EC2 instance that you assigned a role. :)

We can get only the ARN by using the following command:

aws sts get-caller-identity --query Arn

We can assign the ARN to a variable in our bash script like this:

myarn=$(aws sts get-caller-identity --query Arn)

There are a few things we need to fix with the ARN output by that command:

  • Remove the instance name and trailing slash at the end of the ARN.
  • Replace “sts” with “iam”.
  • Replace “assumed-role” with “role”
  • Remove the double quotes.

We can use cut to remove the instance ID and sed to replace and remove the values we don’t want in our ARN, so it matches the format of our other ARNs.

Let’s add one more section to our KMS key deployment script. For now, we’ll give ourselves full permissions to modify this KMS key while we’re testing. We can restrict these permissions further later after we explore what permissions this ARN requires for deployments.

Delete the CloudFormation stack and try again. Unfortunately, we get the same error.

Should we add the root user to our KMS key policy?

The error message appears to be incorrect because we have given our user all access to any KMS resource. However, CloudFormation still warns us that we are locking ourselves out of the ability to update the key policy. Perhaps the CloudFormation deployment code checks to see if the root user in the AWS account where the key exists has access? It’s hard to know because the error message isn’t pinpointing exactly what the problem is.

Why might CloudFormation want the root user to have access? It could be due to the fact that people have been known to completely lock themselves out of their own resources using a faulty policy. At that point, the only recourse is to contact AWS to correct the problem. So what does AWS want us to do? Perhaps we are supposed to ensure the root user in our account has full access to the key.

It would be easy enough to define a policy statement for the IAM user root, but in some cases “root” refers to more than we think it should. Refer to the documentation to determine exactly what adding root to a key policies does (which could be different for other resources, so always check the documentation.)

When the principal in a key policy statement is an AWS account principal expressed as arn:aws:iam::111122223333:root", the policy statement doesn't give permission to any IAM principal.

Well that’s good but I know that root gives access to more than just the root user in an account so what does it do?

Instead, it gives the AWS account permission to use IAM policies to delegate the permissions specified in the key policy. (A principal in arn:aws:iam::111122223333:root" format does not represent the AWS account root user, despite the use of "root" in the account identifier. However, the account principal represents the account and its administrators, including the account root user.)

I wonder how, exactly, does AWS determine who an “administrator” in the account is. A role? A user? The managed admin policy? I’m not sure so I tend to be more explicit when I grant permissions.

But we could try to add the root user of the account where the key is being deployed to allow any administrator in that account to change the key policy to see if that resolves our problem.

Let’s add the root user to the statement that allows any KMS action for our current user. We can reference the current account ID where the key is being deployed:

- !Sub arn:aws:iam::${AWS::AccountId}:root

Delete the stack and try again.

Same error.

Buggy error messages and parsing logic in CloudFormation?

I later realized the error message may not be accurate at all. Is it a bug? Is it a problem with the parsing logic used by CloudFormation? I’m not sure.

According to a blog post I found, you don’t need to add the root users to your policy. You only need the admin policy, which we have. (??) So I fiddled around with the policy, comparing it to that blog post, and I finally got it to deploy with a few tweaks related to single and double quotes possibly. I changed a couple of things and wrote about the possible cause of the error message here and how I got it working:

Since I got this working I just left my three IAM identities in there as administrators for the moment. I plan to remove them but I have to set up the key administrator user to deploy this script first. That’s going to require an AWS CLI profile with MFA to assume the key administrator role. I’ll explain how to do that in an upcoming post.

Here’s our code at the moment I wrote this post.

KMS Key and Policy CloudFormation Template (for the moment — follow for updates):

Parameters:

Resources

Deployment Script:

As with most developers, I want to get on and actually get the system working and all these AWS policies are taking up a lot of time. And that’s where the not-so-zero-trust policies sneak in. But I will revisit this. In fact, if you’re looking at the code in GitHub it’s already been updated. I’ll explain how I did that and what you need to do to execute the code with AWS CLI profiles that use MFA in upcoming posts.

Update: I realized at some point that I was missing something in regards to services that use KMS keys versus keys that users use with AWS services. Two different things. I fixed that in a future post.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2022

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
AWS
Policy
Cloudsecurity
Recommended from ReadMedium