How To Create an Amazon Web Services AWS Identity and Access Management IAM Policy That Lets Users Manage Their Own Credentials and Multi-Factor Authentication MFA

I've been digging into Amazon Web Services (AWS)^1^^ user administration. One of my first goals was to create a user, send them their password, and let them manage the rest of their credentials without me.

The various credential types are located under the "My Security Credentials^2^^" section for each user. They are:

1. IAM Password for console access 2. Access keys for CLI, SDK, & API access 3. Multi-factor authentication (MFA) 4. X.509 certificate 5. SSH Keys 6. HTTPS Git credentials for AWS CodeCommit

Amazon provides five built-in IAM policies that provide access to the credential sets. The first one, `IAMFullAccess`, provides full admin control over the Identity and Access Management (IAM) service. Not only does it allow users to manage their own details, it allows them to create, delete, and otherwise mess with any other user, group, policy, role, etc... Not something to give a non-admin user.

A second built-in AWS policy is `IAMReadOnlyAccess`. It does just what it says on the tin, providing read-only access to the various parts of the IAM dashboard. So, no help there when it comes to letting users set their credentials.

The last three built-in policies (and what they correspond to) are:

1. `IAMSelfManageServiceSpecificCredentials` - allows users to update their HTTPS Git credentials for AWS CodeCommit 2. `IAMUserChangePassword` - allows users to update their IAM Password for console access 3. `IAMUserSSHKeys` - allows users to update their SSH Keys

Half way there, but we're still left without the ability to manage "Access keys for CLI, SDK, & API access", "Multi-factor authentication (MFA)", and "X.509 certificate". Since what I was looking for wasn't built-in, I went about building a custom policy myself.

After referencing a half dozen web pages, IAM docs^3</sup> and just as many StackOverflow<sup>4</sup> pages, I came up with the following policy definition. It provides users with control of all six sets of credentials. It also required Multi-Factor Authentication (MFA)<sup>5^^ and locks users out of all AWS services until it's set up.

Code
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["iam:ListVirtualMFADevices"],
      "Resource": "*"
    },
    {
      "Sid": "AllowUsersToManageCoreCredentials",
      "Effect": "Allow",
      "Action": [
        "iam:*AccessKey*",
        "iam:ChangePassword",
        "iam:GetUser",
        "iam:*ServiceSpecificCredential*",
        "iam:*SigningCertificate*"
      ],
      "Resource": ["arn:aws:iam::*:user/${aws:username}"]
    },
    {
      "Sid": "AllowIndividualUserToListOnlyTheirOwnMFA",
      "Effect": "Allow",
      "Action": ["iam:ListMFADevices"],
      "Resource": [
        "arn:aws:iam::*:mfa/*",
        "arn:aws:iam::*:user/${aws:username}"
      ]
    },
    {
      "Sid": "AllowIndividualUserToManageTheirOwnMFA",
      "Effect": "Allow",
      "Action": [
        "iam:CreateVirtualMFADevice",
        "iam:DeleteVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:ResyncMFADevice"
      ],
      "Resource": [
        "arn:aws:iam::*:mfa/${aws:username}",
        "arn:aws:iam::*:user/${aws:username}"
      ]
    },
    {
      "Sid": "AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA",
      "Effect": "Allow",
      "Action": ["iam:DeactivateMFADevice"],
      "Resource": [
        "arn:aws:iam::*:mfa/${aws:username}",
        "arn:aws:iam::*:user/${aws:username}"
      ],
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    },
    {
      "Sid": "AllowIndividualUserToManageTheirSSHCredentials",
      "Effect": "Allow",
      "Action": [
        "iam:DeleteSSHPublicKey",
        "iam:GetSSHPublicKey",
        "iam:ListSSHPublicKeys",
        "iam:UpdateSSHPublicKey",
        "iam:UploadSSHPublicKey"
      ],
      "Resource": "arn:aws:iam::*:user/${aws:username}"
    },
    {
      "Sid": "BlockMostAccessUnlessSignedInWithMFA",
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:ListMFADevices",
        "iam:ListUsers",
        "iam:ListVirtualMFADevices",
        "iam:ResyncMFADevice"
      ],
      "Resource": "*",
      "Condition": {"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}}
    }
  ]
}

Speaking of MFA, it's easy to use in the web console. Using it on the command line isn't as straight forward. For details on the basic process check out this video from Amazon

**Footnotes**

1. One of the marvels of the modern world, Amazon Web Services](https://aws.amazon.com) is *the* "[Cloud Computing" platform that's eating the software world.

2. Every user has a My Security Credentials section they can use to manage their various credentials, assuming they have permissions to do so. Which, of course, is what this post is all about.

3. Amazon's documentation is some of the best I've ever seen. The IAM docs.

4. Another marvel of the modern world, StackOverflow

5. Multi-factor Authentication that spits out random numbers every 30 seconds. If you don't have the proper numbers to go along with your password, you can't login. The reason this is important is if your password gets stolen, the bad guys can't get in but you still can with your MFA device.