AWSumeを使ってマネコンでロールの連鎖を試してみた

# <font color="rgb(107, 142, 35)">目次</font>

* [はじめに](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
* [要約](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#%E8%A6%81%E7%B4%84)
* [ロールの連鎖](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%AE%E9%80%A3%E9%8E%96)
* [AWSumeとは](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#awsume%E3%81%A8%E3%81%AF)
* [構成](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#%E6%A7%8B%E6%88%90)
* [IAMロール/ポリシーの準備](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#iam%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%AE%E6%BA%96%E5%82%99)
* [CloudShellの準備](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#cloudshell%E3%81%AE%E6%BA%96%E5%82%99)
* [AWSumeのインストール](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#awsume%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
* [ロールの連鎖を実施](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%AE%E9%80%A3%E9%8E%96%E3%82%92%E5%AE%9F%E6%96%BD)
* [終わりに](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%AB)
* [参考記事](https://qiita.com/koji-koji-koji/private/f611126458c7d50cd0a3#%E5%8F%82%E8%80%83%E8%A8%98%E4%BA%8B)

# <font color="rgb(107, 142, 35)">はじめに</font>
特定のアカウントから複数アカウントへスイッチロールする仕組みを構築する機会がありました。スイッチ元IAMロールを踏み台のように使うことで、作業先アカウントの取り違えを防ぐという仕組みを検討していましたが、CUIでしか実現できないということがわかり断念していました。アイデアを実現できないことが悔しく、せっかくなので試してみました。

例えばスイッチ元が`Account A`、作業先が`Account B`の場合、`account-a-role-1`にスイッチロールした後、スイッチ先アカウントを間違えて指定（`Account C`や`Account D`を指定）しても、スイッチロールが不可能なように設定することで作業先の誤りを防ぐイメージ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219490/ecb8f2b0-8128-f92a-4586-a2557c69729b.png)


# <font color="rgb(107, 142, 35)">要約</font>

* ロールの連鎖とは1 つのロールの認証情報を使用して別のロールを引き受けること
* 基本的にロールの連鎖はCUIでしか実現できないが、AWSumeを使うことによりロールの連鎖でコンソールログインが可能
* AWSumeとはセッショントークンを管理し、ロールの資格情報を引き受ける便利なツール


# <font color="rgb(107, 142, 35)">ロールの連鎖</font>

**ロールの連鎖**は公式ドキュメントで下記のように紹介されていました。
> **1 つのロールの認証情報を使用して別のロールを引き受けること**を**ロールの連鎖**と呼びます。


例えば下記のようにAccount AのIAMユーザーでaccount-a-roleにスイッチロールし、
account-a-roleにスイッチロールした状態でその認証情報を利用してaccount-b-roleにスイッチロールする、ということもロールの連鎖に該当すると理解しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219490/b1e109be-5d35-0430-8d68-fe69c8dcab54.png)

また、ドキュメントに明示はされていないものの、**マネジメントコンソール上でロールの連鎖はできない**ように読み取れる記述がありました。（実際試してみましたが、やはりできませんでした）

> ロールの連鎖は、**AWS CLI または API を使用して** 2 つ目のロールを引き受けるロールを使用する場合に発生します。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_terms-and-concepts.html

ですが、AWSumeというツールを使うことでこれが実現できるようです。

# <font color="rgb(107, 142, 35)">AWSumeとは</font>

AWSumeとは**セッショントークンを管理し、ロールの資格情報を引き受ける便利なツール**です。（AWSがリリースしている公式のツールではないようです。）

このツール自体の紹介は下記で行われていますのでご参照いただくと良いと思います。

https://awsu.me/

https://dev.classmethod.jp/articles/awsume/


このツールを使うことで**マネジメントコンソール上でロールの連鎖ができる**ようになるか（正確にはロールの連鎖後、マネジメントコンソールの操作ができる）以降に検証してみた結果を記載します。


# <font color="rgb(107, 142, 35)">構成</font>
ここからはAWSumeでマネジメントコンソール上でのロールの連鎖を検証した結果を記載します。下記のように簡単な構成で実施しました。（※管理が大変になるため2アカウント、1ユーザーのみとしています）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219490/bdc3d6cc-a1ab-ddd5-df22-36dc3d04730a.png)



:::note
ちなみに、個人で複数アカウントを払い出すのが初めてだったため、「複数アカウントを払い出すとなると、12 ヶ月の無料利用枠が複数アカウントで使えるようになるが、それは良いのだろうか」という疑問が湧いたので、サポートに問い合わせてみました。基本的には問題ないと回答いただきました。ただし、Organizationsを利用する際は注意が必要なようでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219490/8253f0ca-bdb4-cca5-f828-852d87525ca6.png)


https://aws.amazon.com/jp/free/free-tier-faqs/
:::



# <font color="rgb(107, 142, 35)">IAMロール/ポリシーの準備</font>

まずは、Account AでIAMロール(account-a-role-1)とポリシーの準備を行いました。

```json:account-a-role-1の信頼ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<Account AのアカウントID>:root"
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}
```
続いてaccount-b-role-1のAssumeRoleを許可するポリシーをアタッチしました。

```json:account-a-role-1にアタッチしたIAMポリシー
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::<Account BのアカウントID>:role/account-b-role-1"
    }
}
```

続いてAccount BでIAMロールの準備を行いました。信頼ポリシーのPrincipalにaccount-a-role-1を指定しました。（アタッチしたIAMポリシーは省略）

```json:account-b-role-1の信頼ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<Account AのアカウントID>:role/account-a-role-1"
            },
            "Action": "sts:AssumeRole",
            "Condition": {}
        }
    ]
}
```



# <font color="rgb(107, 142, 35)">CloudShellの準備</font>

今回はCloudShellを利用してAWSumeコマンドを実行していくため、CloudShellの準備も行いました。具体的には下記ファイルを作成しました。

```text: ~/.aws/config
[default]
region = ap-northeast-1
output = json

[profile account-a-role-1]
role_arn = arn:aws:iam::<Account AのアカウントID>:role/account-a-role-1
source_profile = default

[profile account-b-role-1]
role_arn = arn:aws:iam::<Account BのアカウントID>:role/account-b-role-1
source_profile = account-a-role-1
```


```text: ~/.aws/credentials
[default]
aws_access_key_id = <アクセスキーID>
aws_secret_access_key = <シークレットアクセスキー>
```

:::note warn
今回は便宜上IAMユーザーのアクセスキーID、シークレットアクセスキーを利用しました。
:::


# <font color="rgb(107, 142, 35)">AWSumeのインストール</font>
ここからAWSumeのインストールを行いました。CloudShellで下記を実行しました。

```
pip install awsume
```

awsumeをインストールできたことを確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219490/51be5108-4dc3-1c5b-bf84-ce94eeef360d.png)

また、コンソールログインを可能にするために、Awsume Console Pluginもインストールしました。それだけではうまく動作しなかったため、その他AWSumeのページに記載があったコマンドを実行しました。


```
pip install awsume-console-plugin
```

```
alias awsume=". awsume"
```

```
AWSUME_SKIP_ALIAS_SETUP=true pip install awsume
```

```
$ awsume-configure
===== Setting up bash =====
Wrote alias to /home/cloudshell-user/.bash_profile
Wrote autocomplete script to /home/cloudshell-user/.bash_profile
===== Setting up zsh =====
Wrote alias to /home/cloudshell-user/.zshenv
Wrote autocomplete script to /home/cloudshell-user/.zshenv
Wrote zsh function to /home/cloudshell-user/.awsume/zsh-autocomplete/_awsume
===== Finished setting up =====
```

https://awsu.me/

ここまで完了したら、CloudShellを再起動しました。


# <font color="rgb(107, 142, 35)">ロールの連鎖を実施</font>

AWSumeコマンド`awsume <profile名>`でスイッチロールを実施し、`aws sts get-caller-identiry`コマンドで呼び出し元認証情報を確認しました。

```shell
# スイッチロール前の呼び出し元認証情報を確認
$ aws sts get-caller-identity
{
    "UserId": "<UserId>",
    "Account": "<Account AのアカウントID>",
    "Arn": "arn:aws:iam::<Account AのアカウントID>:user/<IAMユーザー名>"
}

# awsume <profile名>でスイッチロールを実行
$ awsume account-a-role-1
[account-a-role-1] Role credentials will expire 2024-07-13 14:00:48

# スイッチロール後の呼び出し元認証情報を確認
$ aws sts get-caller-identity
{
    "UserId": "<論理Id>:account-a-role-1",
    "Account": "<Account AのアカウントID>",
    "Arn": "arn:aws:sts::<Account AのアカウントID>:assumed-role/account-a-role-1/account-a-role-1"
}
```

account-a-role-1にスイッチロールしたことを確認できました。
続いて、account-b-role-1にスイッチロールを実施し、先ほどインストールしたプラグインを使ってコンソールログインのためのURLを出力させました。

```bash
# account-b-role-1にスイッチロール -clオプションでコンソールのURLが標準出力された
$ awsume account-b-role-1 -cl
[account-a-role-1] Role credentials will expire 2024-07-13 14:20:34
[account-b-role-1] Role credentials will expire 2024-07-13 14:20:35
https://signin.aws.amazon.com/...<省略>
```

出力されたURLにアクセスすると、ログアウトを促すページが表示されました。
「ここをクリックしてください」を選択しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219490/2cbe24fb-cd4a-0a3d-399e-9d14afeefdab.png)

すると、Account Bのaccount-b-role-1にスイッチロールした状態でコンソール画面を開くことができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219490/78f2e6b1-802f-4d3a-a3ec-5b8c51526ed7.png)



# <font color="rgb(107, 142, 35)">終わりに</font>

AWSumeを使ってロールの連鎖を試してみました。ロールの連鎖は、とりあえず面白そうだからやってみたという記事が多い印象だったため、実際のユースケースがあるのだろうかと気になったので調べてみました。ユースケースについて気になる方は下記などを参照してみると良いかと思います。

https://aws.amazon.com/jp/blogs/news/restrict-amazon-redshift-spectrum-external-table-access-to-amazon-redshift-iam-users-and-groups-using-role-chaining/

https://dev.classmethod.jp/articles/cross-account-redshift-copy-with-role-chaining/



# <font color="rgb(107, 142, 35)">参考記事</font>


https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_terms-and-concepts.html

https://awsu.me/

https://dev.classmethod.jp/articles/awsume/

https://aws.amazon.com/jp/free/free-tier-faqs/

https://htnosm.hatenablog.com/entry/2022/12/31/090000


https://aws.amazon.com/jp/blogs/news/restrict-amazon-redshift-spectrum-external-table-access-to-amazon-redshift-iam-users-and-groups-using-role-chaining/

https://dev.classmethod.jp/articles/cross-account-redshift-copy-with-role-chaining/