MFAを使ったAWS CLI認証とEKSクラスターへの接続を一発で終わらす 

# モチベーション
現在、Amazon Elastic Kubernetes Service (Amazon EKS)を使った開発をやっています。EKSクラスターにアクセスする際には乗っ取りを防ぐためにMFA(多要素認証：Multi-Factor Authentication)を使っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/687a3678-14c1-ba5f-d2b4-e89c5204e5ab.png)

毎日CLIから接続設定を打ち込むのが面倒なので、Shellスクリプトを作成して、なるべく自動化したいと思います。

# 前提条件
以下を満たしていることを仮定します
1. AWSのアカウントがあり、EKSクラスターが作成済み
1. AWS CLI、kubectl、eksctl がインストール済み

# 実施手順
1. MFAアプリのインストールとAWS IAMと紐付け
1. shスクリプトの作成
1. 動作確認

## MFAアプリのインストールとAWS IAMとの紐付け

MFAの設定は以下を参考にさせていただきました。

https://cloud5.jp/saitou-enable-mfa-for-users/

私が導入したのは、Microsoft Authenticatorです。
Google Authenticatorでも機能・設定方法に大差ないと思います。

iphoneの方は、Apple Storeからダウロードしてください。
![29032.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/af0f3b8d-60b5-49a7-1173-c339527db2b5.jpeg)

## shスクリプトの作成
> mfa_auth.sh
```shell
#!/bin/bash
# MFA認証用スクリプト
# エラーハンドリングと使用方法の表示
usage() {
    echo "使用方法: source $0 <MFAコード> <クラスター名> <リージョン>"
    exit 1
}

# 引数チェック
if [ $# -ne 3 ]; then
    usage
fi

# 引数から変数に代入
MFA_CODE=$1
CLUSTER_NAME=$2
REGION=$3

echo "MFA_CODE: $MFA_CODE"
echo "CLUSTER_NAME: $CLUSTER_NAME"
echo "REGION: $REGION"

# 固定のシリアルナンバー
SERIAL_NUMBER="{MFA認証の識別子に置き換え※後述}"

# セッショントークンの取得
# duration-secondsで一時的なセッション継続時間を最大36時間まで設定可能。単位は秒
SESSION_TOKEN=$(aws sts get-session-token \
    --duration-seconds 129600 \
    --serial-number "$SERIAL_NUMBER" \
    --token-code "$MFA_CODE")

# 環境変数の設定
export AWS_ACCESS_KEY_ID=$(echo "$SESSION_TOKEN" | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "$SESSION_TOKEN" | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "$SESSION_TOKEN" | jq -r '.Credentials.SessionToken')

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"

# 有効期限を日本時間に変換
EXPIRATION_UTC=$(echo "$SESSION_TOKEN" | jq -r '.Credentials.Expiration')
EXPIRATION_JST=$(date -d "$EXPIRATION_UTC" '+%Y-%m-%d %H:%M:%S %Z')
CURRENT_TIME=$(date '+%Y-%m-%d %H:%M:%S %Z')

# 有効期限の確認
if [[ "$(date -d "$EXPIRATION_UTC" +%s)" -le "$(date +%s)" ]]; then
    echo "❌ 認証情報の有効期限が切れています。"
    echo "現在時刻: $CURRENT_TIME"
    echo "有効期限: $EXPIRATION_JST"
    return 1
fi

# 成功メッセージ
echo "✅ MFA認証が成功しました。一時的な認証情報を設定しました。"
echo "現在時刻: $CURRENT_TIME"
echo "有効期限: $EXPIRATION_JST"

# EKSクラスタの認証情報を更新
aws eks update-kubeconfig --name "$CLUSTER_NAME" --region "$REGION"

# kubectlの設定を確認
echo "✅ EKSクラスタの認証情報を更新しました。"
kubectl config current-context
echo "✅ EKSクラスタの情報"
kubectl cluster-info
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/62c729ef-34d8-0f3a-40d6-aeecbfb98ed2.png)


**SERIAL_NUMBER**　には以下の識別子を設定してください

AWSコンソールホーム画面、右上のアカウント名をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/815c885a-99d4-4696-fe00-ce9165e12882.png)

セキュリティ認証情報をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/8183e09f-decb-c753-2e88-92a6132db618.png)

以下の値が識別子になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/fa23d9c9-7f29-a6c4-fbbb-9eb2f4a98f9c.png)

## 動作確認
### Ubuntuから実施する場合
```bash
source mfa_auth.sh｛MFA認証コード（6桁）｝｛EKSクラスター名｝｛EKSクラスターのリージョン｝
```

**MFA認証コード（6桁）**　にはMFAアプリで表示されている6桁の数字を入れてください。同一コードは30秒しか保持されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/1bda35d7-242b-f375-7f83-1158124e20dd.png)

以下の様に、MFA認証が成功したこととEKSクラスタの情報が表示されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318960/612995c0-9211-8ce9-8081-fb40c227bb77.png)

### Windowsから実施する場合
```powershell
wsl -d Ubuntu bash mfa_auth.sh ｛MFA認証コード（6桁）｝ "｛EKSクラスター名｝" "｛EKSクラスターのリージョン｝"
```
としてください。