Why MFA?

Multi-Factor Authentication is a great approach when you have to ensure the security of your systems. It allows you to add an extra layer of authentication to access the systems or resources you manage. An intruder cannot access the resources using your login credentials until an MFA token from the authorized device is given. Usually, MFA applications like Authy, Google authenticator, e.t.c, help configure the device (generally mobile) with tokens from the destination applications (Cloud, SaaS, PaaS).

We will talk about the AWS command-line access with MFA token in this blog.

Why MFA for Command-line Access?

When we login to the AWS console via the browser, you will be prompted to enter the MFA token if already enabled for your user account.

You will enter the token that is generated by the token generator application on your MFA device. This will let you log in to the console and manage your AWS resources from there. What happens if you are not using the web browser to manage the AWS resources as you have hundreds or thousands of resources created using a cloud infrastructure code software tool like terraform? Or you need to add/delete/modify the AWS resources via AWS CLI itself?

Programmatic Access

The tools like terraform need programmatic access to the AWS accounts into which the resources are being deployed and managed. Anyone can access your AWS account when they have your access key and secret key. There are chances that we accidentally leave it somewhere, for example, pushing it to the Git repo by mistake. In such cases, the command line MFA token helps secure the AWS account from attacks as we have a trusted secondary device with the extra security token without which the account is inaccessible. When using terraform, the usage of MFA comes handy. Terraform communicates to the cloud resources via the API calls. This also needs an MFA for the user to authenticate and make the calls without failure.

How to Enable Command-line MFA for AWS?

In this case, we are considering that we have a landing AWS or shared AWS account where we have all the users and other AWS accounts where the resources are created. This is a best practice as the users are isolated from the AWS accounts with our real resources. This helps in managing the users from a single AWS account as well. In short, below is a cross AWS account mechanism, so that one-to-one and one-to-many methods can be understood simultaneously.

Steps:

We hope that you already have an AWS landing account where you have the AWS user, on your local machine, configure the AWS credentials as given below:

  1. Configure the AWS credentials by moving to the .aws folder in the home directory and add the config and credentials files.
[profile default]
aws_access_key_id = ACCESSKEYHERE
aws_secret_access_key = SECRETKEYHERE

[profile dev]
role_arn = arn:aws:iam::<12-digit-account-ID>:role/dev-role-here
source_profile = default

2. Run the below command from the terminal and copy the output.

aws sts get-session-token --duration 3600 --serial-number arn:aws:iam::<12-digit-account-ID>:mfa/aws_user_name --token-code <token>

3. Please replace the account ID using the shared service account ID in the above command and save the output to the credentials file in the same location in the below format.

[default]
aws_access_key_id = ACCESSKEYHERE
aws_secret_access_key = SECRETKEYHERE
aws_session_token = <token from the above output>

4. Now you will list the resources using the AWS CLI tool and specify the other profile names to get the resources in there. For example:

aws iam list-users

This will list the users in the landing account.

aws iam list-users --profile dev-profile --region eu-west-1

This will list the users in the dev account depends upon what name that you have given in the config file.

5. Once the token is in place you can run AWS CLI commands/terraform to manage AWS resources. The above is a one time step, now you can generate and replace the token (as its not valid for ever) using the script below when you access the resources using AWS CLI.

#!/bin/bash
#Please replace the "user" with your user ID for AWS landing/shared account
echo -n "Please enter username : "
read USER_NAME
echo -n "Please enter Account ID : "
read ACCOUNTID_ORG
ACCOUNTID=`echo $ACCOUNTID_ORG | sed -e 's/-//g'`
echo -n "Please enter MFA token from your configured device : "
read TOKEN
test -f ~/.aws/credentials && cp ~/.aws/credentials ~/.aws/credentials-`date +%Y%m%d%H%M%S`
mkdir -p ~/.aws/
aws sts get-session-token --serial-number arn:aws:iam::$ACCOUNTID:mfa/$USER_NAME --duration-seconds 28800 --token $TOKEN | \
jq --raw-output '. | "[default]
aws_access_key_id = \(.Credentials.AccessKeyId)
aws_secret_access_key = \(.Credentials.SecretAccessKey)
aws_session_token = \(.Credentials.SessionToken)"' \
> ~/.aws/credentials
check_file=`cat ~/.aws/credentials | grep aws_session_token`
if [ $(echo $?) -eq 0 ];
then
echo "The token has been created"
else
echo " "
echo "Token creation failed, Please see the above error...!!!"
fi

That’s it. You have secured the AWS CLI using the MFA token now. Always a best practice, let’s secure the infrastructure.