AWS SSOのユーザx権限一覧をつくる

はじめまして。ZOZOテクノロジーズ CTO室 兼 SRE部 のkotatsu360です。
ウィスキーと葉巻とAWSが好きです∠( ﾟдﾟ)／

# この記事は
[ZOZOテクノロジーズ #2 Advent Calendar 2020 #2](https://qiita.com/advent-calendar/2020/zozo_tech2) 4日目です。

昨日は[tippy](https://qiita.com/tippy)さんの[CSVから一括でファイル名を変更するMacアプリを作った](https://qiita.com/tippy/items/6e7dfaefea0fbce9f3e8)でした。

# AWS SSOのユーザx権限一覧をつくる
## AWS SSO
AWS SSO使ってますか？
複数アカウントへのログインを一つのID/Passで管理できるとても便利な存在です。各AWSアカウントに対してIAMユーザを作る必要もありません。AWS SSO単体でのユーザ管理もできますが、弊社は外部IdPとしてAzure ADを利用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62601/c75678ba-b956-d1ca-3866-05aa0e4b22ae.png)

AWS SSOの詳細は過去このような記事も書いているのでよろしければ御覧ください！
[AWS Single Sign-Onを用いた、セキュアでより良いログイン体験への取り組み - Speaker Deck](https://speakerdeck.com/kotatsu360/aws-single-sign-on-for-a-better-experience-and-more-secure-login) by kotatsu360

## 今日の本題
AWS SSOは長らくWebAPIが存在せず、Webコンソールが唯一のインターフェースでした。しかし、今年の9月にとうとうWebAPIが公開され、機械的な連携が可能になりました！[^api]

[^api]: [AWS Single Sign-On がアカウント割り当て API と AWS CloudFormation サポートを追加して、マルチアカウントアクセス管理を自動化](https://aws.amazon.com/jp/about-aws/whats-new/2020/09/aws-single-sign-on-adds-account-assignment-apis-and-aws-cloudformation-support-to-automate-multi-account-access-management/)

個人的に9月の発表というのが渡りに船でした。ちょうど10月、下期の始まりということでAWS SSOに登録されているユーザとそのユーザが持つ権限の棚卸しをする予定だったためです。

棚卸し、大事です。

## （参考）ちなみに、APIが無いかったらどうなるの・・・？
このようにアカウントごとに「ユーザ」と「権限」が表示されるので、**気合**でコピペします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62601/1aac3b1a-3d1e-7465-8398-caf6256a2993.png)

# API使ってみる
## スクリプト
**これでバッチリ( ﾟдﾟ )ｸﾜｯ!!**

```bash
#!/bin/bash

set -e

export AWS_PAGER=''
export STORE_ID=#####AWS SSO設定画面に表示されているIDストアID#####
export INSTANCE_ARN=#####AWS SSO設定画面に表示されているARN#####

echo "user,account,role" > sso.list.csv

#
# パーミッションセット取得
for permission in $(aws --region us-east-1 sso-admin list-permission-sets --instance-arn ${INSTANCE_ARN} --output text --query PermissionSets); do
    echo $permission
    permission_name=$(aws --region us-east-1 sso-admin describe-permission-set --instance-arn ${INSTANCE_ARN} --permission-set-arn ${permission} --output text --query PermissionSet.Name)

    # パーミッションセットからプロビジョンされているアカウント一覧を取得
    for account in $(aws --region us-east-1 sso-admin list-accounts-for-provisioned-permission-set --instance-arn ${INSTANCE_ARN} --permission-set-arn ${permission} --output text --query AccountIds); do
        echo $account

        # あるアカウントでそのパーミッションセットに所属しているユーザ一覧を取得
        for user in $(aws --region us-east-1 sso-admin list-account-assignments --instance-arn ${INSTANCE_ARN} --account-id ${account} --permission-set-arn ${permission} --output text --query AccountAssignments[].PrincipalId); do
            echo "${user},${account},${permission_name}" >> sso.list.csv
        done
    done
done

for userid in $(cut -f1 -d, sso.list.csv | sort | uniq | grep -E ^[0-9].*$ ) ; do
    username=$(aws --region us-east-1 identitystore describe-user  --identity-store-id ${STORE_ID} --user-id ${userid} --output text --query UserName)
    sed -i  -e "s/${userid}/${username}/g" sso.list.csv
done

for accountid in $(cut -f2 -d, sso.list.csv | sort | uniq | grep -E ^[0-9]+$) ; do
    accountname=$(aws --region us-east-1 organizations describe-account  --account-id ${accountid} --output text --query Account.Name)
    sed -i  -e "s/${accountid}/${accountname}/g" sso.list.csv
done
```

エラー処理・・・？スリープ・・・？loop深くない・・・？
**(∩ﾟдﾟ)ｱｰｱｰきこえなーい**

かなりマッチョな実装になっていますが、ここでは参照だけと割り切って実装しています。
工夫次第でいくらかはスッキリかけるかと思います。

リージョンがus-east-1なのは、AWS SSOのリソースがus-east-1にあるためです。

## 実行
```bash
$ aws --version
aws-cli/2.1.1 Python/3.9.0 Darwin/19.6.0 source/x86_64
$ bash path/to/script.sh
$ cat sso.list.csv
user,account,role
taro.yamada@example.com, acccount-hoge, ReadOnlyAccess # taroさんはaccount-hogeにReadOnly権限を持っている
hanako.tanaka@example.com, account-hoge, ReadOnlyAccess # hanakoさんはaccount-hogeにReadOnly権限を持っている
...
```

取れましたね！

## かんたんな解説
SSOの階層構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62601/8c6802ba-0634-bab0-9862-11d8989bc66f.png)

Q. あるSSOインスタンスで設定されるユーザx権限のリストを作ろうとしたら？

1. SSOインスタンスに存在するパーミッションセット一覧（A, B）を取得
2. パーミッションセットAがプロビジョンされているアカウント一覧（HOGE, FUGA）を取得
3. アカウントHOGEのパーミッションセットAに所属しているユーザ一覧（ユーザ2）を取得

（以下、延々と繰り返し）
簡単ですね（？）

若干、遠回りな気はしますが、上の順番でAPIを実行する必要がありました。ここまで実施すると次の結果が得られます。

```
user,account,role
<user id>,<12桁のAWSアカウントID>,<パーミッションセット名>
```

アカウント棚卸しのためには、`<user id>`と`<account id>`では都合が悪かったので、
スクリプトでは、最後にもう一度APIを叩いてユーザ名とアカウント名で置換しています。

```
user,account,role
taro.yamada@example.com, acccount-hoge, ReadOnlyAccess
```

## 注意点
スクリプトに登場するAWS CLIのサブコマンドの内、`sso-admin`と`organizations`はReadOnly権限があれば実行可能ですが、`identitystore`はより強い権限が必要です。このときはPowerUser権限で実行しています。

# まとめ
若干強引でしたが、APIをつかってAWS SSOからユーザx権限一覧をつくることができました。
一覧さえ取得できれば、あとはどうとでも棚卸しが可能です。

なお、実はスクリプトだけでは考慮できていない状況があります。**どのパーミッションセットにも所属していないユーザは結果に含まれません**。
これについては、現状のAPIでもうまく取得できなかったため、Webコンソールからユーザリストをコピペしています。

最後に。本記事では出番がありませんでしたが、9月の時点で更新系のAPIも公開されています。
現在は、権限を設定する作業をWebAPI経由でできないか検証をしているところです。みなさまもWebAPIで良きAWS SSOライフをお楽しみください！！

明日は、[YasuhiroKimesawa](https://qiita.com/YasuhiroKimesawa)さんの「リモートワークにおける健康について考える」です。お楽しみに！