概要
IAMユーザの権限にAWS CLIからの利用にもMFAが強制されている場合、
- MFAデバイスで一時解除コードを取得
-
get-session-token
で一時的なトークンを取得。このとき一時解除コードを入力 - 取得したトークンを環境変数または設定ファイルに投入
- AWS CLI実行
という手順が必要になります。
AWS CLIが実行できるようにするまでの準備が面倒なので自動化しようというのが今回の趣旨です。
手動だと面倒なところ
get-session-token
すると下記のような出力が得られます。
$ aws --profile <プロファイル> sts get-session-token --serial-number <MFAデバイス識別子> --token-code <一時解除コード> --output json
{
"Credentials": {
"AccessKeyId": "ASXXXXXXXXXXXXXXXXXX",
"SecretAccessKey": "jexxxxbCxxxx11xxxxE2xxxxB3xxxxCbxxxx4zw8",
"SessionToken": "IQoJb3JpZ2luX2VjEG0aDmFwLW5vcnRoZWFzdC0xIkgwRgIhAP2QuV9k(以下略)",
"Expiration": "2024-05-28T16:49:28+00:00"
}
}
AWS CLIを使うには、上記からAccessKeyId、SecretAccessKey、SessionTokenを抜き出して、次のいずれかの作業を行う必要があります。
選択肢1:環境変数AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKENにそれぞれを設定する
export AWS_ACCESS_KEY_ID=ASXXXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=jexxxxbCxxxx11xxxxE2xxxxB3xxxxCbxxxx4zw8
export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjEG0aDmFwLW5vcnRoZWFzdC0xIkgwRgIhAP2QuV9k(以下略)
選択肢2:~/.aws/config
と~/.aws/credentials
にMFA用プロファイルを追記する
[default]
mfa_serial = arn:aws:iam::account_id:mfa/devicename
account = account_id
region = ap-northeast-1
output = json
[profile mfa]
account = account_id
region = ap-northeast-1
output = json
[default]
aws_access_key_id = (略)
aws_secret_access_key = (略)
[mfa]
aws_access_key_id = ASXXXXXXXXXXXXXXXXXX
aws_secret_access_key = jexxxxbCxxxx11xxxxE2xxxxB3xxxxCbxxxx4zw8
aws_session_token = IQoJb3JpZ2luX2VjEG0aDmFwLW5vcnRoZWFzdC0xIkgwRgIhAP2QuV9k(以下略)
get-session-token
のコマンドは長いし、コピペしないといけないパラメータが3つもあるし、/
を含むのでクリックでの自動範囲選択が使えないし、トークンが数行に渡る長さだしと、これを手作業でやろうとすると非常に面倒です。
MFA設定を自動化するスクリプト
という訳で自動化しました。
#!/bin/bash
CONFIG_FILE=~/.aws/config
CREDENTIALS_FILE=~/.aws/credentials
TOKEN_JSON=$(aws --profile $AWS_MFA_PROFILE sts get-session-token --serial-number $AWS_MFA_SERIAL --token-code $1 --output json)
if [ $? -eq 0 ]; then
export AWS_ACCESS_KEY_ID=$(echo ${TOKEN_JSON} | sed -E 's/^.*"AccessKeyId": *"([^"]+)".*$/\1/')
export AWS_SECRET_ACCESS_KEY=$(echo ${TOKEN_JSON} | sed -E 's/^.*"SecretAccessKey": *"([^"]+)".*$/\1/')
export AWS_SESSION_TOKEN=$(echo ${TOKEN_JSON} | sed -E 's/^.*"SessionToken": *"([^"]+)".*$/\1/')
env | grep AWS_ | sort
# ~/.aws/config の更新
if ! grep -q "\[profile ${AWS_MFA_PROFILE}-mfa\]" ${CONFIG_FILE}; then
{
echo ""
echo "[profile ${AWS_MFA_PROFILE}-mfa]"
echo "region = ap-northeast-1"
echo "output = json"
} >> ${CONFIG_FILE}
fi
# ~/.aws/credentials の更新
if grep -q "\[${AWS_MFA_PROFILE}-mfa\]" ${CREDENTIALS_FILE}; then
sed -i "/\[${AWS_MFA_PROFILE//\//\\/}-mfa\]/,/^\[/ {
s|aws_access_key_id.*|aws_access_key_id = ${AWS_ACCESS_KEY_ID}|
s|aws_secret_access_key.*|aws_secret_access_key = ${AWS_SECRET_ACCESS_KEY}|
s|aws_session_token.*|aws_session_token = ${AWS_SESSION_TOKEN}|
}" ${CREDENTIALS_FILE}
else
{
echo ""
echo "[${AWS_MFA_PROFILE}-mfa]"
echo "aws_access_key_id = ${AWS_ACCESS_KEY_ID}"
echo "aws_secret_access_key = ${AWS_SECRET_ACCESS_KEY}"
echo "aws_session_token = ${AWS_SESSION_TOKEN}"
} >> ${CREDENTIALS_FILE}
fi
fi
置き場所はどこでも大丈夫ですが、~/.aws/aws-mfa-set-session-token.sh
に設置した前提で以降進めます。
なおTOKEN_JSONから値を抜き出すsedはこちらの記事を参考にさせていただきました。
何が起きるか
このスクリプトを実行すると、まずアクセスキー、シークレットキー、トークンが環境変数にセットされます。
と同時に、<プロファイル名>-mfa
というプロファイルがaws cliの設定ファイルに追加されます。
すでに同名のプロファイルがある場合、クレデンシャルを新しいもので上書きします。
<プロファイル名>
はこの後設定するAWS_MFA_PROFILE
です。
使い方
~/.bashrc
等にこう書いてください。
~/.bashrc
等を書き換えたときはログインし直してください。
aws-mfa() {
export AWS_MFA_PROFILE=default ##get-session-tokenできるAWS CLIのプロファイル
export AWS_MFA_SERIAL=arn:aws:iam::account_id:mfa/devicename ##MFAデバイスの識別子
source ~/.aws/aws-mfa-set-session-token.sh $1
}
次にMFAデバイスで一時解除コードを取得してください。
最後に作ったスクリプトを下記のように実行してください。
aws-mfa <一時解除コード>
AWS CLI実行方法
スクリプト実行後は普通にAWS CLIが利用可能になります。
スクリプトを実行したセッションにはトークンが環境変数に設定されているので、プロファイルを省略可能です。
プロファイルを指定しない場合、最後にスクリプトを実行したときに取得したトークンを使用します。
aws ec2 describe-instances
スクリプトを実行したのと別のセッションだとトークンが環境変数に設定されてないため、プロファイルを指定する必要があります。
スクリプト実行時のAWS_MFA_PROFILE環境変数に-mfa
を加えたものがプロファイル名になります。
aws ec2 describe-instances --profile <AWS_MFA_PROFILE>-mfa