nginx ModSecurity 설정 변경 사항을 launcher rebuild app 실행 사이에 성공적으로 유지하는 방법을 다음과 같이 공유합니다.
먼저, 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 스크립트를 실행하지 않습니다.
(위에서 수정된) 업데이트된 install-nginx bash 스크립트가 실행되도록(Dockerfile에 의해 실행됨) 트리거하는 유일한 방법(제가 아는 한)은 docker가 새로운 이미지를 빌드하도록 하는 것입니다. 예를 들어, 아래 명령은 docker가 discourse_modsecurity라는 이름의 새 이미지를 빌드하도록 트리거하며, 이 이미지는 로컬에서 수정된 install-nginx 스크립트를 사용하여 빌드됩니다:
docker build --tag 'discourse_modsecurity' /var/discourse/image/base/
불행히도, launcher가 커스텀 이미지를 사용하도록 지시하는 방법을 찾지 못했습니다(run-image를 지정하면 템플릿을 실행하지 않고 지정된 이미지를 직접 사용하므로, nginx를 실제로 구성[설치만 하는 것이 아님]하는 데 필요합니다). 따라서 launcher 스크립트에 정의된 image 변수를 대체하여 discourse_modsecurity라는 이름의 새 로컬 docker 이미지를 사용하도록 합니다.
# "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 이미지를 사용하게 되며, nginx가 OWASP CRS를 사용하도록 구성됩니다.
/var/discourse/launcher rebuild app