はじめに
今回は、GitHub Webhookを使った自動デプロイの構成を作っていく中で、
- なぜ
www-data
にgit pull
させてはいけないのか? -
deploy
ユーザーを作る意味とは? -
sudoers
は何のためにあるのか?
といった「ユーザーと権限設計」に関する疑問を通じて、
セキュリティ設計の視点を持つことの重要性に改めて気づかされました。*
きっかけ:Webhookで自動デプロイしたい
開発したWebアプリを AWS + Ubuntu + Nginx で公開する際に、
ローカルで
git push
したら、自動で本番環境が更新されるようにしたい
と考え、Webhookを使った自動デプロイを構築しました。
構成は以下の通りです。
ローカルで git push
↓
GitHub → Webhook 送信
↓
EC2サーバーの PHP(www-data)が受信
↓
PHP が git pull を実行してコードを更新
最初のつまずき:PHPから git pull
できない
shell_exec("git pull")
をPHPで実行してみたところ、次のようなエラーが発生。
fatal: cannot open .git/FETCH_HEAD: Permission denied
.git
にアクセスできないという問題です。
原因:PHPは www-data
ユーザーで動作している
PHPは www-data
ユーザーで実行されるため、.git
にアクセスするには書き込み権限が必要になります。
しかし、www-data
に .git
を触らせるのは、セキュリティ上非常に危険。理由は、www-data は Webサーバー(nginxやApache)やPHPの実行ユーザーであり、インターネットからのリクエストに直接応答する存在。間接的に.gitを操作されてしまう危険性があるため。たとえば、PHPに脆弱性(コマンドインジェクションなど)があれば、リクエスト経由で .git を操作される可能性があるため、Web経由で触れられるユーザーには .git の権限を与えるべきではない。
解決策:ユーザーを役割ごとに分離する
以下のように、ユーザーごとに役割を明確に分ける構成に変更した。
ユーザー | 役割 |
---|---|
ubuntu |
サーバー構成・管理(管理者) |
deploy |
デプロイ専用(git pull のみ許可) |
www-data |
Webサーバーとしてリクエストを受ける |
www-data
は、ただWebhookを受け取るだけの中継役とし、Gitの操作はすべて deploy
ユーザーが行うようにした。
sudoers設定で、必要最小限のコマンドだけ許可
www-data
が deploy
として git pull
を実行するには、sudo設定を変更する必要がある。それはsudo権限はubuntu以外のユーザーは持っていないから。
sudo visudo
以下の設定を追記します。
www-data ALL=(deploy) NOPASSWD: /usr/bin/git -C /var/www/project-textSnippetSharingService/public/Text-Snippet-Sharing-Service pull
これにより、www-data
はこのコマンド1つだけを、パスワードなしで deploy
として実行可能になる。
PHPのコード例(署名検証付き)
$secret = Settings::env(DEPLOY_KEY);
$githubSignature = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';
$payload = file_get_contents('php://input');
$calculatedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($calculatedSignature, $githubSignature)) {
http_response_code(403);
exit('Invalid signature');
}
$command = 'sudo -u deploy /usr/bin/git -C /var/www/{project-path} pull 2>&1';
$output = shell_exec($command);
file_put_contents('log.txt', $output, FILE_APPEND);
学び:最初からユーザーを分けて設計すべきだった
当初は安易に www-data
に git pull
させようとした結果、
- 所有権やパーミッションの問題
- sudoの制限
- Web経由でのセキュリティリスク
といった課題に直面した。
最初から ubuntu
/ deploy
/ www-data
の役割を分けて設計しておけば、トラブルを避けられたと痛感した。
補足:Recursion共同創業者 ジェフリーさんからのアドバイス
Recursionコミュニティで設計について相談した際、元Metaエンジニアのジェフリーさんから次のアドバイスをいただいた。
- GitHubからのリクエストは 必ず署名を検証する
- shellコマンドは リテラル文字列に限定 し、ユーザー入力や動的な値を含めない
- cronやフレームワークのschedulerで 別プロセスとして実行 する方法も有効
まとめ
課題 | 解決策 |
---|---|
.git にアクセスできない |
所有者を deploy にして、www-data からは触らせない |
www-data に git pull させたい |
sudoersに対象コマンドのみ許可する設定を追加 |
セキュリティ面が不安 | ユーザー分離、署名検証、静的コマンド指定で対策 |