💾 Archived View for capsule.adrianhesketh.com › 2020 › 11 › 09 › aws-migrate-to-mfa captured on 2023-12-28 at 15:23:34. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2021-11-30)
-=-=-=-=-=-=-
Like many people, I've set up a personal account, but I haven't really given it much attention. I set up my account, set myself up an IAM user with Admin access, created some access keys and put them into my `~/.aws/credentials` file.
This isn't very secure. The credentials are almost as powerful as the root ones, and are just stored on disk. If they were leaked, anyone that got hold of them could abuse my account and potentially spend a lot of money.
I migrated to `aws-vault` a while back [0] to stop keeping my credentials unencryped on disk. `aws-vault` uses a password manager to store the credentials, but when I want to use them, it simply puts them into the shell environment (you can see this by typing `env | grep AWS`). The credentials are long-lived, and are also powerful enough to be used to create new users and generally wreak havoc in my account, so if they're leaked, it would be bad news.
It's best practice to give AWS IAM Users very basic permissions in place, but give them permission to "assume" a more powerful role to do their work. "Assuming a role" in AWS means that you use the AWS STS service to generate credentials that are valid for a short duration, typically one hour. You can configure roles to requires multi-factor authentication to be assumed, so even if the basic credentials are leaked, the fact that multi-factor authentication is also required stops the attacker from getting any further.
So, I decided to give my personal account some of the same features as my clients.
`aws-vault` supports this workflow by adding the `mfa_serial` and `role_arn` into the `~/.aws/config` file [see migrate-to-aws-vault for details](/2020/11/09/migrate-to-aws-vault), but I needed to do a few things on the AWS side to reduce the permissions on my user.
- Create an `Administrator` IAM Role for me to assume that requires MFA. (`Administrator` role)
- Create an IAM Policy that allows the IAM Role to be assumed. (`allowAssumeAdministratorRole` policy)
- Create an IAM Policy that allows users to manage their passwords. (`allowAccountManagement` policy)
- Create an IAM Group that has the 2 new IAM Policies attached. (`Administrators` group)
- Add my user to the new IAM Group.
- Remove any directly attached IAM Policies and Inline Policies from my user.
I'll go through the steps.
First, you need to set up a new role for us to assume. In my case, I created a role called Administrator and attached the AWS built-in Administrator policy to it because I want to have full permissions in my account once I assume that role, using MFA.
To create the IAM Role this within the console, within IAM you can click on "Create role", choose "Another AWS account" as the trusted entity, enter your AWS account ID in the box, check the "Require MFA" checkbox and click "Next: Permissions" to choose what permissions the role will have. I checked "AdministratorAccess" before moving on to giving it the name "Administrator".
The role is then ready to use, but first you need to give your user permission to assume it. To do this, you'll need to attach an IAM Policy to your user that gives your user the permission to assume the new Administrator IAM Role.
You _can_ attach IAM Policies to your user in a few ways. You can attach an IAM Policy directly, create an IAM Policy and attach that, or you can add the user to Groups that have the IAM Policies attached.
In my day-to-day work, I use Groups because we're assigning permissions to people based on their job role rather than who they are, so that's what I'll do here, but first I'll create the two policies we need.
I've called it `allowAssumeAdministratorRole` because it allows the holder of the Policy to assume the Administrator IAM Role. You can do this in the IAM console by clicking on "Policies", "Create policy", then choosing the JSON tab to copy/paste in the code. Remember to modify the resource ARN to use your AWS Account ID and IAM Role name.
{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::<your_account_id>:role/Administrator", "Condition": { "BoolIfExists": { "aws:MultiFactorAuthPresent": "true" } } } }
I called this IAM Policy `allowAccountManagement`.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowViewAccountInfo", "Effect": "Allow", "Action": [ "iam:GetAccountPasswordPolicy", "iam:GetAccountSummary", "iam:ListVirtualMFADevices" ], "Resource": "*" }, { "Sid": "AllowManageOwnPasswords", "Effect": "Allow", "Action": ["iam:ChangePassword", "iam:GetUser"], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "AllowManageOwnAccessKeys", "Effect": "Allow", "Action": [ "iam:CreateAccessKey", "iam:DeleteAccessKey", "iam:ListAccessKeys", "iam:UpdateAccessKey" ], "Resource": "arn:aws:iam::*:user/${aws:username}" }, { "Sid": "AllowManageOwnSigningCertificates", "Effect": "Allow", "Action": [ "iam:DeleteSigningCertificate", "iam:ListSigningCertificates", "iam:UpdateSigningCertificate", "iam:UploadSigningCertificate" ], "Resource": "arn:aws:iam::*:user/${aws:username}" } ] }
Head over to the IAM Console, click on "Groups" and then the "Create New Group" button. You'll be prompted to enter a group name, I chose "Administrators".
Don't attach the "AdministratorAccess" Policy, or you'll bypass the need to assume the role and require MFA, choose the two new policies we've just made `allowAssumeAdministratorRole` and `allowAccountManagement`, then click "Next Step" and "Create Group".
Next, you should add your Administrator Users to the new Administrators Group. This will give them permission to assume the Administrator role.
There's no point doing all this unless you remember to remove excess permissions from the user(s), so make sure that the only policies your user has are inherited from the Groups you've assigned them to. In my case, it looks like this.
All of this means that your users won't be able to use the AWS Console after authentication without first assuming the role you've given them access to.
The easiest thing to do is to give your users a link that adds the role to the user information drop down in the AWS Console. You can find the link by viewing the IAM Role you created within the console.
Check out [1] to see how to configure CLI access.