ペイロードを受信するようにサーバーが設定されると、設定したエンドポイントに送信されたペイロードがリッスンされます。 セキュリティ上の理由から、GitHub からのリクエストに制限することをお勧めします。 これを行うにはいくつかの方法があります。たとえば、GitHub の IP アドレスからのリクエストを許可することですが、はるかに簡単な方法は、シークレットトークンを設定して情報を検証することです。
REST API を利用し、リポジトリ、組織、アプリ Webhook を管理できます。 Webhook の Webhook 配信を一覧表示したり、Webhook の個別の配信を取得して再配信したりできます。Webhook は、外部のアプリまたはサービスに統合できます。 REST API を使用して、Webhook の構成を変更することもできます。 たとえば、ペイロードURL、コンテントタイプ、SSLの検証、シークレットを変更できます。 詳細については、次を参照してください。
シークレットトークンを設定する
シークレットトークンは、GitHub とサーバーの 2 か所に設定する必要があります。
GitHub にトークンを設定するには:
-
Webhook を設定しているリポジトリに移動します。
-
リポジトリ名の下にある [設定] をクリックします。 [セキュリティ] タブが表示されない場合は、 [] ドロップダウン メニューを選び、 [設定] をクリックします。
-
左側のサイドバーで、 [ Webhooks] をクリックします。
-
Webhook の横にある [編集] をクリックします。
-
"シークレット" フィールドに、エントロピが高いランダムな文字列を入力します。 たとえば、ターミナルで
ruby -rsecurerandom -e 'puts SecureRandom.hex(20)'
を含む文字列を生成できます。 -
[webhook の更新] をクリックします。
次に、このトークンを保存する環境変数をサーバーに設定します。 通常、これは実行と同じくらい簡単です。
$ export SECRET_TOKEN=YOUR-TOKEN
トークンをアプリにハードコーディングしないでください。
GitHub からのペイロードを検証する
シークレットトークンが設定されると、GitHub Enterprise Server はそれを使用して各ペイロードでハッシュ署名を作成します。 このハッシュ署名は、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として扱うようにしてください。
言語とサーバーの実装は、この例で使用したコードとは異なる場合があります。 ただし、次のようないくつかの非常に重要な事項があります。
-
どの実装を使用する場合でも、ハッシュ署名は
sha256=
で始まり、シークレット トークンのキーとペイロード本文を使用します。 -
プレーン
==
演算子の使用はお勧めしません。secure_compare
のようなメソッドは、"定数時間" の文字列比較を実行します。これは、通常の等式演算子に対する特定のタイミング攻撃を軽減するのに役立ちます。