adrianhesketh.com

AWS - migrate to MFA

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, https://adrianhesketh.com/2020/11/09/migrate-to-aws-vault, 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 https://adrianhesketh.com/2020/11/09/migrate-to-aws-vault for details, but I needed to do a few things on the AWS side to reduce the permissions on my user.

I’ll go through the steps.

Create an Administrator IAM Role that requires MFA to be in place

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.

Create an IAM Policy that permits the principal (thing that has the Policy attached) to assume the Administrator role

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"
            }
        }
    }
}

Create an IAM Policy that allows password reset and other basic functionality

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}"
    }
  ]
}

Create an Administrators IAM Group, attach the new policies, and add your users to it

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.

Strip back user permissions

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.

Next

Check out migrate-to-aws-vault to configure CLI access.