柔軟な設定ができるnginxの設定ファイルのlinterを作った
これまで業務などでnginxを利用してきてnginx自体は高性能で便利ではあるけど罠ポイントなど色々あって、覚えていてもたまにうっかり罠にハマることがあるということでlinterや罠についてまとまった一覧などが欲しいと考えていました。
最近Claude Codeを触ってみていておもちゃのKVSを書いてみたりしていたのだけどもうちょっと実用的な例でlinterとか作るのには非常に向いていそうということでやってみた。
wasmにできるようにRustで作ったので、 https://walf443.github.io/nginx-lint/ からどんな感じなのかブラウザで試せます。
nginxの設定ファイルのlintといえば gixy とかあったりするのではありますが、あまり利用事例を聞く機会がなく、野良のnginx moduleとかを自前でビルドして使っている環境やhttpからincludeされているファイルだけ良い感じにチェックできるみたいなケースで使えるようなものがあるとCI/CDとかでの検証にも便利なのかなと思って作ってみた。
nginx-lintの場合、実行するときに--context http などのように指定することができて、この場合sites-availableにあるファイルとかでnginx.confからは動線がないけどlintしておきたいファイルをチェックしたりできるようになっている。複数ファイルを一気にやりたいときや毎回指定が面倒なときはファイルの冒頭にコメントとして
# nginx-lint:context http
と書いておけばその前提でチェックすることができるので小さくlintを始めることもできる。
それらを柔軟にやれるようにするために設定ファイルで個別ルールの無効化/有効化ができるようになっていて、さらに誤検出してしまうケースなどでコメントしつつルールを黙らせることができるようにしている。
一般的なルールにはしづらいけど組織のガイドラインとしてはチェックしておきたい、みたいなのにも対応できるように個別のルールはwasmとして作成できるようになっていて、対応するインターフェースを持ったwasmを作れば新ルールを拡張したりできるようにしてある。
wasm自体のインターフェースが色々なルールを作るために十分なものかわからないなということでひとまずコアのルールの実装も大半はwasm化はしたけど、wasm自体の実行のオーバーヘッドはけっこう大きくてnative実装と比べると100倍ぐらい遅いという悲しさはあるけどnginxの設定ファイルをlintする用途ではわりかし十分な性能が出てはいるんじゃないかなと思ってはいる。
これまで色々なlinterを使ってきていて、lintにひっかかったときにwebで調べるのがけっこう面倒だなと思っていたので、whyというサブコマンドを作っていて、そのあとに検出されたルール名を入れると、どういうパターンでどうするのが推奨なのかわかるコマンドを用意した。
$ nginx-lint why deprecated-ssl-protocol
Rule: deprecated-ssl-protocol
Category: security
Severity: warning
Why:
SSLv2, SSLv3, TLSv1.0, and TLSv1.1 have known vulnerabilities and
are deprecated. Using these protocols makes your server vulnerable to
attacks like POODLE, BEAST, and CRIME.
Only TLSv1.2 and above should be used.
Bad Example:
────────────────────────────────────────────────────────────
server {
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
}
────────────────────────────────────────────────────────────
Good Example:
────────────────────────────────────────────────────────────
server {
ssl_protocols TLSv1.2 TLSv1.3;
}
────────────────────────────────────────────────────────────
References:
• https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols
• https://wiki.mozilla.org/Security/Server_Side_TLS
その副産物として https://walf443.github.io/nginx-lint/rules.html ができたのだけどこれもまぁlint自体は使わなくてもまずまず便利なのではないでしょうか。
Discussion
v0.2.0では builtin-pluginについてはwasm化せずnative codeのまま実行できるようにしたので速度面の問題はだいぶ改善できました。(ルールのコードについてはwasm化もできる形で書くようにしてあるので自作の参考にすることはできます)