launcher rebuild app を実行しても、nginx の ModSecurity 設定変更が失われることなく永続化できることを確認しました。手順は以下の通りです。
まず、discourse_docker リポジトリ から取得し、/var/discourse/ にクローンされている install-nginx のローカルコピーを更新します。
cd /var/discourse/image/base
cp install-nginx install-nginx.`date "+%Y%m%d_%H%M%S"`.orig
# nginx ソースをダウンロードする直前に ModSecurity nginx モジュールをチェックアウトするブロックを追加
grep 'ModSecurity' install-nginx || sed -i 's%\(curl.*nginx\.org/download.*\)%# mod_security\napt-get install -y libmodsecurity-dev modsecurity-crs\ncd /tmp\ngit clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git\n\n\1%' install-nginx
# 上記でチェックアウトした ModSecurity モジュールを含むように configure コマンド行を更新
sed -i '/ModSecurity/! s%^[^#]*./configure \(.*nginx.*\)%#./configure \1\n./configure \1 --add-module=/tmp/ModSecurity-nginx%' install-nginx
# クリーンアップセクションに行を追加
grep 'rm -fr /tmp/ModSecurity-nginx' install-nginx || sed -i 's%\(rm -fr.*/tmp/nginx.*\)%rm -fr /tmp/ModSecurity-nginx\n\1%' install-nginx
なお、install-nginx スクリプトを実行する Dockerfile は、イメージがビルドされる際に実行されます。このイメージは、docker hub にアップロードされる前に、Discourse チームによってのみビルドされます。Discourse の ./launcher rebuild app コマンドを実行すると(アップデートが利用可能な場合)、docker pull がトリガーされ、docker hub から最新の Discourse docker イメージが取得されます。繰り返しになりますが、これはイメージを再ビルドしたり、Dockerfile や上記で修正した install-nginx スクリプトを実行したりするものではありません。
(Dockerfile によって実行される)更新された install-nginx bash スクリプトを実行させる唯一の方法(私が知る限り)は、docker に新しいイメージをビルドさせることです。例えば、以下のコマンドは discourse_modsecurity という名前の新しいイメージを docker にビルドさせます。これは、ローカルで修正した install-nginx スクリプトを使用してビルドされます。
docker build --tag 'discourse_modsecurity' /var/discourse/image/base/
残念ながら、launcher にカスタムイメージを使用させる方法が見つかりませんでした(run-image を指定すると、実際に nginx を設定するために必要なテンプレートの適用を行わず、指定されたイメージが直接使用されます)。そのため、launcher スクリプトで定義されている image 変数を、新しいローカル docker イメージ discourse_modsecurity を使用するように置き換えます。
# "image="discourse/base:<version>" という行を 'image="discourse_modsecurity"' に置き換え
grep 'discourse_modsecurity' launcher || sed --in-place=.`date "+%Y%m%d_%H%M%S"` '/base_image/! s%^\(\s*\)image=\(.*\)$%#\1image=\2\n\1image="discourse_modsecurity"%' /var/discourse/launcher
次に、必要な modsecurity ファイル/ブロックを含む nginx 設定をセットアップするための新しいテンプレートファイルを追加します。
cat << EOF > /var/discourse/templates/web.modsecurity.template.yml
run:
- exec:
cmd:
- sudo apt-get install -y modsecurity-crs
- cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
- sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf
- sed -i 's^\(\s*\)[^#]*SecRequestBodyInMemoryLimit\(.*\)^\1#SecRequestBodyInMemoryLimit\2^' /etc/modsecurity/modsecurity.conf
- sed -i '/nginx/! s%^\(\s*\)[^#]*SecAuditLog \(.*\)%#\1SecAuditLog \2\n\1SecAuditLog /var/log/nginx/modsec_audit.log%' /etc/modsecurity/modsecurity.conf
- file:
path: /etc/nginx/conf.d/modsecurity.include
contents: |
################################################################################
# File: modsecurity.include
# Version: 0.1
# Purpose: Defines mod_security rules for the discourse vhost
# This should be included in the server{} blocks nginx vhosts.
# Author: Michael Altfield <michael@opensourceecology.org>
# Created: 2019-11-12
# Updated: 2019-11-12
################################################################################
Include "/etc/modsecurity/modsecurity.conf"
# OWASP Core Rule Set, installed from the 'modsecurity-crs' package in debian
Include /etc/modsecurity/crs/crs-setup.conf
Include /usr/share/modsecurity-crs/rules/*.conf
- replace:
filename: "/etc/nginx/conf.d/discourse.conf"
from: /server.+{/
to: |
server {
modsecurity on;
modsecurity_rules_file /etc/nginx/conf.d/modsecurity.include;
EOF
そして、このテンプレート(templates/web.modsecurity.template.yml)を、アプリの yaml 設定ファイルの templates ブロックに追加します。以下のような形になります。
[root@osestaging1 discourse]# vim /var/discourse/containers/app.yml
...
[root@osestaging1 discourse]# grep -A 6 'templates:' /var/discourse/containers/app.yml
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/web.socketed.template.yml"
- "templates/web.modsecurity.template.yml"
[root@osestaging1 discourse]#
これで、Discourse docker アプリを再ビルドすると、modsecurity を搭載した nginx を使用する新しい discourse_modsecurity docker イメージが使用され、OWASP CRS を使用するよう nginx が設定されます。
/var/discourse/launcher rebuild app