It is a good practice to use temporary credentials in AWS instead of permanent IAM generated credentials that are long term and potentially leaked. AWS has different services that issue temporary credentials with given permission policies such as IAM Instance Profiles for EC2 instances, Lambda Execution Roles, ECS Task Roles, and IAM Roles Anywhere for those cases that require providing trusted access permissions to a process running outside of AWS.
One such way is to use the
action in AWS Security Token Service to generate a pair of temporary
credentials with an expiry date. Doing so allows using AWS credentials without
having to hardcode long lived IAM credentials and worry about the
credentials getting leaked.
However, there’s a caveat when it comes to using credentials generated from
GenerateSessionToken action. Unless the API action is executed with the MFA
token (for MFA enabled users), the generated credentials cannot be used to
invoke any IAM API calls. This would put a blocker for any use case you had for
running (ex:) IaC scripts with the temporary credentials.
I came across this scenario when using the popular
aws-vault tool generate
sessions with temporary credentials.
aws-vault also uses
GenerateSessionToken, but it depends on the AWS configuration file
$HOME/.aws/config) to provide the MFA configuraiton to it. Without the MFA
device serial and the token generation process defined in the config, it was generating
credentials that couldn’t perform any of the IAM API operations I needed.
One of the best ways to enable strong second factor authentication in AWS is to use a Yubikey device. However, the second factor authentication protocols supported by the AWS web console isn’t the same as the one supported by the AWS CLI and the SDKs. AWS web console supports FIDO-U2F, while the CLI and SDKs, based on the configuration, supports OATH-TOTP.
To get this working on the AWS CLI (and other tools that use the standard AWS SDKs), couple of steps need to be executed.
- Setup the CLI tool to generate the OATH-TOTP from the Yubikey
- Configure AWS configuration to point the MFA generation process to the OATH-TOTP generation tool
- Supported Yubikey device
- AWS CLI or SDK based script
- AWS credentials with proper permissions to invoke
The following assumes an Ubuntu Linux environment, however other Linux distributions will also have the dependencies required for the Yubikey CLI tool.
ykman is the Yubico provided
CLI key management tool. Installing this on Ubuntu is straightforward.
# Install the dependencies needed
sudo apt update && \
sudo apt install pcscd libpcsclite-dev swig
# Install ykman
pip3 install yubikey-manager
Configuring MFA with OATH-TOTP
This step involves the following.
- Registering a new Virtual MFA device in AWS IAM
- Usig the Secret Key used in the process to register a new
- Configuring AWS config to use
ykmanas the command to generate the OATH-TOTP MFA
Navigate to the AWS IAM console and select the user that needs to register the
MFA device for CLI authentication. Select the Security Credentials tab and
then on Assign MFA Device button. Select Authenticator App as the
device and input a device name. Note down this name as we’ll be using it to
register the device on the
Proceed to the next step. AWS provides a QR code for an authenticator app to use, however for this use case, what’s useful is the secret key. Copy the secret key for the next step.
Open the terminal and execute the following command using the appropriate
account_id and the
ykman oath accounts add -t arn:aws:iam::account_id:mfa/device_id
ykman will ask to input the (base32 encoded) secret key. Note that the value
copied from the AWS console is already base32 encoded so just directly paste
the value. This also specifies that the Yubikey should be touched to generate the key
by using the
Now two consecurtive OATH-TOTP codes should be generated and added to the console to finalise the device registration. However, instead of doing this immediately, I’ve experienced success by waiting a while (~5 minutes) for some unknown reason. I’m guessing this is related to the time window being populated someway, however whenever I’d immediately generate tokens, AWS would report them as invalid.
To generate a OATH-TOTP code, run the following command, again replacing
device_id with proper values. Wait 30 seconds before the
next token is generated since the time slice configuration is usually set to 30
ykman oath accounts code --single arn:aws:iam::account_id:mfa/device_id
Now that the device is registered in
ykman and AWS, it can be directly used
For the CLI command
get-session-token to use MFA in the process (in an AWS context with
proper permissions) the flags
--token-code have to be
used, which will trigger the touch request. Not providing these two flags will
generate credentials without MFA.
The MFA device serial can be copied from the AWS IAM console.
aws sts get-session-token --serial-number arn:aws:iam::account_id:mfa/device_id \
--token-code $(ykman oath accounts code --single arn:aws:iam::account_id:mfa/device_id)
AssumeRole operation, the MFA device and the code
generation command to use can be provided through the AWS config file. To do
under the proper profile in
$HOME/.aws/config file (replacing
device_id with proper values).
mfa_process=ykman oath accounts code --single arn:aws:iam::account_id:mfa/device_id
That’s it! That’s the entire process.
Now whenever temporary credentials are generated through
AssumeRole, the AWS
SDK credentials provider will use
ykman with the above command to trigger a
Yubikey touch to generate an OATH-TOTP
token, ensuring the temporary credentials are generated with MFA involved.