【IBM Security Verify】ユーザーの登録・変更・削除イベントをSlackに通知する。

# はじめに

IBM Security Verifyで管理者がユーザーの作成・変更・削除・パスワードリセットを行った際に、Slackに通知するという設定を行ってみました。
少し前にリリースされた通知Webhook機能を利用して設定を行っています。
機能のマニュアルについては下部の参考情報を参照ください。
![qiita-webhook (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/60405338-4fcf-db76-0a4a-924104146728.png)

# 1.通知Webhook設定概要
マニュアルだけだと理解が難しかったため、設定内容を整理してみました。
IBM Security Verifyの通知Webhook設定には、大きく3つの設定があります。

![qiita-webhook (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/6a95bd84-0ec6-e6b3-c00a-d2b657cbb39b.png)

それぞれの設定について簡単に紹介します。
|項目|管理画面のGUI上の表記|説明|設定方法|対応するAPIのBodyパラメータ|
|---|---|---|---|---|
|通知先の設定|接続の詳細|呼び出し先URL（SlackのIncomming WebhookのURL）を設定する。<br>通知先によっては認証方法や認証ヘッダーの情報も設することができる。|GUI/APIいずれでも設定可能|urls/name/type/purposeなど|
|通知イベントの設定|イベント・サブスクリプション|IBM Security Verifyのどのイベントを通知するか設定できる。<br>事前定義のイベントや、カスタムで設定できる。<br>今回は、管理イベントを対象として設定する。|GUI/APIいずれでも設定可能|notification-interests|
|イベントデータ変換設定|(GUI上は表記無し)|IBM Security Verifyのイベントペイロードを、Slackのmessage payloadのフォーマットに変換する。|GUIでは設定できない。<br>APIで設定が必要|transform-outgoing|

# 2.SlackのIncomming Webhook設定について

①Slackにログインします。
https://slack.com/intl/ja-jp/

②Security Verifyというワークスペースと、webhookというchannelを用意します。
![qiita-webhook (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/d161b6e6-316c-06bf-17eb-613f11329a58.png)

③Incomming webhookの設定を行います。下記URLにアクセスします。
https://api.slack.com/

④Create an appを選択します。
![qiita-webhook (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/fd87bb85-8164-71c7-1b16-848175d70ad8.png)

⑤From Scratchを選択します。
![qiita-webhook (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/a3b26927-7dd5-9246-2073-dc55810d7ee1.png)



⑥AppNameとワークスペース名を設定して、「Create App」をクリックします。
![qiita-webhook (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/a6c3e213-8f9f-8421-52d2-a24f02662bad.png)


⑦Incomming WebhookをONに設定します。
![qiita-webhook (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/52f5df22-eaa4-02f7-7627-c49fb4de7675.png)


⑧channelを指定してAllowをクリックします。
![qiita-webhook (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/48830829-edf6-2737-e7b8-85c57fe58b32.png)

⑨表示されたWebhookのURLをコピーします。
https://hooks.slack.com/services/xxxx/xxxx/xxxx

⑩Slackに通知できるかテストします。
```
curl -X POST -H "Content-type: application/json" --data "{\"text\":\"Hello, World!\"}" https://hooks.slack.com/services/xxxx/xxxx/xxxx
```
⑪テストメッセージが表示されることを確認します。
![qiita-webhook (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/a88a278f-67cd-5499-3942-34cd3c42729f.png)


# 3.IBM Security Verifyの通知Webhook設定について
Slack側の準備ができたので、IBM Security Verify側の設定を行います。
POST /config/v1.0/webhooks/で、通知Webhookの設定を登録します。
JSONのdataは以下の通りです。
```
{
    "name": "user_management_webhook",
    "type": "notification",
    "transform": {
        "outgoing": "statements:\r\n- context: \"isEventType1 := (body.data.resource == 'user')&&(body.data.action == 'created')\"\r\n- context: \"isEventType2 := (body.data.resource == 'user')&&(body.data.action == 'modified')\"\r\n- context: \"isEventType3 := (body.data.resource == 'user')&&(body.data.action == 'deleted')\"\r\n- context: \"isEventType4 := (body.data.resource == 'user')&&(body.data.action == 'reset password')\"\r\n- if:\r\n    match: context.isEventType1 \r\n    block:\r\n      - context: \"d := body['data']\"\r\n      - return: \"{'body': {'text': '<!channel> :new: ユーザーが作成されました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }\"\r\n- if:\r\n    match: context.isEventType2 \r\n    block:\r\n      - context: \"d := body['data']\"\r\n      - return: \"{'body': {'text': '<!channel> :sound: ユーザーが変更されました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }\"\r\n- if:\r\n    match: context.isEventType3 \r\n    block:\r\n      - context: \"d := body['data']\"\r\n      - return: \"{'body': {'text': '<!channel> :warning: ユーザーが削除されました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }\"\r\n- if:\r\n    match: context.isEventType4 \r\n    block:\r\n      - context: \"d := body['data']\"\r\n      - return: \"{'body': {'text': '<!channel> :unlock: ユーザーのパスワードがリセットされました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }\"\r\n- return: \"{'body':  {'text':'other'}}\""
    },
    "urls": [
        "https://hooks.slack.com/services/xxxx/xxxx/xxxx"
    ],
    "purpose": [
        "notifications"
    ],
    "notification": {
        "interests": [
            {
                "name": "management events",
                "description": "",
                "clauses": [
                    {
                        "operation": "include",
                        "key": "data.resource",
                        "value": "user"
                    }
                ]
            }
        ],
        "enabled": true
    }
}
```

データ変換にあたる、"transform"-"outgoing"は、Common Expression Language (CEL) 形式で記載します。記載方法については、[API を使用した Webhook の管理 - 変換](https://www.ibm.com/docs/ja/security-verify?topic=apis-transformations)や、[複数行ルール実行プログラム](https://www.ibm.com/docs/ja/security-verify?topic=attributes-multi-line-rule-executor)を参照ください。
以下は改行など省いて見やすくしたデータ変換ルールになります。

```
statements:
- context: "isEventType1 := (body.data.resource == 'user')&&(body.data.action == 'created')"
- context: "isEventType2 := (body.data.resource == 'user')&&(body.data.action == 'modified')"
- context: "isEventType3 := (body.data.resource == 'user')&&(body.data.action == 'deleted')"
- context: "isEventType4 := (body.data.resource == 'user')&&(body.data.action == 'reset password')"
- if:
    match: context.isEventType1
        block:
            - context: "d := body['data']"
            - return: "{'body': {'text': '<!channel> :new: ユーザーが作成されました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }"
- if:
   match: context.isEventType2
       block:
             - context: "d := body['data']"
             - return: "{'body': {'text': '<!channel> :sound: ユーザーが変更されました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }"
- if:
    match: context.isEventType3
       block:
             - context: "d := body['data']"
             - return: "{'body': {'text': '<!channel> :warning: ユーザーが削除されました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }"
- if:
    match: context.isEventType4 
       block:
             - context: "d := body['data']"
             - return: "{'body': {'text': '<!channel> :unlock: ユーザーのパスワードがリセットされました '+'対象ユーザー：'+context.d.target+' 実施者：'+context.d.performedby_username} }"
- return: "{'body':  {'text':'other'}}"h

```

絵文字については、[Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/)を参考にしました。

# 4.通知Webhookの動作確認
IBM Security Verifyの管理画面で、ユーザーの作成・変更・削除、パスワードリセット操作を行い、Slackに通知されることを確認します。
![qiita-webhook (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/60405338-4fcf-db76-0a4a-924104146728.png)

# 5.Webhook機能の制約事項について
マニュアルには、[Webhook の制限](https://www.ibm.com/docs/ja/security-verify?topic=apis-webhook-limitations)が記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/5145b8a7-4410-5a91-6f56-a50bc13253a0.png)

すべてのイベントを取得するような使い方の場合は、イベントAPI（ [Get all events for a tenant.](https://docs.verify.ibm.com/verify/reference/getallevents) ）のほうが適して言います。

# 参考情報
IBM Security Verifyの通知Webhook機能
- [ユーザー・インターフェースを使用した Webhook の管理 - 通知 Webhook の作成](https://www.ibm.com/docs/ja/security-verify?topic=interface-creating-notification-webhook)
- [API を使用した Webhook の管理 - 通知 Webhook](https://www.ibm.com/docs/ja/security-verify?topic=apis-notification-webhooks)
- [Create a Webhook (API)](https://docs.verify.ibm.com/verify/reference/webhookpost)
- [Security Learning Academy:Webhooks in Verify SaaS and the new use cases they support](https://www.securitylearningacademy.com/course/view.php?id=6780)
- [Webhook の制限](https://www.ibm.com/docs/ja/security-verify?topic=apis-webhook-limitations)

Slackのincomming Webhook機能
- [Sending messages using Incoming Webhooks](https://api.slack.com/messaging/webhooks
)
- [Reference: Message payloads](https://api.slack.com/reference/messaging/payload)
- [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/)