[AWS]sts assume roleの一時クレデンシャル発行＆設定をワンライナーでやってみた

# はじめに
AWSでSwitch Roleやサービス間のクロスアカウントアクセスを実現するために、IAMロールを使用したアクセスの委任が必要で、そのための一時クレデンシャルの発行をaws cliで行うケースもよく出てくると思います。
aws cliを使った一時クレデンシャルの発行と設定にはいくつかの方法があるかと思いますが、コマンド一行で、つまりワンライナーで実現できないかについて調べてみました。

# やりたいこと
例えば、以下のようにアカウントAのEC2インスタンスから、アカウントBのAWSリソース（S3やDynamoDBなど）にアクセスしたいとします。
![Screenshot 2022-11-28 at 17.55.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/7f134344-d4cf-02dc-bd82-a9d20f201a56.png)
IAMポリシー等の説明は割愛しますが、この場合、以下の流れになると思います。
1. 権限を引き受けるEC2インスタンスプロファイル（IAMロール）でaws sts assume-roleを呼び出す
1. stsからアカウントBにあるassumed roleを利用するための一時的なクレデンシャルが発行される
1. EC2インスタンスで一時的なクレデンシャルを環境変数に設定し、アカウントBにあるAWSサービスにアクセスする

# 今までのやり方
以下のコマンドを実行すると、一時的なクレデンシャルがJSON形式で返ってきます。（クレデンシャル情報は[AWS公式ドキュメント](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html)より抜粋していますが、念の為マスクしておきます）
```bash
aws sts assume-role --role-arn <アカウントBにあるassumed roleのARN> --role-session-name <role session name>
```

```json
{
    "Credentials": {
        "SecretAccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "SessionToken": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxx",
        "Expiration": "2014-12-11T23:08:07Z",
        "AccessKeyId": "xxxxxxxxxxxxxxxxxxxx"
    }
}
```
これらを以下のように環境変数に設定します。
```bash
export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export AWS_SESSION_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxx
```
ただこれだと、手動で設定する必要があるというのと、クレデンシャル情報がコマンド履歴に残ってしまうので、なんか嫌ですよね。
なので、以下のように、JSONから該当クレデンシャルをjqというツールで取得し、環境変数に設定するという方法もあります。
```bash
role_credentials=$(aws sts assume-role --role-arn <アカウントBにあるassumed roleのARN> --role-session-name <role session name>)
export AWS_ACCESS_KEY_ID=$(echo $role_credentials | \
jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $role_credentials | \
jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $role_credentials | \
jq -r '.Credentials.SessionToken')
```
aws sts assume-roleコマンドで取得したJSON形式の情報をrole_credentialsという変数に格納してから、必要な環境変数を設定していきます。環境変数の値にjqで抽出した該当クレデンシャルを渡すという感じですね。
確かにスクリプトに書くことで、楽にはなるかと思いますが、jqを（なければ）インストールする必要があるし、複数のコマンドを実行しているので、もう少し簡潔に書きたいですよね。

# ワンライナーで書いてみる
ということで、以下のコマンドに辿り着きました。
```bash
export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" \
$(aws sts assume-role \
--role-arn <アカウントBにあるassumed roleのARN> \
--role-session-name <role session name> \
--query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
--output text))
```
`--query`と`--output`というaws cliのオプションを使って、aws sts assume-roleコマンドで取得したJSONから該当クレデンシャルを抽出します。そして`printf`で入力データを整形して表示する内容のプレスホルダー（文字列の場合は`%s`）に該当クレデンシャルを挿入し、環境変数にexportするという処理になります。--queryと--outputオプションでデータをフィルタリングできるので、jqなどのツールを別途インストールしなくても済みます。
これでスッキリしましたね！
※複雑すぎるコマンドは逆に可読性を下げる可能性があるので、その場合処理ごとに分けて書いたほうがいいかもしれません。