めっっっっちゃくちゃ苦戦
とりあえずflaskでの自作ページのログイン機能として
Register処理とLogin処理をSQLite3と連携させることを考えていた
dbファイルへのアクセスとしては
Registerが「書き込み」
Loginが「読み込み」
にあたる
が
Apacheの本番環境で動作させると
どちらの処理もdbファイルへのアクセスに問題があった
■背景
デバッグモードではDBへの連携はできていた
なのでApacheで動かしているときの動作に問題があるのだと気づいた
そしてログを確認
自分の場合は
tail -f /var/log/httpd/error_log
例えばRegisterページで登録しようとするとこのエラーが出ていた
sqlite3.OperationalError: unable to open database file
んーファイルがそもそも開けていないっぽい
開発環境でflask runでは処理できていたのに...
普通にdbファイルの権限の問題だと思って
chmodとかchownとか触りまくってたけど
そんな甘い世界ではなかった
そしてググりまくった結果判明した原因は3つ
原因1
dbファイルのパーミッション
原因2
__init__.pyでのdbファイルパスの渡し方
原因3
SELinuxによるアクセス制限
■原因1 dbファイルのパーミッション
これはとりあえずそう
ずっとrootでやってたこともありdbファイルを置くフォルダも全てrootでやっていた
だからapacheに変更
# chown -R apache:apache [dbファイルがあるフォルダ名]
まずこれが1つ
■原因2 __init__.pyでのdbファイルパスの渡し方
これはエラーログとかをコピペしてググりまくって
同じ境遇の人が記事書いているのを発見。
どうやらパスの渡し方が問題だったらしい
以下__init__.pyを一部抜粋
変更前
import os from flask import Flask app = Flask(__name__) app.config.from_mapping( SECRET_KEY='dev', DATABASE=os.path.join(app.instance_path, 'FlaskApp.sqlite'), )
変更後
import os from flask import Flask app = Flask(__name__) app.config.from_mapping( SECRET_KEY='dev', DATABASE=os.path.join('/var/www/FlaskApp/instance', 'FlaskApp.sqlite'), )
変更前のは公式のやつをそのまま持ってきてた
os.pathとapp.instance_pathを組み合わせてdbファイルのパスを取得しようとしている
そして変更後はdbファイルのパスを直接渡してみることにした
これでLoginは成功した、つまりdbファイルの「読み込み」はできるようになった
しかし、「書き込み」はできていなかった
■原因3 SELinuxによるアクセス制限
LoginはできてもRegisterはできなかった
つまり書き込み
何回やってもInternal Server Errorが返る
再度ログを確認してみる
sqlite3.OperationalError: attempt to write a readonly database
さっきとは微妙に違う
今回は明らかに権限が原因だと思ったので
またchmodとchownで色々してみたけどどれでもなかった
すると画面右上にあるエラーメッセージが上がっていることに気づいた
「AVC拒否」
「SELinux は問題を検出しました」
うそだろ...?
ここにきてSELinuxによる制限どうこうが入ってくるのか?
たしかにCent7を使い始めたばかりだが
SELinuxのメッセージの詳細を確認したところ
やはり結局httpdがdbファイルへのアクセスを許可されていなかった
後々知ることになるが、SELinuxでの今回のエラーログはこんな感じで見れる
cat /var/log/audit/audit.log | grep "type=AVC"
type=AVC msg=audit(1548864798.247:345): avc: denied { write } for pid=8108 comm="httpd" name="FlaskApp.sqlite" dev="dm-0" ino=10397195 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_sys_content_t:s0 tclass=file
画面右上のメッセージをクリックして
さらに表示されている解決策となるコマンドを入力
# semanage fcontext -a -t httpd_sys_rw_content_t /var/www/FlaskApp/instance/FlaskApp.sqlite
# restorecon -v /var/www/FlaskApp/instance/FlaskApp.sqlite
#setsebool -P httpd_unified 1
#ausearch -c 'httpd' --raw | audit2allow -M my-httpd
#semodule -i my-httpd.pp
改行ごとのまとまりでそれぞれ解決策が異なるコマンドらしいが、
もうどっちでもいいので全てを入力した
そしてApacheを再起動
apachectl restart
きてる...
きてる!!!!!!
Registerがきちんと処理してくれた!!!!
ここでまさかのSELinixuが初対面でここまでしてくれていたとは...
■まとめ
学んだこととしては
・tail -f /var/log/error_logでエラーを確認することはとても大切
そしてエラーログを元にググりまくるのもとても大切
・パーミッションがいつもやっているようなchmodとかだけではなくて
SELiuxのアクセス制御によっても行われている
・CentOS7に来てSELinuxと戦う必要が今後もあるかもしれない
これでDBとの連携はとりあえずは完了
あとは。。。なんだ
BBS作りか
■ちなみに
前回記事で書いたWifiアダプタ
注文したやつが届いたのやってみたが
そんなに変わらない印象
結局NEHの感度が悪いわけではなさそうだった。。。
まぁこれも勉強か