WIP
This commit is contained in:
1
ansible/roles/waf_install/.gitignore
vendored
Normal file
1
ansible/roles/waf_install/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/docs/
|
||||
146
ansible/roles/waf_install/README.md
Normal file
146
ansible/roles/waf_install/README.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Web Application Firewall
|
||||
|
||||
Ce rôle Ansible déploie un WAF basé sur Caddy, Coraza et les OWASP Core Security Rules.
|
||||
|
||||
## Principes
|
||||
|
||||
### Go
|
||||
|
||||
Caddy, Coraza, le module Coraza pour Caddy et l'outil `xcaddy` sont
|
||||
développés avec le langage Go.
|
||||
|
||||
L'outil `xcaddy` a besoin d'une version récente des outils de
|
||||
développement Go. C'est pourquoi le rôle installe Go depuis
|
||||
le site de téléchargement officiel et non via le gestionnaire
|
||||
de paquets de la distribution Linux.
|
||||
|
||||
Go est installé dans le répertoire `/usr/local/go-1.25.5/go` et
|
||||
un lien symbolique est créé de `/usr/local/bin/go` vers
|
||||
`/usr/local/go-1.25.5/go/bin/go`.
|
||||
|
||||
### Caddy
|
||||
|
||||
Caddy est un serveur Web et reverse proxy HTTP puissant et versatile.
|
||||
|
||||
Étant développé en Go, son déploiement prend la forme d'un simble
|
||||
binaire exécutable qui contient toutes les librairies requises. Ce
|
||||
programme est construit avec l'outil `xcaddy` puis copié dans le
|
||||
fichier `/usr/local/bin/caddy`. La ligne de commande utilisée pour
|
||||
construire ce binaire est enregsitrée dans le fichier
|
||||
`/usr/local/bin/.caddy.buil`.
|
||||
|
||||
Le fichier de configuration de caddy utilise le format `Caddyfile`.
|
||||
Il est généré automatiquement à partir des paramètres du rôle puis
|
||||
enregistré sous `/etc/caddy/Caddyfile`.
|
||||
|
||||
### Coraza
|
||||
|
||||
Coraza est directement inclus dans le binaire `caddy`
|
||||
|
||||
### Module Coraza pour Caddy
|
||||
|
||||
### xcaddy
|
||||
|
||||
qui permet de lier tous les modules Go requis
|
||||
pour le WAF
|
||||
|
||||
### Plugins OWASP CRS
|
||||
|
||||
(À ne pas confondre avec les plugins Coraza.)
|
||||
|
||||
Voir: https://github.com/coreruleset/plugin-registry
|
||||
|
||||
- name: "drupal-rule-exclusions"
|
||||
- name: "wordpress-rule-exclusions"
|
||||
- name: "nextcloud-rule-exclusions"
|
||||
- name: "dokuwiki-rule-exclusions"
|
||||
- name: "phpmyadmin-rule-exclusions"
|
||||
- name: "roundcube-rule-exclusions"
|
||||
- name: "sogo-rule-exclusions"
|
||||
|
||||
|
||||
## Paramètres du rôle Ansible
|
||||
|
||||
|
||||
|
||||
## TODO
|
||||
|
||||
Fonctionnalités déjà implémentées:
|
||||
|
||||
- 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
|
||||
- Redirect (SSL et www et autres)
|
||||
- Filtrage par:
|
||||
- adresses IP
|
||||
- réseaux IP
|
||||
- Antibot par:
|
||||
- défi JavaScript
|
||||
- Passive backend checks
|
||||
- Compression Gzip et zstd
|
||||
|
||||
|
||||
Fomctionnalités à ajouter:
|
||||
|
||||
- Active backend checks
|
||||
- Antibot par:
|
||||
- Cookie
|
||||
- Captcha
|
||||
- reCAPTCHA
|
||||
- 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
|
||||
- (ip:danmeuk-tor-exit, ua:mitchellkrogza-bad-user-agents, /etc/hapee-1.9/blacklist.acl)
|
||||
- Gestion CORS
|
||||
- Client cache
|
||||
- Proxy cache
|
||||
- Filtrage par pays
|
||||
- Compression Brotli
|
||||
- En-têtes de sécurité:
|
||||
- HSTS
|
||||
- CSP
|
||||
- X-Frame-Options
|
||||
- X-Content-Type-Options
|
||||
- Referrer Policy
|
||||
- Permissions Policy
|
||||
- Keep Headers
|
||||
- Cookie Flags
|
||||
- Custom headers
|
||||
- Reverse scan
|
||||
- Robots.txt (DarkVisitors API/Community Lists/Custom URLs/Manual Rules)
|
||||
- Sessions
|
||||
- Whitelist
|
||||
- Bad behavior
|
||||
- Auth
|
||||
- Anti DoDS
|
||||
- Greylist
|
||||
- HTML injection
|
||||
- Metrics (Elasticsearch + Metabase)
|
||||
- Static files et FastCGI pour PHP
|
||||
|
||||
|
||||
## Ressources
|
||||
|
||||
- [Documentation officielle Caddy](https://caddyserver.com/docs/)
|
||||
- [Site Officiel de Coraza](https://coraza.io)
|
||||
- [Coraza WAF Caddy module](https://github.com/corazawaf/coraza-caddy)
|
||||
- [Documentation AWOSP CRS](https://coreruleset.org/docs/)
|
||||
|
||||
Modules
|
||||
- []()
|
||||
- []()
|
||||
27
ansible/roles/waf_install/defaults/main.yml
Normal file
27
ansible/roles/waf_install/defaults/main.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
waf_install_go_version: "1.25.5"
|
||||
waf_install_xcaddy_version: "0.4.5"
|
||||
waf_install_caddy_version: "2.10.2"
|
||||
waf_install_coraza_caddy_version: "2.1.0" # Coraza v3.3.3
|
||||
waf_install_owasp_crs_version: "4.21.0"
|
||||
|
||||
# Cluster mode (e.g. with consul)
|
||||
waf_install_cluster: false
|
||||
|
||||
# Cf.: https://github.com/coreruleset/plugin-registry
|
||||
waf_install_crs_plugins:
|
||||
- name: "drupal-rule-exclusions"
|
||||
version: "1.0.0"
|
||||
- name: "wordpress-rule-exclusions"
|
||||
version: "1.2.0"
|
||||
- name: "nextcloud-rule-exclusions"
|
||||
version: "1.5.0"
|
||||
- name: "dokuwiki-rule-exclusions"
|
||||
version: "1.0.0"
|
||||
- name: "phpmyadmin-rule-exclusions"
|
||||
version: "1.0.0"
|
||||
- name: "roundcube-rule-exclusions"
|
||||
version: "1.0.4"
|
||||
provider: "EsadCetiner"
|
||||
- name: "sogo-rule-exclusions"
|
||||
version: "1.0.4"
|
||||
provider: "EsadCetiner"
|
||||
5
ansible/roles/waf_install/handlers/main.yml
Normal file
5
ansible/roles/waf_install/handlers/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- name: Restart Caddy
|
||||
ansible.builtin.service:
|
||||
name: "caddy"
|
||||
state: "restarted"
|
||||
daemon_reload: true
|
||||
47
ansible/roles/waf_install/tasks/install_plugin.yml
Normal file
47
ansible/roles/waf_install/tasks/install_plugin.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
- name: Download plugin {{ plugin.name }}
|
||||
ansible.builtin.get_url:
|
||||
url: "https://github.com/{{ plugin.provider | default('coreruleset') }}/{{ plugin.name }}-plugin/archive/refs/tags/v{{ plugin.version }}.tar.gz"
|
||||
dest: "/usr/local/src/"
|
||||
mode: "0644"
|
||||
register: "waf_install_plugin_downloaded"
|
||||
|
||||
- name: Deploy plugin {{ plugin.name }}
|
||||
# noqa: no-handler
|
||||
when: "waf_install_plugin_downloaded.changed"
|
||||
block:
|
||||
|
||||
- name: Get temp dir {{ plugin.name }}
|
||||
ansible.builtin.tempfile:
|
||||
state: "directory"
|
||||
register: "waf_install_temp_plugin_dir"
|
||||
|
||||
- name: Unarchive plugin {{ plugin.name }}
|
||||
ansible.builtin.unarchive:
|
||||
src: "/usr/local/src/{{ plugin.name }}-plugin-{{ plugin.version }}.tar.gz"
|
||||
dest: "{{ waf_install_temp_plugin_dir.path }}"
|
||||
remote_src: true
|
||||
|
||||
- name: Copy plugin files {{ plugin.name }}
|
||||
ansible.builtin.copy:
|
||||
src: "{{ waf_install_temp_plugin_dir.path }}/{{ plugin.name }}-plugin-{{ plugin.version }}/plugins/"
|
||||
dest: "/etc/caddy/plugins/"
|
||||
mode: "0644"
|
||||
# directory_mode: "0750"
|
||||
group: "caddy"
|
||||
remote_src: true
|
||||
notify:
|
||||
- "Reload Caddy"
|
||||
|
||||
# FIXME: bad hack, why is it required?
|
||||
- name: Adjust /etc/caddy/plugins permissions
|
||||
ansible.builtin.file:
|
||||
path: "/etc/caddy/plugins"
|
||||
state: "directory"
|
||||
group: "caddy"
|
||||
mode: "0750"
|
||||
|
||||
- name: Delete temp dir {{ plugin.name }}
|
||||
when: "waf_install_temp_plugin_dir.path is defined"
|
||||
ansible.builtin.file:
|
||||
path: "{{ waf_install_temp_plugin_dir.path }}"
|
||||
state: "absent"
|
||||
125
ansible/roles/waf_install/tasks/main.yml
Normal file
125
ansible/roles/waf_install/tasks/main.yml
Normal file
@@ -0,0 +1,125 @@
|
||||
- name: Remove packaged Go
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- "golang"
|
||||
state: "absent"
|
||||
autoremove: true
|
||||
purge: true
|
||||
|
||||
- name: Install requirements
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- "git"
|
||||
- "libnss3-tools"
|
||||
|
||||
- name: Create Go directory
|
||||
ansible.builtin.file:
|
||||
path: "/usr/local/go-{{ waf_install_go_version }}"
|
||||
state: "directory"
|
||||
mode: "0755"
|
||||
|
||||
- name: Install Go
|
||||
ansible.builtin.unarchive:
|
||||
src: "https://go.dev/dl/go{{ waf_install_go_version }}.linux-amd64.tar.gz"
|
||||
dest: "/usr/local/go-{{ waf_install_go_version }}"
|
||||
remote_src: true
|
||||
|
||||
- name: Link Go
|
||||
ansible.builtin.file:
|
||||
src: "/usr/local/go-{{ waf_install_go_version }}/go/bin/go"
|
||||
dest: "/usr/local/bin/go"
|
||||
state: "link"
|
||||
|
||||
# FIXME: no .deb
|
||||
- name: Install xcaddy
|
||||
when: |
|
||||
'xcaddy' not in ansible_facts.packages
|
||||
or ansible_facts.packages['xcaddy'][0]['version'] != waf_install_xcaddy_version
|
||||
ansible.builtin.apt:
|
||||
deb: "{{ waf_install_xcaddy_download }}/v{{ waf_install_xcaddy_version }}/xcaddy_{{ waf_install_xcaddy_version }}_linux_amd64.deb"
|
||||
force: true
|
||||
|
||||
- name: Create Caddy build command
|
||||
ansible.builtin.set_fact:
|
||||
waf_install_build_command: >
|
||||
xcaddy build v{{ waf_install_caddy_version }}
|
||||
{% if waf_install_cluster %} --with github.com/pteich/caddy-tlsconsul{% endif %}
|
||||
--with github.com/corazawaf/coraza-caddy/v2@v{{ waf_install_coraza_caddy_version }}
|
||||
--with github.com/mholt/caddy-ratelimit
|
||||
--with github.com/steffenbusch/caddy-bot-barrier
|
||||
--output /usr/local/bin/caddy
|
||||
|
||||
- name: Test Caddy version
|
||||
ansible.builtin.copy:
|
||||
dest: "/usr/local/bin/.caddy.build"
|
||||
content: "{{ waf_install_build_command }}"
|
||||
mode: "0644"
|
||||
register: waf_install_test_caddy_version
|
||||
|
||||
- name: Build Caddy
|
||||
# noqa: no-handler
|
||||
when: "waf_install_test_caddy_version.changed"
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ waf_install_build_command }}"
|
||||
creates: "/usr/local/bin/caddy"
|
||||
notify:
|
||||
- "Restart Caddy"
|
||||
|
||||
- name: Create caddy system group
|
||||
ansible.builtin.group:
|
||||
name: "caddy"
|
||||
system: true
|
||||
|
||||
- name: Create caddy system user
|
||||
ansible.builtin.user:
|
||||
name: "caddy"
|
||||
group: "caddy"
|
||||
groups: ["ssl-cert"]
|
||||
password: "!"
|
||||
system: true
|
||||
home: "/opt/caddy"
|
||||
|
||||
- name: Create caddy config directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: "directory"
|
||||
group: "caddy"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "/etc/caddy"
|
||||
- "/etc/caddy/plugins"
|
||||
- "/etc/caddy/sites"
|
||||
|
||||
- name: Create caddy log dir
|
||||
ansible.builtin.file:
|
||||
path: "/var/log/caddy"
|
||||
state: "directory"
|
||||
group: "caddy"
|
||||
mode: "0770"
|
||||
|
||||
- name: Install OWASP CRS
|
||||
ansible.builtin.unarchive:
|
||||
src: "https://github.com/coreruleset/coreruleset/archive/refs/tags/v{{ waf_install_owasp_crs_version }}.tar.gz"
|
||||
dest: "/etc/caddy"
|
||||
group: "caddy"
|
||||
remote_src: true
|
||||
|
||||
- name: Install plugins
|
||||
loop: "{{ waf_install_crs_plugins }}"
|
||||
loop_control:
|
||||
loop_var: "plugin"
|
||||
ansible.builtin.include_tasks: "install_plugin.yml"
|
||||
|
||||
- name: Deploy caddy service file
|
||||
ansible.builtin.template:
|
||||
src: "templates/caddy.service"
|
||||
dest: "/etc/systemd/system/caddy.service"
|
||||
mode: "0644"
|
||||
notify:
|
||||
- "Restart Caddy"
|
||||
|
||||
- name: Enable Caddy
|
||||
ansible.builtin.service:
|
||||
name: "caddy"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
20
ansible/roles/waf_install/templates/caddy.service
Normal file
20
ansible/roles/waf_install/templates/caddy.service
Normal file
@@ -0,0 +1,20 @@
|
||||
[Unit]
|
||||
Description=Caddy
|
||||
Documentation=https://caddyserver.com/docs/
|
||||
After=network.target network-online.target
|
||||
Requires=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
User=caddy
|
||||
Group=caddy
|
||||
ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile
|
||||
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force
|
||||
TimeoutStopSec=15s
|
||||
LimitNOFILE=1048576
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
1
ansible/roles/waf_install/vars/main.yml
Normal file
1
ansible/roles/waf_install/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
waf_install_xcaddy_download: "https://github.com/caddyserver/xcaddy/releases/download"
|
||||
Reference in New Issue
Block a user