Utility for AWS CLI MFA Authentication

Author: Rob Pulsipher

Posted:

Last updated:

Summary

As far as I am aware, AWS doesn't provide a simple solution for using MFA (multi-factor authentication) from the CLI (command line interface). It is, frankly, much more difficult than it should be.

This article first presents the relevant background on how to manually login to AWS from the CLI using MFA, and then it introduces our simple (Python script), utility which automates the process.

The utility is available on github at https://github.com/reusabit/awsmfa under an Apache 2.0 license.

Background

AWS CLI Configuration Without MFA

This section covers how to configure an IAM user account for CLI access. It assumes that you have already created the IAM account.

Security Notes: It is not recommended to use the root account for CLI access. Create a separate IAM user account for CLI access. Additionally, I would suggest setting some reasonable quotas on that account and restricting the user from changing the quota. This will help prevent the unlimited use of resources by an attacker in the event that the user's credentials are stolen.

Step 1: Create Access Keys using the AWS Console

Under IAM -> Users -> select the user -> Security Credentials (tab) -> Access Keys (heading), click "Create access key" button. Keep track of the access key ID and the secret access key.

Step 2: Create the credentials file

Edit the ~/.aws/credentials file, and insert the values from step 1. Each section of the config file is a profile. Here, "exampleProfilePerm" is the name of the profile. Note: The "Perm" suffix (short for "Permanent") is used here for consistency with later instructions for configuring MFA.


[exampleProfilePerm]
aws_access_key_id = REDACTED
aws_secret_access_key = REDACTED
  

Step 3: Optional Recommendation: Use AWS_PROFILE to change profiles

You can specify the profile for each aws cli command with the --profile flag, but it is typically easier to use the AWS_PROFILE environment variable.

I generally do not export AWS_PROFILE in my startup scripts, but rather export it when I need it.

I find that explicitly setting the profile once per session helps prevent using the wrong profile by mistake. (This practice requires the profile to be actively set, but keeps the --profile argument out of the command history.)

Requiring MFA for the Account

Step 1: Turn on MFA for the account

Assign an MFA device to the user: IAM -> Users -> Summary (heading) -> Security Credentials (tab) -> Sign-in credentials (heading) -> Assigned MFA device. Click manage, and assign an MFA device, such as a virtual authenticator on your phone.

After performing the above step, MFA authentication will be required to log in to the console. However, the access key created above will still work from the CLI without MFA.

You need the access key in the credentials file in order to obtain a temporary session token with MFA. In order to protect the account, the next step alters permissions so that the account can only do things when authenticated with MFA.

Step 2: Require MFA for all permissions

If you haven't done so already, create a group for users who require MFA (the "RequireMfaGroup") to login.

Go to IAM -> Groups -> RequireMfaGroup -> Permissions (tab). You can either attach a new policy, or add to an existing policy. Add a new "condition" to the policy. For example:


{
    "Version": "2012-10-17",
    "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}
  

Having done this, the access key will no longer work on the CLI, unless you are authenticated using MFA.

Authenticating Manually with MFA from the CLI

Authenticating manually with the CLI is a fairly involved process, especially considering that this is something that you will most likely want to do several times a day. This section describes the manual authentication process for informational purposes. The next section will introduces our utility which automates the process.

First, you need the same ID and secret from above. I refer to this as the "permanent" credentials because they don't change (unless you go into the AWS console and change them on purpose). These credentials are used to connect with the "aws sts" command, which, when provided with a code from the MFA device, returns a set of credentials for a temporary session. I refer to this as the "temporary" credentials.

Second, you place the temporary credentials obtained from the "aws sts" command in the credentials file, with a different profile name.

For example, consider the following ~/.aws/credentials file:


[myaccountPerm]
aws_access_key_id = REDACTED
aws_secret_access_key = REDACTED

[myaccount]
  

Then, the following command is run with a code from the MFA device:


$ aws sts get-session-token --token-code 123456 --profile myaccountPerm --serial-number arn:aws:iam::REDACTED:mfa/REDACTED
{
    "Credentials": {
        "AccessKeyId": "REDACTED",
        "SecretAccessKey": "REDACTED",
        "SessionToken": "REDACTED",
        "Expiration": "2021-03-13T09:37:10Z"
    }
}

  

The results are then extracted from the above output and appended to the (previously empty) "myaccount" profile (e.g., the temporary profile) in ~/.aws/credentials


[myaccount]
aws_access_key_id = REDACTED
aws_secret_access_key = REDACTED
aws_session_token = REDACTED
  

This "temporary" profile can now be referenced with --profile or AWS_PROFILE until it expires. Then a new temporary profile must be obtained.

Automating the Process With Our Utility

The manual process begs to be automated, for which we have written an open source utility (https://github.com/reusabit/awsmfa).

The utility will look up the serial number from the config file, request the temporary session, and add it to the credentials file in one step. The process looks then like this:


$ export AWS_PROFILE=myprofile
$ awsmfa login --token-code 123456
$ # Do some aws cli stuff
$ awsmfa logout
  

(Configuration instructions are located on the github site.)

Logout

The logout command above removes the temp session from the file, but as far as I'm aware, there is not a way to invalidate the session on the AWS side.

There is this AWS article which references revoking active sessions, but it seems crazy to me to alter permissions in order to invalidate a session.

Reusabit Software LLC Digital Signal