httpd 2.4、CentOS7系で、SuEXECで、Internal Server Errorに少しはまった件です。
httpdは、yumでインストールをしています。
「パーミッション」「権限」の重要性
デザイン系のWEB制作者でも、「パーミッション」とか「権限」とか聞いた事があると思います。
WEBアプリ(CGI)を動かすときに、避けて通れないものです。
デザイナーは、「755にしないと!実行権限をつけないと!改行に気をつけないと!」
と「気をつけないと!」と思っているかと思います。
「パーミッション」「権限」は、それほど、WEBアプリ(CGI)には、頻繁に出てくるキーワードです。
SuEXECを試す
今回、あるプログラムから、サーバー内の「実行ユーザ」を「特定のもの」にする必要がありました。
実際には、「Postfix3.3 迷惑メール対策 SpamAssassin(スパムアサシン)[ユーザ毎の設定]」の記事の「SpamAssassin」の設定ファイルをCGIで、読み込ませるためです。
「Postfix、マルチドメイン」のディレクトリは、「特定のユーザ」のみが閲覧できます。
httpd 2.4など初期設定では、「apache」などのユーザでプログラムが動きます。
つまり、「apache」というユーザが、「SpamAssassin」の特定のファイルが読めるようになっていないといけません。
かし、実際には、「apache」ではなく、「違う特定のユーザ」で、「Postfixのマルチドメイン環境」が構成されています。
そこで、apache 1.3 の時代から、「SuEXEC」という「指定されたユーザで実行する」という設定が、apache(httpd)で可能です。
今回、httpd2.4 の中のVirtualHostの中で、SuEXECを活用して、「Postfixの設定ファイル(SpamAssassinの設定ファイル)」が読めるようにしました。
具体的には、
<VirtualHost *:80> ServerName (独自ドメインFQDN) ServerAdmin (管理者メールアドレス) SuexecUserGroup (動かしたいユーザ) (動かしたいグループ) DocumentRoot /home/(dir)/www CustomLog /home/(dir)/logs/access_log combined ErrorLog /home/(dir)/logs/error_log </VirtualHost>
が書かれたファイルを
/etc/httpd/conf.d/
の下に、置きました。
(ファイル名は、任意のファイル名で大丈夫です)
SuEXECが有効か?
perlで書かれたWEBアプリ(CGI)を、ブラウザ上から起動すると、
「InternalServerError」がでます。
最初は、「SuEXEC」が有効になっているのか?
を疑いました。
有効かどうかは、「apachectl -V」というコマンドで調べます。
# apachectl -V Server version: Apache/2.4.34 () Server built: XXX XX 2019 XX:XX:XX Server's Module Magic Number: XXXXXX:XX Server loaded: APR 1.6.3, APR-UTIL 1.6.1 Compiled using: APR 1.6.3, APR-UTIL 1.6.1 Architecture: 64-bit Server MPM: prefork threaded: no forked: yes (variable process count) Server compiled with.... -D APR_HAS_SENDFILE -D APR_HAS_MMAP -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) -D APR_USE_SYSVSEM_SERIALIZE -D APR_USE_PTHREAD_SERIALIZE -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT -D APR_HAS_OTHER_CHILD -D AP_HAVE_RELIABLE_PIPED_LOGS -D DYNAMIC_MODULE_LIMIT=256 -D HTTPD_ROOT="/etc/httpd" -D SUEXEC_BIN="/usr/sbin/suexec" -D DEFAULT_PIDLOG="/run/httpd/httpd.pid" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="conf/mime.types" -D SERVER_CONFIG_FILE="conf/httpd.conf"
上記の「 -D SUEXEC_BIN=”/usr/sbin/suexec”」と指定があります
かつ
# ls -al /usr/sbin/suexec -r-x--x--- 1 root apache 15280 XXX XX 2019 /usr/sbin/suexec
とファイルもあります。
有効になっています。
再度試行錯誤します。
journalctlで、SuEXECのエラーを確認する。
次に「journalctl」コマンドで、チェックします。
ソースコードで、httpdを入れる場合、SuEXECのエラーファイルの指定することができます。
また、/var/log/httpd/suexec.log というファイルに書かれる場合もありますが、CentOS7系のyumで入れると、そのようなファイルは作成されません。
# journalctl -f suexec[4799]: cannot run as forbidden gid (100/check.cgi)
↑というエラーメッセージがでてきました。
check.cgiというファイル名を実行しようとしています。
上記は、「実行グループが、許可されていなよ」というエラーです。
suexecの仕様をチェックしてみます。
# suexec -V -D AP_DOC_ROOT="/var/www" -D AP_GID_MIN=1000 -D AP_HTTPD_USER="apache" -D AP_LOG_SYSLOG -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin" -D AP_UID_MIN=1000 -D AP_USERDIR_SUFFIX="public_html"
↑この中で、
-D AP_GID_MIN=1000
と指定されています。
「グループのIDが、最低でも1000だよ。」ということです。
今回、「100」のグループIDで実行しようとしました。
調整をします。
再び、check.cgiを実行しようとしたところ、InternalServerErrorがでました。
# journalctl -f suexec[4988]: command not in docroot (/home/(dir)/check.cgi)
というエラーが出てきました。
プログラムを動かす場所が「ダメ」というものです。
再度、SuEXECの仕様を見てみます。
# suexec -V -D AP_DOC_ROOT="/var/www" -D AP_GID_MIN=1000 -D AP_HTTPD_USER="apache" -D AP_LOG_SYSLOG -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin" -D AP_UID_MIN=1000 -D AP_USERDIR_SUFFIX="public_html"
↑この中で、
-D AP_DOC_ROOT="/var/www"
とあります。
つまり、「/var/www」以下にコンテンツがないといけません。
そこで、コンテンツを
/home/以下
から
/var/www/html
に持ってきます。
これでやっと、CGIが動きました。
SuEXECの、DOC_ROOTを変える
この「/var/www」を変更するには、基本、「httpdのソースインストール」しかないようです。
裏技的には、「/usr/sbin/suexec」のバイナリの中身を変更する。という方法もあるようですが・・・
「そこまでして・・・。ならば、ソースインストールしますわ。」という気持ちになります。
SuEXECを活用したい場合、VirtualHostで、
「このドメインは、このユーザ権限で」
「あのドメインは、あのユーザ権限で」
という発想があるからだと思います。
一つのドメインならば、httpd.confで、指定している大元のユーザ名を希望のものにすればいいはずです。
おそらく、VirtualHostの指定を
/var/www/html01
/var/www/html02
などと、すればいいのかと思います。
/home/(dir01)/www/
/home/(dir02)/www/
というのは、ちょっと、異質的な発想なのかもしれません・・・
SuEXEC、その他のエラー
そのほか、指定したユーザ/グループ以外が書き込める状態だとエラーになる。
など、「権限」に厳しいです。
「journalctl -f」コマンドで確認しましょう。
SuEXEC、まとめ
エラーは、
journalctl -f
suexec -V
で、チェック
当然ながら、CGI自体のエラーがあるかもしれません。
気分でエラーを出している分けではないので、「なにか原因があります」
根気よく探しましょう!