Yubico docs: https://developers.yubico.com/yubikey-manager/
Right now, Yubico distributes yubikey-manager
under the official ppa yubico/stable
for apt. Double-check this is still the case when you're reading this guide — you don't want to trust a non-official distribution of yubikey-manager
.
sudo apt-add-repository ppa:yubico/stable
sudo apt update
sudo apt install yubikey-manager
The apt package is named yubikey-manager
, but the cli it exposes is named ykman
.
- Log into https://aws.amazon.com/
- Go to Security Credentials
- Under the Multi-factor authentication (MFA), click Assign MFA Device
- Give it whatever device name you wish.
- Under Select MFA device you need to choose Authenticator app. This is unintuitive UI, but it really means "OATH device". If you choose Hardware Device here, you'll only be able to use it when you log into aws in the browser, not in the terminal.
- Next screen will show you a QR which you can normally scan with your phone. You should also see a Show secret key button (visually rendered as a link). Click it, copy it and save it somewhere safe. You'll need this in the next step.
- Do not close this screen just yet.
- Set up an OATH account in your YubiKey device with the Secret Key you just obtained:
ykman oath accounts add -t aws-otp <AWS_MFA_CODE>
.aws-otp
is the name of the account stored inside the YubiKey. We'll useaws-otp
for this example, but it can be anything you want. - Now the AWS UI will request that you type two consecutive MFA codes. Use
ykman oath accounts code aws-otp
once to get the first, then use the same command again several times until you get a new OTP. - Hit Assign MFA and you're done!
To get an OTP from your YubiKey you need to run ykman oath accounts code aws-otp
.
You then need to run aws sts get-session-token --serial-number arn:aws:iam::000000000000:mfa/2fa-device-name --token-code $otp
, where $otp
is the OTP returned by ykman oath accounts code aws-otp
and the value of --serial-number
is the ARN of the OTP device you set up in aws.amazon.com.
aws sts get-session-token
returns a new AccessKeyId
, SecretAccessKey
and SessionToken
which you'll need to place into your ~/.aws/credentials
file. Doing this by hand each time would make no sense, so here are two functions that do this for you :)
# This function will request you to touch your YubiKey and return the OTP created by it.
yubiotp() {
ykman oath accounts code aws-otp | tee | tr -s " " | cut -d" " -f2
}
# This function will request you to touch your YubiKey
# and then add a [mfa] section to ~/.aws/credentials and [profile mfa] to ~/.aws/config
# It needs an existing [default] profile with aws_access_key_id and aws_secret_access_key set
# that has access to the MFA device set up in AWS.
# Warning: if there's a [mfa] aws profile in your ~/.aws/credentials and/or .config, it'll be replaced.
awsotp() {
echo "Logging-in to aws cli with Yubikey"
local otp=$(yubiotp)
echo "OTP: $otp"
echo "Getting new settion token from AWS..."
local json=$(aws sts get-session-token --serial-number arn:aws:iam::000000000000:mfa/2fa-device-name --token-code $otp)
local AccessKeyId=$(echo $json | jq .Credentials.AccessKeyId | tr -d '"')
local SecretAccessKey=$(echo $json | jq .Credentials.SecretAccessKey | tr -d '"')
local SessionToken=$(echo $json | jq .Credentials.SessionToken | tr -d '"')
echo "Configuring mfa profile..."
aws configure set aws_access_key_id $AccessKeyId --profile mfa
aws configure set aws_secret_access_key $SecretAccessKey --profile mfa
aws configure set aws_session_token $SessionToken --profile mfa
aws configure set region us-east-1 --profile mfa
aws configure set output json --profile mfa
echo "Success!"
}
You can copy-paste these two functions to your /.bashrc
and just call awsotp
from the terminal whenever you need a new AWS OTP.
Then just use the aws
cli app normally, always passing --profile mfa
like so:
aws ec2 describe-instances --region us-east-1 --profile mfa
If you get a PC/SC error like the following, the pcscd.socket
is probably not running.
WARNING: PC/SC not available. Smart card (CCID) protocols will not function.
ERROR: Unable to list devices for connection
ERROR: Failed to connect to YubiKey.
Let's check it status:
$ systemctl status pcscd.socket
○ pcscd.socket - PC/SC Smart Card Daemon Activation Socket
Loaded: loaded (/lib/systemd/system/pcscd.socket; enabled; vendor preset: enabled)
Active: inactive (dead)
Triggers: ● pcscd.service
Listen: /run/pcscd/pcscd.comm (Stream)
Start it like so:
sudo systemctl start pcscd.socket
If the service is always inactive after rebooting, you may need to enable it:
sudo systemctl enable pcscd.socket
See this bug report for more info on this topic.