diff --git a/README.md b/README.md index 4095ad6..33768d1 100644 --- a/README.md +++ b/README.md @@ -67,11 +67,11 @@ Voir: https://github.com/coreruleset/plugin-registry Fonctionnalités déjà implémentées: +- OWASP CRS - Multisite (cavec configuration des CRS par site) - Redirection vers nom canonique - Rediction HTTP vers HTTPS -- Certificats SSL (autmotiques via Let's Encrypt et customs) -- OWASP CRS +- Certificats SSL (automatiques via Let's Encrypt et customs) - Redirect (SSL et www et autres) - Filtrage par: - adresses IP @@ -80,7 +80,19 @@ Fonctionnalités déjà implémentées: - défi JavaScript - Passive backend checks - Compression Gzip et zstd +- Mieux tester le configuration des CRS +- Mode détection sans blocage +- Filtrage par: + - méthode HTTP +Urgemment: + +- Connexion à consul +- ACL consul +- Changement de format de configuration: Caddyfile -> JSON +- Lire doc. config JSON de Caddy +- Renommer tous les répertoires/utilisateurs caddy -> byow +- Collection Ansible Fomctionnalités à ajouter: @@ -92,16 +104,12 @@ Fomctionnalités à ajouter: - hCaptcha - Turnstile - mCaptcha -- Changement de format de configuration: Caddyfile -> JSON - Mise en œuvre d'un cluster Redis (ou Consul) pour le partage de informations entre les WAF d'un cluster -- Mieux tester le configuration des CRS -- Mode détection sans blocage - Filtrage par: - rDNS - DNSBL - ASN - User-Agent (robots, crawlers, IA bots) - - méthode HTTP - taille - URI patterns - pays @@ -127,7 +135,7 @@ Fomctionnalités à ajouter: - Whitelist - Bad behavior - Auth -- Anti DoDS +- Anti DDoS - Greylist - HTML injection - Metrics (Elasticsearch + Metabase) @@ -140,6 +148,7 @@ Fomctionnalités à ajouter: - [Site Officiel de Coraza](https://coraza.io) - [Coraza WAF Caddy module](https://github.com/corazawaf/coraza-caddy) - [Documentation AWOSP CRS](https://coreruleset.org/docs/) +- https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v3.x) Modules - []() diff --git a/ansible/play-config.yml b/ansible/play-config.yml index c6849e0..90f1220 100644 --- a/ansible/play-config.yml +++ b/ansible/play-config.yml @@ -18,7 +18,7 @@ - "IP:{{ ansible_default_ipv4.address }}" waf_config_sites: "{{ common.sites }}" roles: - - "certs" + - "local_ca_certs" - "waf_config" tags: - "waf" diff --git a/ansible/play-main.yml b/ansible/play-main.yml index b64855a..f3f181f 100644 --- a/ansible/play-main.yml +++ b/ansible/play-main.yml @@ -72,7 +72,7 @@ consul_servers: ["waf1", "waf2", "waf3"] consul_server: true consul_services: - - name: "in" + - name: "www" port: 443 check_http: "http://{{ ansible_default_ipv4.address }}:80/" # keepalived_script_user: "caddy" diff --git a/ansible/roles/consul/defaults/main.yml b/ansible/roles/consul/defaults/main.yml index 2c7af57..83bd2c0 100644 --- a/ansible/roles/consul/defaults/main.yml +++ b/ansible/roles/consul/defaults/main.yml @@ -18,3 +18,5 @@ consul_bind_addr: "{{ ansible_default_ipv4.address }}" consul_advertise_addr: "{{ ansible_default_ipv4.address }}" consul_default_check_interval: "15s" consul_default_check_timeout: "2s" + +consul_acl_bootstraped: false diff --git a/ansible/roles/consul/tasks/main.yml b/ansible/roles/consul/tasks/main.yml index 7d49906..7a61dc7 100644 --- a/ansible/roles/consul/tasks/main.yml +++ b/ansible/roles/consul/tasks/main.yml @@ -77,12 +77,30 @@ enabled: true daemon_reload: true +# consul acl bootstrap -format=json +# { +# "CreateIndex": 1042, +# "ModifyIndex": 1042, +# "AccessorID": "50f8bfb6-b259-4c08-f9aa-2dc0eeb08e99", +# "SecretID": "b7f16a8a-0b4f-4661-fea2-f79d95dd011b", +# "Description": "Bootstrap Token (Global Management)", +# "Policies": [ +# { +# "ID": "00000000-0000-0000-0000-000000000001", +# "Name": "global-management" +# } +# ], +# "Local": false, +# "CreateTime": "2026-01-19T18:41:13.294800712+03:00", +# "Hash": "X2AgaFhnQGRhSSF/h0m6qpX1wj/HJWbyXcxkEM/5GrY=" +# } + - name: Register services to consul loop: "{{ consul_services }}" community.general.consul_agent_service: name: "{{ item.name }}" service_port: "{{ item.port }}" - tags: ="{{ item.tags | default([]) }}" + tags: "{{ item.tags | default([]) }}" - name: Register HTTP checks to consul loop: "{{ consul_services }}" diff --git a/ansible/roles/consul/templates/config.json b/ansible/roles/consul/templates/config.json index a03f47d..4634975 100644 --- a/ansible/roles/consul/templates/config.json +++ b/ansible/roles/consul/templates/config.json @@ -23,6 +23,18 @@ "performance": { "raft_multiplier": 1 }, + "acl": { + "enabled": true, +{% if not consul_acl_bootstraped %} + "default_policy": "allow", +{% else %} + "default_policy": "deny", + "tokens": { + "agent": "FIXME" + }, +{% endif %} + "down_policy": "extend-cache" + }, {% endif %} "retry_join": ["{{ consul_servers | join('", "') }}"] } diff --git a/ansible/roles/waf_config/defaults/main.yml b/ansible/roles/waf_config/defaults/main.yml index 7443a56..14ce3e5 100644 --- a/ansible/roles/waf_config/defaults/main.yml +++ b/ansible/roles/waf_config/defaults/main.yml @@ -35,12 +35,14 @@ waf_config_defaults: custom_key_file: "" plugins: [] + # caddy-ratelimit rate_events: 1000 rate_window: "1m" + # steffenbusch/caddy-bot-barrier bot_barrier: false - # CRS defaults + # corazawaf/coraza-caddy log_only: false paranoia_level: 1 detection_paranoia_level: null @@ -178,6 +180,8 @@ waf_config_defaults: - "/x-method-override/" - "/x-middleware-subrequest/" - "/expect/" + restricted_headers_extended: + - "/accept-charset/" allowed_http_versions: - "HTTP/1.0" - "HTTP/1.1" @@ -185,8 +189,6 @@ waf_config_defaults: - "HTTP/2.0" - "HTTP/3" - "HTTP/3.0" - restricted_headers_extended: - - "/accept-charset/" allowed_request_content_type_charset: - "|utf-8|" - "|iso-8859-1|" diff --git a/ansible/roles/waf_config/templates/Caddyfile b/ansible/roles/waf_config/templates/Caddyfile index 25d21a1..3c04643 100644 --- a/ansible/roles/waf_config/templates/Caddyfile +++ b/ansible/roles/waf_config/templates/Caddyfile @@ -1,5 +1,4 @@ { -# storage redis grace_period 10s order coraza_waf first {% if waf_config_email | default(None) != None %} @@ -15,7 +14,7 @@ log waf { format json include "http.handlers.waf" - output file /var/log/caddy/waf.log + output stdout } {% if waf_config_local_ca_name | default(None) != None %} @@ -117,6 +116,28 @@ ` } + # Cf. https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html + header { +# Access-Control-Allow-Origin "https://secure.gravatar.com" + Content-Security-Policy "upgrade-insecure-requests; worker-src 'self' blob:; connect-src 'self'; media-src 'self'; img-src 'self' data: https://secure.gravatar.com/avatar/; font-src 'self' data:; style-src 'self' 'unsafe-inline'; object-src 'none'; frame-src 'self' blob:; child-src 'self'; form-action 'self'; frame-ancestors 'self'" +# Cross-Origin-Embedder-Policy "require-corp" + Cross-Origin-Opener-Policy "same-origin" + Cross-Origin-Resource-Policy "same-site" + Permissions-Policy "geolocation=(), camera=(), microphone=(), interest-cohort=()" + Referrer-Policy "strict-origin-when-cross-origin" + Strict-Transport-Security "max-age=2635200; includeSubDomains" + X-Content-Type-Options "nosniff" + X-Frame-Options "DENY" + X-Robots-Tag "noindex, nofollow" + ?Content-Type "text/html; charset=UTF-8" + >Set-Cookie "(.*)" "$1; SameSite=None; Secure;" + -Server + -Via + -X-Powered-By + -X-AspNet-Version + -X-AspNetMvc-Version + } + handle_errors 403 { header X-Blocked "true" respond "Your request was blocked." diff --git a/ansible/roles/wordpress/tasks/main.yml b/ansible/roles/wordpress/tasks/main.yml index de6d045..1382709 100644 --- a/ansible/roles/wordpress/tasks/main.yml +++ b/ansible/roles/wordpress/tasks/main.yml @@ -9,6 +9,10 @@ - "php-xml" - "php-mbstring" - "php-zip" + - "php-igbinary" + - "php-imagick" + - "php-intl" + - "php-apcu" - "zip" - name: Installation de wp-cli @@ -171,8 +175,9 @@ - name: Apply permissions when: "wordpress_create_master != None and wordpress_create_master == ansible_hostname" loop: - - "uploads" - "cache" + - "upgrade" + - "uploads" ansible.builtin.file: path: "/var/www/{{ wordpress_user }}/{{ wordpress_site }}/wp-content/{{ item }}/" owner: "{{ wordpress_user }}"