【Chatbot】Channelガードレールとは?AWS Chatbotで新しく出来た権限周りについて調べてみた

# 背景
つい最近、Slackにエラーを通知させようと新規にChatbotを作成しようとしたところ、channelガードレールという設定項目などが追加されており、しかも設定必須項目だったのでこれは調べないとなと思いザッと調査しました。※チャットクライアントはAmazon Chimeではなくslackを想定して書いていきます。(22年1月時点)

<img width="794" alt="スクリーンショット 2022-01-23 15.17.01.png (47.0 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/6dec171a-bac1-45e1-bd7e-5e55e5e1fc11.png">

ここで話す、Chatbot権限周りとしての登場人物は以下の3つ
- チャネルIAMロール
- ユーザロール
- channelガードレール

Slackからaws-cliコマンドを用いてChatbot経由で多くのawsリソースに対して操作が可能になった事で追加された権限制御機能と思われる。(21年11月29日プレビュー)

https://aws.amazon.com/jp/about-aws/whats-new/2021/11/aws-chatbot-management-resources-slack

※これまではlambdaの呼び出しやリソース参照系など限られたコマンドしか対応していませんでした。

# チャネルIAMロール と ユーザロール
Chatbot では、slackからアクション (CLI コマンドの実行やインタラクティブなメッセージへの応答) を実行するために IAM ロールを指定します。その際に、チャネルIAMロールとユーザロールの2種があり、どちらか一方か或いは両方を指定する事が可能です。

- チャネルIAMロール
slackのチャンネルに存在するメンバー全てに同じ権限を付与する事ができるロール

- ユーザロール
slackのチャンネルに存在するメンバーそれぞれに別々の権限を付与する事ができるロール

## ユースケース
- 対象slackチャンネルの構成メンバーによって使い分ける
    - 開発者のみや、個別に権限を分ける必要がない単一種別のメンバーによって構成されるチャンネル
        - チャネルIAMロールを使用して必要な権限を一括付与
    - 開発者以外或いは開発者の中でも権限が別れているメンバーで構成されるチャンネル
        - チャネルIAMロールでは必要最低限の読み取り権限などを付与
        - 開発者などにはユーザロールで個別に必要な権限を付与
        - そもそもチャネルIAMロールを使わず、ユーザロールのみで権限を付与

# Channel ガードレールとは
チャネルIAMロールやユーザロールによって実行可能な権限を設定する事が出来ましたが、それらの定義に関わらず、**Channel ガードレールは両者よりも優先される**特徴があります。

<img width="649" alt="スクリーンショット 2022-01-23 15.53.14.png (50.4 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/6fca3f89-e272-42e8-bd32-0163e3633a59.png">

## 誤解
優先されるという事は、チャネルIAMロールなどより強い権限が設定されていたら、そちらの実行権限範囲が反映されるのかというとそうでもない。**Channel ガードレールにadmin権限が付与されていても、チャネルIAMロールやユーザロールで指定した権限以上のアクションは出来ない。その名の通り、飽くまでも予防的な位置付け**

## 実際
**Channel ガードレールで許可されていない権限は、例えチャネルIAMロールやユーザIAMロールで許可設定されていても実行不可。**

# 実行可能権限範囲
- 大前提としてChannelガードレールで許可されていないアクションは実行不可
- Slackチャンネルメンバーは、Channelガードレールで許可された権限とチャネルIAMロールで許可された権限が被る範囲内でアクションを実行可能
- ユーザーロールにマッピングされたSlackチャンネルメンバーは、Channelガードレールで許可された権限とユーザロールで許可された権限が被る範囲内でアクション実行可能
    - チャネルIAMロールも設定されている場合はそちらで許可された権限とChannelガードレールと被る範囲内でもアクション実行可能

<img width="533" alt="スクリーンショット_2022-01-23_19_42_08.png (79.5 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/30a19708-c86f-4a42-96c9-f528e04f69e6.png">

# CloudFormationでChatbotを作成する場合
Chatbotを作成する際にCloudFormationを用いている場合、これまで(21年11月?以前)Channel ガードレールに関する設定値が存在しなかったため、以前のままの定義を使用してスタックを作成するとDefaultではChannel ガードレールのポリシーにadmin権限が付与されます。また、現状CloudFormationの場合はChannelガードレールに関するプロパティは定義必須ではないようです。

## 新規追加プロパティ
 - GuardrailPolicies

>GuardrailPolicies
Channel ガードレールとして適用されるIAMポリシーARNのリスト。
*これが設定されていない場合、AWSが管理する「AdministratorAccess」ポリシーがデフォルトとして適用されます。*
現在、サポートされているIAMポリシーは1つだけです。
必須：いいえ
タイプ：文字列のリスト
更新が必要です：中断なし

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-chatbot-slackchannelconfiguration.html

読んだ当初は、なんて仕様だ…と思いましたが、調査した結果Channel ガードレールの特性の理解に誤解があったので、ここでいうDefault=admin付与とはチャネルIAMロールやユーザロールで指定した権限をそのまま適用させるという意味合いになるのである程度納得がいった。

この仕様のため、Channel ガードレールできちんと制御させたい場合は別途ポリシーを定義して紐付けてあげる必要があります。

# 既存ChatbotのChannelガードレール権限について
既存のChatbot(21年11月?以前)に作成されたものはChannel ガードレールに「保護ポリシー」というものが適用されている。

<img width="836" alt="スクリーンショット_2022-01-21_19_43_40.png (49.2 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/21/108350/9c3956f0-5832-4eb0-98d5-a21bb89a7501.png">

## What's 保護ポリシー
>使用可能なCLIコマンドの拡張により、チャネルメンバーはAWSリソースを作成、読み取り、更新、および削除できます。これを防ぐために、予期しない変更を防ぐために、デフォルトで既存のAWSチャットボット設定に保護ポリシーが適用されます。具体的には、すべてのCLIコマンドが使用可能になる前に使用可能だったものにアクセス許可とアクションを制限します。このポリシーは取り外し可能ですが、すべてのガードレール、チャネルIAMの役割、およびユーザーの役割がガバナンスポリシーまたはチャネルの要件に適合していることを確認するまで、このポリシーをそのままにしておくことを強くお勧めします。詳細については、保護ポリシーを参照してください。

https://docs.aws.amazon.com/chatbot/latest/adminguide/chatbot-cli-commands.html#protection-policy

要するに、**機能が拡張される前から使えていたawsコマンドのみを定義したポリシー**とのこと

## 保護ポリシーの中身
```json
{
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:Invoke*",
                "support:*",
                "ssm-incidents:*"
            ],
            "Resource": "*"
        }
    ]
}
```

なので、既に作成されているChatbotを使用して保護ポリシーより広い権限を与えたい場合は、Channel ガードレールのポリシー権限を変更する必要があります。

# 実際にやってみた

## IAMロール&ポリシー作成
下記の様にChannel ガードレールにadmin権限、チャネルIAMロールにSNSのTopic作成権限を付与

 - Channel ガードレール 

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}
```

- チャネルIAMロール

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "create topic",
            "Effect": "Allow",
            "Action": "sns:CreateTopic",
            "Resource": "*"
        }
    ]
}
```

## snsTopic作成コマンド実行
Topic名`chatbot-test-sns`を作成します。

```
@aws sns create-topic --name chatbot-test-sns --region ap-northeast-1
```
対象のslack上でcliコマンドを実行すると下の図の様に実行確認が返って来ましたので、`[Run] command`を押下。

<img width="690" alt="スクリーンショット_2022-01-23_16_01_03.png (47.9 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/97d399c2-211f-444c-b208-bce13f15047d.png">

コマンドが実行されましたよと返って来ました

<img width="682" alt="スクリーンショット_2022-01-23_16_01_21.png (24.4 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/a7e159a7-2475-4fec-a20f-af527079aaab.png">

実際に作成されたか確認してみましょう。
## コンソールで確認

<img width="776" alt="スクリーンショット_2022-01-23_16_07_35.png (25.9 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/db93c3b3-9a8c-4f23-89b8-4fa98cc4f550.png">

無事、`chatbot-test-sns`が作成されていますね。

## snsTopicをlistコマンドで確認
```
@aws sns list-topics --region ap-northeast-1
```

<img width="665" alt="スクリーンショット_2022-01-23_16_12_21.png (82.3 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/6502716f-effc-4a93-b4bf-90fb1bd5bb49.png">

SNS:ListTopicsを実効する権限がありませんと返ってきました。
これにより、Channelガードレールで全てのアクションが実行可能であっても、チャネルIAMロールでsnsTopicの作成権限与えていないためTopicの参照までは出来ないことが確認できましたね。

# チャネルIAMロールとユーザーロール、Channel ガードレールの違いをそれぞれ確認

## ユーザーロール
チャネルIAMロールとChannelガードレールの挙動の違いは分かったので、ユーザーロールを交えての違いも見ていきたいと思います。先ず改めての説明になりますが、チャネルIAMロールは対象のSlackチャンネルにいるメンバー全員が同じ権限を持ちます。

これまでは`TestMember-01`のSlackメンバーで動作確認を行ってましたが、`TestMember-02`のメンバーでも同様の事が出来るか確認します。

## Topic名`chatbot-test-sns-2`を作成して、Listで確認

```
@aws sns create-topic --name chatbot-test-sns-2 --region ap-northeast-1
```

<img width="673" alt="スクリーンショット_2022-01-23_16_30_28.png (71.0 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/741ba6ea-12bd-422d-81e2-7a8b4dc029ff.png">

<img width="665" alt="スクリーンショット_2022-01-23_16_30_48.png (90.3 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/20ad0261-3e9f-4c34-8fa0-b75976f6291e.png">

`TestMember-02`でも結果は同じですね。

対するユーザーロールはSlackメンバー個別で権限の制御が可能です。事前準備として適用予定のIAMロール&ポリシーの作成とChatbotとSlackのメンバーIDを事前にマッピングする必要があります。

## 適用予定IAMロール&ポリシー作成
それぞれ以下の権限を持たせたIAMロールを作成します。

- chatbot-test-role-1
    - snsList権限を付与

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "user role policy1",
            "Effect": "Allow",
            "Action": "sns:ListTopics",
            "Resource": "*"
        }
    ]
}
```

- chatbot-test-role-2
    - snsタグ付け権限を付与

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "user role policy2",
            "Effect": "Allow",
            "Action": "sns:TagResource",
            "Resource": "*"
        }
    ]
}
```

## Slackメンバーとユーザーロールをマッピング

`TestMember-01`側で以下コマンドを実行


```
@aws switch-role
```
※本来は既存の権限では足りない場合にユーザロール画面に飛ぶためのコマンドらしいですが、既存Slackメンバーをマッピングするピンポイントなコマンドが見当たらなかったので代用。

AWSアカウントをクリックしてねと表示されるのでクリック

<img width="638" alt="スクリーンショット_2022-01-23_17_05_46.png (41.6 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/274680a6-af8e-40f2-95cc-c69091acc9f5.png">

事前に用意したIAMロールを選択して「保存」を押下

<img width="832" alt="スクリーンショット_2022-01-23_17_02_32.png (116.7 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/339c5439-b699-4b6b-b2eb-0f9548edbc70.png">

Slack画面に遷移してアクセス権限リクエスト画面より「許可する」を押下
<img width="548" alt="スクリーンショット_2022-01-23_17_02_43.png (73.1 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/f9085f83-61dd-4933-bd3c-efceda7b2665.png">

Slack側でロール適用が成功と表示されます。

<img width="595" alt="スクリーンショット_2022-01-23_17_03_06.png (15.6 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/1860e5ef-cc27-44a1-af2c-be921d2b074e.png">

同様の作業を`TestMember-02`でも実行
※`TestMember-02`は別のロールを適用

Chatbotコンソールの「ユーザのアクセス許可」よりマッピングの確認

<img width="1508" alt="スクリーンショット_2022-01-23_17_04_43.png (122.2 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/03508218-261d-441c-8c74-b3354274b709.png">

## snslistコマンドを実行してTopicを確認
```
@aws sns list-topics --region ap-northeast-1
```

### TestMember-01の場合(**List権限有り**
期待通りList結果が返ってきました。

<img width="669" alt="スクリーンショット_2022-01-23_17_25_03.png (55.7 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/19283cea-c3d6-489c-b228-6477654f8bea.png">

### TestMember-02の場合(**List権限無し**
こちらも期待通りに権限不足でエラーとなりました。

<img width="674" alt="スクリーンショット_2022-01-23_17_25_23.png (90.2 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/f17c6e04-d3b9-4aa0-a519-1301e54c0a0d.png">

## snsタグ付与コマンド実行
`chatbot-test-sns-2`にNameタグを付与
※AWSアカウントIDは各自置き換え

```
@aws sns tag-resource --resource-arn arn:aws:sns:ap-northeast-1:AWSアカウントID:chatbot-test-sns-2 --tags Key=Name,Value=chatbot-test-sns-2
```

### TestMember-01の場合(**tag付け権限無し**
期待通りに権限不足でエラーとなりました。

<img width="692" alt="スクリーンショット_2022-01-23_17_28_07.png (106.7 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/5d7057c0-5b56-434e-98ed-a1300c3b4e27.png">

### TestMember-02の場合(**tag付け権限有り**
期待通りにタグ付けが実行されました

<img width="956" alt="スクリーンショット_2022-01-23_17_27_46.png (47.5 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/39de0f45-1236-4436-9521-2af00c52e382.png">

念の為コンソールでも確認

<img width="956" alt="スクリーンショット_2022-01-23_17_41_08.png (52.2 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/1db28833-f3e7-416c-907b-edc7ba2f65ca.png">

# Channelガードレールで権限制御
ここまでChannelガードレールは全てadmin権限が付与された状態でした。つまり、チャネルIAMロールやユーザロールで定義した権限がそのまま適用されて実行出来ていた訳ですが、今度はChannelガードレールで実行権限を制限してみようと思います。

以下はチャネルIAMロールで付与されている`CreateTopic`、chatbot-test-role-1に付与されいてる`ListTopics`、chatbot-test-role-2に付与されている`TagResource`のみのアクションを許可しているポリシーになります。このポリシーが設定されたロールを作成してChannelガードレールに適用。

## Channelガードレール用IAMロール&ポリシー作成

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ChannelGuardRail",
            "Effect": "Allow",
            "Action": [
                "sns:TagResource",
                "sns:CreateTopic",
                "sns:ListTopics"
            ],
            "Resource": "*"
        }
    ]
}
```

コンソールの「ガードレールを設定」から、作成したIAMロールをChannelガードレールに設定

<img width="1281" alt="スクリーンショット_2022-01-23_18_00_01.png (77.1 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/9fd7ebd5-f612-41bc-b3e2-b44945addef0.png">


## chatbot-test-role-1に権限追加
chatbot-test-role-1にTopic:`chatbot-test-sns`のみを削除できる権限を新たに追加しました。
※AWSアカウントIDは各自置き換え

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "new user role policy 1",
            "Effect": "Allow",
            "Action": "sns:DeleteTopic",
            "Resource": "arn:aws:sns:ap-northeast-1:AWSアカウントID:chatbot-test-sns"
        },
        {
            "Sid": "user role policy 1",
            "Effect": "Allow",
            "Action": "sns:ListTopics",
            "Resource": "*"
        }
    ]
}
```

## snsTopic削除コマンド実行
```
@aws sns delete-topic --topic-arn arn:aws:sns:ap-northeast-1:AWSアカウントID:chatbot-test-sns
```
コマンド実行後、このアクションはリソースを削除するものですという注意が表示されるので`[Confirm] command`をクリック

その直後にChannelガードレールによりアクションの実行拒否が表示されました。

<img width="669" alt="スクリーンショット_2022-01-23_18_04_31.png (96.2 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/30309af0-e8cb-4bb2-824e-46bf5a4a0ddb.png">

# Channel ガードレールの使い道
開発中の場合は開発者には強めの権限が付与されがちだが、Slack経由でのコマンド実行では○○まではさせないようにしたいというケースでChannel ガードレールが効いてくるかなと思いました。

既に払い出している開発者のIAMロールなどをユーザロールに設定して、ChatOps用のIAMロールを別途用意する手間を省きつつ、Slackチャンネルにいるメンバー個別で制御出来るのに加えて、Channel ガードレールで更に細かく権限を絞っていくスタイルが実現できそうです。

ただ、親アカウントである程度権限を制御してSSO経由でログインしている場合は、ログイン先アカウントで改めて個別のIAMロールを事前に作っているというケースがどれだけあるか微妙なところ。どの道ユーザーロール用のロールを作ってあげる方が多いかもしれない。

# ユーザーロールのマッピングを強制するには
新規にSlackチャンネルにメンバーが追加された際に、**ユーザーロールの要件を有効化**する事で`@aws`コマンドを実行するとユーザーロールのマッピングをするよう強制する事が出来ます。

<img width="598" alt="スクリーンショット_2022-01-23_19_56_30.png (31.6 kB)" src="https://img.esa.io/uploads/production/attachments/10655/2022/01/23/108350/6689ae11-78b0-401d-b45c-3688f7f774b0.png">

# 使用できないコマンド
ほぼ全てのawscliコマンドがSlack上から使用できるようになったが、下記のコマンドは未対応。

https://docs.aws.amazon.com/chatbot/latest/adminguide/chatbot-cli-commands.html#protection-policy

- Chatbot
    - All Operations
- Amazon Cognito user pools
    - All Operations
- IAM
    - All Operations
- AWS Key Management Service
    - All Operations
- Amazon SimpleDB
    - All Operations
- Secrets Manager
    - All Operations
- AWS Single Sign-On
    - All Operations
- AWS Security Token Service
    - All Operations
- AWS AppSync
    - ListApiKeys
- AWS CodeCommit
    - GetFile
    - GetCommit
    - GetDifferences
- Amazon Connect
    - GetFederationToken
- Amazon DynamoDB
    - BatchGetItem
    - GetItem
- Amazon EC2
    - GetPasswordData
- Amazon ECR
    - GetAuthorizationToken
    - GetLogin
    - GameLift
    - RequestUploadCredentials
    - GetInstanceAccess
- Lightsail
    - DownloadDefaultKeyPair
    - GetInstanceAccessDetail
    - GetKeyPair
    - GetKeyPairs
- Amazon Redshift
    - GetClusterCredentials
    - StorageGateway
    - DescribeChapCredentials
- Amazon S3
    - GetObject
    - HeadObject
- Snowball
    - GetJobUnlockCode

# その他制限
- Chatbotのロール権限にかかわらず、ユーザーはSlackチャネル内でIAM、AWS Security Token Service、AWS Key Management Serviceのコマンドを実行不可。
- S3コマンドエイリアス(ls, cpなど)をサポートしていない。
- 任意のAWSサービスの秘密鍵やキーペアの表示や解読、IAM資格情報は取得出来ない。
- SlackチャンネルでAWS CLIのコマンドメモリ（↑または↓キーを押したときに直近のコマンドが表示されること）は使用不可。
- SlackチャンネルからAWSのサポートケースを作成できるが、ファイルの添付は不可。
- Slackチャンネルは、標準的なAWS CLIのページ分割は不可。

# まとめ
去年のRe:inventでChatbotに関する機能が拡張されたことは知っていて、プレビューだし触るのはまだ先かなと思っていて、ひょんなタイミングで調査することになりましたがSlackから多くのAWSリソースをcliコマンドで操作出来るのはいいですね。

Chatbotを使用する場合、何かをslackへ通知するケースが殆どだと思いますが今後新規に作成する際にChannelガードレールなど権限周りに関してこれで迷わずに済むはず。。

# 参考
https://docs.aws.amazon.com/chatbot/latest/adminguide/chatbot-cli-commands.html