たいそうなタイトルだけど実際そんなことない。思ったより長くなってしまったのでお時間のあるときにどうぞ。
今までWordPressのデプロイにはrsyncを使って同期させていたんですが、WordPress専用のRuby製デプロイツール、WordMoveを使ってみようと思い立ちこちらの記事を参考にしながら準備しました。
WordMoveはSSHやFTPでログインしてファイルを置き換えるために、ログインユーザーがドキュメントルート以下への書き込み権限を持っていないとデプロイできません。
前述の参考記事ではドキュメントルート以下の所有者と、ウェブサーバーの実行ユーザーをec2-userに変更する荒技で解決しています。ここが自分の中でめちゃくちゃ引っかかったので、セキュリティ的により良いと考える権限管理ついて書いてみます。
(後から調べたことですが、Red Hatが共有ディレクトリのベストプラクティスとして提案していたようです。)
今回のゴール
- デプロイ用の専用ユーザーを作り、WordMoveはデプロイ用のユーザーからデプロイを実施する
- ウェブサーバーの実行ユーザーは変更しない(apacheまたはnginx)
- 上記のままうまく回るようにユーザーとディレクトリのパーミッションを変更する
デプロイ元の環境で鍵ペアを作る
今回はVCCWを使ったVagrant内のWordMoveを使います。特にWordMoveはrootになって使う必要もないので、今回はvagrantユーザーで鍵を作ります。
|
$ ssh-keygen $ less ~/.ssh/id_rsa.pub |
秘密鍵のパスフレーズは必要に応じて設定してください。
ssh-keygenコマンドで鍵ペアが生成されますが、触れていいのは ~/.ssh/id_rsa.pub のように最後にpubが付いたものだけです。これがWordMoveの公開鍵になるので控えておきます。なお、当然ですが ~/.ssh/id_rsa は秘密鍵です。これを漏らしてしまうとデプロイ対象のドキュメントルート以下を丸々書き換えることができてしまうので、十分に気をつけてください。
デプロイ用のユーザーを準備する
ここでは deployer という名前で作成します。
|
sudo useradd deployer # ユーザー追加 sudo -u deployer mkdir -p /home/deployer/.ssh # ディレクトリ作って sudo -u deployer vim /home/deployer/.ssh/authorized_keys # WordMoveの公開鍵を登録 sudo -u deployer chmod 600 /home/deployer/.ssh/authorized_keys # authorized_keysを保護 |
デプロイユーザーが対象のディレクトリに書き込めるようにする
今回のデプロイ対象はウェブサーバーの実行ユーザーが所有しているドキュメントルートです。
今回はnginxを使っており、所有権はnginx:nginxです。戦略としては、nginxのグループにdeployerユーザーを追加し、ドキュメントルート以下のディレクトリに対してグループ内からの書き込み権限を付与します。
|
sudo usermod -G nginx deployer # nginxグループにdeployerユーザーを追加 sudo chown nginx:nginx -R /usr/share/nginx # ドキュメントルート以下を再帰的にnginx:nginxに所有権変更 sudo chmod g+w -R /usr/share/nginx # グループに書き込み権限を与える |
これで終わり…なら簡単で、記事にすることもないんですが、2つ問題があります。
deployerでファイルの編集をしてみます。問題なくできます。
|
sudo -u deployer vim /usr/share/nginx/html/index.php |
次はデプロイ先にないファイルをデプロイしてファイルを作成することを想定してtouchしてみます。
|
sudo -u deployer touch /usr/share/nginx/html/index-new.php |
次にパーミッションをチェックします。
|
$ ls -l /usr/share/nginx/html | grep index -rw-rw-r-- 1 nginx nginx 5 12月 24 04:26 index.php -rw-r--r-- 1 deployer deployer 5 12月 24 04:26 index-new.php |
1つめの問題です。このように、新規でファイルを作成してしまうと所有権は deployer:deployer になってしまいます。deployerグループにnginxを追加してしまう方法もありますが、一貫性が無くなってしまう上に、何かグループに対して権限を付与する際にも複数のグループを気にすることとなり運用コストが高まります。
これを解決する方法として特殊なパーミッションビット、setgidを使います。
setgidを理解する
setgidというのは、setuid, setgid, sticky bit と並んで紹介されることの多いLinux系ファイルシステムにおける特殊なパーミッションビットのことです。今回はsetuidとsticky bitは使わないので省略します。
setgidはset group idの略で、このパーミッションを有効にしたディレクトリ内でファイルやサブディレクトリを作成すると、setgidを付与したディレクトリと同じグループが所有グループとなります。グループを継承することができるということです。
setgidはchmodコマンドで g+s を指定することで設定できます。
|
sudo chmod g+ws -R /usr/share/nginx # setgidビットフラグを起てる |
|
sudo -u deployer touch /usr/share/nginx/html/index-new2.php |
チェックしてみます。
|
$ ls -l /usr/share/nginx/html | grep index -rw-rwSr-- 1 nginx nginx 5 12月 24 04:26 index.php -rw-rwSr-- 1 deployer deployer 5 12月 24 04:26 index-new.php -rw-r--r-- 1 deployer nginx 3 12月 24 09:23 index-new2.php |
デフォルトでグループがnginxに割り当てられています。
今度こそ終わり… と思ったら、新しく作られたファイルのグループはnginxになっていますが、よく見るとグループへの書き込み権限がありません。2つめの問題です。
デフォルトパーミッションを変更する
ここまでで、ファイルやディレクトリを作成したときに所有グループを継承できるようになりました。最後は、デフォルトのパーミッションでグループに書き込み権限を付与することです。これにはumaskを使います。
umaskは許可*しない*ビットを指定する方法なのでかなり柔軟に設定できます。デフォルトではumask 022(=新規ファイルは644、自分だけ書き込み可)になっていますので、今回はumask 002(=664、自分とグループの人が書き込み可)に変更したいわけです。
今回はdeployerユーザーにumask 002を付与したいので、deployerユーザーの .bash_profile を利用します。
|
sudo vim /home/deployer/.bash_profile |
|
# .bash_profile +umask 002 |
テストしてみます。ただし、sudo -u deployerを使うとrootのログインシェルに入ってしまいumask 022が適用されてしまいますので、su – を使います。
|
sudo su - deployer touch /usr/share/nginx/html/index-new3.php |
|
$ ls -l /usr/share/nginx/html | grep index -rw-rwSr-- 1 nginx nginx 5 12月 24 04:26 index.php -rw-rwSr-- 1 deployer deployer 5 12月 24 04:26 index-new.php -rw-r--r-- 1 deployer nginx 3 12月 24 09:23 index-new2.php -rw-rw-r-- 1 deployer nginx 3 12月 24 09:39 index-new3.php |
新規ファイルも664のパーミッションで、グループを継承できました!念のためにサブディレクトリを作って、その中でファイルを作っても同様の結果になることを確認しておきましょう。テストが済んだらテスト用ファイルはすべて消しておきます。
WordMoveでデプロイしてみる
今回はWordMoveを使っていますがWordMoveの紹介ではないので簡単に。実際にdeployerユーザーを使ってデプロイしてみます。
|
vagrant ssh cd /vagrant wordmove pull --all |
Pulling Databaseで、サーバー側でmysqldumpが効かなくて一度コケましたがmysqlをyumで入れて解決しました。
ちゃんとプッシュできていることを確認して終わりです。お疲れ様でした。
雑感
ここまで書いておいて何ですが、本当はこのように役割ごとにユーザーを切り分けるべきだと信じています。ただめちゃくちゃ面倒くさくて、最後デプロイツールでも一工夫必要なことを考えると、同一ユーザーでやってしまいたくなるのもとても分かります。難しいですね。