diff --git a/.drone.yml b/.drone.yml index ab3ead5..b0f6ba4 100644 --- a/.drone.yml +++ b/.drone.yml @@ -11,3 +11,8 @@ steps: image: bdebyl/yamllint command: - make lint-ci + +trigger: + event: + - pull_request + - push diff --git a/ansible/roles/http/defaults/main.yml b/ansible/roles/http/defaults/main.yml index 6cd2ba6..741c708 100644 --- a/ansible/roles/http/defaults/main.yml +++ b/ansible/roles/http/defaults/main.yml @@ -1,8 +1,31 @@ --- -ci_server_email: bastian@bdebyl.net -ci_server_name: ci.bdebyl.net - deps: [ certbot, - nginx + nginx, + nginx-mod-modsecurity ] + +nginx_dir: /etc/nginx +nginx_conf_dir: "{{ nginx_dir }}/conf" +modsec_rules_dir: "{{ nginx_conf_dir }}/rules" +modsec_crs_before_rule_conf: + "{{ modsec_rules_dir }}/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf" +modsec_crs_after_rule_conf: + "{{ modsec_rules_dir }}/REQUEST-999-EXCLUSION-RULES-AFTER-CRS.conf" + +ci_server_name: ci.bdebyl.net + +modsec_conf_url: + https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended + +modsec_unicode_url: + https://github.com/SpiderLabs/ModSecurity/raw/v3/master/unicode.mapping + +crs_setup_url: + https://github.com/coreruleset/coreruleset/raw/v3.4/dev/crs-setup.conf.example + +crs_before_url: + https://github.com/coreruleset/coreruleset/raw/v3.4/dev/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example + +crs_after_url: + https://github.com/coreruleset/coreruleset/raw/v3.4/dev/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example diff --git a/ansible/roles/http/files/nginx/modsec_includes.conf b/ansible/roles/http/files/nginx/modsec_includes.conf new file mode 100644 index 0000000..123966e --- /dev/null +++ b/ansible/roles/http/files/nginx/modsec_includes.conf @@ -0,0 +1,3 @@ +include modsecurity.conf +include conf/crs-setup.conf +include conf/rules/*.conf diff --git a/ansible/roles/http/files/nginx/nginx.conf b/ansible/roles/http/files/nginx/nginx.conf index fce002d..8fc5fbd 100644 --- a/ansible/roles/http/files/nginx/nginx.conf +++ b/ansible/roles/http/files/nginx/nginx.conf @@ -1,14 +1,17 @@ user http; worker_processes 1; -error_log /var/log/nginx/error.log; +load_module /usr/lib/nginx/modules/ngx_http_modsecurity_module.so; + +error_log /var/log/nginx/error.log info; events { worker_connections 1024; } http { - include mime.types; + include mime.types; + default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' @@ -18,6 +21,7 @@ http { access_log /var/log/nginx/access.log main; sendfile on; + server_tokens off; #tcp_nopush on; keepalive_timeout 65; @@ -25,6 +29,11 @@ http { gzip on; gzip_disable "mise6"; + client_body_buffer_size 1k; + client_header_buffer_size 1k; + client_max_body_size 2k; + large_client_header_buffers 2 1k; + add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; diff --git a/ansible/roles/http/tasks/main.yml b/ansible/roles/http/tasks/main.yml index 8558561..8f657d3 100644 --- a/ansible/roles/http/tasks/main.yml +++ b/ansible/roles/http/tasks/main.yml @@ -1,5 +1,6 @@ --- - import_tasks: deps.yml +- import_tasks: modsec.yml - import_tasks: http.yml - import_tasks: ssl.yml - import_tasks: cron.yml diff --git a/ansible/roles/http/tasks/modsec.yml b/ansible/roles/http/tasks/modsec.yml new file mode 100644 index 0000000..c549fc0 --- /dev/null +++ b/ansible/roles/http/tasks/modsec.yml @@ -0,0 +1,51 @@ +--- +- name: create nginx/conf directory + become: true + file: + path: "{{ item }}" + state: directory + owner: root + group: root + mode: 0644 + with_items: + - "{{ nginx_conf_dir }}" + - "{{ modsec_rules_dir }}" + tags: modsec + +- name: create modsec_includes.conf + become: true + copy: + src: files/nginx/modsec_includes.conf + dest: "{{ nginx_dir }}/modsec_includes.conf" + mode: 0644 + notify: restart_nginx + tags: modsec + +- name: fetch core rule set files for mod-security + become: true + get_url: + url: "{{ item.url }}" + dest: "{{ item.dest }}" + mode: 0644 + with_items: + - {"url": "{{ modsec_conf_url }}", + "dest": "{{ nginx_dir }}/modsecurity.conf"} + - {"url": "{{ modsec_unicode_url }}", + "dest": "{{ nginx_dir }}/unicode.mapping"} + - {"url": "{{ crs_setup_url }}", + "dest": "{{ nginx_conf_dir }}/crs-setup.conf"} + - {"url": "{{ crs_before_url }}", + "dest": "{{ modsec_crs_before_rule_conf }}"} + - {"url": "{{ crs_after_url }}", + "dest": "{{ modsec_crs_after_rule_conf }}"} + notify: restart_nginx + tags: modsec + +- name: activate mod-security + become: true + lineinfile: + path: /etc/nginx/modsecurity.conf + regexp: '^SecRuleEngine' + line: 'SecRuleEngine On' + notify: restart_nginx + tags: modsec diff --git a/ansible/roles/http/templates/nginx/sites/ci.bdebyl.net.https.conf.j2 b/ansible/roles/http/templates/nginx/sites/ci.bdebyl.net.https.conf.j2 index bdeb554..7aeee15 100644 --- a/ansible/roles/http/templates/nginx/sites/ci.bdebyl.net.https.conf.j2 +++ b/ansible/roles/http/templates/nginx/sites/ci.bdebyl.net.https.conf.j2 @@ -10,7 +10,7 @@ server { add_header Strict-Transport-Security max-age=6307200; add_header Allow "GET, POST, HEAD" always; - limit_except GET POST { deny all; } + #limit_except GET POST { deny all; } ssl_certificate /etc/letsencrypt/live/{{ ci_server_name }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ ci_server_name }}/privkey.pem; @@ -28,14 +28,17 @@ server { ssl_prefer_server_ciphers off; location / { - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; + modsecurity on; + modsecurity_rules_file {{ nginx_dir }}/modsec_includes.conf; - proxy_pass http://drone; - proxy_redirect off; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + + proxy_pass http://drone; + proxy_redirect off; proxy_http_version 1.1; - proxy_buffering off; + proxy_buffering off; chunked_transfer_encoding off; } diff --git a/ansible/vars/vault.yml b/ansible/vars/vault.yml index 1a512d4..6088c9d 100644 Binary files a/ansible/vars/vault.yml and b/ansible/vars/vault.yml differ