大量のAWSアカウントから、aws cliで任意の情報を取得する（MFA対応）

# 前提条件

- Dockerが動く環境がある。
- 複数アカウントにスイッチロールできるIAMユーザーがある
- そのユーザーは、アクセスキー・シークレットキーを持っている。
- スイッチロール先のロールは、適正なものを付与している。

# この記事について
大量のAWSアカウントを管理している際に、複数アカウントで任意の情報を取得したいケースがあります。
MFAを有効にしている場合「MFAの番号入力の要求が出ないでエラーになる」または「スイッチの度に、毎回MFAの入力を要求される」のどちらかの問題が発生します。
どちらにしても問題があるので、セッショントークンを使って、この問題を回避する方法をまとめました。
「任意の情報を取得」としていますが、権限が適正であれば、aws cliで実行できる事は、追加でも更新でも可能です。

## 事前情報

例えば「s3バケット名が知りたい」場合、単一アカウントであれば、下記のようなコマンドで取得できます。

```
$ aws s3 ls --region ap-northeast-1
```

MFAの制約が無ければ、「~/.aws/config」にそれぞれのAWSアカウント用profileを追加すれば「--profile 別アカウントのプロファイル」のように指定する事で、スイッチ先の情報を取得できます。

```
$ aws s3 ls --profile gotchamall-dev --region ap-northeast-1
$ aws s3 ls --profile gotchamall-stg --region ap-northeast-1
$ aws s3 ls --profile gotchamall-prd --region ap-northeast-1
```

## 用意するファイル

以下のファイルを、ローカル環境に用意します。

- Dockerfile
- mfa_token_register.sh
- describe.sh
- config.txt
- profile.txt

```docker:Dockerfile
FROM amazonlinux:2

WORKDIR /root

SHELL ["/bin/bash", "-c"]
RUN yum update -y && \
    yum install -y make gcc glibc-langpack-ja bzip2 bzip2-devel openssl11-devel readline readline-devel git wget gcc-c++ libffi-devel jq tar.x86_64 unzip && \
    yum clean all && \
    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
    unzip awscliv2.zip && \
    ./aws/install

RUN mkdir /root/.aws && \
    chown root:root /root/.aws

COPY profile.txt /root/profile.txt
COPY config.txt /root/.aws/config
```

```bash:mfa_token_register.sh
#!/bin/bash

ACCOUNT_ID=$1 # MFAを設定しているAWSのアカウントID
MFA_NAME=$2 # MFAデバイスを登録する時につけている名前

# セッショントークン等の生成
SESSION_INFO=$(aws --profile default sts get-session-token --serial-number arn:aws:iam::$ACCOUNT_ID:mfa/$MFA_NAME --token-code $3 --output json)
if [ $? -ne 0 ]; then
    exit 1
fi

# 生成された情報の整理
MFA_ACCESS_KEY=$(echo $SESSION_INFO | jq -r '.Credentials.AccessKeyId')
MFA_SECRET_ACCESS_KEY=$(echo $SESSION_INFO | jq -r '.Credentials.SecretAccessKey')
MFA_SESSION_TOKEN=$(echo $SESSION_INFO | jq -r '.Credentials.SessionToken')
MFA_EXPIRATION=$(echo $SESSION_INFO | jq -r '.Credentials.Expiration')

# credentialsファイルに設定するプロファイル名
MFA_PROFILE_NAME=default-mfa

# credentialsファイルへ設定を登録
aws --profile $MFA_PROFILE_NAME configure set aws_access_key_id $MFA_ACCESS_KEY
aws --profile $MFA_PROFILE_NAME configure set aws_secret_access_key $MFA_SECRET_ACCESS_KEY
aws --profile $MFA_PROFILE_NAME configure set aws_session_token $MFA_SESSION_TOKEN

echo "successfully. profile: $MFA_PROFILE_NAME, expiration: $MFA_EXPIRATION"
```

describe.shの中で、aws cliを使い、取得したい情報を取ってきている。
必要に応じて、コマンドの中身を書き換えること。

```bash:describe.sh
IFS=$'\n'
for PROFILE in `cat profile.txt`; do
    for S3_DATA in `aws s3 ls --region ap-northeast-1 --profile ${PROFILE} --output text`; do
            echo -e "$PROFILE\t${S3_DATA}"
    done
done
```

config.txtは、「~/.aws/config」のファイルになります。
環境に応じて、AWSアカウントの数だけプロファイルを用意して下さい。
role_arnは「role_arn = arn:aws:iam::切り替え先のAWSアカウント番号:role/切り替え先のIAMロール」です。

```config.txt（参考例）
[default]
output=json
region=ap-northeast-1

[profile gotchamall-dev]
role_arn = arn:aws:iam::111111111111:role/OrganizationAccountAccessRole
source_profile=default-mfa

[profile gotchamall-stg]
role_arn = arn:aws:iam::222222222222:role/OrganizationAccountAccessRole
source_profile=default-mfa

[profile gotchamall-prd]
role_arn = arn:aws:iam::333333333333:role/OrganizationAccountAccessRole
source_profile=default-mfa
```

profile.txtは、切り替え用プロファイルの名前を列挙したものです。
環境に応じて用意して下さい。

```profile.txt（参考例）
gotchamall-dev
gotchamall-stg
gotchamall-prd
```

## Docker経由で実行

Docker経由でコマンドを実行し、まずはセッショントークンを生成します。

```
$ docker build -t gotchamall-aws-describe -f Dockerfile .
$ docker run -it --rm gotchamall-aws-describe /bin/bash

bash-4.2# vi .aws/credentials
[default]
aws_access_key_id = 複数アカウントにスイッチロールできるIAMユーザーのアクセスキー
aws_secret_access_key = 複数アカウントにスイッチロールできるIAMユーザーのシークレットキー

bash-4.2# bash mfa_token_register.sh AWSアカウント番号 IAMユーザー名 123456
successfully. profile: default-mfa, expiration: 2023-06-07 15:15:00
```

この時点で、一定期間の間、MFA認証をスキップできます。
あとは以下のコマンドで、複数アカウントで任意の情報を取得します。

```
bash-4.2# bash describe.sh
```

# 参考元
- https://rurukblog.com/post/aws-cli-mfa-input/
- https://dev.classmethod.jp/articles/temp-credentials-request-against-iam-user/