VPN 経由で Jenkins を開けても、所有者の異なる二つの接続だからという理由で、GitHub が webhook の失敗を報告するのを目にすることがあります。ブラウザーはノート PC がネゴシエートしたトンネルを通りますが、GitHub の配信サービスはパブリックインターネットから始まり、プライベートネットワークへの経路を持ちません。Jenkins 自身が同じリポジトリーから問題なく取得できるとしても、リポジトリーへのアクセスがあってもそれは変わりません。受信経路、リレー、ポーリングのいずれかを選び、イベントが実際に通る経路を検証してください。

ブラウザーのセッションが証明するのは一方向だけ

VPN 接続が答えるのは、このノート PC が内部ホストに到達できるかという一つの問いです。webhook の配信が問うのは、外部サービスがそのホストへの接続を開けるかという別のことです。Jenkins がリポジトリーを取得するのは外向きの通信であり、内向きの到達性については何も語りません。図では両方向を別々の行に分け、どちらがどちらを開始するのかも書き込んでください。

何かを変える前に配信記録を読んでください。タイムアウト、接続リセット、どのジョブにも一致しなかった承認済みリクエストは、ネットワーク、プロキシー、トリガー設定という三つの異なる所有者を持ちます。

案 A:狭いエンドポイントを公開する

組織がすでに承認済みの受信経路を公開しているなら、ダッシュボードではなく webhook の経路を公開します。通常は、フック URL への POST を受け付けて Jenkins に転送するリバースプロキシーのルールを置き、管理画面は外部から到達できないままにします。

curl -sS -o /dev/null -w "%{http_code}\n" -X POST https://jenkins.example.com/github-webhook/

トンネルの内側からの成功は何も証明しないため、そのテストは VPN アクセスのないネットワークから実行してください。エンドポイントは、GitHub が署名ヘッダーとして送る共有シークレットのないリクエストを拒否し、公開した単一の経路とメソッドだけを受け入れるべきです。公開された Jenkins コンソールは webhook の修正ではなく、次のスキャナーに見つかるのを待つインシデントです。アプリケーションの残りの部分が以前のアクセス制御を保てるよう、ルールは十分に狭くしてください。

案 B:リレーで方向を反転させる

受信公開が承認されない場合、ネットワーク内の小さなクライアントが リレーへの外向き接続を保持し、転送されたイベントを受け取れます。リレーは配信経路の一部になるため、その可用性と認証はビルドジョブと同じくらい重要です。

ssh -N -R 9000:localhost:8080 relay.example.net

ファイアウォール背後の webhook に関する Jenkins の指針 はこの形を説明しており、独自のフォワーダーを書く前に読む価値があります。落ちたトンネルは決して送られなかったイベントとまったく同じに見えるため、リレーで TLS を終端し、イベントがジョブに届く前に署名を検証し、外向きリンクを監視してください。途中で解析されて再エンコードされた JSON では署名検証が失敗するため、リレーがリクエスト本文をバイト単位で保つことも確認してください。

案 C:代わりにリポジトリーをポーリングする

ポーリングは遅延と引き換えに単純さを得て、受信経路をまったく必要としません。Jenkins はスケジュールでポーリングできますし、小さなジョブが API に問い合わせ、見慣れないリビジョンを見つけたらビルドを開始することもできます。

curl -sS -u "$USER:$TOKEN" "https://api.github.com/repos/OWNER/REPO/commits?per_page=1"

各ポーリングは API 呼び出しを消費し、push とビルドの間に、多忙なリポジトリーや共有のレート制限で目に見える遅延を加えます。また、ポーラーが動く場所に認証情報を保存する必要があるので、トークンはリポジトリーへの読み取り専用アクセスに限定し、他のシークレットと同じようにローテーションしてください。イベント量が少ないとき、あるいは受信経路が決して承認されないときにこれを選び、ビルドが遅れる理由を後から誰も不思議に思わないよう、ジョブの説明にその旨を書いてください。

ページ読み込みではなく、実際の配信を受け入れる

どの案を選んだとしても、受け入れテストはソースプラットフォームが送るイベントであり、特権を持つノート PC から開いたブラウザーのタブではありません。スクラッチブランチに空のコミットを push し、配信の応答コード、リレーのログ、ポーリングジョブの出力の順に読んでください。エンドポイントから 200 が返ってビルドがないならトリガーのフィルターが誤りであり、タイムアウトなら経路はまだ閉じています。次にデバッグする人がブラウザーのテストを繰り返して同じ行き止まりに着かないよう、三つの設計のどれを使っているかを記録してください。

人間がすでに VPN セッションを持っていても、それぞれがプライベートアプリケーションへの独自の経路を必要とするため、同じ考え方を決済のコールバックや他の外部通知にも当てはめてください。配信経路はアプリケーションの設計に属するもので、ネットワークの脚注ではありません。

関連記事