How to use MFA with AWS CLI?

Amazon Web-Services

Amazon Web-Services Problem Overview


How do I type in the MFA code when using the AWS CLI? I have checked the documentation page of IAM http://docs.aws.amazon.com/cli/latest/reference/iam/index.html.

I have the MFA-Devices already enabled under my username.

aws iam list-mfa-devices --user-name X

returns

{
"MFADevices": [
    {
        "UserName": "X", 
        "SerialNumber": "arn:aws:iam::+++:mfa/X", 
        "EnableDate": "2016-01-13T23:15:43Z"
    }
]
}

Amazon Web-Services Solutions


Solution 1 - Amazon Web-Services

The CLI can manage a lot of this for you if you're using roles. Described here: http://docs.aws.amazon.com/cli/latest/userguide/cli-roles.html

In my credentials file I have:

[my_iam_user]
aws_access_key_id = AKIABLAHBLAHBLAHBLAH
aws_secret_access_key = <blah>
region = us-east-1

[my_admin_role]
role_arn = arn:aws:iam::123456789123:role/my_admin_role
source_profile = my_iam_user
mfa_serial = arn:aws:iam::123456789123:mfa/my_iam_user
region = us-east-1

Note the mfa_serial entry. You can get this value from your user details in the AWS IAM console. This entry tells the CLI that MFA is required for that role.

When I call aws s3 ls --profile my_admin_role it says Enter MFA code:, after I paste in the code it returns the listing.

Note: I haven't found a way to get the CLI to ask for MFA when calling a user profile (--profile my_iam_user) only calling a role profile triggers the MFA request.

The MFA token is then carried forward and the user profile can be used as well:

aws sts get-caller-identity --profile my_iam_user
 # {
 # "Account": "123456789123",
 # "UserId": "AIDABLAHBLAHBLAHBLAH",
 # "Arn": "arn:aws:iam::123456789123:user/my_iam_user"
 # }

aws sts get-caller-identity --profile my_admin_role
 # {
 # "Account": "123456789123",
 # "UserId": "AROABLAHBLAHBLAHBLAH:AWS-CLI-session-1234567890",
 # "Arn": "arn:aws:sts::123456789123:assumed-role/my_admin_role/AWS-CLI-session-1234567890"
 # }

Solution 2 - Amazon Web-Services

Call aws sts get-session-token --serial-number <serial> --token-code <code> documented here. This will give you a temporary security token. Documentation on using the temporary security token can be found here.

Solution 3 - Amazon Web-Services

Step-by-step manual solution:

  1. Request a session token with MFA
aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from-token

arn-of-the-mfa-device: visible from your user IAM

  • Option: Use CLI to retrieve: aws iam list-mfa-devices --user-name ryan
  • Option: View in IAM console: IAM --> Users --> --> Security Credentials

code-from-token: 6 digit code from your configured MFA device

  1. Create a profile with the returned credentials
aws configure --profile cli

aws configure set --profile cli aws_session_token <SESSION_TOKEN_HERE>

aws_session_token is not included in aws configure

  1. Test command
aws s3 ls --profile cli

Solution 4 - Amazon Web-Services

I have published a PR for aws-cli, which will allow to use mfa_serial in the credentials, that will force you to enter the token before making request to AWS (and it will be cached while token is valid)

Feel free to vote, if you want to get it in.

Solution 5 - Amazon Web-Services

Wrote a tool to add MFA support for standard IAM user profiles until @outcoldman PR gets merged: https://github.com/tongueroo/aws-mfa-secure

Setup for those in a hurry

  1. Install gem
gem install aws-mfa-secure
  1. Setup your ~/.aws/credentials with mfa_serial

~/.aws/credentials:

[mfa]
aws_access_key_id = BKCAXZ6ODJLQ1EXAMPLE
aws_secret_access_key = ABCDl4hXikfOHTvNqFAnb2Ea62bUuu/eUEXAMPLE
mfa_serial = arn:aws:iam::112233445566:mfa/MFAUser

3. Add the alias to your ~/.bash_profile

alias aws="aws-mfa-secure session"

Restart your terminal.

Example with Output

$ export AWS_PROFILE=mfa
$ aws s3 ls
Please provide your MFA code: 751888
2019-09-21 15:53:34 my-example-test-bucket
$ aws s3 ls
2019-09-21 15:53:34 my-example-test-bucket
$

Assume Role Profiles

Assume role profiles work already for the AWS CLI, here's an example:

~/.aws/credentials:

[mfa]
aws_access_key_id = BKCAXZ6ODJLQ1EXAMPLE
aws_secret_access_key = ABCDl4hXikfOHTvNqFAnb2Ea62bUuu/eUEXAMPLE
mfa_serial = arn:aws:iam::112233445566:mfa/MFAUser

[assumed-role]
role_arn = arn:aws:iam::112233445566:role/Admin
source_profile = mfa
role_session_name = MFAUser
mfa_serial = arn:aws:iam::112233445566:mfa/MFAUser

Solution 6 - Amazon Web-Services

On Windows

I'm on windows and I created a batch file to pass in my MFA code and have it automatically set up my credentials. First, you need to set up your production credentials in AWS:

aws configure --profile prod

Answer the questions appropriately with your key and secret. Then, I run my script like this:

C:\> mfa-getCreds.bat 229168

Your credentials are set up, and will expire on 2019-05-12T04:04:13Z

Now you should be able to run aws commands like this: aws s3 ls

Here are the contents of my mfa-getCreds.bat:

@echo off
   
set TOKEN=%1
if not defined TOKEN goto showUsage   

@call aws sts get-session-token --profile prod --serial-number "arn:aws:iam::109627855994:mfa/ryan.shillington" --token-code %* > c:\temp\mfa-getCreds.json

FOR /F "tokens=* USEBACKQ" %%g IN (`jq -r ".Credentials.AccessKeyId" c:\temp\mfa-getCreds.json`) do (SET AWS_ACCESS_KEY=%%g)
FOR /F "tokens=*" %%g IN ('jq -r ".Credentials.SecretAccessKey" c:\temp\mfa-getCreds.json') do (SET "AWS_SECRET_KEY=%%g")
FOR /F "tokens=*" %%g IN ('jq -r ".Credentials.SessionToken" c:\temp\mfa-getCreds.json') do (SET "AWS_SESSION_TOKEN=%%g")
FOR /F "tokens=*" %%g IN ('jq -r ".Credentials.Expiration" c:\temp\mfa-getCreds.json') do (SET "EXPIRATION=%%g")

set AWS_ACCESS_KEY_ID=%AWS_ACCESS_KEY%
set "AWS_SECRET_ACCESS_KEY=%AWS_SECRET_KEY%"

echo.
echo Your credentials are set up, but will expire on %EXPIRATION%
echo.
echo Now you should be able to run aws commands like this: aws s3 ls

goto :EOF

:showUsage
echo Usage: %0 [MFA Token]
goto :EOF

For this to run, you'll need the excellent jq package in your path.

Solution 7 - Amazon Web-Services

My use-case is I have a root account where all IAM users are created and assigned to IAM groups which in turn have the capability to assume roles on a different account with varying degree of access depending on the group they are on. I have a few house rules in place;

  1. No one is allowed to do anything on the root account except to manage their own IAM Users account.
  2. Required password reset.
  3. Required MFA.
  4. You cannot switch accounts without logging in with MFA.

This has been set up using AWS Shared Organizations.

Previously, I've been using a python script I wrote to let my users to login via cli with MFA and switch accounts. This is done by manipulating the ~/.aws/credentials.

I've since migrated to using this project https://gitlab.com/severity1/aws-auth, which is written in Go and allows me to do the same without much setup and it works on windows, macosx and linux.

This effectively gives all my users the ability to do local testing while developing Apps for AWS without having to hardcode AWS Credentials into their code.

Solution 8 - Amazon Web-Services

aws-mfa acts as a wrapper around sts and works really well: https://github.com/broamski/aws-mfa

Solution 9 - Amazon Web-Services

I wrote a small bash script to get over this annoying problem. You can find it here: https://gist.github.com/geekgunda/db4c9c8d850c08a48d1d60f119628032

Assumptions:

  1. Your original AWS Creds should be stored at ~/.aws/credentials
  2. You've corrected ARN for MFA device (search for FIXME)
  3. You've given correct MFA Code as cli argument
  4. You have jq installed. Ref: https://stedolan.github.io/jq/

Solution 10 - Amazon Web-Services

We documented a few considerations for AWS API multifactor in general (where to add the conditions, what are the implications etc.) in the documentation for some custom tooling (https://github.com/kreuzwerker/awsu) we developed for using Yubikeys as source for the TOTP tokens. This makes working with roles and long-term credentials + session tokens pretty easy.

Solution 11 - Amazon Web-Services

I have forked Chinmay's gist and updated it to pull the device serial from aws instead of hardcoding it. I have also updated the exits to return a status of 1 instead of just exiting.

Available here: https://gist.github.com/jpribyl/e44021ae5cbf7fd1b4549598e85b5341

I am using it in deploy scripts like this (I renamed the script to awsMfaCli.sh):

. awsMfaCli.sh
script_status=$?

if [[ $script_status -ne 1 ]]; then
    echo "Building production"
    if npm run build ; then
       echo "Build Successful"
    else
      echo "Error building, exiting.."
      return 1
    fi


    echo "Removing all files on bucket.."
    aws s3 rm --recursive s3://mybucket

    echo "Uploading site.."
    aws s3 sync build/ s3://mybucket
    echo "S3 Upload complete.."
    echo "Deployment complete."
else
    return 1
fi

Solution 12 - Amazon Web-Services

AWS MFA use on the command line can be rather unpleasant and cumbersome, especially if you have multiple profiles and roles.

I have released awscli-mfa.sh script that makes MFA/role session management on the command line a lot easier. A companion script enable-disable-vmfa-device.sh similarly makes it easy to enable or disable a virtual MFA device on an IAM user account.

awscli-mfa.sh persists a started session in ~/.aws/credentials (with some info in ~/.aws/config), or allows you to start an in-env session only so that its details don't get persisted. When executed in Windows Subsystem for Linux, the script also provides session activation strings for PowerShell and Windows command line. However, the script itself only runs in bash (written for macOS, Linux, and WSL bash with Ubuntu).

You can find the scripts and the example MFA policies in my GitHub repo at https://github.com/vwal/awscli-mfa

Solution 13 - Amazon Web-Services

Run the sts get-session-token AWS CLI command, replacing the variables with information from your account, resources, and MFA device:

$ aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from-token

https://aws.amazon.com/premiumsupport/knowledge-center/authenticate-mfa-cli/

Solution 14 - Amazon Web-Services

A one-liner to authorize and append an MFA user to your credentials file using jq:

SERIAL_NUMBER=arn:aws:iam::000000000000:mfa/john TOKEN_CODE=123123 PROFILE_NAME=my_aws_2fa; \
aws sts get-session-token --serial-number $SERIAL_NUMBER --token-code $TOKEN_CODE \
   | jq -r '.Credentials | ("aws_access_key_id = " + .AccessKeyId), ("aws_secret_access_key = " + .SecretAccessKey), ("aws_session_token = " + .SessionToken)' \
   | (echo "\n[$PROFILE_NAME]" && cat) >> ~/.aws/credentials

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHello ladView Question on Stackoverflow
Solution 1 - Amazon Web-ServicesJoe HarrisView Answer on Stackoverflow
Solution 2 - Amazon Web-ServicesMark BView Answer on Stackoverflow
Solution 3 - Amazon Web-ServicesrmharrisonView Answer on Stackoverflow
Solution 4 - Amazon Web-ServicesoutcoldmanView Answer on Stackoverflow
Solution 5 - Amazon Web-ServicestonguerooView Answer on Stackoverflow
Solution 6 - Amazon Web-ServicesRyan ShillingtonView Answer on Stackoverflow
Solution 7 - Amazon Web-ServicesunexpectedGuestView Answer on Stackoverflow
Solution 8 - Amazon Web-ServicesryantuckView Answer on Stackoverflow
Solution 9 - Amazon Web-ServicesChinmay BhattarView Answer on Stackoverflow
Solution 10 - Amazon Web-ServicesyawnView Answer on Stackoverflow
Solution 11 - Amazon Web-ServiceskibbleView Answer on Stackoverflow
Solution 12 - Amazon Web-ServicesVilleView Answer on Stackoverflow
Solution 13 - Amazon Web-ServicesmellifluousView Answer on Stackoverflow
Solution 14 - Amazon Web-ServicesrcodeView Answer on Stackoverflow