J’ai pu conserver avec succès mes modifications de configuration nginx ModSecurity à travers les exécutions de launcher rebuild app comme suit :
Tout d’abord, nous mettons à jour la copie locale de install-nginx provenant du dépôt discourse_docker et clonée dans /var/discourse/.
cd /var/discourse/image/base
cp install-nginx install-nginx.`date "+%Y%m%d_%H%M%S"`.orig
# ajouter un bloc pour récupérer le module nginx ModSecurity juste avant le téléchargement du code source 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
# mettre à jour la ligne de configuration pour inclure le module ModSecurity récupéré ci-dessus
sed -i '/ModSecurity/! s%^[^#]*./configure \(.*nginx.*\)%#./configure \1\n./configure \1 --add-module=/tmp/ModSecurity-nginx%' install-nginx
# ajouter une ligne à la section de nettoyage
grep 'rm -fr /tmp/ModSecurity-nginx' install-nginx || sed -i 's%\(rm -fr.*/tmp/nginx.*\)%rm -fr /tmp/ModSecurity-nginx\n\1%' install-nginx
Notez que le Dockerfile responsable de l’exécution du script install-nginx est exécuté lors de la construction de l’image. L’image n’est construite que par l’équipe Discourse avant d’être téléchargée sur docker hub. Lorsque la commande Discourse ./launcher rebuild app est exécutée, elle déclenche (si des mises à jour sont disponibles) un docker pull, qui récupère la dernière image Docker Discourse depuis docker hub. Encore une fois, cela ne reconstruit pas l’image, n’exécute pas le Dockerfile, ni n’exécute le script install-nginx modifié ci-dessus.
La seule façon (que je connaisse) de déclencher l’exécution du script bash install-nginx mis à jour (qui est exécuté par le Dockerfile) est de faire construire une nouvelle image par Docker. Par exemple, cela déclenche Docker pour construire une nouvelle image nommée discourse_modsecurity – qui sera construite en utilisant le script install-nginx localement modifié :
docker build --tag 'discourse_modsecurity' /var/discourse/image/base/
Malheureusement, je n’ai pas trouvé de moyen de dire à launcher d’utiliser une image personnalisée (spécifier un run-image utilise l’image spécifiée directement, sans exécuter les modèles contre elle – comme nécessaire pour configurer réellement [par opposition à simplement installer] nginx). Nous remplaçons donc la variable image définie dans le script launcher pour utiliser notre nouvelle image Docker locale nommée discourse_modsecurity.
# remplacer la ligne "image="discourse/base:<version>" par '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
Maintenant, nous ajoutons un nouveau fichier de modèle pour configurer nos paramètres nginx afin d’inclure les fichiers/blocs modsecurity nécessaires.
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, installé depuis le paquet 'modsecurity-crs' dans 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
Et nous ajoutons ce modèle (templates/web.modsecurity.template.yml) au bloc templates du fichier de configuration YAML de notre application, de sorte que cela ressemble à quelque chose comme ceci :
[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]#
Maintenant, lorsque vous reconstruisez l’application Docker Discourse, elle utilisera votre nouvelle image Docker discourse_modsecurity avec nginx et modsecurity, et configurera nginx pour utiliser OWASP CRS.
/var/discourse/launcher rebuild app