ペイロードを受信するようにサーバーが設定されると、設定したエンドポイントに送信されたペイロードがリッスンされます。 セキュリティ上の理由から、GitHub からのリクエストに制限することをお勧めします。 これを行うにはいくつかの方法があります。たとえば、GitHub の IP アドレスからのリクエストを許可することですが、はるかに簡単な方法は、シークレットトークンを設定して情報を検証することです。
The webhook REST APIs enable you to manage repository, organization, and app webhooks. You can also use the REST API to change the configuration of the webhook. たとえば、ペイロードURL、コンテントタイプ、SSLの検証、シークレットを変更できます。 詳しい情報については、以下を参照してください。
シークレットトークンを設定する
シークレットトークンは、GitHub とサーバーの 2 か所に設定する必要があります。
GitHub にトークンを設定するには:
- webhook を設定しているリポジトリに移動します。
- シークレットテキストボックスに入力します。 エントロピーの高いランダムな文字列を使用します (たとえば、
ruby -rsecurerandom -e 'puts SecureRandom.hex(20)'
を端末で取得することによって)。 - [Update Webhook] をクリックします。
次に、このトークンを保存する環境変数をサーバーに設定します。 通常、これは実行と同じくらい簡単です。
$ export SECRET_TOKEN=your_token
トークンをアプリケーションにハードコーディングしないでください。
GitHub からのペイロードを検証する
シークレットトークンが設定されると、GitHub Enterprise Server はそれを使用して各ペイロードでハッシュ署名を作成します。 This hash signature is included with the headers of each request as X-Hub-Signature-256
.
注釈: 下位互換性のために、SHA-1 ハッシュ関数を使用して生成される X-Hub-Signature
ヘッダーも含まれています。 可能であれば、セキュリティを向上させるために X-Hub-Signature-256
ヘッダを使用することをお勧めします。 以下は、X-Hub-Signature-256
ヘッダの使用例です。
たとえば、webhook をリッスンする基本的なサーバーがある場合、次のように設定されている可能性があります。
require 'sinatra'
require 'json'
post '/payload' do
request.body.rewind
push = JSON.parse(request.body.read)
"I got some JSON: #{push.inspect}"
end
目的は、SECRET_TOKEN
を使用してハッシュを計算し、結果が GitHub Enterprise Server のハッシュと一致することを確認することです。 GitHub Enterprise Server は HMAC hex digest を使用してハッシュを計算するため、サーバーを次のように再設定できます。
post '/payload' do
request.body.rewind
payload_body = request.body.read
verify_signature(payload_body)
push = JSON.parse(payload_body)
"I got some JSON: #{push.inspect}"
end
def verify_signature(payload_body)
signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], payload_body)
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])
end
注釈: Webhookペイロードには、Unicode 文字を含めることができます。 言語とサーバーの実装で文字エンコーディングが指定されている場合は、ペイロードをUTF-8として扱うようにしてください。
言語とサーバーの実装は、この例で使用したコードとは異なる場合があります。 ただし、次のようないくつかの非常に重要な事項があります。
-
No matter which implementation you use, the hash signature starts with
sha256=
, using the key of your secret token and your payload body. -
プレーンな
==
演算子を使用することはお勧めしません。secure_compare
のようなメソッドは、「一定時間」の文字列比較を実行します。これは、通常の等式演算子に対する特定のタイミング攻撃を軽減するのに役立ちます。