1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Webhookによる自動デプロイを構築してわかったセキュリティ設計の重要性

Posted at

はじめに

今回は、GitHub Webhookを使った自動デプロイの構成を作っていく中で、

  • なぜ www-datagit 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-datadeploy として 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-datagit pull させようとした結果、

  • 所有権やパーミッションの問題
  • sudoの制限
  • Web経由でのセキュリティリスク

といった課題に直面した。

最初から ubuntu / deploy / www-data の役割を分けて設計しておけば、トラブルを避けられたと痛感した。


補足:Recursion共同創業者 ジェフリーさんからのアドバイス

Recursionコミュニティで設計について相談した際、元Metaエンジニアのジェフリーさんから次のアドバイスをいただいた。

  • GitHubからのリクエストは 必ず署名を検証する
  • shellコマンドは リテラル文字列に限定 し、ユーザー入力や動的な値を含めない
  • cronやフレームワークのschedulerで 別プロセスとして実行 する方法も有効

まとめ

課題 解決策
.git にアクセスできない 所有者を deploy にして、www-data からは触らせない
www-datagit pull させたい sudoersに対象コマンドのみ許可する設定を追加
セキュリティ面が不安 ユーザー分離、署名検証、静的コマンド指定で対策
1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?