tracは、チケットやWikiのデータを触ったり、subversionに触ったり、結構色々するプログラムである。httpdを動かしているユーザーにこれらの権限を与えたくないのでsuexecすることにする。
調べて分かったこと
lighttpdのパッケージにはsuexecは含まれていない。
lighttpd自体にはapacheの様にsuexecのパスを知っていたり、configuration次第で透過的にsuexecしてくれたり、そういう機能は無い。
fastcgiプログラムごとに、bin-pathに指定するしかない。
See Also:
やってみる
とりあえず、lighttpdのドキュメントに書いてあるphpの場合に合わせてやってみた。各pathはdebian sargeの場合。私はapache2-commonをインストールしたので実行ファイル名はsuexec2になってる。
起動スクリプトを用意
なんか、ドキュメントのやりかただとfastcgiプログラムごとに一々起動スクリプトが必要な気がするんだけど。
/usr/local/lib/trac/trac.fcgi.suexec にこんな感じのファイルを書いた。で、実行ビットを立てる。
#!/bin/sh user=trac group=trac cd /var/www/trac exec /usr/lib/apache2/suexec2 $user $group trac.fcgi
環境変数設定
/var/www/trac/trac.fcgi にこんな感じのものを置いた。suexecがコンパイル時規定の DOCUMENT_ROOT
外のスクリプトは拒絶するので、必ず /var/www 配下に置く。
#!/bin/sh exec env TRAC_ENV_PARENT_DIR=/var/trac /usr/share/trac/cgi-bin/trac.fcgi
このファイルは必ず、実行したいユーザーとグループの所有にしておく。でないとsuexecが拒絶する。
lighttpdの設定
で、あとは、bin-pathにさっきの起動スクリプトを設定。
fastcgi.server = ( "/trac" => ( "trac" => ( "socket" => "/var/run/fastcgi/trac.sock", "bin-path" => "/usr/local/lib/trac/trac.fcgi.suexec", "check-local" => "disable", "bin-environment" => ( "TRAC_ENV_PARENT_DIR" => "/var/trac" ), "min-procs" => 1, "max-procs" => 4, "idle-timeout" => 20 ) ) )
ちょっと直してみる
一応、上記がドキュメントに従った設定。でも、fastcgiプログラムごとに起動スクリプトを書くのは嫌な感じだ。で、こんなのを書いてみた。
/usr/local/lib/suexec/suexec.sh:
#!/bin/sh if [ "_$PATH_TRANSLATED" = "_" ]; then exit 1 fi DIR=`dirname $PATH_TRANSLATED` COMMAND=`basename $PATH_TRANSLATED` USER=`stat -c '%U' $PATH_TRANSLATED` GROUP=`stat -c '%G' $PATH_TRANSLATED` cd $DIR exec /usr/lib/apache2/suexec2 $USER $GROUP $COMMAND
lighttpdの設定も直す。
fastcgi.server = ( "/trac" => ( "trac" => ( "socket" => "/var/run/fastcgi/trac.sock", "bin-path" => "/usr/local/lib/suexec/suexec.sh", "check-local" => "disable", "bin-environment" => ( "PATH_TRANSLATED" => "/var/www/trac/trac.fcgi" ), "min-procs" => 1, "max-procs" => 4, "idle-timeout" => 20 ) ) )
/etc/init.d/lighttpd
なんか、suexec経由で走らせる様にしたら、lighttpdをstopするときにfastcgiプロセスが止まらずにinit(8)に引き継がれてしまう。止める直前に見てみるとfastcgiプロセスのPPIDはlighttpdになってるんだけど。このへんの挙動ってexecに影響されたっけ?
仕方がないから、/etc/init.d/lighttpdのstop処理部分をこんな風にしてみた。
stop) log_daemon_msg "Stopping $DESC" $NAME + PID=`cat $PIDFILE` + SID=`ps -p $PID -o sid --no-headers` if start-stop-daemon --quiet --stop --pidfile $PIDFILE --exec $DAEMON; then + PIDS=`ps -s $SID -o pid --no-headers` + if [ "_" != "_$PIDS" ]; then + kill -INT $PIDS > /dev/null + fi rm -f $PIDFILE log_end_msg 0 else log_end_msg 1 exit 1 fi ;;