avatarTeri Radichel

Summarize

Assuming the AWS Organizations Role In a Job that Creates a New AWS Account

ACM.418 Leveraging a container that requires MFA to deploy resources to assume the organizations role after creating a new account

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

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

🔒 Related Stories: AWS Organizations | IAM | Deploying a Static Website

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

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

In the last post I looked at creating an account alias for new AWS Accounts in an Organization but stopped short of assuming the AWS Organizations role.

I’m going to figure out how to do that with my job code in a container that requires MFA in this post.

Fixing our SCP that allows any role action without MFA

Here’s the issue. I want to enforce MFA on anything a user does including assuming a role, so I added an SCP to enforce that in this post:

There’s a gap in this logic however because once I assume a role, then this policy allows that role to assume another role without MFA. That’s called role chaining and can cause security problems if you’re not careful.

For one role to assume another, you’d have to allow that role assumption in the role’s trust policy. But let’s say you never want that to happen?

I can deny the STS Assume Role action for any role:

But in this case the challenge is that in order to assume the role to configure the account as a user, I would have to provide another MFA token and I’m running a script inside a container.

I could possibly pass in two tokens but in this case, I think I’ll just allow the root-orgadminrole to assume the AWS organizations role in any account.

We can disallow role chaining except for the role-orgadmin account something like this, but what’s the problem with the statement below?

Anyone can create a role with that name in any account to bypass the above restriction.

I just saw someone recommending in a question and answer forum to simply remove the account ID to resolve a similar problem. Make sure you understand the implications if you do that.

We can make this more specific by obtaining the ARN from the CloudFormation stack that created the role. Recall that I have a common naming convention for outputs so they always include the ARN and ID output for a resource, so I can use the following (in theory):

If I do that, I have to ensure the role stack is deployed before the policy stack, which is not ideal. But if I create the role, the SCP, and then the user that assumes the role it should be OK.

Well, I fought with Fn::ImportValue for a while and gave up and changed it to a sub. That eliminates the need to create the resources in a particular order. Then I fought with that for a while and couldn’t see what was wrong with it. I hardcoded the value and it worked. Finally, I copied and pasted code that looked pretty much exactly like what I had and it worked.

Tangent — CloudFormation is throwing me these weird errors in policies about tabs in some policies and error messages that tell me absolutely nothing in other policies. I wonder if when I copied and pasted I eliminated some tabs. Not sure. Anyway, it deployed as shown above which is, I think, exactly what I had when I was getting errors.

Like I said, the role in the root account can likely bypass the policy anyway. But that statement makes it clear to anyone looking at the policy that is happening.

By the way I’m also thinking about IAM PassRole here but will deal with that later.

How my container jobs require MFA to get temporary credentials to create an AWS CLI profile — recap

I am running the job to create accounts with the root-orgadminrole and what to assume the AWS Organizations role in a new account I just created to add an account alias.

Recall that I started to create an account deployment script that looks like this, but we’re going to edit it further:

I need to implement the assume_role function but I’m actually going to name it assume_organizations_role in my account_functions.sh file and pass in the account name.

The function can determine the organizations role name, environment name and obtain the account id using the account name and other account functions thanks to our naming convention and id lookup function

But what should the role profile be that calls sts assume-role to assume the organizations account?

Recall that when I run the job using my local test script (a variation of which can run in EC2 userdata later as I demonstrated previously).

  • I first retrieve the user credentials using the role that simulates the EC2 instance role.
  • That role currently requires MFA so I enter a token for the MFA associated with the EC2 instance role (something that won’t be required when running on EC2.)
  • The EC2 instance role obtains the user credentials from Secrets Manager for the specified user. The secret name matches the username.
  • The user passes in a token (I showed how to do this with an EC2 instance) and temporary credentials are retrieved using STS assume role to run the job.
  • The temporary credentials are passed to the container.

The container job/run.sh script executes when the container starts and creates a CLI profile using the temporary credentials.

The role name ($rolename) which is used for the AWS CLI profile name also gets passed to the script ($script) the job runs:

The script that is called gets the role name as the first argument to the script which it names profile. All the functions we call look for a profile value to run commands. This profile value is essentially a global argument with the CLI profile name to use when executing any AWS CLI commands by the job. The profile name matches the role name specified to run the job.

So essentially we can just use the value of $profile to call sts assume-role.

I didn’t really need to re-explain all that for what we are about to do next. I just wanted to walk through all that to remind everyone including myself how it all works.

Assuming the AWS Organizations role in a new account

We can reuse some of the above code to create a profile for the organizations role. In this case, the profile name will be the account name.

First I calculate or retrive the values I need. Thanks to my consistent naming convention I wrote about a few posts back and our account micro-template used for every new account, I can easily calculate the name of the Organizations role in the new account.

Next I assume the role and get temporary credentials:

Create a role profile:

Clear the variables:

Call a command with the new profile to verify it works:

Now I need to pass in the account profile to my account alias functions. If the profile is not provided, use the primary profile name so this will still work with the root account alias I wrote about in the prior post. Otherwise, the account profile that leverages the credentials for the AWS Organizations account role is simply the account name after calling the assume_organizations_role function.

Now I can update my account deployment script to call the create_account_alias function:

What I realized along the way is that if the alias already exists we can’t call the command to create it. I had to address that by checking to see if an alias exists before running the command.

Switching back to the job role

So if we assume the organizations role how do we get back to the original role? Reference the original profile name.

  • The profile for the account role profile is the account name
  • The profile for the original job profile in this case is root-orgadminrole which matches the name of the role that’s running the job.

Now we have a way to configure new accounts. There are likely other things we’ll want to configure for each new account.

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
AWS
Assume Role
Sts
Organizations
Account
Recommended from ReadMedium