Sono riuscito con successo a mantenere le modifiche alla configurazione di nginx ModSecurity tra le esecuzioni di launcher rebuild app come segue:
Per prima cosa, aggiorniamo la copia locale di install-nginx che proviene dal repository discourse_docker ed è clonata in /var/discourse/.
cd /var/discourse/image/base
cp install-nginx install-nginx.`date "+%Y%m%d_%H%M%S"`.orig
# aggiungi un blocco per controllare il modulo nginx di modsecurity subito prima di scaricare il sorgente di 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
# aggiorna la riga di configurazione per includere il modulo ModSecurity controllato sopra
sed -i '/ModSecurity/! s%^[^#]*./configure \(.*nginx.*\)%#./configure \1\n./configure \1 --add-module=/tmp/ModSecurity-nginx%' install-nginx
# aggiungi una riga alla sezione di pulizia
grep 'rm -fr /tmp/ModSecurity-nginx' install-nginx || sed -i 's%\(rm -fr.*/tmp/nginx.*\)%rm -fr /tmp/ModSecurity-nginx\n\1%' install-nginx
Nota che il Dockerfile responsabile dell’esecuzione dello script install-nginx viene eseguito quando l’immagine viene costruita. L’immagine viene costruita solo dal team di Discourse prima di essere caricata su docker hub. Quando viene eseguito il comando Discourse ./launcher rebuild app, viene attivato (se sono disponibili aggiornamenti) un docker pull, che scarica l’ultima immagine docker di Discourse da docker hub. Ancora una volta, questo non ricostruisce l’immagine, non esegue il Dockerfile né esegue lo script install-nginx modificato sopra.
L’unico modo (che io sappia) per attivare l’esecuzione dello script bash aggiornato install-nginx (che viene eseguito dal Dockerfile) è far sì che docker costruisca una nuova immagine. Ad esempio, questo attiva docker per costruire una nuova immagine denominata discourse_modsecurity – che verrà costruita utilizzando lo script install-nginx modificato localmente:
docker build --tag 'discourse_modsecurity' /var/discourse/image/base/
Sfortunatamente, non sono riuscito a trovare un modo per dire a launcher di utilizzare un’immagine personalizzata (specificare un run-image utilizza l’immagine specificata direttamente, senza eseguire i template su di essa – come necessario per configurare effettivamente [anziché solo installare] nginx). Quindi sostituiamo la variabile image definita nello script launcher per utilizzare la nostra nuova immagine docker locale denominata discourse_modsecurity
# sostituisci la riga "image="discourse/base:<versione>" con '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
Ora aggiungiamo un nuovo file di template per impostare le nostre configurazioni nginx per includere i file/blocchi modsecurity necessari
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: Definisce le regole mod_security per il vhost discourse
# Questo dovrebbe essere incluso nei blocchi server{} dei vhost nginx.
# Author: Michael Altfield <michael@opensourceecology.org>
# Created: 2019-11-12
# Updated: 2019-11-12
################################################################################
Include "/etc/modsecurity/modsecurity.conf"
# OWASP Core Rule Set, installato dal pacchetto 'modsecurity-crs' 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
E aggiungiamo questo template (templates/web.modsecurity.template.yml) al blocco templates del file di configurazione yaml della nostra app, in modo che assomigli a qualcosa del genere:
[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]#
Ora, quando ricostruisci l’app docker di Discourse, utilizzerà la tua nuova immagine docker discourse_modsecurity con nginx e modsecurity e configurerà nginx per utilizzare l’OWASP CRS.
/var/discourse/launcher rebuild app