Edited at

GitHubのWebhookをPHPで自作する時に書く検証コード


GitHubのWebhookをPHPで自作するには

GitHubにはWebhookが提供されているので、誰でも好きにカスタマイズするWebHookを作ることができますが、PHPのサンプルコードが本家マニュアルに見当たらなかったのでまとめてみました。


Webhookを作成する


Secret文字列を作成する

まずWebhookを作成する際にsecret文字列を入力する。

長くて複雑で容易に推測されないような文字列にすると良いと思います。

テキトーですが、例えばPHPで強引にやろうとすればこんな感じに作れます。

$ php -r 'echo base64_encode(random_bytes(32)) . "\n";'


リポジトリのWebhookを追加する

Githubの該当リポジトリの Settings -> Webhooks から新たにWebhookを追加します。

Payload URL, Content Type, Secret, Which events would you like to trigger this webhook?

という項目の入力が必要だと思います。

入力方法は、空気を読んでください。

(たぶん、Webhookを作成しようというモチベーションのある貴殿には説明不要かとおもいます)

Secretには、さっき作成したSecret文字列を入力します。


Webhookの実装コード

あとはコード書くだけ・・・とは行かず、セキュアなWebhookにするためには環境変数にSecret文字列を設定するといいよということだそうです。


環境変数にセットする

GitHubのマニュアルページには、絶対にソースコードにSecret文字列をハードコーディングするなよ。絶対だぞ。と、前振りがございますので(?)ご注意ください。

不本意ではございますが、ハードコーディングせずに環境変数にセットすることにします。

$ export SECRET_TOKEN="your_secret_token"

apache2の設定ファイル(.htaccessでも可)に設定するなら、こんな風にも書けると思います。

SetEnv SECRET_TOKEN "your_secret_token"

※ 言わずもがなyour_secret_tokenはちゃんと各自のSecret文字列に置き換えてくださいませ。


Webhookの実装サンプル

Payload URLから呼び出されるPHPのコードにこのような検証コードを書くと、正しい検証ができるのではないかと思います。

// Webhookを作成した時に入力したsecret文字列

$secret = getenv('SECRET_TOKEN');
$postdata = file_get_contents('php://input');
$signature = 'sha1='.hash_hmac('sha1', $postdata, $secret);
if ($_SERVER['HTTP_X_HUB_SIGNATURE'] !== $signature) {
header('HTTP/1.1 403 Forbidden');
echo 'Signatures didn\'t match... ';
exit;
}

// 以降は好きにしたらよろし


参考

GitHub - Securing your webhooks

https://developer.github.com/webhooks/securing/