AWS CLIでスイッチロール

CloudShellでスイッチする方法と、ローカルにインストールしたAWS CLIでスイッチする方法をやります。

 - 複数アカウントの準備は[おひとりさまOrganizationsやってみた](https://qiita.com/emiki/items/f68bec2ef6f5d3dfe14f)参照。
 - スイッチロールするためのユーザ・ロール・権限の準備は[AWSマネジメントコンソールでスイッチロールする](https://qiita.com/emiki/items/bfb900fff199ecdf455d)を参照。

# 0.事前準備
今回はアカウントA（スイッチ元）からアカウントB（スイッチ先）にAWS CLIでスイッチロールする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/da651aca-193b-a40e-4490-b41e772af6c4.png)
 - アカウントA（スイッチ元）
   - IAMユーザ：AccountA_user
     - 「AccountB_role」を引き受ける権限が必要
     - CloudShellを使う場合は`AWSCloudShellFullAccess`権限が必要

```json:ユーザーベースのポリシー
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::<スイッチ先(アカウントB)AWSアカウントID>:role/AccountB_role"
    }
}
#CloudShellを使う場合はこれに追加で AWSCloudShellFullAccess もアタッチしておく
```
 - アカウントB（スイッチ先）
   - IAMロール：AccountB_role
     - 信頼ポリシーのPrincialとしてアカウントAの設定が必要

```json:ユーザーベースのポリシー
#今回はReadOnlyAccessをアタッチしておく
```

```json:信頼ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<スイッチ元(アカウントA)AWSアカウントID>:user/AccountA_user"
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}
```

信頼ポリシーのprincipal部分にユーザを複数記載する場合は以下のようにカンマ区切りで記載する。
```
"Principal": {
  "AWS": [
    "arn:aws:iam::AWS-account-ID:user/user-name-1", 
    "arn:aws:iam::AWS-account-ID:user/user-name-2"
  ]
}
```

# 1.CloudShellのAWS CLIでスイッチロール
アカウントAでCloudShellを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/152a1321-81ac-92cb-aa86-839dfd00b43b.png)

IAMロールから認証情報を取得して環境変数に設定していく。

```shell
#aws sts assume-roleコマンドでアカウントBのAccountB_roleの
#アクセスキー・シークレットアクセスキーなどのクレデンシャル情報を表示し、
#変数role_credentialsに格納する
role_credentials=$(aws sts assume-role \
  --role-arn "arn:aws:iam::アカウントBのアカウントID:role/AccountB_role" \
  --role-session-name session-name)

#AccountB_roleのアクセスキーを環境変数AWS_ACCESS_KEY_IDに格納する
export AWS_ACCESS_KEY_ID=$(echo $role_credentials | \
  jq -r '.Credentials.AccessKeyId')

#AccountB_roleのシークレットアクセスキーを環境変数AWS_SECRET_ACCESS_KEYに格納する
export AWS_SECRET_ACCESS_KEY=$(echo $role_credentials | \
  jq -r '.Credentials.SecretAccessKey')

#セッショントークンを環境変数AWS_SESSION_TOKENに格納する
export AWS_SESSION_TOKEN=$(echo $role_credentials | \
  jq -r '.Credentials.SessionToken')

#現在の権限（スイッチしたロールの情報）を確認する
aws sts get-caller-identity

```
`aws sts get-caller-identity`を実行すると以下のように、現在のスイッチロールの情報が表示される。
 - AssumedRoleID
 - スイッチ先のアカウントBのアカウントID
 - 一時認証情報のARN

```shell
{
    "UserId": "AROxxxxxxxxxxxxxxxNYQ:session-name",
    "Account": "アカウントBのアカウントID",
    "Arn": "arn:aws:sts::アカウントBのアカウントID:assumed-role/AccountB_role/session-name"
}
```

セッションを切断する（`Ctr+d`）、もしくはセッションがExpireするまでは、スイッチした状態の権限でAWS CLI操作ができる。

`aws s3 ls`コマンドで、アカウントBのS3バケットが表示されることが確認できる。

```
[cloudshell-user@ip-10-0-47-62 ~]$ aws s3 ls
2022-03-26 09:36:37 emiki-bucket1
2022-03-26 09:37:07 emiki-bucket2
[cloudshell-user@ip-10-0-47-62 ~]$ 
```

スイッチバックは以下のコマンドを入力する。
（もしくは`ctr+d`でセッションを切断する）

```shell
#環境変数の削除
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

#現在の権限（スイッチしたロールが何か）を確認する
aws sts get-caller-identity
```

ユーザがアカウントAのユーザにスイッチバックしていることが確認できる。
```
[cloudshell-user@ip-10-0-47-62 ~]$ aws sts get-caller-identity
{
    "UserId": "AxxxxxxxxxxxxxxxxxxH",
    "Account": "アカウントAのアカウントID",
    "Arn": "arn:aws:iam::アカウントAのアカウントID:user/AccountA_user"
}
[cloudshell-user@ip-10-0-47-62 ~]$
```

# 2.ローカルにインストールしたAWS CLIでスイッチロール
今回はWindows10にインストールしたWSLでスイッチロールする。
アカウントA（スイッチ元）ユーザのアクセスキーとシークレットアクセスキーが必要になるので、発行しておく。
WSLでAWS CLIを使う方法は[Windows10でWSL2をインストールしAWS CLIを実行する](https://qiita.com/emiki/items/f26e8b5e76ddb73a5316)を参照。

## 2-1.設定ファイル
configファイルにアカウントBのロールプロファイルを記載しておく。
```
[profile AccountB_RO]
region = ap-northeast-1
role_arn = arn:aws:iam::アカウントBのアカウントID:role/AccountB_role
source_profile = default
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/b2b887f9-b0b5-90d3-be0e-e252094dd751.png)

credentialsファイルにアカウントAのユーザのクレデンシャル情報（アクセスキー・シークレットアクセスキー）を記載しておく。
```
[AccountA_user]
aws_access_key_id=Axxxxxxxxxxxxxxxxxx4
aws_secret_access_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/8b075846-4ef3-c6cf-3220-3e20cf06d555.png)

このままだとデフォルトのプロファイルが使われてしまうので、アカウントAユーザで AWS CLIを実行するように環境変数を設定しておく。
```shell
#デフォルトプロファイルにアカウントAのユーザを設定
export AWS_DEFAULT_PROFILE=AccountA_user
#現在のユーザを確かめる
aws sts get-caller-identity
```
アカウントAのユーザでAWS CLIが実行されていることが確認できる。
```
[cloudshell-user@ip-10-0-47-62 ~]$ aws sts get-caller-identity
{
    "UserId": "AxxxxxxxxxxxxxxxxxxxH",
    "Account": "アカウントAのアカウントID",
    "Arn": "arn:aws:iam::アカウントAのアカウントID:user/AccountA_user"
}
[cloudshell-user@ip-10-0-47-62 ~]$
```
スイッチロールする準備ができた。

## 2-2.スイッチロールする
`aws s3 ls`コマンドに`--profile`オプションでアカウントBのロールを指定して実行し、アカウントBのS3バケットが表示されることが確認できる。
```shell
emi@LAPTOP-AOJR4Q2P:~$ aws s3 ls --profile AccountB_RO
2022-03-26 18:36:37 emiki-bucket1
2022-03-26 18:37:07 emiki-bucket2
emi@LAPTOP-AOJR4Q2P:~$
```

スイッチしてからの作業が終わったら、デフォルトのプロファイルを使うように、環境変数を削除しておく。
```shell
unset AWS_DEFAULT_PROFILE
```


# 参考
https://qiita.com/emiki/items/f68bec2ef6f5d3dfe14f

https://qiita.com/emiki/items/bfb900fff199ecdf455d

https://www.yamamanx.com/aws-cli-iamrole-assumerole/

https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-assume-role-cli/

https://dev.classmethod.jp/articles/cli-switch-role/

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html

https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-assume-role-cli/

https://dev.classmethod.jp/articles/sts-sessionname/

https://dev.classmethod.jp/articles/aws-cli-assume-role-with-session-name/