IAM Identity Centerで、特定の許可セットを割当中のユーザーに、別の許可セットを追加で割り当てるスクリプトを作った

IAM Identity Center、AWSさんのドキュメントや資料でも`IdC`や`IIC`など略し方が異なるので、内部でも決まっているわけでは無いんだな～と思う今日この頃です。~~SSOのままで良かったんじゃ...~~
本稿では仮に IdC と略すことにします。

# 背景

制限を追加したいが、いきなり既存の許可セットに追加して影響が出ないように、
既存の許可セットに制限を加えた別の許可セットを作成して、既存の許可セットが割当たっているユーザー（＆グループ）に追加で割り当てたいです。
ちょうど良さそうなAPIは無かったので、スクリプトを作りました。

# 要件

タイトルの通りです。
対象はOrganization内の全てのアカウントです。
数が多いのでAPIで対応したいです。

# 方針

以下のAPIを用いれば、要件を満たせそうです。

[ListAccountsForProvisionedPermissionSet](https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_ListAccountsForProvisionedPermissionSet.html)
[ListAccountAssignments](https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_ListAccountAssignments.html)
[CreateAccountAssignment](https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_CreateAccountAssignment.html)

1. 対象の許可セットが定義されているアカウントのリストを取得する
2. 取得したアカウントのリストを用いて、アカウントに対象の許可セットで割り当てられているユーザーとグループのリストを取得する
3. アカウントにユーザーと許可セットを指定して割り当てる

# 環境情報

EC2で動かしました。
IdCを操作できる権限を持ったIAM権限の設定と、AWSCLIのプロファイル設定も行ってください。

```shell-session
$ ec2-metadata --ami-id
ami-id: ami-0947c48ae0aaf6781
$ cat /etc/system-release
Amazon Linux release 2023 (Amazon Linux)
$ aws --v
aws-cli/2.9.19 Python/3.9.16 Linux/6.1.38-59.109.amzn2023.x86_64 source/x86_64.amzn.2023 prompt/off
```

# 実装

スクリプト内の`USER`指定している箇所を`GROUP`に変更するとグループを対象にできます。

```bash:assign-another-permissionset.sh
#!/bin/bash

########
# 設定 #
########
AWS_CLI_PROFILE_NAME='example' # Your AWS CLI Profile Name
INSTANCE_ARN='arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxxxx' # TIPS:IdC>Settings>Instance ARN
PROVISIONED_PERMISSIONSET_ARN='arn:aws:sso:::permissionSet/ssoins-xxxxxxxxxxxxxxxx/ps-xxxxxxxxxxxxxxxx' # 特定の許可セットARN
ASSIGN_PERMISSIONSET_ARN='arn:aws:sso:::permissionSet/ssoins-xxxxxxxxxxxxxxxx/ps-0123456789abcdef' # 追加する許可セットのARN

########
# 処理 #
########
echo '許可セットが定義されているアカウントのリストを取得'
accounts=`aws sso-admin list-accounts-for-provisioned-permission-set \
    --instance-arn ${INSTANCE_ARN} \
    --permission-set-arn ${PROVISIONED_PERMISSIONSET_ARN} \
    --provisioning-status "LATEST_PERMISSION_SET_PROVISIONED" \
    --profile ${AWS_CLI_PROFILE_NAME} \
    --output json` # textの方が後続の処理で扱いやすいが、ログの視認性のためにjsonで出力

# TODO:NextToken対応を追加する

echo $accounts | jq . | tee provision-account_ids.json

account_ids=$(echo "$accounts" | jq '.AccountIds[]')
if [ -z "$account_ids" ]; then
    echo '対象の許可セットが定義されているアカウントはありませんでした'
    exit 0
fi

for accountid in $(echo $accounts | jq -c -r '.AccountIds[]'); do
    echo "対象の許可セットでaccountid ${accountid} に割り当てられているユーザーとグループのリストを取得"
    principals=`aws sso-admin list-account-assignments \
        --account-id ${accountid} \
        --instance-arn ${INSTANCE_ARN} \
        --permission-set-arn ${PROVISIONED_PERMISSIONSET_ARN} \
        --profile ${AWS_CLI_PROFILE_NAME} \
        --output json`

    # TODO:NextToken対応を追加する

    echo $principals | jq . | tee -a target-principals.log

    for principalid in $(echo $principals | jq -r '.AccountAssignments[] | select(.PrincipalType == "USER") | .PrincipalId'); do
        echo "アカウントに対象principalid ${principalid} と許可セットを割り当て"
        aws sso-admin create-account-assignment \
            --instance-arn ${INSTANCE_ARN} \
            --permission-set-arn ${ASSIGN_PERMISSIONSET_ARN} \
            --principal-id ${principalid} \
            --principal-type "USER" \
            --target-id ${accountid} \
            --target-type "AWS_ACCOUNT" \
            --profile ${AWS_CLI_PROFILE_NAME}

        # スロットリング対策
        sleep 1
    done
done

cat target-principals.log | jq -s > target-principals.json

echo Script Completed!
```

因みに、パラメータは同じなので create-account-assignment コマンドを[delete-account-assignment](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sso-admin/delete-account-assignment.html)に変えれば、許可セットの削除もできます。
その場合、設定の PROVISIONED_PERMISSIONSET_ARN や ASSIGN_PERMISSIONSET_ARN の値はどちらも削除したい許可セットのARNにしてください。

# 参考

[ListAccountsForProvisionedPermissionSet - IAM Identity Center](https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_ListAccountsForProvisionedPermissionSet.html)
[list-accounts-for-provisioned-permission-set — AWS CLI Command Reference](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sso-admin/list-accounts-for-provisioned-permission-set.html)

[ListAccountAssignments - IAM Identity Center](https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_ListAccountAssignments.html)
[list-account-assignments — AWS CLI Command Reference](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sso-admin/list-account-assignments.html)

[CreateAccountAssignment - IAM Identity Center](https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_CreateAccountAssignment.html)
[create-account-assignment — AWS CLI Command Reference](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sso-admin/create-account-assignment.html)

[DeleteAccountAssignment - IAM Identity Center](https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_DeleteAccountAssignment.html)
[delete-account-assignment — AWS CLI Command Reference](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sso-admin/delete-account-assignment.html)