Webhook
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated
Webhookは、リアルタイム通知によってGitLabを他のツールやシステムに接続します。GitLabで重要なイベントが発生すると、Webhookはその情報を外部アプリケーションに直接送信します。マージリクエスト、コードプッシュ、イシューの更新に反応して自動化ワークフローをビルドします。
Webhookを使用すると、変更発生時にチームが連携の取れた状態を維持できます。
- GitLabイシューが変更されると、外部イシュートラッカーが自動的に更新されます。
- チャットアプリケーションが、パイプラインの完了をチームメンバーに通知します。
- コードがmainブランチに到達すると、カスタムスクリプトがアプリケーションをデプロイします。
- モニタリングシステムが、組織全体での開発アクティビティを追跡します。
Webhookイベント
Webhookは、GitLabのさまざまなイベントによってトリガーできます。例:
- リポジトリへのコードプッシュ。
- イシューへのコメントの投稿。
- マージリクエストの作成。
Webhookの制限
GitLab.comは、次のWebhookの制限を適用します。
- プロジェクトまたはグループごとのWebhookの最大数。
- 1分あたりのWebhook呼び出し数。
- Webhookのタイムアウト期間。
GitLab Self-Managedでは、管理者がこれらの制限を変更できます。
プッシュイベントの制限
GitLabは、複数の変更を含むプッシュイベントに対するWebhookのトリガーを制限します:
- デフォルトの制限: プッシュごとに3つのブランチまたはタグ。
- 超過した場合の動作: プッシュイベント全体に対してWebhookはトリガーされません。
- 適用対象: プロジェクトWebhookとシステムフックの両方。
- 設定: GitLab Self-Managedの管理者は、アプリケーション設定APIを通じて
push_event_hooks_limit設定を変更できます。
複数のタグやブランチを同時に頻繁にプッシュする必要があり、Webhook通知が必要な場合は、GitLabの管理者に連絡してこの制限を増やしてもらってください。
グループWebhook
- プラン: Premium、Ultimate
グループWebhookは、グループとそのサブグループ内のすべてのプロジェクトのイベントに関する通知を送信するカスタムHTTPコールバックです。
グループWebhookイベントの種類
次のイベントをリッスンするようにグループWebhookを設定できます。
- グループおよびサブグループ内のプロジェクトで発生するすべてのイベント
- グループメンバーイベント、プロジェクトイベント、サブグループイベントを含む、グループ固有のイベント
プロジェクトとグループの両方のWebhook
グループとそのグループ内のプロジェクトの両方で同一のWebhookを設定すると、そのプロジェクト内のイベントに対して両方のWebhookがトリガーされます。これにより、GitLab組織のさまざまなレベルで柔軟なイベント処理が可能になります。
Webhookを設定する
GitLabでWebhookを作成、設定して、プロジェクトのワークフローと統合します。これらの機能を使用して、特定の要件を満たすWebhookを設定します。
Webhookを作成する
新しいWebhookには、シークレットトークンの代わりに署名トークンを使用します。署名トークンは、ペイロードのHMAC-SHA256署名を計算するため、お使いのエンドポイントはリクエストの真正性と整合性の両方を検証することができます。シークレットトークンは、ヘッダーにプレーンテキスト値を提供するだけであり、保証は弱くなります。新しいWebhookにはシークレットトークンの使用は推奨されません。
プロジェクトまたはグループ内のイベントに関する通知を送信するWebhookを作成します。
前提条件:
- プロジェクトWebhookの場合、プロジェクトのメンテナーまたはオーナーロールが必要です。
- グループWebhookの場合、グループのオーナーロールを持っている必要があります。
Webhookを作成するには、次の手順に従います。
- 上部のバーで、検索または移動先を選択して、プロジェクトまたはグループを見つけます。
- 左サイドバーで、設定 > Webhooksを選択します。
- 新しいWebhookを追加を選択します。
- URLに、WebhookエンドポイントのURLを入力します。特殊文字にはパーセントエンコードを使用します。
- (オプション)Webhookの名前と説明を入力します。
- (オプション)リクエスト認証を設定します。より強力なセキュリティのために署名トークンを使用します:
- 署名トークン: 署名トークンを生成を選択します。トークンは一度しか表示されないため、今すぐコピーして保存してください。お使いのWebhookエンドポイントは、このトークンを使用してHMAC-SHA256署名を検証できます。
- シークレットトークン: シークレットトークンフィールドにトークンを入力します。このトークンは
X-Gitlab-TokenHTTPヘッダーでプレーンテキストとして送信され、署名トークンよりもセキュリティ保証が弱くなります。新しいWebhookには、代わりに署名トークンを使用します。
- トリガーセクションで、Webhookをトリガーするイベントを選択します。
- (オプション)SSL検証を無効にするには、SSLの検証を有効にするチェックボックスをオフにします。
- Webhookを追加を選択します。
署名トークン
署名トークンを使用して、WebhookのペイロードがGitLabから送信され、改ざんされていないことを検証することができます。シークレットトークンとは異なり、署名トークンはペイロードのHMAC-SHA256署名を計算するために使用されます。これは、受信者が受信したペイロードの真正性と整合性の両方を個別に検証することができることを意味します。
GitLabのWebhook配信は、Standard Webhooksの仕様に従っています。すべてのWebhookリクエストには、webhook-idとwebhook-timestampのヘッダーが含まれます。署名トークンが設定されている場合、GitLabはHMAC-SHA256署名とともにwebhook-signatureヘッダーも含まれます。各署名はv1,{base64_signature}の形式です。ヘッダーには、スペースで区切られた複数の署名が含まれる場合があります。GitLabは現在1つの署名を送信しますが、これは将来変更される可能性があります。署名は{message_id}.{timestamp}.{body}の文字列に基づいて計算されます。ここで:
{message_id}はwebhook-idヘッダーの値です。{timestamp}はwebhook-timestampヘッダーの値です。{body}はraw JSONリクエストボディです。
署名を検証する
Webhookエンドポイントで署名を検証するには:
webhook-id、webhook-timestamp、およびwebhook-signatureヘッダーの値を取得する。webhook-signatureの値をスペースで分割して署名リストを取得します。- メッセージ文字列
"{message_id}.{timestamp}.{body}"を構築します。 - 署名トークンをデコードします:
whsec_プレフィックスを削除し、残りをbase64デコードします。 - デコードされたキーを使用してHMAC-SHA256ダイジェストを計算します。
- ダイジェストをbase64としてエンコードし、
v1,をプレフィックスとして付加します。 - 計算された署名が署名リスト内のいずれかのエントリと一致するかどうかを確認します。タイミング攻撃を防ぐために定時間比較を使用します。
Rubyでの例:
require 'base64'
require 'openssl'
def valid_signature?(signing_token, message_id, timestamp, body, received_signatures)
raw_key = Base64.strict_decode64(signing_token.delete_prefix('whsec_'))
message = "#{message_id}.#{timestamp}.#{body}"
digest = OpenSSL::HMAC.digest('sha256', raw_key, message)
expected = "v1,#{Base64.strict_encode64(digest)}"
received_signatures.split(' ').any? do |sig|
ActiveSupport::SecurityUtils.secure_compare(expected, sig)
end
endPythonでの例:
import base64
import hashlib
import hmac
def valid_signature(signing_token, message_id, timestamp, body, received_signatures):
raw_key = base64.b64decode(signing_token.removeprefix('whsec_'))
message = f"{message_id}.{timestamp}.{body}".encode('utf-8')
digest = hmac.new(raw_key, message, hashlib.sha256).digest()
expected = "v1," + base64.b64encode(digest).decode('utf-8')
return any(
hmac.compare_digest(expected, sig)
for sig in received_signatures.split(' ')
)下位互換性
署名トークンは、既存のシークレットトークンと連携して機能します。両方を同じWebhookで設定できます:
- シークレットトークンが設定されている場合、
X-Gitlab-Tokenヘッダーは引き続き送信されます。 - 署名トークンが設定されている場合、
webhook-signatureおよびwebhook-idヘッダーが送信されます。
ダウンタイムなしで既存のWebhookをシークレットトークンから署名トークンに移行するには、移行中に両方のトークンを同じWebhookで設定します。Webhookレシーバーを更新して、webhook-signatureが存在する場合は署名を検証するようにし、それ以外の場合はシークレットトークンにフォールバックするようにします。
Webhookレシーバーが署名を正しく処理するようになったら、Webhook設定からシークレットトークンを削除できます。
セキュリティに関する考慮事項
リプレイ攻撃を防ぐために、webhook-timestampのタイムスタンプが新しいことをペイロードの処理前に検証する。
署名トークンはAPIによって返されることはありません。
Webhook URLの機密部分をマスクする
セキュリティを強化するため、Webhook URLの機密部分をマスクします。マスクされた部分は、Webhookの実行時に設定された値に置き換えられ、ログに記録されず、データベースでの保存時には暗号化されます。
Webhook URLの機密部分をマスクするには、次の手順に従います。
- 上部のバーで、検索または移動先を選択して、プロジェクトまたはグループを見つけます。
- 左サイドバーで、設定 > Webhooksを選択します。
- URLに、Webhookの完全なURLを入力します。
- マスクする部分を定義するには、URLマスキングの追加を選択します。
- URLの機密部分に、マスクするURLの部分を入力します。
- UIの外観についてに、マスクされた部分の代わりに表示する値を入力します。変数名には、小文字(
a-z)、数字(0-9)、アンダースコア(_)のみを使用する必要があります。 - 変更を保存を選択します。
マスクされた値はUIでは非表示になります。たとえば、変数pathとvalueを定義した場合、Webhook URLは次のようになります。
https://webhook.example.com/{path}?key={value}カスタムヘッダー
外部サービスへの認証のために、カスタムヘッダーをWebhookリクエストに追加します。Webhookごとに最大20個のカスタムヘッダーを設定できます。
カスタムヘッダーは以下の条件を満たしている必要があります。
- 配信ヘッダーの値を上書きしない。
- 英数字、ピリオド、ダッシュ、アンダースコアのみが含まれている。
- 文字で始まり、文字または数字で終わる。
- 連続したピリオド、ダッシュ、またはアンダースコアがない。
カスタムヘッダーは、マスクされた値とともに最近のイベントに表示されます。
カスタムWebhookテンプレート
リクエスト本文で送信されるデータを制御するWebhookのカスタムペイロードテンプレートを作成します。
カスタムWebhookテンプレートを作成する
- プロジェクトWebhookの場合、プロジェクトのメンテナーまたはオーナーロールが必要です。
- グループWebhookの場合、グループのオーナーロールを持っている必要があります。
カスタムWebhookテンプレートを作成するには、次の手順に従います。
- Webhookの設定に移動します。
- カスタムWebhookテンプレートを設定します。
- テンプレートが有効なJSONとしてレンダリングされることを確認します。
テンプレート内でイベントのペイロードからフィールドを使用します。例:
{{build_name}}(ジョブイベント){{deployable_url}}(デプロイイベント)
ネストされたプロパティにアクセスするには、ピリオドを使用してパスセグメントを区切ります。
カスタムWebhookテンプレートの例
次のカスタムペイロードテンプレートの場合
{
"event": "{{object_kind}}",
"project_name": "{{project.name}}"
}その結果作成されるpushイベントのリクエストペイロードは次のようになります。
{
"event": "push",
"project_name": "Example"
}カスタムWebhookテンプレートは、配列内のプロパティにアクセスできません。
ブランチでプッシュイベントをフィルタリングする
Webhookエンドポイントに送信されるpushイベントをブランチ名でフィルタリングします。次のいずれかのフィルタリングオプションを使用します。
- 全てのブランチ: すべてのブランチからプッシュイベントを受信します。
- ワイルドカードパターン: ワイルドカードパターンに一致するブランチからプッシュイベントを受信します。
- 正規表現: 正規表現(regex)に一致するブランチからプッシュイベントを受信します。
ワイルドカードパターンを使用する
ワイルドカードパターンを使用してフィルタリングするには、次の手順に従います。
- Webhook設定でワイルドカードパターンを選択します。
- パターンを入力します。例:
*-stableは、-stableで終わるブランチに一致します。production/*は、production/ネームスペース内のブランチに一致します。
正規表現を使用する
正規表現を使用してフィルタリングするには、次の手順に従います。
- Webhook設定で正規表現を選択します。
- RE2構文に従っている正規表現パターンを入力します。
たとえば、mainブランチを除外するには、次を使用します。
\b(?:m(?!ain\b)|ma(?!in\b)|mai(?!n\b)|[a-l]|[n-z])\w*|\b\w{1,3}\b|\W+相互TLSをサポートするようにWebhookを設定する
- 提供形態: GitLab Self-Managed
PEM形式のグローバルクライアント証明書を設定して、相互TLSをサポートするようにWebhookを設定します。
前提条件:
- GitLab管理者である必要があります。
Webhookの相互TLSを設定するには、次の手順に従います。
- PEM形式のクライアント証明書を準備します。
- (オプション)PEMパスフレーズで証明書を保護します。
- 証明書を使用するようにGitLabを設定します。
/etc/gitlab/gitlab.rbを編集します:gitlab_rails['http_client']['tls_client_cert_file'] = '<PATH TO CLIENT PEM FILE>' gitlab_rails['http_client']['tls_client_cert_password'] = '<OPTIONAL PASSWORD>'ファイルを保存し、GitLabを再設定します:
sudo gitlab-ctl reconfigure
docker-compose.ymlを編集します:version: "3.6" services: gitlab: image: 'gitlab/gitlab-ee:latest' restart: always hostname: 'gitlab.example.com' environment: GITLAB_OMNIBUS_CONFIG: | gitlab_rails['http_client']['tls_client_cert_file'] = '<PATH TO CLIENT PEM FILE>' gitlab_rails['http_client']['tls_client_cert_password'] = '<OPTIONAL PASSWORD>'ファイルを保存し、GitLabを再起動します:
docker compose up -d
/home/git/gitlab/config/gitlab.ymlを編集します:production: &base http_client: tls_client_cert_file: '<PATH TO CLIENT PEM FILE>' tls_client_cert_password: '<OPTIONAL PASSWORD>'ファイルを保存し、GitLabを再起動します:
# For systems running systemd sudo systemctl restart gitlab.target # For systems running SysV init sudo service gitlab restart
設定が完了したら、GitLabはWebhook接続のTLSハンドシェイク中にこの証明書をサーバーに提示します。
Webhookトラフィックのファイアウォールを設定する
GitLabがWebhookを送信する方法に基づいて、Webhookトラフィックのファイアウォールを設定します。
- Sidekiqノードから非同期的に送信(最も一般的)
- Railsノードから同期的に送信(特定のケース)
UIでWebhookをテストまたは再試行すると、WebhookはRailsノードから同期的に送信されます。
ファイアウォールを設定するときには、SidekiqノードとRailsノードの両方がWebhookトラフィックを送信できることを確認してください。
Webhookを管理する
GitLabで設定済みWebhookをモニタリングおよび保守します。
Webhookリクエストの履歴を表示する
Webhookリクエストの履歴を表示して、パフォーマンスをモニタリングし、問題のトラブルシューティングを行います。
前提条件:
- プロジェクトWebhookの場合、プロジェクトのメンテナーまたはオーナーロールが必要です。
- グループWebhookの場合、グループのオーナーロールを持っている必要があります。
Webhookのリクエスト履歴を表示するには、次の手順に従います。
- 上部のバーで、検索または移動先を選択して、プロジェクトまたはグループを見つけます。
- 左サイドバーで、設定 > Webhooksを選択します。
- Webhookの編集を選択します。
- 最近のイベントセクションに移動します。
最近のイベントセクションには、過去2日間にWebhookに対して行われたすべてのリクエストが表示されます。テーブルには以下の内容が示されます。
- HTTPステータスコード:
- コード
200~299の場合は緑 - その他のコードの場合は赤
- 配信に失敗した場合は
internal error
- コード
- トリガーされたイベント
- リクエストの経過時間
- リクエストが行われた時点の相対時間
リクエストと応答の詳細を調べる
前提条件:
- プロジェクトWebhookの場合、プロジェクトのメンテナーまたはオーナーロールが必要です。
- グループWebhookの場合、グループのオーナーロールを持っている必要があります。
最近のイベントにある各Webhookリクエストには、リクエストの詳細ページがあります。このページには、次の本文とヘッダーが含まれています。
- GitLabがWebhookレシーバーエンドポイントから受信した応答
- GitLabが送信したWebhookリクエスト
Webhookイベントのリクエストと応答の詳細を調べるには、次のようにします。
- 上部のバーで、検索または移動先を選択して、プロジェクトまたはグループを見つけます。
- 左サイドバーで、設定 > Webhooksを選択します。
- Webhookの編集を選択します。
- 最近のイベントセクションに移動します。
- イベントの詳細を表示を選択します。
同じデータと同じIdempotency-Keyヘッダーでリクエストを再度送信するには、リクエストを再送するを選択します。Webhook URLが変更された場合、リクエストを再送信できません。プロジェクトWebhook APIを通じて、リクエストをプログラムで再送信することもできます。
Webhookをテストする
Webhookが正しく機能していることを確認したり、無効になっているWebhookを再度有効にしたりするには、Webhookをテストします。
前提条件:
- プロジェクトWebhookの場合、プロジェクトのメンテナーまたはオーナーロールが必要です。
- グループWebhookの場合、グループのオーナーロールを持っている必要があります。
push eventsをテストするには、プロジェクトに少なくとも1つのコミットが必要です。
Webhookをテストするには、次のようにします。
- 上部のバーで、検索または移動先を選択して、プロジェクトまたはグループを見つけます。
- 左サイドバーで、設定 > Webhooksを選択して、このプロジェクトのすべてのWebhookを表示します。
- 設定済みWebhookのリストから直接Webhookをテストするには:
- テストするWebhookを見つけます。
- テストドロップダウンリストから、テストするイベントの種類を選択します。
- Webhookを編集中にテストするには:
- テストするWebhookを見つけて、編集を選択します。
- Webhookに変更を加えます。
- Testドロップダウンリストを選択し、テストするイベントのタイプを選択します。
プロジェクトWebhookとグループWebhookの特定の種類のイベントでは、テストはサポートされていません。詳細については、イシュー379201を参照してください。
Webhookリファレンス
このテクニカルリファレンスは、次の目的で使用します。
- GitLab Webhookの仕組みを理解する。
- システムとWebhookを統合する。
- Webhookの設定、トラブルシューティング、最適化を行う。
Webhookレシーバーの要件
信頼性の高いWebhook配信を確保するために、高速で安定したWebhookレシーバーエンドポイントを実装します。
遅い、不安定な、または誤って設定されたWebhookレシーバーは自動的に無効になる可能性があります。無効なHTTP応答は、失敗したリクエストとして扱われます。
Webhookレシーバーを最適化するには、次の手順に従います。
200または201のステータスで迅速に応答します。- 同じリクエストでWebhookを処理しないでください。
- 受信後、キューを使用してWebhookを処理します。
- タイムアウト制限内に応答して、GitLab.comでの自動無効化を防ぎます。
- 潜在的な重複イベントを処理します。
- Webhookがタイムアウトする場合の重複イベントに備えます。
- エンドポイントが常に高速かつ安定していることを確認します。
- 応答ヘッダーと本文を最小限に抑える。
- GitLabは、後で検査できるように応答ヘッダーとボディを保存します。
- 返されるヘッダーの数とサイズを制限します。
- 空の本文で応答することを検討してください。
- 適切なステータスコードを使用します。
- クライアントエラーステータス応答(
4xxの範囲)は、誤った設定のWebhookに対してのみ返します。 - サポートされていないイベントの場合は、
400を返すか、ペイロードを無視します。 - 処理されたイベントに対する
500サーバーエラー応答を回避します。
- クライアントエラーステータス応答(
自動的に無効化されたWebhook
この機能の利用可否は、機能フラグによって制御されます。詳細については、履歴を参照してください。
GitLabは、4回連続して失敗したプロジェクトまたはグループのWebhookを自動的に無効にします。
自動的に無効になったWebhookを表示するには、次の手順に従います。
- 上部のバーで、検索または移動先を選択して、プロジェクトまたはグループを見つけます。
- 左サイドバーで、設定 > Webhooksを選択します。
Webhookリストでは、自動的に無効になったWebhookは次のように表示されます。
- 4回連続で失敗した場合、一時的に無効になります。
- 40回連続で失敗した場合、無効になります。
一時的に無効化されたWebhook
Webhookは4回連続して失敗すると、一時的に無効になります。Webhookが40回連続で失敗すると、完全に無効になります。
次の場合に失敗が発生します:
- Webhookレシーバーは、
4xxまたは5xxの範囲の応答コードを返します。 - WebhookがWebhookレシーバーへの接続を試行中にタイムアウトします。
- Webhookでその他のHTTPエラーが発生した場合。
一時的に無効化されたWebhookは、最初は1分間無効になります。この期間は、後続の失敗発生時に延長され、最大で24時間まで延長されます。この期間が経過すると、これらのWebhookは自動的に再度有効になります。
永久に無効化されたWebhook
Webhookは、40回連続して失敗すると永久に無効になります。一時的に無効化されたWebhookとは異なり、これらのWebhookは自動的に再度有効になりません。
GitLab 17.10以前に永久に無効化されたWebhookに対してデータ移行が行われました。これらのWebhookは、UIでは40回の失敗が表示されていても、最近のイベントでは4回の失敗が表示される場合があります。
無効化されたWebhookを再度有効にする
無効になっているWebhookを再度有効にするには、テストリクエストを送信します。テストリクエストが2xxの範囲の応答コードを返すと、Webhookが再度有効になります。
配信ヘッダー
GitLabは、お使いのエンドポイントへのWebhookリクエストに以下のヘッダーを含みます。
| ヘッダー | 説明 | 例 |
|---|---|---|
Idempotency-Key | Webhookの再試行全体で一貫性のある一意のID。互換性のために利用可能ですが、webhook-idを優先してください。 | "f5e5f430-f57b-4e6e-9fac-d9128cd7232f" |
User-Agent | "Gitlab/<VERSION>"形式のユーザーエージェント。 | "GitLab/15.5.0-pre" |
webhook-id | Webhookの再試行全体で一貫性のあるユニークなメッセージID。Idempotency-Keyと等しい。 | "f5e5f430-f57b-4e6e-9fac-d9128cd7232f" |
webhook-signature | スペースで区切られたHMAC-SHA256署名リストで、各署名はv1,{base64_signature}の形式です。署名トークンが設定されている場合にのみ含まれます。 | "v1,abc123def456==" |
webhook-timestamp | リクエストが生成されたときのUnixタイムスタンプ(エポックからの秒数)。 | "1744578123" |
X-Gitlab-Event-UUID | 非再帰Webhookの一意のID。再帰Webhook(以前のWebhookによってトリガーされる)は同じ値を共有します。 | "13792a34-cac6-4fda-95a8-c58e00a3954e" |
X-Gitlab-Event | Webhookタイプ名。"<EVENT> Hook"の形式のイベントタイプに対応します。 | "Push Hook" |
X-Gitlab-Instance | Webhookを送信したGitLabインスタンスのホスト名。 | "https://gitlab.com" |
X-Gitlab-Token | Webhookのシークレットトークンで、プレーンテキストとして送信されます。シークレットトークンが設定されている場合にのみ含まれます。 | "my-secret-token" |
X-Gitlab-Webhook-UUID | 各Webhookの一意のID。 | "02affd2d-2cba-4033-917d-ec22d5dc4b38" |
Webhook本文での画像URLの表示
GitLabは、Webhook本文内の相対的な画像参照を絶対URLに書き換えます。
画像URLの書き換えの例
マージリクエスト、コメント、またはWikiページ内の元の画像参照が次のようであるとします。
Webhook本文内で書き換えられた画像参照は次のようになります。
この例では、以下を前提としています。
- GitLabが
gitlab.example.comにインストールされている。 - プロジェクトIDが
123にある。
画像URLの書き換えの例外
次の場合、GitLabは画像URLを書き換えません。
- HTTP、HTTPS、またはプロトコル相対URLをすでに使用している場合。
- リンクラベルなど、高度なMarkdown機能を使用している場合。

