AWS SSO + CLIでロール連鎖をする際のセッション時間制限をマシにする方法を考えてみた

## これは何
3000文字Tipsイベントの参加記事です。

https://qiita.com/official-events/d523df99d6479293ffa7

## はじめに

本記事では、AWS SSO利用時にネックとなりやすい、[ロール連鎖における1時間のセッション時間上限](https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-role-chaining-limit/)による使い勝手の悪さをマシにする方法についてご紹介します。

Webサービスプロバイダである弊社では複数のAWSアカウントを管理しており、IT運用部門と開発部門が協力して[AWS SSO](https://aws.amazon.com/jp/blogs/news/aws-single-sign-on-now-enables-command-line-interface-access-for-aws-accounts-using-corporate-credentials/ )の導入を進めています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375883/2472600d-afa9-2321-9d86-5e6ba83ce6cd.png)
運用概要は上記のようにしております。
AWS SSOの機能で、各AWSアカウントに一律でアクセス権限セットにより定義したロール(RoleA)がプロビジョンされます。
各AWSアカウントを管理する各チームが、実運用に必要なポリシーと、利用を許可するユーザーのprincipalを付与したロール(RoleB)を定義します。
これにより、実運用に必要なユーザーのみがRoleBのCredentialを得て活動できる、ということになります。

ただ、この運用ではCLI利用時に問題が起こります。
AWS SSOコンソールで発行されるCLI向け認可情報は、ロールベースの一時Credentialです。このCredentialを元にさらにAssume Roleで別のCredentialを発行しようとする場合、上で紹介したロール連鎖扱いになるため、指定できるdurationsecondsの上限は3600秒です。

最終的に利用するCredentialを発行するまでの流れとしては、

- AWS SSOコンソールにアクセス
- [目的のAWSアカウントを探し、"Command line or programmatic access"から踏み台となるロール(RoleA)のCredentialを入手。クリップボードにコピー](https://aws.amazon.com/jp/blogs/news/aws-single-sign-on-now-enables-command-line-interface-access-for-aws-accounts-using-corporate-credentials/ )
- ターミナルでCredentialを貼り付け、aws sts assume-roleコマンドで本命のロール(RoleB)のCredentialを発行
- アクセスキー、シークレット、セッショントークンをシェル環境変数にセット

となります。
特に開発環境において、上記の流れをセッションが切れる度に行うのはあまりにも面倒だ、ということで、今回のやり方を考えました。

## ソリューション

ざっくりと以下3つの段階で実現します。

1. .aws/credentialにRoleAのCredentialを保存
    - このCredentialはセッション時間を12時間まで伸ばせる
1. .aws/credentialに保存したRoleAのCredentialを呼び出してAssume Roleし、得た認証情報を.aws/credentialに保存

AWS SSOコンソールで発行される一時Credentialはロール連鎖扱いになっていないため、セッション時間を最大12時間まで延長できます。
このセッション時間はAWS SSO側の設定に依存します。

このソリューションのポイントとしては、手順1.を実施した後は最大12時間、RoleBのセッションが切れる度に「シェルを一つ実行するだけでよい」ことです。

### .aws/credentialにRoleAのCredentialを保存

<details><summary>setSSOCredential.sh</summary><div>

```setSSOCredential.sh
#!/bin/bash
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile SSOCredential
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile SSOCredential
aws configure set aws_session_token $AWS_SESSION_TOKEN --profile SSOCredential

echo "Finished to set SSO credential to env and .aws/credentials."
```
</div></details>

- AWS SSOコンソールからRoleAのCredentialを入手し、ターミナルにペースト
- `bash setSSOCredential.sh` を実行

`aws configure set`コマンドは、.aws/credentialファイルにCredentialを保存するコマンドです。
ここでは、RoleAのCredentialを保存するためのプロファイルを"SSOCredential"という名前に指定して、そこにCredentialを取っておきます。

### .aws/credentialに保存したRoleAのCredentialを呼び出してAssume Roleし、得た認証情報を.aws/credentialに保存

<details><summary>setRoleCredential.sh</summary><div>

```setRoleCredential.sh
#!/bin/bash
output=$(aws sts assume-role --role-arn arn:aws:iam::999999999999:role/RoleB --duration-seconds 3600 --role-session-name cold-wisteria@works-hi.com --profile SSOCredential)

export AWS_ACCESS_KEY_ID=$(echo $output | jq .Credentials.AccessKeyId -r)
export AWS_SECRET_ACCESS_KEY=$(echo $output | jq .Credentials.SecretAccessKey -r)
export AWS_SESSION_TOKEN=$(echo $output | jq .Credentials.SessionToken -r)

aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile default
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile default
aws configure set aws_session_token $AWS_SESSION_TOKEN --profile default

echo "Finished to set role credential to env and .aws/credentials."
```
(assumerole対象のロールやrole-session-name、profileは適宜書き換えてください)
</div></details>



setSSOCredential.sh の実行後は、SSOCredentialのセッション時間中はsetRoleCredential.shを実行するたびにdefaultプロファイルに新しいCredential情報を書き込むことができます。
`timeout 36000 watch -n 3500 bash setRoleCredential.sh` みたいなコマンドで繰り返し処理にしておいてもいいかもしれません。

この状態になれば、後はdefaultプロファイルに保存されたCredentialを使ってAWS CLIでの作業を行うことが可能です。


## 最後に
本記事の執筆途中で、[aws configure sso](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-sso.html)コマンドの存在に気づきました。
が、こちらは以下の理由からそこまで使いやすくない/利用しづらいケースもあるかな、と思います。

- AWS CLI v2が必要
- 結構CLIの対話フローが長い
- 結局CLIのフローの中で、一部ブラウザアクセスとブラウザ上での操作を要求される
- 以下のように、対話の中で対象のAWSアカウントをCLI上で選択させられる  
  SSOコンソールでなら検索が可能だが、CLIではキーボードの上下で選択するしかなく、多くのAWSアカウントがSSO対象になっていると選択が辛い
  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375883/7248f7f8-aad4-dca3-6737-6b7372a11303.png)