8
2

More than 1 year has passed since last update.

Box Webhookでファイル操作をイベント通知してみた

Last updated at Posted at 2022-12-30

はじめに

Box上のファイルが更新されたら、即座に検知し特定アクションを行いたい場合があります。
Webhookの仕組みを用いて、Boxにイベントトリガーを設定し、イベント通知してみました。

構成図

image.png

Webhook(ウェブフック)とは

  • Webアプリケーションで特定のイベントが発生したら別のWebアプリケーションに通知を発行する仕組み
  • Web開発でカスタムコールバックを用いてWebアプリケーションの動作を追加または変更するための方法
  • リクエストは、HTTP POSTリクエストとして行われる
  • フォーマットには通常JSONが利用される

Box Webhook V2とは

イベントトリガーが発動されたら、指定URLにHTTP POSTリクエストするための
Webhook APIが用意されています。

  • Webhookの作成
  • Webhookの更新
  • Webhookの削除
  • Webhook署名検証
    • Boxから送信されたWebhookペイロードが改ざんされていないことを確認する
    • 署名により、中間者攻撃またはリプレイ攻撃による影響が大幅に軽減される

Webhookを使用するためのBoxの設定

認証方法の設定

  • Boxアプリケーション設定画面で、OAuth 2.0 with JSON Web Tokens (Server Authentication)を選択

webhook_authentication_method.jpg

  • Boxアプリケーション設定画面で、アプリ設定Jsonファイルをダウンロード

webhook_app_settings_json.jpg

Manage Webhooksスコープを設定

  • Boxアプリケーション設定画面で、Application ScopesセクションのManage Webhooksにチェックを入れ、設定を保存

step1.jpg

  • Boxアプリケーション承認画面で、Review and Submitボタンをクリックし承認申請を行う

step2.jpg

  • Box管理者が、カスタムアプリ管理画面で、アプリケーションの承認申請を許可(管理者のみ実施可能)

step3.jpg

Webhook操作用のPythonサンプルプログラム

"""BOX Webhook操作プログラム"""
# 前提としてboxsdkのインストールが必要
#   pip install boxsdk

from boxsdk import Client, JWTAuth

# Boxからダウンロードしたアプリ設定Jsonデータ
CONNECTION_INFO = {
    "boxAppSettings": {
        "clientID": "xxx",
        "clientSecret": "xxx",
        "appAuth": {
            "publicKeyID": "xxx",
            "privateKey": "xxx",
            "passphrase": "xxx",
        },
    },
    "enterpriseID": "xxx",
}


class WebhookOper:
    """Webhookの操作"""

    def __init__(self, connection_info: dict):
        config = JWTAuth.from_settings_dictionary(connection_info)
        self.client = Client(config)

    def list_webhookids(self):
        """全webhook_idリストを取得"""
        webhooks = self.client.get_webhooks()
        for webhook in webhooks:
            print(f"The webhook ID is {webhook.id} and the address is {webhook}")

    def get_folder_id(self, webhook_id: str):
        """webhook_idに紐づくfolder_idを取得"""
        webhook = self.client.webhook(webhook_id=str(webhook_id)).get()
        print(webhook.target)

    def create_webhook(self, folder_id: str, notify_url: str):
        """フォルダにwebhook作成(ファイル操作イベントトリガーを指定)"""
        folder = self.client.folder(folder_id=folder_id)
        webhook = self.client.create_webhook(
            folder,
            [
                "FILE.UPLOADED",
                "FILE.DELETED",
                "FILE.TRASHED",
                "FILE.RESTORED",
                "FILE.COPIED",
                "FILE.MOVED",
                "FILE.RENAMED",
            ],
            notify_url,
        )
        print(f"Webhook ID is {webhook.id} and the address is {webhook.address}")

    def delete_webhook(self, webhook_id: str):
        """webhookを削除"""
        self.client.webhook(webhook_id=webhook_id).delete()
        print(f"webhook_id={webhook_id} has been deleted")


if __name__ == '__main__':
    # Webhook操作
    who = WebhookOper(CONNECTION_INFO)
    folder_id = 'xxx'  # Webhook設定対象のフォルダID
    notify_url = 'https://xxx'  # Webhook通知先URL

    # Webhookをfolder_idに作成
    who.create_webhook(folder_id, notify_url)

    # Webhook一覧を表示
    who.list_webhookids()

Webhookイベント通知のサンプルデータ

Boxフォルダ移動により通知されるFOLDER.MOVEDイベントのリクエストボディサンプルです。

{
   "type": "webhook_event",
   "id": "xxx",
   "created_at": "2022-12-30T05:28:48-07:00",
   "trigger": "FOLDER.MOVED",
    "webhook": {
        "id": "770111431",
        "type": "webhook"
    },
    "created_by": {
        "type": "user",
        "id": "20188107977",
        "name": "name1",
        "login": "name1@ari-jp.com"
    },
    "source": {
        "id": "169775002763",
        "type": "folder",
        "sequence_id": "3",
        "etag": "3",
        "name": "test2",
        "created_at": "2022-12-30T01:17:18-07:00",
        "modified_at": "2022-12-30T05:01:55-07:00",
        "description": "",
        "size": 78666,
        "path_collection": {
            "total_count": 3,
            "entries": [
                {
                    "type": "folder",
                    "id": "0",
                    "sequence_id": null,
                    "etag": null,
                    "name": "All Files"
                },
                {
                    "type": "folder",
                    "id": "169370964125",
                    "sequence_id": "0",
                    "etag": "0",
                    "name": "私のBox Notes"
                },
                {
                    "type": "folder",
                    "id": "169780883554",
                    "sequence_id": "1",
                    "etag": "1",
                    "name": "test3"
                }
            ]
        },
        "created_by": {
            "type": "user",
            "id": "20188107977",
            "name": "name1",
            "login": "name1@ari-jp.com"
        },
        "modified_by": {
            "type": "user",
            "id": "20188107977",
            "name": "name1",
            "login": "name1@ari-jp.com"
        },
        "trashed_at": null,
        "purged_at": null,
        "content_created_at": "2022-12-30T01:17:18-07:00",
        "content_modified_at": "2022-12-30T05:01:55-07:00",
        "owned_by": {
            "type": "user",
            "id": "20188107977",
            "name": "name1",
            "login": "name1@ari-jp.com"
        },
        "shared_link": null,
        "folder_upload_email": null,
        "parent": {
            "type": "folder",
            "id": "169780883554",
            "sequence_id": "1",
            "etag": "1",
            "name": "test3"
        },
        "item_status": "active"
    },
    "additional_info": {
        "after": {
            "id": "169780883554",
            "type": "folder"
        },
        "before": {
            "id": "169370964125",
            "type": "folder"
        }
    }
}

(余談)Webhookのイベント通知で、HTTPリクエストのヘッダーとボディの長さに制限がないか問い合わせた結果

GitHubプロジェクトbox-python-sdkにissueを投げてみました。
https://github.com/box/box-python-sdk/issues/774

  • 質問
Is there a limitation on length of HTTP Header and Body 
included in a notification from V2 webhooks?
  • 回答
    boxsdk API側では制限を設けておらず、HTTP仕様に準拠するとのことでした。
I've asked service owners but they have not specified any limit.
 So this response follow HTTP specification.
  • ちなみに、RFC 7230の仕様では、HTTPヘッダーのフィールド長に制限は設けられていないようです。

3.2.5.  Field Limits

   HTTP does not place a predefined limit on the length of each header
   field or on the length of the header section as a whole, as described
   in Section 2.5.

おわりに

Box上のファイル操作を、Webhookを使ってイベント通知してみました。
受信イベントは、ビジネスプロセス(分析や監視)に活用できそうです。

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2