Apache のログのアクセス権の分離
ログには,時として個人情報につながる情報が記録されます.ですので,コンテンツのログは担当者以外が読めてはいけません.一方,通常はコンテンツ a と b ではその担当者が,そして時には担当部署もが異なります.つまり,コンテンツ a の担当者が,b のログを読めるのは読めてはいけない,ということです.
まず前提として,コンテンツ a とコンテンツ b の運用のためのユーザ user_a,user_b があります.これらはそれぞれ group_a,group_b というグループに属しています.それぞれのグループに属するユーザは,user_a,user_b のみです.
コンテンツ a と b のログのためのディレクトリを,それぞれ以下の所有者/グループとアクセス権でもって作成します.
drwxr-x--- apache gourp_a log_a
drwxr-x--- apache gourp_b log_b
apache というのは,Apache の実行ユーザです.即ち,log_a のディレクトリにあるファイルは apache ユーザは読み書きできて,group_a に属するユーザ = user_a のみが読むことができます.log_b のディレクトリも同じです."それ以外"のユーザに対するアクセス権は --- になっていますから,user_a は log_b のディレクトリにあるファイルを読むことはできなくなります.
さて,これで一見目的を達成できたように見えます.実際のところ,コンテンツが完全に静的なものであれば,これでも問題ありません.
しかしながら,大半のコンテンツは動的な要素を含んでいます.即ちプログラムが動作します.そのプログラムは 例えば PHP や CGI であれば apache ユーザで動作します.(CGI の場合,suexec を使えば apache 以外のユーザで動作しますが,それは別の問題を含んでいるので使いません.)そしてそのプログラムを管理しているのはコンテンツの担当者,即ち user_a や user_bです.つまり,user_a や user_b は log_b や log_a のディレクトリを読むプログラムを,Apache = apache ユーザに実行させることができるのです.
では,apache ユーザが読めないようにするにはどうすれば良いでしょうか.単純に,apache ユーザの権限から読出し権限 r を落としてみると良いと思うかもしれません.こんな風に
d-wxr-x--- apache gourp_a log_a
d-wxr-x--- apache gourp_b log_b
けれども,log_a や log_b の所有者は依然として apache です.とうことは,apache ユーザはこのディレクトリの権限を自由に変更できる,ということです.
では,このディレクトリの所有者とグループを逆転させてみるとどうでしょうか.即ち
drwx-wx--- user_a httpd log_a
drwx-wx--- user_b httpd log_b
(httpd グループは,apache ユーザのみが属するグループとします.)
これらのディレクトリはディレクトリのグループが httpd になっていて,グループに対する権限として書き込み権が与えられていますので,apache ユーザでのログを出力することができます.且つ,これらのディレクトリは apache ユーザの持ち物では無いので,CGI や PHP から権限を変更される心配もありません.しかしながら,アクセスを禁止したいのはこれらのディレクトリ自体ではなくて,このディレクトリの下にできるログファイルです.そしてそのログファイルを作成するのは apache ユーザですので,ログが作られるディレクトリやログファイル自体の権限をいくら工夫しようが,依然として apache ユーザはそれを読むことができるのです.ということで,apache ユーザがログを書き出す限りは,CGI や PHP を経由したログの読み出しを止めることはできそうにありません.
問題は apache ユーザがログファイルを作成するから発生することがわかりました.ですので今回の答えは,ログファイルへの出力は apache ユーザ以外が行えばいい,ということになります.方法はいくつかありますが,DSAS で採用しているのは次の方法です.
Apache のログ出力は,CustomLog ディレクティブで設定します.このディレクティブではログの出力先として,単純なファイルの指定の他に,外部のプログラムを指定することができます.ログの出力先としてプログラムが指定された場合,Apache はログをそのプログラムの標準入力へと書き出します.このプログラムを実行するユーザを,apache 以外にしてやれば,問題は解決できます.プログラムを,起動したユーザ以外のユーザの権限で動作せる方法はいくつかありますが,DSAS では次の用に設定しています.
CustomLog "|/bin/su log -c rotatelogs log_a/access_log.%Y-%m-%d 86400 +540" combine
(実際は,rotatelogs や ログディレクトリの指定は絶対パスで行います.)
ここで使用している rotatelogs は Apache に付属しているログ書き出し用の外部プログラムで,このような形で引数を与えると,1日ごとにログのローテートを自動的にしてくれます.この rotatelogs を su コマンドを使用してログ管理用のユーザ log にて起動し,それぞれのコンテンツのログを出力しています.この場合の log_a のディレクトリの権限は次のようになります.
drwxr-x--- log group_a log_a
このディレクトリ及び作成されるログファイルのオーナは,apache ユーザとは関係のないユーザですので,CGI や PHP から触ることはでき無くなります.