Your AWS account is one of the most valuable things you own if you run a business on AWS. If you only own a single AWS account, you’re facing a serious security risk! The post will show you why this a problem and how you can solve it.

The Risky Default: A Single AWS Account

A single AWS account contains IAM users together with EC2 virtual servers, S3 buckets, RDS databases, and everything else you need to run your business. You basically have two ways to log in to your account: AWS Management Console (using username + password) or AWS access credentials used by the CLI and SDKs. The figure demonstrates how this works.

When you type something like

$ aws ec2 describe-instances

into your terminal, your AWS access credentials (usually residing somewhere at ~/.aws/) are used to authenticate your request. You authenticate as an IAM user. The IAM user in most cases has AdministratorAccess , which means you can do anything. Why? Because you need to be able to administer all services. If someone gets access to your AWS access credentials, you’re in trouble.

You can improve this situations two ways.

1st improvement: don’t use a user with AdministratorAccess

To follow the principle of least privilege, it’s very unlikely that AdministratorAccess is what you need. PowerUserAccess is an improvement, because it doesn’t let you use the IAM service. Much better is having ReadOnlyAccess and using writing permissions only when needed. But that’s difficult to implement using IAM users. You need to create a user for each “least privilege,” and you need to create access credentials for each user. This quickly becomes unmanageable if you aren’t the only user in your AWS account. I’ll call this security debt.

2nd improvement: use multi-factor authentication

AWS provides excellent support for multi-factor authentication (MFA). You can use a hardware device or a software device to generate a token. Your password or access credentials together with the MFA token are then used to authenticate. Getting access to your account is now much more difficult.

Read on to learn how to implement these improvements.

Separating Concerns With a Bastion Account

Instead of a single AWS account, you create another account. I’ll call this your bastion account. The bastion account contains only your IAM users — nothing else. The figure illustrates the idea.

IAM users in the bastion account are very limited. They can only get temporary credentials and assume a role. Implement this by creating a group in the bastion account with an inline policy, as follows:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "1", "Effect": "Allow", "Action": [ "sts:AssumeRole" ], "Resource": "*", "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}} }, { "Sid": "2", "Effect": "Allow", "Action": [ "sts:GetSessionToken" ], "Resource": "*" } ] }

Assign this group to all the IAM users in the bastion account. Make sure they don’t have any other policies attached!

The first Statement lets a user assume a role (but only if the request is authenticated using MFA). The second Statement lets a user get a temporary session by providing the MFA token. Let’s look at how this works.

The Secure Solution: MFA With Role Delegation

It’s time to summarize the solution: How does it work? The following figure shows the MFA authentication and role-delegation flow.

You have AWS access credentials for your IAM user in the bastion account on your machine (usually in ~/.aws/ or in your environment variables). You make a call to the AWS API to get temporary credentials by providing a MFA token. If the MFA token is valid, you’ve created a temporary session for your IAM user in the bastion account. You receive temporary credentials to authenticate as your IAM user. With the temporary credentials, you can assume a role in another account (this wasn’t possible before, because assuming a role is only allowed for this user if the user is authenticated with MFA). To assume a role in another account, the role must explicitly be allowed to be used with your account! The maximum permissions a role should have is PowerUserAccess . Don’t allow the role to interact with IAM! You receive temporary credentials and can begin working with your AWS account.

Implementation

The AWS CLI can be used with MFA. Andreas has wirrten up detailed instructions here.

Read more about Amazon Web Services

Are you interested in learning more about Amazon Web Services? Andreas and I are writing a book called Amazon Web Services in Action, published by Manning. The book is written for developers and DevOps engineers who are moving traditionally deployed distributed applications to the AWS platform. No experience with AWS is required.