Discourse + Web Application Firewall (WAF) mod_security

Ich konnte meine Änderungen an der nginx-ModSecurity-Konfiguration erfolgreich über mehrere launcher rebuild app-Durchläufe hinweg beibehalten, und zwar wie folgt:

Zuerst aktualisieren wir die lokale Kopie von install-nginx, die aus dem discourse_docker-Repository stammt und nach /var/discourse/ geklont wurde.

cd /var/discourse/image/base
cp install-nginx install-nginx.`date "+%Y%m%d_%H%M%S"`.orig

# Füge einen Block hinzu, um das ModSecurity-nginx-Modul kurz vor dem Herunterladen der nginx-Quellen auszuchecken
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

# Aktualisiere die Konfigurationszeile, um das oben ausgecheckte ModSecurity-Modul einzubeziehen
sed -i '/ModSecurity/! s%^[^#]*./configure \(.*nginx.*\)%#./configure \1\n./configure \1 --add-module=/tmp/ModSecurity-nginx%' install-nginx

# Füge eine Zeile zum Bereinigungsbereich hinzu
grep 'rm -fr /tmp/ModSecurity-nginx' install-nginx || sed -i 's%\(rm -fr.*/tmp/nginx.*\)%rm -fr /tmp/ModSecurity-nginx\n\1%' install-nginx

Beachten Sie, dass die für die Ausführung des install-nginx-Skripts zuständige Dockerfile beim Erstellen des Images ausgeführt wird. Das Image wird jedoch nur vom Discourse-Team erstellt, bevor es auf Docker Hub hochgeladen wird. Wenn der Discourse-Befehl ./launcher rebuild app ausgeführt wird, wird (falls Updates verfügbar sind) ein docker pull ausgelöst, der das neueste Discourse-Docker-Image von Docker Hub herunterlädt. Dies führt erneut nicht zu einem Neuaufbau des Images, zur Ausführung der Dockerfile oder zur Ausführung des oben geänderten install-nginx-Skripts.

Der einzige Weg (den ich kenne), um das aktualisierte install-nginx-Bash-Skript zur Ausführung zu bringen (das von der Dockerfile ausgeführt wird), besteht darin, dass Docker ein neues Image erstellt. Beispielsweise löst dies den Build eines neuen Images namens discourse_modsecurity aus – das unter Verwendung des lokal modifizierten install-nginx-Skripts erstellt wird:

docker build --tag 'discourse_modsecurity' /var/discourse/image/base/

Leider konnte ich keinen Weg finden, launcher anzuweisen, ein benutzerdefiniertes Image zu verwenden (die Angabe eines run-image verwendet das angegebene Image direkt, ohne die Vorlagen darauf auszuführen – wie es erforderlich ist, um nginx tatsächlich zu konfigurieren [anstatt nur zu installieren]). Daher ersetzen wir die im launcher-Skript definierte Variable image, um unser neues lokales Docker-Image namens discourse_modsecurity zu verwenden:

# Ersetze die Zeile "image="discourse/base:<version>" durch '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

Nun fügen wir eine neue Vorlagendatei hinzu, um unsere nginx-Konfigurationen so einzurichten, dass sie die erforderlichen ModSecurity-Dateien/Blöcke enthalten:

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, installiert aus dem Paket '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
```\n
Fügen Sie diese Vorlage (templates/web.modsecurity.template.yml) zum `templates`-Block der YAML-Konfigurationsdatei Ihrer App hinzu, sodass sie ungefähr so aussieht:

[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]#

Wenn Sie jetzt die Discourse-Docker-App neu aufbauen, wird das neue Docker-Image `discourse_modsecurity` mit nginx und ModSecurity verwendet, und nginx wird so konfiguriert, dass es das OWASP CRS nutzt.

/var/discourse/launcher rebuild app