【小ネタ】PythonでZendeskのWebhook署名検証を行う

2022.06.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

ZendeskにてWebhookを作成した場合、受け取り側で、そのWebhookが本当にZendeskからのものであることを確認・検証する必要があります。Zendeskのリファレンスでは、NodeJSの例が記載されているので、そちらを参考にPythonで書いてみます。

リファレンス
Verifying webhook authenticity

実装コード

※Lambdaで実装したため引数にeventを取っています。

import hashlib
import hmac

def is_valid_signature(signature, body, timestamp):
    secret_key = 'xxxxxxxxxxxxxxx' # zendeskで払い出したWebbhook用のsecret key
    new_hmac = hmac.new(bytes(secret_key, "UTF-8"), bytes(timestamp + body, "utf-8"), digestmod=hashlib.sha256)
    sig_base64 = base64.b64encode(new_hmac.digest())

    return hmac.compare_digest(signature, sig_base64.decode("utf-8"))

def validate(event):
    signature = event["headers"]["X-Zendesk-Webhook-Signature"]
    timestamp = event["headers"]["X-Zendesk-Webhook-Signature-Timestamp"]
    event_body = event["body"]

    return is_valid_signature(signature, event_body, timestamp)

経緯

プロダクトの開発で利用するため、チームメンバーにZendesk Webhookの設定を行なっていただきました。そのため、Webhookを受け取る側の処理として、上記の署名検証を行う必要がありました。

Zendesk Webbhookの作成方法については、 Takaaki Kakeiさんのブログをご参照ください。

Zendeskチケットの添付ファイルを取得して、S3に保存してみた

感想

PythonやLambdaに関して不慣れで、pythonのメソッドやリファレンスを調べながらの実装となりました。ハマった点として, はじめにLambdaAuthorizerで署名検証を行いたいな...と思いましたが、Authorizerでは、仕様上Webhookからくるリクエストjsonbodyを受け取ることが出来ませんでした。以下、リファレンス引用です。

For a Lambda authorizer of the REQUEST type, API Gateway passes request parameters to the authorizer Lambda function as part of the event object. The request parameters include headers, path parameters, query string parameters, stage variables, and some of request context variables. The API caller can set the path parameters, headers, and query string parameters. The API developer must set the stage variables during the API deployment and API Gateway provides the request context at run time.
引用: Input to an Amazon API Gateway Lambda authorizer

他のサービス・アプリにおいても検証が必要な場合は、多々あると思います。もしかしたら、近いコードで実装が出来るかもしれません。
以上、どなたかの参考になりましたら幸いです。

参考