OpenSUSE(Leap)の15.4がリリースされ、15.3から15.4にアップグレードしたあとにapache内で実行するPHPスクリプトがことごとく動かず、「Access denied」やら「Error!」やら表示されるようになってしまった。
原因はApparmorです
調べると、原因はApparmorによってphp-fpmの動きが阻害されている模様。
よく見ると「/var/log/audit/audit.log」に詳細が記載されている。
下記のようなコマンドを実行すると、ずらっとエラーが表示されて
app armorでphp-fpmが阻害されていることがわかると思う。
# tail -n 2000 /var/log/audit/audit.log | grep 'apparmor="DENIED"'
Apparmorの例外ルールに追加
ここまででphp-fpmが動いておらず悩んでいるということは、
apparmorのルールに「php-fpm」が作られているハズなので(なければ作って)、例外を追加していく。
一般的なディレクトリであれば、「/etc/apparmor.d/php-fpm」になっているはずなので
(なければ自分でルールディレクトリ探して作って)どういう構造になっているかをチェック。
# cat /etc/apparmor.d/php-fpm
おそらくデフォでは下記のような構成になっている。
# Last Modified: Sun Feb * *:*:* 2022 abi <abi/3.0>, include <tunables/global> # vim: ft=apparmor profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) { include <abstractions/base> include <abstractions/nameservice> include <abstractions/openssl> include <abstractions/php> include <abstractions/ssl_certs> include <abstractions/user-tmp> include if exists <local/php-fpm> include if exists <php-fpm.d> capability chown, capability dac_override, capability kill, capability net_admin, capability setgid, capability setuid, signal send peer=php-fpm//*, deny / rw, /usr/sbin/php-fpm* rix, /var/log/php*-fpm.log rw, @{PROC}/@{pid}/attr/{apparmor/,}current rw, @{run}/php{,-fpm}/php*-fpm.pid rw, @{run}/php{,-fpm}/php*-fpm.sock rwlk, owner /etc/ImageMagick-7-SUSE/english.xml r, owner /etc/ImageMagick-7-SUSE/locale.xml r, owner /etc/ImageMagick-7-SUSE/log.xml r, owner /etc/ImageMagick-7-SUSE/policy.xml r, change_profile -> php-fpm//*, }
この下のほうにあるゴチャゴチャしたところ(30行目~38行目の間)に、
例外するディレクトリと許可する権限を右に書く。
今回は、/home/全ユーザー/scripts/下に設置されたすべてのスクリプトを信頼して、読み/書き/ロックを許可するように記述を追加する。
/home/*/scripts/** rwk,
*は1個だけだとそのディレクトリにしか効果を及ぼさないため、
ディレクトリ下の階層にも波及させたい場合は**(アスタリスクを2個)を使う。
詳細なapparmorの記述ルールについては、公式マニュアル参照。
最終的な/etc/apparmor.d/php-fpmは下記の通り。
# Last Modified: Sun Feb * *:*:* 2022 abi <abi/3.0>, include <tunables/global> # vim: ft=apparmor profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) { include <abstractions/base> include <abstractions/nameservice> include <abstractions/openssl> include <abstractions/php> include <abstractions/ssl_certs> include <abstractions/user-tmp> include if exists <local/php-fpm> include if exists <php-fpm.d> capability chown, capability dac_override, capability kill, capability net_admin, capability setgid, capability setuid, signal send peer=php-fpm//*, deny / rw, /home/*/scripts/** rwk, /usr/sbin/php-fpm* rix, /var/log/php*-fpm.log rw, @{PROC}/@{pid}/attr/{apparmor/,}current rw, @{run}/php{,-fpm}/php*-fpm.pid rw, @{run}/php{,-fpm}/php*-fpm.sock rwlk, owner /etc/ImageMagick-7-SUSE/english.xml r, owner /etc/ImageMagick-7-SUSE/locale.xml r, owner /etc/ImageMagick-7-SUSE/log.xml r, owner /etc/ImageMagick-7-SUSE/policy.xml r, change_profile -> php-fpm//*, }
Apparmorのルールを書き換えたら、ルールを再読み込みさせなければならないので、
下記コマンドを実行する。(/etc/apparmor.d/php-fpmの部分は更新したルールファイル)
# apparmor_parser -r /etc/apparmor.d/php-fpm
このコマンドで(構文エラーさえなければ)即時リロードされ、php-fpmの実行が可能になっているはず。
は? キレそう。まだエラー出るんだけど?
原因は下記コマンド実行で探れる。
# logprof
実行すると、audit.logからブロックされている部分を拾ってきて、対話的にどうするかを聞いてくる。
対話的に指定したAllow/Denyなどは質問の最後でSaveを選ぶと特定のルールファイルにルールが追加され、ルールファイルのリロードまでを行ってくれる。
ただし、ガチでファイル一個一個に許可/拒否を聞いてくるので、WordPressのようなPHPの塊のようなシステムだとワケわからんくなる。なのでlogprofである程度原因探ってSaveせずにAbortして、自分で例外ファイルにディレクトリ指定で突っ込んだほうが早い。