Multi-Factor Authentication (MFA) Enforcement on AWS CLI

Jerry L
PREDICTif Ponders
Published in
5 min readSep 27, 2022

AWS multi-factor authentication (MFA) is a recommended practice for AWS Identity and Access Management (IAM) that requires an authentication factor in addition to the standard user name and password. MFA provides increased security by preventing unauthorized access to your AWS resources.

How does it work?

Users must provide their user name and password to access the AWS access portal once multi-factor authentication (MFA) has been enabled. The first factor is something they are aware of. Additionally, users must log in using either a security key or a code. The second factor is something they have or something they are. An authentication code generated from their mobile device or tapping on a security key connected to their computer could serve as the second factor.

We’ve all heard stories of people having their AWS accounts hacked and receiving huge bills totaling thousands, even tens of thousands of dollars.

Now we understand the importance of enabling MFA for AWS accounts. It is easy to enable MFA for the AWS console, nevertheless, to enable MFA for AWS CLI can be challenging.

We already know that you can create an IAM user’s security key and access key, which enables programmatic access to the AWS resources. When you run the aws configure command, it will be saved in the .aws folder. But think if someone got a hold of your computer or you went on vacation and neglected to lock your screen.

There isn’t a straightforward “button click” way to configure this through the console setting. IAM policy configuration is required for this. We’ll go over how to configure it for AWS CLI to access AWS resources in this article.

Require MFA

This policy does not allow users to view the Users page in the IAM console or use that page to access their user information.

  • This policy will require MFA for both Console and CLI.
  • New users will need to enable MFA before having access to AWS.
  • New users will be able to change the password now upon signing in if Require password reset upon creation because we added iam:ChangePassword and iam:GetAccountPasswordPolicy to the statement DenyAllExceptListedIfNoMFA

IAM Policy

{
"Version": "2012-10-17",
"Statement": [

{
"Sid": "DenyAllExceptListedIfNoMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:GetUser",
"iam:ListMFADevices",
"iam:ListVirtualMFADevices",
"iam:ResyncMFADevice",
"iam:ChangePassword",
"iam:GetAccountPasswordPolicy",
"sts:GetSessionToken"
],
"Resource": "*",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}

Note

  • This example policy does not allow users to reset a password while signing in to the AWS Management Console for the first time. We recommend that you do not grant permissions to new users until after they sign in. For more information, see How do I securely create IAM users? This also prevents users with an expired password from resetting their password during sign-in. You can allow this by adding iam:ChangePassword and iam:GetAccountPasswordPolicy to the statement DenyAllExceptListedIfNoMFA. However, we do not recommend this because allowing users to change their password without MFA can be a security risk.
  • If you intend to use this policy for programmatic access, you must call GetSessionToken to authenticate with MFA. For more information, see Configuring MFA-protected API access.

* GetSessionToken: No permissions are required for users to perform this operation. The purpose of the sts:GetSessionToken operation is to authenticate the user using MFA. You cannot use policies to control authentication operations. For more information, see Permissions for GetSessionToken in the IAM User Guide.

Manually

1. Create a profile with the original access_key and secret_access_key. eg. [original]

[original]
aws_access_key_id = XXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXX

2. Get the session token and replace the default profile. ( So you don’t have to specify with — the profile flag EVERYTIME! )

aws sts get-session-token \
--duration-seconds *** \ (this line is optional, default is 12 hour)
--serial-number YourMFADeviceSerialNumber \
--token-code YourMFAcodeFromDevice

* The \ doesn't work in the Windows terminal, then just make it one line. For example: aws sts get-session-token --serial-number YourMFADeviceSerialNumber" --duration-seconds *** --token-code "YourMFAcodeFromDevice"

* YourMFADeviceSerialNumber can be found under IAM->Users->Security credentials->Sign-in credentials-> Assigned MFA device e.g. arn:aws:iam::XXXXX:mfa/XXX@XXXXXX.com

* If you have the following error: Unbale to redirect output to pager. Received the following error when opening pager:[Errno 2] No such file or directory:'less' , then run the following:

sudo apt-get update && sudo apt-get install -yy less

3. Then create a profile in the credentials file.

[default]
aws_access_key_id = value returned from sts get-session-token
aws_secret_access_key = value returned from sts get-session-token
aws_session_token = value returned from sts get-session-token

4. Then create the default region in the config file:

[default]
region = eu-west-2

Using script:

To save some time, here is the basic script to get session tokens:

aws-session() {local MFA_CODE
local MFA_DEVICE_ARN='YOUR MFA_DEVICE_ARN'
export AWS_ACCESS_KEY_ID='AKIA6...V5PIHU'
export AWS_SECRET_ACCESS_KEY='Zd2DWkNQY...6q2Pf09Z89XJ'
echo "Please enter your MFA code for ${MFA_DEVICE_ARN}:"
read -r MFA_CODE
RES=$(aws sts get-session-token \
--serial-number $MFA_DEVICE_ARN \
--duration-seconds 28800 \ (this line is optional for now, default is 12 hour)
--token-code $MFA_CODE)
if [[ $? -ne 0 ]]; then
echo "Retrieving session info failed!"
return
fi
KEY=$(echo $RES | jq -r .Credentials.AccessKeyId)
SECRET=$(echo $RES | jq -r .Credentials.SecretAccessKey)
SESSION=$(echo $RES | jq -r .Credentials.SessionToken)
aws configure set aws_access_key_id ${KEY}
aws configure set aws_secret_access_key ${SECRET}
aws configure set aws_session_token ${SESSION}
}
  • add the session duration if you need. default is 12 hours. --duration-seconds ***
  • name it get_session_token and save it in /.aws
  • run source ./get_session_token in the terminal in the folder
  • then run aws-session

The default profile should be updated. if you want to update to curtain profile. Here is how to modify the according to lines in the script:

aws configure set aws_access_key_id ${KEY} --profile ${PROFILE}
aws configure set aws_session_token ${SESSION} --profile ${PROFILE}
aws configure set aws_secret_access_key ${SECRET} --profile ${PROFILE}

* duration-seconds (integer)

The duration, in seconds, that the credentials should remain valid. Acceptable durations for IAM user sessions range from 900 seconds (15 minutes) to 129,600 seconds (36 hours), with 43,200 seconds (12 hours) as the default. Sessions for Amazon Web Services account owners are restricted to a maximum of 3,600 seconds (one hour). If the duration is longer than one hour, the session for Amazon Web Services account owners defaults to one hour.

Originally published at https://www.predictifsolutions.com/

--

--