Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d22405d3b | |||
| 7fe5e3f1e5 | |||
| 91417f0e22 | |||
| 7a35ed33bc | |||
| 1260ffcac0 | |||
| 5eeb74d53e | |||
| f80735417b | |||
| 91f0e92014 | |||
| 58ecc8ef98 | |||
| 295b19aaa8 | |||
| b02fbe7117 | |||
| 00c1f607f8 | |||
| e3fc368704 | |||
| 06112d7009 | |||
| d04643955a | |||
| 33fa678a40 | |||
| 67cea2f19e | |||
| b4f98a207d | |||
| c826b3a390 | |||
| 72107cb471 | |||
| 501cfacfe6 | |||
| df6f913d95 | |||
| 943423143d | |||
| bbec8d35c5 | |||
| eecd5e9972 | |||
| 34f208b75b | |||
| 34e401784b | |||
| 17a52312dd | |||
| a42ab66d4f | |||
| 99e240eec0 | |||
| 4aee70b07a | |||
| 24034ad284 | |||
| d08e03e28c | |||
| d8ab34029f | |||
| ac36dec16c | |||
| c6edcc9bc5 | |||
| df42ad6e88 | |||
| a213a75f72 | |||
| d7b6e468d7 | |||
| 7e4857f762 | |||
| ccdabff0be | |||
| cbef8530f0 | |||
| 798e748a1f | |||
| 43af15bd4d | |||
| 10a7ac53aa | |||
| 6f17dcffc6 | |||
| 4e30f03c0e | |||
| 5257840222 | |||
| 52cd626f82 | |||
| 78be28c68e | |||
| 1208e5092b | |||
| 717aaca7eb | |||
| 98506f9803 | |||
| 309a0cd971 | |||
| c5b82f5b48 | |||
| 82a299bf33 | |||
| a717aa378f | |||
| e40cd47d28 | |||
| a7bcb0728b | |||
| bc46ae6ada |
@@ -1,8 +1,10 @@
|
|||||||
name: Publish collection to Galagxy
|
name: Publish collection to Galaxy
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
branches:
|
branches:
|
||||||
- main
|
- "main"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
@@ -10,10 +12,22 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- run: apt install -y pipx
|
- run: apt install -y pipx
|
||||||
- run: pipx install ansible==12.3.0 --include-deps
|
- run: pipx install ansible==12.3.0 --include-deps
|
||||||
- run: pipx inject ansible ansible-lint --include-apps
|
- run: pipx install yq
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
- run: cd seb4itik/byow && /root/.local/bin/ansible-galaxy collection build
|
- run: >
|
||||||
- uses: actions/upload-artifact@v3
|
cd seb4itik/byow &&
|
||||||
with:
|
VER=$(yq -r '.version' galaxy.yml) &&
|
||||||
name: seb4itik-byow
|
/root/.local/bin/ansible-galaxy collection build &&
|
||||||
path: /workspace/itik/bgwaf/seb4itik/byow/seb4itik-byow-0.1.2.tar.gz
|
/root/.local/bin/ansible-galaxy collection publish seb4itik-byow-${VER}.tar.gz --api-key ${{ secrets.GALAXY_API_KEY }}
|
||||||
|
# - uses: actions/gitea-upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# path: /workspace/itik/bgwaf/seb4itik/byow/seb4itik-byow-0.1.2.tar.gz
|
||||||
|
- name: Push artifacts
|
||||||
|
run: |
|
||||||
|
GITEA_REPO_OWNER=$(echo $GITEA_REPOSITORY | cut -d"/" -f1) && \
|
||||||
|
GITEA_REPO_NAME=$(echo $GITEA_REPOSITORY | cut -d"/" -f2) && \
|
||||||
|
curl \
|
||||||
|
-X PUT \
|
||||||
|
-H "Authorization: token ${{ secrets.CI_GITEA_PACKAGES_TOKEN }}" \
|
||||||
|
--upload-file seb4itik-byow-${VER}.tar.gz \
|
||||||
|
$GITEA_SERVER_URL/api/packages/${GITEA_REPO_OWNER}/generic/${GITEA_REPO_NAME}/${GITEA_SHA}/seb4itik-byow-${VER}.tar.gz
|
||||||
|
|||||||
@@ -2,4 +2,6 @@
|
|||||||
|
|
||||||
A WAF _à la carte_.
|
A WAF _à la carte_.
|
||||||
|
|
||||||
|
**WARNING: This is still a work in process**
|
||||||
|
|
||||||
See [seb4itik/byow/README.md](seb4itik/byow/README.md)
|
See [seb4itik/byow/README.md](seb4itik/byow/README.md)
|
||||||
|
|||||||
@@ -2,30 +2,6 @@ linux:
|
|||||||
vars:
|
vars:
|
||||||
ansible_user: "root"
|
ansible_user: "root"
|
||||||
|
|
||||||
debian13:
|
ubuntu2404lts:
|
||||||
vars:
|
|
||||||
ansible_python_interpreter: "/usr/bin/python3.13"
|
|
||||||
|
|
||||||
ubuntu24:
|
|
||||||
vars:
|
vars:
|
||||||
ansible_python_interpreter: "/usr/bin/python3.12"
|
ansible_python_interpreter: "/usr/bin/python3.12"
|
||||||
|
|
||||||
waf:
|
|
||||||
hosts:
|
|
||||||
waf1:
|
|
||||||
waf2:
|
|
||||||
waf3:
|
|
||||||
|
|
||||||
mysql:
|
|
||||||
hosts:
|
|
||||||
sql1:
|
|
||||||
|
|
||||||
nfs:
|
|
||||||
hosts:
|
|
||||||
nfs1:
|
|
||||||
|
|
||||||
www:
|
|
||||||
hosts:
|
|
||||||
www1:
|
|
||||||
www2:
|
|
||||||
www3:
|
|
||||||
|
|||||||
36
example/ansible/inventory/multipass.py
Executable file
36
example/ansible/inventory/multipass.py
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
|
out = subprocess.run(["multipass", "list", "--format=json"], capture_output=True)
|
||||||
|
if out.returncode != 0:
|
||||||
|
print(f"ERR executing multipass list: {out.returncode}")
|
||||||
|
sys.exit(out.returncode)
|
||||||
|
|
||||||
|
instances = json.loads(out.stdout)
|
||||||
|
ret = {
|
||||||
|
"_meta": {"hostvars": {}},
|
||||||
|
"linux": {"hosts": []}
|
||||||
|
}
|
||||||
|
|
||||||
|
for instance in instances['list']:
|
||||||
|
if instance['state'] != "Running":
|
||||||
|
continue
|
||||||
|
|
||||||
|
release = instance['release'].replace(' ', '').replace('.', '').lower()
|
||||||
|
if release not in ret:
|
||||||
|
ret[release] = {"hosts": []}
|
||||||
|
|
||||||
|
group = re.search('^[a-z]+', instance['name']).group()
|
||||||
|
if group not in ret:
|
||||||
|
ret[group] = {"hosts": []}
|
||||||
|
|
||||||
|
ret['_meta']['hostvars'][instance['name']] = {"ansible_host": instance['ipv4'][0] }
|
||||||
|
ret['linux']['hosts'].append(instance['name'])
|
||||||
|
ret[release]['hosts'].append(instance['name'])
|
||||||
|
ret[group]['hosts'].append(instance['name'])
|
||||||
|
|
||||||
|
print(json.dumps(ret))
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
multipass list --format=json |jq '{
|
|
||||||
_meta: {hostvars: [.list[] | {(.name): {ansible_host: .ipv4[0]}}] | add},
|
|
||||||
linux: {hosts: [.list[].name]},
|
|
||||||
ubuntu24: {hosts: [.list[].name]},
|
|
||||||
}'
|
|
||||||
@@ -17,6 +17,11 @@
|
|||||||
- "DNS:{{ ansible_hostname }}"
|
- "DNS:{{ ansible_hostname }}"
|
||||||
- "IP:{{ ansible_default_ipv4.address }}"
|
- "IP:{{ ansible_default_ipv4.address }}"
|
||||||
caddy_config_only: true
|
caddy_config_only: true
|
||||||
|
caddy_consul: true
|
||||||
|
caddy_consul: true
|
||||||
|
caddy_consul_delegate_to: "waf1"
|
||||||
|
caddy_consul_admin_token: "{{ secrets.consul.bootstrap_secret }}"
|
||||||
|
caddy_consul_aes_key: "{{ secrets.caddy.storage_consul_aes_key }}"
|
||||||
caddy_sites: "{{ common.sites }}"
|
caddy_sites: "{{ common.sites }}"
|
||||||
roles:
|
roles:
|
||||||
- "local_ca_certs"
|
- "local_ca_certs"
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
vars:
|
vars:
|
||||||
caddy_debug: true
|
caddy_debug: true
|
||||||
caddy_config_only: true
|
caddy_config_only: true
|
||||||
|
caddy_consul: true
|
||||||
|
caddy_consul_delegate_to: "waf1"
|
||||||
|
caddy_consul_admin_token: "{{ secrets.consul.bootstrap_secret }}"
|
||||||
|
caddy_consul_aes_key: "{{ secrets.caddy.storage_consul_aes_key }}"
|
||||||
caddy_sites: "{{ common.sites }}"
|
caddy_sites: "{{ common.sites }}"
|
||||||
roles:
|
roles:
|
||||||
- "caddy"
|
- "caddy"
|
||||||
|
|||||||
@@ -24,6 +24,20 @@
|
|||||||
tags:
|
tags:
|
||||||
- "local_ca"
|
- "local_ca"
|
||||||
|
|
||||||
|
- name: Proxy server
|
||||||
|
hosts: proxy
|
||||||
|
gather_facts: false
|
||||||
|
vars_files:
|
||||||
|
- "vars/common.yml"
|
||||||
|
- "vars/secrets.yml"
|
||||||
|
vars:
|
||||||
|
squid_authorized_networks:
|
||||||
|
- "{{ ansible_default_ipv4.network }}/24"
|
||||||
|
roles:
|
||||||
|
- "squid"
|
||||||
|
tags:
|
||||||
|
- "proxy"
|
||||||
|
|
||||||
- name: Common
|
- name: Common
|
||||||
hosts: all
|
hosts: all
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
@@ -31,6 +45,7 @@
|
|||||||
- "vars/common.yml"
|
- "vars/common.yml"
|
||||||
- "vars/secrets.yml"
|
- "vars/secrets.yml"
|
||||||
vars:
|
vars:
|
||||||
|
common_proxy_server: "{{ hostvars['proxy1'].ansible_default_ipv4.address }}:3128"
|
||||||
common_default_packages:
|
common_default_packages:
|
||||||
- "net-tools"
|
- "net-tools"
|
||||||
- "htop"
|
- "htop"
|
||||||
@@ -59,6 +74,8 @@
|
|||||||
- cn: "server.{{ common.consul.datacenter }}.{{ common.consul.domain }}"
|
- cn: "server.{{ common.consul.datacenter }}.{{ common.consul.domain }}"
|
||||||
domains:
|
domains:
|
||||||
- "DNS:server.{{ common.consul.datacenter }}.{{ common.consul.domain }}"
|
- "DNS:server.{{ common.consul.datacenter }}.{{ common.consul.domain }}"
|
||||||
|
- "DNS:{{ ansible_fqdn }}"
|
||||||
|
- "DNS:{{ ansible_hostname }}"
|
||||||
# Sites
|
# Sites
|
||||||
- cn: "test.lab"
|
- cn: "test.lab"
|
||||||
domains:
|
domains:
|
||||||
@@ -66,13 +83,16 @@
|
|||||||
- "DNS:{{ ansible_fqdn }}"
|
- "DNS:{{ ansible_fqdn }}"
|
||||||
- "DNS:{{ ansible_hostname }}"
|
- "DNS:{{ ansible_hostname }}"
|
||||||
- "IP:{{ ansible_default_ipv4.address }}"
|
- "IP:{{ ansible_default_ipv4.address }}"
|
||||||
|
consul_server: true
|
||||||
consul_domain: "{{ common.consul.domain }}"
|
consul_domain: "{{ common.consul.domain }}"
|
||||||
consul_datacenter: "{{ common.consul.datacenter }}"
|
consul_datacenter: "{{ common.consul.datacenter }}"
|
||||||
|
consul_bootstrap_secret: "{{ secrets.consul.bootstrap_secret }}"
|
||||||
consul_secret_key: "{{ secrets.consul.secret_key }}"
|
consul_secret_key: "{{ secrets.consul.secret_key }}"
|
||||||
consul_servers: ["waf1", "waf2", "waf3"]
|
consul_servers: ["waf1", "waf2", "waf3"]
|
||||||
consul_server: true
|
consul_ui_secret_id: "{{ secrets.consul.ui_secret }}"
|
||||||
consul_services:
|
consul_services:
|
||||||
- name: "www"
|
- name: "www"
|
||||||
|
address: "{{ ansible_default_ipv4.address }}"
|
||||||
port: 443
|
port: 443
|
||||||
check_http: "http://{{ ansible_default_ipv4.address }}:80/"
|
check_http: "http://{{ ansible_default_ipv4.address }}:80/"
|
||||||
# keepalived_script_user: "byow"
|
# keepalived_script_user: "byow"
|
||||||
@@ -98,21 +118,27 @@
|
|||||||
unbound_stub_zones:
|
unbound_stub_zones:
|
||||||
- name: "{{ common.consul.datacenter }}.{{ common.consul.domain }}"
|
- name: "{{ common.consul.datacenter }}.{{ common.consul.domain }}"
|
||||||
stub_to: "127.0.0.1@8600"
|
stub_to: "127.0.0.1@8600"
|
||||||
|
caddy_consul: true
|
||||||
|
caddy_consul_delegate_to: "waf1"
|
||||||
|
caddy_consul_admin_token: "{{ secrets.consul.bootstrap_secret }}"
|
||||||
|
caddy_consul_aes_key: "{{ secrets.caddy.storage_consul_aes_key }}"
|
||||||
|
caddy_consul_client_cert: "/etc/ssl/certs/server.lab.itik.fr.crt"
|
||||||
|
caddy_consul_client_key: "/etc/ssl/private/server.lab.itik.fr.key"
|
||||||
caddy_sites: "{{ common.sites }}"
|
caddy_sites: "{{ common.sites }}"
|
||||||
ovh_ldp_cluster: "gra2.logs.ovh.com"
|
# ovh_ldp_cluster: "gra2.logs.ovh.com"
|
||||||
ovh_ldp_token: ¨{{ secrets.ovh_ldp.token }}
|
# ovh_ldp_token: "{{ secrets.ovh_ldp.token }}"
|
||||||
roles:
|
roles:
|
||||||
- "local_ca_certs"
|
- "local_ca_certs"
|
||||||
- "consul"
|
- "consul"
|
||||||
- "caddy"
|
- "caddy"
|
||||||
# - "keepalived"
|
# - "keepalived"
|
||||||
- "unbound"
|
- "unbound"
|
||||||
- "ovh_ldp"
|
# - "ovh_ldp"
|
||||||
tags:
|
tags:
|
||||||
- "waf"
|
- "waf"
|
||||||
|
|
||||||
- name: MySQL servers
|
- name: MySQL servers
|
||||||
hosts: mysql
|
hosts: bdd
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
vars_files:
|
vars_files:
|
||||||
- "vars/common.yml"
|
- "vars/common.yml"
|
||||||
@@ -136,22 +162,11 @@
|
|||||||
password: "{{ secrets.wordpress.mysql_password }}"
|
password: "{{ secrets.wordpress.mysql_password }}"
|
||||||
priv: "wordpress.*:ALL"
|
priv: "wordpress.*:ALL"
|
||||||
host: "{{ ansible_default_ipv4.network }}/255.255.255.0"
|
host: "{{ ansible_default_ipv4.network }}/255.255.255.0"
|
||||||
consul_domain: "{{ common.consul.domain }}"
|
|
||||||
consul_datacenter: "{{ common.consul.datacenter }}"
|
|
||||||
consul_secret_key: "{{ secrets.consul.secret_key }}"
|
|
||||||
consul_key_file: "/etc/ssl/private/{{ ansible_fqdn }}.key"
|
|
||||||
consul_cert_file: "/etc/ssl/certs/{{ ansible_fqdn }}.crt"
|
|
||||||
consul_servers: ["waf1", "waf2", "waf3"]
|
|
||||||
consul_services:
|
|
||||||
- name: "test-lab-mysql"
|
|
||||||
port: 3306
|
|
||||||
check_tcp: "{{ ansible_default_ipv4.address }}:3306"
|
|
||||||
roles:
|
roles:
|
||||||
- "local_ca_certs"
|
- "local_ca_certs"
|
||||||
- "mysql"
|
- "mysql"
|
||||||
- "consul"
|
|
||||||
tags:
|
tags:
|
||||||
- "mysql"
|
- "bdd"
|
||||||
|
|
||||||
- name: NFS servers
|
- name: NFS servers
|
||||||
hosts: nfs
|
hosts: nfs
|
||||||
@@ -208,22 +223,11 @@
|
|||||||
wordpress_admin_email: "seb@itik.fr"
|
wordpress_admin_email: "seb@itik.fr"
|
||||||
wordpress_themes: ["twentytwentyfive"]
|
wordpress_themes: ["twentytwentyfive"]
|
||||||
wordpress_active_theme: "twentytwentyfive"
|
wordpress_active_theme: "twentytwentyfive"
|
||||||
wordpress_db_host: "sql1"
|
wordpress_db_host: "bdd1"
|
||||||
wordpress_db_pass: "{{ secrets.wordpress.mysql_password }}"
|
wordpress_db_pass: "{{ secrets.wordpress.mysql_password }}"
|
||||||
consul_domain: "{{ common.consul.domain }}"
|
|
||||||
consul_datacenter: "{{ common.consul.datacenter }}"
|
|
||||||
consul_secret_key: "{{ secrets.consul.secret_key }}"
|
|
||||||
consul_key_file: "/etc/ssl/private/{{ ansible_fqdn }}.key"
|
|
||||||
consul_cert_file: "/etc/ssl/certs/{{ ansible_fqdn }}.crt"
|
|
||||||
consul_servers: ["waf1", "waf2", "waf3"]
|
|
||||||
consul_services:
|
|
||||||
- name: "test-lab-www"
|
|
||||||
port: 80
|
|
||||||
check_http: "http://localhost:80/"
|
|
||||||
roles:
|
roles:
|
||||||
- "local_ca_certs"
|
- "local_ca_certs"
|
||||||
- "nfs_client"
|
- "nfs_client"
|
||||||
- "wordpress"
|
- "wordpress"
|
||||||
- "consul"
|
|
||||||
tags:
|
tags:
|
||||||
- "www"
|
- "www"
|
||||||
|
|||||||
@@ -18,22 +18,28 @@ common:
|
|||||||
- "http://www1"
|
- "http://www1"
|
||||||
- "http://www2"
|
- "http://www2"
|
||||||
- "http://www3"
|
- "http://www3"
|
||||||
|
proxy_lb_policy: "random"
|
||||||
|
proxy_active_checks: true
|
||||||
|
proxy_active_checks_status: "301"
|
||||||
|
proxy_passive_checks: false
|
||||||
custom_cert: true
|
custom_cert: true
|
||||||
custom_cert_file: "/etc/ssl/certs/test.lab.crt"
|
custom_cert_file: "/etc/ssl/certs/test.lab.crt"
|
||||||
custom_cert_key_file: "/etc/ssl/private/test.lab.key"
|
custom_cert_key_file: "/etc/ssl/private/test.lab.key"
|
||||||
filter_whitelist: ["10.60.117.1"]
|
rate_limit_events: 10
|
||||||
|
rate_limit_window: "1m"
|
||||||
|
# filter_whitelist: ["10.60.117.1"]
|
||||||
crs_plugins:
|
crs_plugins:
|
||||||
- "wordpress-rule-exclusions"
|
- "wordpress-rule-exclusions"
|
||||||
crs_exceptions:
|
# crs_exceptions:
|
||||||
# Cf. https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v3.x)
|
# Cf. https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v3.x)
|
||||||
# before_request:
|
# before_request:
|
||||||
# - 'SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" "id:1,nolog,ctl:ruleRemoveById=932260"'
|
# - 'SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" "id:1,nolog,ctl:ruleRemoveById=932260"'
|
||||||
after_response:
|
# after_response:
|
||||||
- 'SecRuleUpdateTargetById 932260 "!ARGS:tag-name"'
|
# - 'SecRuleUpdateTargetById 932260 "!ARGS:tag-name"'
|
||||||
header_cross_origin_embedder_policy: "unsafe-none"
|
header_cross_origin_embedder_policy: "unsafe-none"
|
||||||
header_content_security_policy:
|
header_content_security_policy:
|
||||||
worker-src: "'self' blob:"
|
worker-src: "'self' blob:"
|
||||||
img-src: "'self' data: https://secure.gravatar.com/avatar/"
|
img-src: "'self' data: https://secure.gravatar.com/avatar/ https://s.w.org/images/"
|
||||||
font-src: "'self' data:"
|
font-src: "'self' data:"
|
||||||
script-src: "'self' 'unsafe-eval'"
|
script-src: "'self' 'unsafe-eval'"
|
||||||
script-src-elem: "'self' 'unsafe-inline'"
|
script-src-elem: "'self' 'unsafe-inline'"
|
||||||
|
|||||||
@@ -2,3 +2,5 @@ users:
|
|||||||
- name: "root"
|
- name: "root"
|
||||||
ssh_authorized_keys:
|
ssh_authorized_keys:
|
||||||
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOHAAcWecBuLe9gt/NLC5b3DCl68knbwCFcHrH9wPPTk seb@itik.fr"
|
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOHAAcWecBuLe9gt/NLC5b3DCl68knbwCFcHrH9wPPTk seb@itik.fr"
|
||||||
|
package_update: false
|
||||||
|
package_upgrade: false
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
vms = {
|
vms = {
|
||||||
waf1 = {},
|
proxy1 = {
|
||||||
waf2 = {},
|
disk = "20g"
|
||||||
waf3 = {},
|
},
|
||||||
sql1 = {},
|
waf1 = {
|
||||||
|
cpus = 4
|
||||||
|
},
|
||||||
|
waf2 = {
|
||||||
|
cpus = 4
|
||||||
|
},
|
||||||
|
waf3 = {
|
||||||
|
cpus = 4
|
||||||
|
},
|
||||||
|
bdd1 = {},
|
||||||
nfs1 = {},
|
nfs1 = {},
|
||||||
www1 = {},
|
www1 = {},
|
||||||
www2 = {},
|
www2 = {},
|
||||||
|
|||||||
@@ -69,11 +69,11 @@ Voir: https://github.com/coreruleset/plugin-registry
|
|||||||
|
|
||||||
Fonctionnalités déjà implémentées:
|
Fonctionnalités déjà implémentées:
|
||||||
|
|
||||||
- Déploiement et configuration avec Ansible
|
- Déploiement et configuration avec une collection Ansible
|
||||||
- Serveurs transient
|
- Serveurs transient
|
||||||
- VIP (avec Keepalived)
|
- VIP (avec Keepalived)
|
||||||
- DNS dynamique (via Nomad)
|
- DNS dynamique (via Consul)
|
||||||
- Cluster via Nomad
|
- Cluster via Consul
|
||||||
- OWASP CRS
|
- OWASP CRS
|
||||||
- Multisite (avec configuration complète des CRS par site)
|
- Multisite (avec configuration complète des CRS par site)
|
||||||
- Alias avec redirection optionnelle vers nom canonique
|
- Alias avec redirection optionnelle vers nom canonique
|
||||||
@@ -105,18 +105,15 @@ Fonctionnalités déjà implémentées:
|
|||||||
- Collecte des logs via OVH LDP
|
- Collecte des logs via OVH LDP
|
||||||
- Whitelist
|
- Whitelist
|
||||||
- Static files et FastCGI pour PHP (NON, par design !)
|
- Static files et FastCGI pour PHP (NON, par design !)
|
||||||
|
- Authorizations (NON, par design !)
|
||||||
Urgemment:
|
- CORS
|
||||||
|
|
||||||
- Connexion à consul, ACL consul
|
|
||||||
- Collection Ansible
|
|
||||||
- Revérifier gestion CORS
|
|
||||||
- Active backend checks
|
|
||||||
- Correction de la collecte des logs via OVH LDP
|
|
||||||
|
|
||||||
Fomctionnalités à ajouter:
|
|
||||||
|
|
||||||
- Rate limiting distribué
|
- Rate limiting distribué
|
||||||
|
|
||||||
|
Fonctionnalités à ajouter:
|
||||||
|
|
||||||
|
- version de crs-setup.conf en fonction de la version des OWASP CRS
|
||||||
|
- option "api: true" for activating API default settings
|
||||||
|
- Antivirus
|
||||||
- Antibot par:
|
- Antibot par:
|
||||||
- Cookie
|
- Cookie
|
||||||
- Captcha
|
- Captcha
|
||||||
@@ -133,17 +130,24 @@ Fomctionnalités à ajouter:
|
|||||||
- (ip:danmeuk-tor-exit, ua:mitchellkrogza-bad-user-agents)
|
- (ip:danmeuk-tor-exit, ua:mitchellkrogza-bad-user-agents)
|
||||||
- Client cache
|
- Client cache
|
||||||
- Proxy cache
|
- Proxy cache
|
||||||
|
- Random WAF signatures
|
||||||
- Compression Brotli
|
- Compression Brotli
|
||||||
- Reverse scan
|
- Reverse scan
|
||||||
- Robots.txt (DarkVisitors API/Community Lists/Custom URLs/Manual Rules)
|
- Robots.txt (DarkVisitors API/Community Lists/Custom URLs/Manual Rules)
|
||||||
- Gestion des sessions
|
- Gestion des sessions
|
||||||
- Bad behavior (via Caddy events ?)
|
- Bad behavior (via Caddy events ?)
|
||||||
- Authentification
|
- Authentification
|
||||||
|
- cf. https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
|
||||||
|
- avec vérification force du mot de passe (cf. CdC Essor)
|
||||||
|
- avec test mot de passe moins un caractère
|
||||||
|
- avec test mot de passe comprommis
|
||||||
- Anti DDoS
|
- Anti DDoS
|
||||||
- Greylist
|
- Greylist
|
||||||
|
- HTML Sanitization
|
||||||
- HTML injection
|
- HTML injection
|
||||||
- Metrics (Elasticsearch + Metabase)
|
- Metrics (Elasticsearch + Metabase)
|
||||||
- Crowdsec
|
- Crowdsec
|
||||||
|
- Stream support
|
||||||
- Caddy as internal CA
|
- Caddy as internal CA
|
||||||
- https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list
|
- https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list
|
||||||
|
|
||||||
@@ -156,9 +160,17 @@ Fomctionnalités à ajouter:
|
|||||||
- [Documentation AWOSP CRS](https://coreruleset.org/docs/)
|
- [Documentation AWOSP CRS](https://coreruleset.org/docs/)
|
||||||
- https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v3.x)
|
- https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v3.x)
|
||||||
|
|
||||||
Modules
|
- (1) https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
|
||||||
- []()
|
- (2) https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Strict_Transport_Security_Cheat_Sheet.html
|
||||||
- []()
|
- https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Cookie_Theft_Mitigation_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Credential_Stuffing_Prevention_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html
|
||||||
|
- https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html
|
||||||
|
|
||||||
|
|
||||||
### Installation d'Ansible avec pipx
|
### Installation d'Ansible avec pipx
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace: "seb4itik"
|
namespace: "seb4itik"
|
||||||
name: "byow"
|
name: "byow"
|
||||||
version: "0.1.2"
|
version: "0.2.1"
|
||||||
readme: "README.md"
|
readme: "README.md"
|
||||||
authors:
|
authors:
|
||||||
- "S. Namèche <sebastien@itik.fr>"
|
- "S. Namèche <sebastien@itik.fr>"
|
||||||
|
|||||||
@@ -1,41 +1,36 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
class FilterModule(object):
|
|
||||||
def filters(self):
|
|
||||||
return {
|
|
||||||
'dict2str': self.dict2str
|
|
||||||
}
|
|
||||||
|
|
||||||
def dict2str(self, d, sep1='=', sep2=';', sep3=''):
|
DOCUMENTATION = r"""
|
||||||
return sep2.join(
|
|
||||||
[ str(k) + (sep1+str(v) if v!=None and v!='' else '') for k, v in d.items() ]
|
|
||||||
) + sep3
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = """
|
|
||||||
name: dict2str
|
name: dict2str
|
||||||
author: Sébastien Namèche (@seb4itik)
|
short_description: This filter transforms a flat dict into a string using 4 separators.
|
||||||
version_added: "0.1.1"
|
version_added: "0.1.1"
|
||||||
short_description: This filter transforms a flat dict into a string using 3 separators.
|
author: Sébastien Namèche (@seb4itik)
|
||||||
description:
|
description:
|
||||||
- If my_dict is {one: "un", two: "deux", three: "trois"}, then:
|
- If my_dict is {one: "un", two: "deux", three: "trois"}, then:
|
||||||
- {{ my_dict | dict2str(sep1=' is ', sep2=', ', sep3='.') }}
|
- {{ my_dict | dict2str(sep1=' is ', sep2=', ', sep3='.') }}
|
||||||
- will produce:
|
- will produce:
|
||||||
- "one is un, two is deux, three is trois."
|
- "one is un, two is deux, three is trois."
|
||||||
options:
|
options:
|
||||||
|
_input:
|
||||||
|
description: A flat dict.
|
||||||
|
type: dict
|
||||||
|
elements: str, int, bool
|
||||||
|
required: true
|
||||||
|
sep0:
|
||||||
|
description: Unique initial separator at the beginning of string.
|
||||||
|
type: str
|
||||||
|
default: ""
|
||||||
sep1:
|
sep1:
|
||||||
description:
|
description: Separator between each key and value pairs of the dict.
|
||||||
- separator between each key and value pairs of the dict
|
|
||||||
type: str
|
type: str
|
||||||
default: "="
|
default: "="
|
||||||
sep2:
|
sep2:
|
||||||
description:
|
description: Separator between key/value pairs of the dict that has been combined with sep1.
|
||||||
- separator between key/value pairs of the dict that has been combined with sep1
|
|
||||||
type: str
|
type: str
|
||||||
default: ";"
|
default: ";"
|
||||||
sep3:
|
sep3:
|
||||||
description:
|
description: Unique final separator at the end of string.
|
||||||
- unique final separator at the end of string
|
|
||||||
type: str
|
type: str
|
||||||
default: ""
|
default: ""
|
||||||
notes:
|
notes:
|
||||||
@@ -43,9 +38,22 @@ DOCUMENTATION = """
|
|||||||
- sep2 will not be used.
|
- sep2 will not be used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
|
||||||
data:
|
RETURN = r"""
|
||||||
|
_value:
|
||||||
type: str
|
type: str
|
||||||
description:
|
description:
|
||||||
- String representating the dict using provided separators.
|
- String representating the dict using provided separators.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'dict2str': self.dict2str
|
||||||
|
}
|
||||||
|
|
||||||
|
def dict2str(self, d, sep0='', sep1='=', sep2=';', sep3=''):
|
||||||
|
return sep0 + sep2.join(
|
||||||
|
[ str(k) + (sep1+str(v) if v!=None and v!='' else '') for k, v in d.items() ]
|
||||||
|
) + sep3
|
||||||
|
|||||||
52
seb4itik/byow/plugins/filter/listadddel.py
Normal file
52
seb4itik/byow/plugins/filter/listadddel.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
|
||||||
|
DOCUMENTATION = r"""
|
||||||
|
name: listadddel
|
||||||
|
short_description: This filter add and remove items to/from a list.
|
||||||
|
version_added: "0.2.2"
|
||||||
|
author: Sébastien Namèche (@seb4itik)
|
||||||
|
description:
|
||||||
|
- If my_list is ["un", "deux", "trois"], then:
|
||||||
|
- {{ my_list | listadddel(["quatre", "cinq"], ["un"]) }}
|
||||||
|
- will produce:
|
||||||
|
- ["deux", "trois", "quatre", "cinq"]
|
||||||
|
options:
|
||||||
|
_input:
|
||||||
|
description: A list of strings.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: true
|
||||||
|
add:
|
||||||
|
description: A list of string to add to _input.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
default: []
|
||||||
|
delete:
|
||||||
|
description: A list of string to remove from _input.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
default: []
|
||||||
|
notes:
|
||||||
|
- delete is tronger than add. If the string is present in both delete and
|
||||||
|
add, it will not be in returned list.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
RETURN = r"""
|
||||||
|
_value:
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
description:
|
||||||
|
- List of strings with new and removed elements.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'listadddel': self.listadddel
|
||||||
|
}
|
||||||
|
|
||||||
|
def listadddel(self, l, add=[], delete=[]):
|
||||||
|
return [e for e in l+add if e not in delete]
|
||||||
@@ -1,36 +1,59 @@
|
|||||||
# Defaults
|
# Several instances of the WAF can be deployed onto the same host if their
|
||||||
caddy_config_only: false
|
# names are different and they bind to different ports/interfaces. These
|
||||||
caddy_debug: false
|
# instances may use different versions of Go, xcaddy, Caddy, and Coraza.
|
||||||
|
caddy_my_name: "mywaf"
|
||||||
caddy_http_port: 80
|
caddy_http_port: 80
|
||||||
caddy_https_port: 443
|
caddy_https_port: 443
|
||||||
caddy_default_bind: ""
|
caddy_default_bind: null
|
||||||
|
|
||||||
caddy_version: "2.10.2"
|
# If true, will not install software, just deploy Caddy and OWASP CRS
|
||||||
caddy_go_version: "1.25.6"
|
# configuration files.
|
||||||
caddy_xcaddy_version: "0.4.5"
|
caddy_config_only: false
|
||||||
caddy_coraza_caddy_version: "2.1.0" # Coraza v3.3.3
|
|
||||||
caddy_owasp_crs_versions: ["4.22.0"]
|
|
||||||
|
|
||||||
caddy_my_name: "mywaf"
|
# Debug will go to /var/log/<caddy_my_name>/debug.log.
|
||||||
caddy_system_user: "{{ caddy_my_name }}"
|
caddy_debug: false
|
||||||
caddy_system_group: "{{ caddy_my_name }}"
|
|
||||||
caddy_home_dir: "/opt/{{ caddy_my_name }}"
|
|
||||||
caddy_config_dir: "/etc/{{ caddy_my_name }}"
|
|
||||||
caddy_log_dir: "/var/log/{{ caddy_my_name }}"
|
|
||||||
|
|
||||||
# Required for Let's Encrypt auto certificates
|
# Required for Let's Encrypt auto certificates.
|
||||||
caddy_email: null
|
caddy_email: null
|
||||||
|
|
||||||
# If a custom CA root have to be used
|
# If a custom CA root have to be used.
|
||||||
caddy_ca_root: null
|
caddy_ca_root: null
|
||||||
|
|
||||||
|
# For using a Consul cluster.
|
||||||
|
caddy_consul: false
|
||||||
|
caddy_consul_server: "{{ ansible_fqdn }}:8501"
|
||||||
|
caddy_consul_delegate_to: null # Required, Consul host for running Consul commands
|
||||||
|
caddy_consul_admin_token: null # Required
|
||||||
|
caddy_consul_aes_key: null # Required, 32 characters
|
||||||
|
caddy_consul_client_cert: null # Required
|
||||||
|
caddy_consul_client_key: null # Required
|
||||||
|
|
||||||
|
# Accound id and license key are required if a site use Geoip filtering.
|
||||||
# See: https://dev.maxmind.com/geoip/updating-databases/
|
# See: https://dev.maxmind.com/geoip/updating-databases/
|
||||||
caddy_geoip_account_id: null
|
caddy_geoip_account_id: null
|
||||||
caddy_geoip_license_key: null
|
caddy_geoip_license_key: null
|
||||||
caddy_geoip_edition_ids: "GeoLite2-ASN,GeoLite2-Country,GeoLite2-City"
|
caddy_geoip_edition_ids: "GeoLite2-ASN,GeoLite2-Country,GeoLite2-City"
|
||||||
caddy_geoip_update_frequency: 86400 # In seconds
|
caddy_geoip_update_frequency: 86400 # In seconds
|
||||||
|
|
||||||
|
# Sotware versions
|
||||||
|
caddy_version: "2.10.2"
|
||||||
|
caddy_go_version: "1.25.6"
|
||||||
|
caddy_xcaddy_version: "0.4.5"
|
||||||
|
caddy_coraza_caddy_version: "v2@v2.1.0" # Coraza v3.3.3
|
||||||
|
# Different sites can use different versions of OWASP CRS
|
||||||
|
caddy_owasp_crs_versions: ["4.23.0"]
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
caddy_binary: "/usr/local/bin/{{ caddy_my_name }}"
|
||||||
|
caddy_system_user: "{{ caddy_my_name }}"
|
||||||
|
caddy_system_group: "{{ caddy_my_name }}"
|
||||||
|
caddy_home_dir: "/opt/{{ caddy_my_name }}"
|
||||||
|
caddy_config_dir: "/etc/{{ caddy_my_name }}"
|
||||||
|
caddy_crs_plugins_dir: "{{ caddy_config_dir }}/crs-plugins"
|
||||||
|
caddy_sites_dir: "{{ caddy_config_dir }}/sites"
|
||||||
|
caddy_log_dir: "/var/log/{{ caddy_my_name }}"
|
||||||
|
|
||||||
|
# OWASP CRS plugins that will can be actived per site.
|
||||||
# Cf.: https://github.com/coreruleset/plugin-registry
|
# Cf.: https://github.com/coreruleset/plugin-registry
|
||||||
caddy_crs_plugins:
|
caddy_crs_plugins:
|
||||||
- name: "drupal-rule-exclusions"
|
- name: "drupal-rule-exclusions"
|
||||||
@@ -52,15 +75,16 @@ caddy_crs_plugins:
|
|||||||
provider: "EsadCetiner"
|
provider: "EsadCetiner"
|
||||||
|
|
||||||
|
|
||||||
# For each site, mandatories parameters
|
# Sites
|
||||||
caddy_sites: []
|
caddy_sites: []
|
||||||
# - id: ""
|
# - id: "" # Mandatory: short id for the site (for site specific directories and files)
|
||||||
# name: ""
|
# name: "" # Mandatory: canonical domain name
|
||||||
# paths:
|
# paths: # Mandatory: targets for the reverse proxy
|
||||||
# - path: "" (default "*")
|
# - path: "" # Optionnal: path of the request, default "*"
|
||||||
# addrs: (minimum 1 required)
|
# addrs: # Mandatory: upstreams
|
||||||
# - ""
|
# - "" # Mandatory: URL of the upstream, minimum 1 required
|
||||||
|
|
||||||
|
|
||||||
# Will be merged with caddy_global_sites_defaults
|
# For overriding default global parameters. Will be merged with
|
||||||
|
# caddy_global_sites_defaults (in vars/main.yml).
|
||||||
caddy_my_sites_defaults: {}
|
caddy_my_sites_defaults: {}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
- name: Reload systemd
|
||||||
|
ansible.builtin.service:
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
- name: Restart Caddy
|
- name: Restart Caddy
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
name: "{{ caddy_my_name }}"
|
name: "{{ caddy_my_name }}"
|
||||||
state: "restarted"
|
state: "restarted"
|
||||||
|
|
||||||
# - name: Update GeoIP databases
|
|
||||||
# ansible.builtin.command:
|
|
||||||
# cmd: "/usr/bin/geoipupdate"
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
- name: Create sites config directories
|
- name: Create sites config directories
|
||||||
loop: "{{ caddy_sites }}"
|
loop: "{{ caddy_sites }}"
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ caddy_config_dir }}/sites/{{ item.id }}"
|
path: "{{ caddy_sites_dir }}/{{ item.id }}"
|
||||||
state: "directory"
|
state: "directory"
|
||||||
group: "{{ caddy_system_group }}"
|
group: "{{ caddy_system_group }}"
|
||||||
mode: "0750"
|
mode: "0750"
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
loop_var: "site"
|
loop_var: "site"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: "templates/coraza.conf"
|
src: "templates/coraza.conf"
|
||||||
dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/coraza.conf"
|
dest: "{{ caddy_sites_dir }}/{{ site.id }}/coraza.conf"
|
||||||
group: "{{ caddy_system_group }}"
|
group: "{{ caddy_system_group }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
notify:
|
notify:
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
loop_var: "site"
|
loop_var: "site"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: "templates/crs-setup.conf"
|
src: "templates/crs-setup.conf"
|
||||||
dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/crs-setup.conf"
|
dest: "{{ caddy_sites_dir }}/{{ site.id }}/crs-setup.conf"
|
||||||
group: "{{ caddy_system_group }}"
|
group: "{{ caddy_system_group }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
notify:
|
notify:
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
loop_var: "site"
|
loop_var: "site"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: "templates/exclusions-request-before.conf"
|
src: "templates/exclusions-request-before.conf"
|
||||||
dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-request-before.conf"
|
dest: "{{ caddy_sites_dir }}/{{ site.id }}/exclusions-request-before.conf"
|
||||||
group: "{{ caddy_system_group }}"
|
group: "{{ caddy_system_group }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
notify:
|
notify:
|
||||||
@@ -52,16 +52,7 @@
|
|||||||
loop_var: "site"
|
loop_var: "site"
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: "templates/exclusions-response-after.conf"
|
src: "templates/exclusions-response-after.conf"
|
||||||
dest: "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-response-after.conf"
|
dest: "{{ caddy_sites_dir }}/{{ site.id }}/exclusions-response-after.conf"
|
||||||
group: "{{ caddy_system_group }}"
|
|
||||||
mode: "0640"
|
|
||||||
notify:
|
|
||||||
- "Restart Caddy"
|
|
||||||
|
|
||||||
- name: Generate Caddyfile
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: "templates/Caddyfile"
|
|
||||||
dest: "{{ caddy_config_dir }}/Caddyfile"
|
|
||||||
group: "{{ caddy_system_group }}"
|
group: "{{ caddy_system_group }}"
|
||||||
mode: "0640"
|
mode: "0640"
|
||||||
notify:
|
notify:
|
||||||
@@ -76,18 +67,17 @@
|
|||||||
notify:
|
notify:
|
||||||
- "Restart Caddy"
|
- "Restart Caddy"
|
||||||
|
|
||||||
# - name: Generate GeoIP config file
|
- name: Generate Caddyfile
|
||||||
# when: "caddy_geoip_account_id != None and caddy_geoip_license_key != None"
|
ansible.builtin.template:
|
||||||
# ansible.builtin.template:
|
src: "templates/Caddyfile"
|
||||||
# src: "templates/GeoIP.conf"
|
dest: "{{ caddy_config_dir }}/Caddyfile"
|
||||||
# dest: "/etc/GeoIP.conf"
|
group: "{{ caddy_system_group }}"
|
||||||
# mode: "0640"
|
mode: "0640"
|
||||||
# notify:
|
notify:
|
||||||
# - "Update GeoIP databases"
|
- "Restart Caddy"
|
||||||
|
|
||||||
- name: Enable and start Caddy
|
- name: Enable and start Caddy
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
name: "{{ caddy_my_name }}"
|
name: "{{ caddy_my_name }}"
|
||||||
state: "started"
|
state: "started"
|
||||||
enabled: true
|
enabled: true
|
||||||
daemon_reload: true
|
|
||||||
|
|||||||
47
seb4itik/byow/roles/caddy/tasks/caddy_consul.yml
Normal file
47
seb4itik/byow/roles/caddy/tasks/caddy_consul.yml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
- name: Create consul policy for Caddy TLS and rate limit
|
||||||
|
delegate_to: "{{ caddy_consul_delegate_to }}"
|
||||||
|
run_once: true
|
||||||
|
community.general.consul_policy:
|
||||||
|
token: "{{ caddy_consul_admin_token }}"
|
||||||
|
name: "caddy"
|
||||||
|
rules: |
|
||||||
|
key_prefix "caddy-{{ caddy_my_name }}-tls" {
|
||||||
|
policy = "write"
|
||||||
|
}
|
||||||
|
key_prefix "caddy-{{ caddy_my_name }}-rl" {
|
||||||
|
policy = "write"
|
||||||
|
}
|
||||||
|
session_prefix "" {
|
||||||
|
policy = "write"
|
||||||
|
}
|
||||||
|
node_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
agent_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Create/retrieve Consul Caddy accessor_id
|
||||||
|
ansible.builtin.shell:
|
||||||
|
executable: "/usr/bin/bash"
|
||||||
|
cmd: |
|
||||||
|
set -o pipefail
|
||||||
|
if test -f /root/.consul_caddy_accessor_id; then
|
||||||
|
echo OK
|
||||||
|
else
|
||||||
|
uuidgen > /root/.consul_caddy_accessor_id
|
||||||
|
echo CHANGED
|
||||||
|
fi
|
||||||
|
cat /root/.consul_caddy_accessor_id
|
||||||
|
register: "consul_out_caddy_accessor_id"
|
||||||
|
changed_when: "consul_out_caddy_accessor_id.stdout_lines[0] == 'CHANGED'"
|
||||||
|
|
||||||
|
- name: Create/retrieve consul token
|
||||||
|
delegate_to: "{{ caddy_consul_delegate_to }}"
|
||||||
|
community.general.consul_token:
|
||||||
|
token: "{{ caddy_consul_admin_token }}"
|
||||||
|
accessor_id: "{{ consul_out_caddy_accessor_id.stdout_lines[1] }}"
|
||||||
|
description: "Caddy {{ caddy_my_name }} {{ ansible_fqdn }}"
|
||||||
|
policies:
|
||||||
|
- name: "caddy"
|
||||||
|
register: "caddy_out_consul_token"
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
- "git"
|
- "git"
|
||||||
- "libnss3-tools"
|
- "libnss3-tools"
|
||||||
- "ssl-cert"
|
- "ssl-cert"
|
||||||
# - "geoipupdate"
|
|
||||||
|
|
||||||
- name: Create Go directory
|
- name: Create Go directory
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -16,6 +15,9 @@
|
|||||||
ansible.builtin.unarchive:
|
ansible.builtin.unarchive:
|
||||||
src: "https://go.dev/dl/go{{ caddy_go_version }}.linux-amd64.tar.gz"
|
src: "https://go.dev/dl/go{{ caddy_go_version }}.linux-amd64.tar.gz"
|
||||||
dest: "/usr/local/go-{{ caddy_go_version }}"
|
dest: "/usr/local/go-{{ caddy_go_version }}"
|
||||||
|
creates: "/usr/local/go-{{ caddy_go_version }}/bin/go"
|
||||||
|
extra_opts:
|
||||||
|
- "--strip-components=1"
|
||||||
remote_src: true
|
remote_src: true
|
||||||
|
|
||||||
- name: Create xcaddy directory
|
- name: Create xcaddy directory
|
||||||
@@ -28,6 +30,7 @@
|
|||||||
ansible.builtin.unarchive:
|
ansible.builtin.unarchive:
|
||||||
src: "https://github.com/caddyserver/xcaddy/releases/download/v{{ caddy_xcaddy_version }}/xcaddy_{{ caddy_xcaddy_version }}_linux_amd64.tar.gz"
|
src: "https://github.com/caddyserver/xcaddy/releases/download/v{{ caddy_xcaddy_version }}/xcaddy_{{ caddy_xcaddy_version }}_linux_amd64.tar.gz"
|
||||||
dest: "/usr/local/xcaddy-{{ caddy_xcaddy_version }}"
|
dest: "/usr/local/xcaddy-{{ caddy_xcaddy_version }}"
|
||||||
|
creates: "/usr/local/xcaddy-{{ caddy_xcaddy_version }}/xcaddy"
|
||||||
remote_src: true
|
remote_src: true
|
||||||
|
|
||||||
- name: Create Caddy build command
|
- name: Create Caddy build command
|
||||||
@@ -35,18 +38,18 @@
|
|||||||
caddy_build_command: >
|
caddy_build_command: >
|
||||||
/usr/local/xcaddy-{{ caddy_xcaddy_version }}/xcaddy build v{{ caddy_version }}
|
/usr/local/xcaddy-{{ caddy_xcaddy_version }}/xcaddy build v{{ caddy_version }}
|
||||||
--with github.com/pteich/caddy-tlsconsul
|
--with github.com/pteich/caddy-tlsconsul
|
||||||
--with github.com/corazawaf/coraza-caddy/v2@v{{ caddy_coraza_caddy_version }}
|
--with github.com/corazawaf/coraza-caddy/{{ caddy_coraza_caddy_version }}
|
||||||
--with github.com/mholt/caddy-ratelimit
|
--with github.com/mholt/caddy-ratelimit
|
||||||
--with github.com/steffenbusch/caddy-bot-barrier
|
--with github.com/steffenbusch/caddy-bot-barrier
|
||||||
--with github.com/zhangjiayin/caddy-geoip2
|
--with github.com/zhangjiayin/caddy-geoip2
|
||||||
--output /usr/local/bin/{{ caddy_my_name }}
|
--output {{ caddy_binary }}
|
||||||
|
|
||||||
- name: Remember and test Caddy version
|
- name: Remember and test Caddy version
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: "/usr/local/bin/.caddy.build"
|
dest: "/usr/local/bin/.caddy.{{ caddy_my_name }}.build"
|
||||||
content: >
|
content: >
|
||||||
XCADDY_WHICH_GO=/usr/local/go-{{ caddy_go_version }}/go/bin/go
|
XCADDY_WHICH_GO=/usr/local/go-{{ caddy_go_version }}/bin/go
|
||||||
{{ caddy_build_command }}"
|
{{ caddy_build_command }}
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
register: caddy_test_caddy_version
|
register: caddy_test_caddy_version
|
||||||
|
|
||||||
@@ -54,10 +57,10 @@
|
|||||||
# noqa: no-handler
|
# noqa: no-handler
|
||||||
when: "caddy_test_caddy_version.changed"
|
when: "caddy_test_caddy_version.changed"
|
||||||
environment:
|
environment:
|
||||||
XCADDY_WHICH_GO: "/usr/local/go-{{ caddy_go_version }}/go/bin/go"
|
XCADDY_WHICH_GO: "/usr/local/go-{{ caddy_go_version }}/bin/go"
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
cmd: "{{ caddy_build_command }}"
|
cmd: "{{ caddy_build_command }}"
|
||||||
creates: "/usr/local/bin/{{ caddy_my_name }}"
|
creates: "{{ caddy_binary }}"
|
||||||
notify:
|
notify:
|
||||||
- "Restart Caddy"
|
- "Restart Caddy"
|
||||||
|
|
||||||
@@ -73,39 +76,57 @@
|
|||||||
groups: ["ssl-cert"]
|
groups: ["ssl-cert"]
|
||||||
password: "!"
|
password: "!"
|
||||||
system: true
|
system: true
|
||||||
|
shell: "/usr/sbin/nologin"
|
||||||
home: "{{ caddy_home_dir }}"
|
home: "{{ caddy_home_dir }}"
|
||||||
|
|
||||||
- name: Create Caddy config directories
|
- name: Create Caddy directories
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ item }}"
|
path: "{{ item.path }}"
|
||||||
state: "directory"
|
state: "directory"
|
||||||
|
owner: "{{ item.owner | default('root') }}"
|
||||||
group: "{{ caddy_system_group }}"
|
group: "{{ caddy_system_group }}"
|
||||||
mode: "0750"
|
mode: "{{ item.mode | default('0750') }}"
|
||||||
loop:
|
loop:
|
||||||
- "{{ caddy_config_dir }}"
|
- path: "{{ caddy_config_dir }}"
|
||||||
- "{{ caddy_config_dir }}/crs-plugins"
|
- path: "{{ caddy_crs_plugins_dir }}"
|
||||||
- "{{ caddy_config_dir }}/sites"
|
- path: "{{ caddy_sites_dir }}"
|
||||||
|
- path: "{{ caddy_log_dir }}"
|
||||||
- name: Create Caddy log dir
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ caddy_log_dir }}"
|
|
||||||
state: "directory"
|
|
||||||
group: "{{ caddy_system_group }}"
|
|
||||||
mode: "0770"
|
mode: "0770"
|
||||||
|
- path: "{{ caddy_home_dir }}/geoip2"
|
||||||
|
owner: "{{ caddy_system_user }}"
|
||||||
|
|
||||||
- name: Install OWASP CRS
|
- name: Install OWASP CRS
|
||||||
loop: "{{ caddy_owasp_crs_versions }}"
|
loop: "{{ caddy_owasp_crs_versions }}"
|
||||||
ansible.builtin.unarchive:
|
ansible.builtin.unarchive:
|
||||||
src: "https://github.com/coreruleset/coreruleset/archive/refs/tags/v{{ item }}.tar.gz"
|
src: "https://github.com/coreruleset/coreruleset/archive/refs/tags/v{{ item }}.tar.gz"
|
||||||
dest: "{{ caddy_config_dir }}"
|
dest: "{{ caddy_config_dir }}"
|
||||||
|
creates: "{{ caddy_config_dir }}/coreruleset-{{ item }}/rules/"
|
||||||
group: "{{ caddy_system_group }}"
|
group: "{{ caddy_system_group }}"
|
||||||
remote_src: true
|
remote_src: true
|
||||||
|
|
||||||
- name: Install plugins
|
- name: Install plugins
|
||||||
loop: "{{ caddy_crs_plugins }}"
|
loop: "{{ caddy_crs_plugins }}"
|
||||||
loop_control:
|
ansible.builtin.unarchive:
|
||||||
loop_var: "plugin"
|
src: "https://github.com/{{ item.provider | default('coreruleset') }}/{{ item.name }}-plugin/archive/refs/tags/v{{ item.version }}.tar.gz"
|
||||||
ansible.builtin.include_tasks: "plugin_install.yml"
|
dest: "{{ caddy_crs_plugins_dir }}"
|
||||||
|
creates: "{{ caddy_crs_plugins_dir }}/{{ item.name }}-config.conf"
|
||||||
|
include:
|
||||||
|
- "*.conf"
|
||||||
|
extra_opts:
|
||||||
|
- "--strip-components=2"
|
||||||
|
- "--wildcards"
|
||||||
|
mode: "0644"
|
||||||
|
group: "{{ caddy_system_group }}"
|
||||||
|
remote_src: true
|
||||||
|
|
||||||
|
- name: Create plugins after config
|
||||||
|
loop: "{{ caddy_crs_plugins }}"
|
||||||
|
when: "not(item.has_after_config | default(false))"
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: ""
|
||||||
|
dest: "{{ caddy_crs_plugins_dir }}/{{ item.name }}-after.conf"
|
||||||
|
mode: "0644"
|
||||||
|
group: "{{ caddy_system_group }}"
|
||||||
|
|
||||||
- name: Deploy caddy service file
|
- name: Deploy caddy service file
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
@@ -113,4 +134,5 @@
|
|||||||
dest: "/etc/systemd/system/{{ caddy_my_name }}.service"
|
dest: "/etc/systemd/system/{{ caddy_my_name }}.service"
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
notify:
|
notify:
|
||||||
|
- "Reload systemd"
|
||||||
- "Restart Caddy"
|
- "Restart Caddy"
|
||||||
|
|||||||
@@ -2,5 +2,9 @@
|
|||||||
when: "not(caddy_config_only)"
|
when: "not(caddy_config_only)"
|
||||||
ansible.builtin.include_tasks: "caddy_install.yml"
|
ansible.builtin.include_tasks: "caddy_install.yml"
|
||||||
|
|
||||||
|
- name: Configure Consul for Caddy
|
||||||
|
when: "caddy_consul"
|
||||||
|
ansible.builtin.include_tasks: "caddy_consul.yml"
|
||||||
|
|
||||||
- name: Configure Caddy
|
- name: Configure Caddy
|
||||||
ansible.builtin.include_tasks: "caddy_config.yml"
|
ansible.builtin.include_tasks: "caddy_config.yml"
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
- 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: "caddy_plugin_downloaded"
|
|
||||||
|
|
||||||
- name: Deploy plugin {{ plugin.name }}
|
|
||||||
# noqa: no-handler
|
|
||||||
when: "caddy_plugin_downloaded.changed"
|
|
||||||
block:
|
|
||||||
|
|
||||||
- name: Get temp dir {{ plugin.name }}
|
|
||||||
ansible.builtin.tempfile:
|
|
||||||
state: "directory"
|
|
||||||
register: "caddy_temp_plugin_dir"
|
|
||||||
|
|
||||||
- name: Unarchive plugin {{ plugin.name }}
|
|
||||||
ansible.builtin.unarchive:
|
|
||||||
src: "/usr/local/src/{{ plugin.name }}-plugin-{{ plugin.version }}.tar.gz"
|
|
||||||
dest: "{{ caddy_temp_plugin_dir.path }}"
|
|
||||||
remote_src: true
|
|
||||||
|
|
||||||
- name: Copy plugin files {{ plugin.name }}
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "{{ caddy_temp_plugin_dir.path }}/{{ plugin.name }}-plugin-{{ plugin.version }}/plugins/"
|
|
||||||
dest: "{{ caddy_config_dir }}/crs-plugins/"
|
|
||||||
mode: "0644"
|
|
||||||
# directory_mode: "0750"
|
|
||||||
group: "{{ caddy_system_group }}"
|
|
||||||
remote_src: true
|
|
||||||
notify:
|
|
||||||
- "Restart Caddy"
|
|
||||||
|
|
||||||
- name: Create after config {{ plugin.name }}
|
|
||||||
when: "not(plugin.has_after_config | default(false))"
|
|
||||||
ansible.builtin.copy:
|
|
||||||
content: ""
|
|
||||||
dest: "{{ caddy_config_dir }}/crs-plugins/{{ plugin.name }}-after.conf"
|
|
||||||
mode: "0644"
|
|
||||||
group: "{{ caddy_system_group }}"
|
|
||||||
|
|
||||||
# FIXME: bad hack, why is it required?
|
|
||||||
- name: Adjust plugins diretory permissions
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ caddy_config_dir }}/crs-plugins"
|
|
||||||
state: "directory"
|
|
||||||
group: "{{ caddy_system_group }}"
|
|
||||||
mode: "0750"
|
|
||||||
|
|
||||||
- name: Delete temp dir {{ plugin.name }}
|
|
||||||
when: "caddy_temp_plugin_dir.path is defined"
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ caddy_temp_plugin_dir.path }}"
|
|
||||||
state: "absent"
|
|
||||||
@@ -1,18 +1,33 @@
|
|||||||
{
|
{
|
||||||
http_port {{ caddy_http_port }}
|
http_port {{ caddy_http_port }}
|
||||||
https_port {{ caddy_https_port }}
|
https_port {{ caddy_https_port }}
|
||||||
|
{% if caddy_default_bind != None %}
|
||||||
default_bind {{ caddy_default_bind }}
|
default_bind {{ caddy_default_bind }}
|
||||||
|
{% endif %}
|
||||||
order geoip2_vars first
|
order geoip2_vars first
|
||||||
order coraza_waf first
|
order coraza_waf first
|
||||||
admin off
|
admin off
|
||||||
persist_config off
|
persist_config off
|
||||||
|
|
||||||
|
{% if caddy_consul %}
|
||||||
|
storage consul {
|
||||||
|
address "{{ caddy_consul_server }}"
|
||||||
|
token "{{ caddy_out_consul_token.token.SecretID }}"
|
||||||
|
timeout 10
|
||||||
|
prefix "caddy-{{ caddy_my_name }}-tls"
|
||||||
|
value_prefix "{{ caddy_my_name }}"
|
||||||
|
aes_key "{{ caddy_consul_aes_key }}"
|
||||||
|
tls_enabled "true"
|
||||||
|
tls_insecure "false"
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if caddy_geoip_account_id != None and caddy_geoip_license_key != None %}
|
{% if caddy_geoip_account_id != None and caddy_geoip_license_key != None %}
|
||||||
geoip2 {
|
geoip2 {
|
||||||
accountId "{{ caddy_geoip_account_id }}"
|
accountId "{{ caddy_geoip_account_id }}"
|
||||||
licenseKey "{{ caddy_geoip_license_key }}"
|
licenseKey "{{ caddy_geoip_license_key }}"
|
||||||
databaseDirectory "{{ caddy_home_dir }}"
|
databaseDirectory "{{ caddy_home_dir }}/geoip2"
|
||||||
lockFile "{{ caddy_home_dir }}/.geoip2.lock"
|
lockFile "{{ caddy_home_dir }}/geoip2/.geoip2.lock"
|
||||||
editionID "{{ caddy_geoip_edition_ids }}"
|
editionID "{{ caddy_geoip_edition_ids }}"
|
||||||
updateUrl "https://updates.maxmind.com"
|
updateUrl "https://updates.maxmind.com"
|
||||||
updateFrequency {{ caddy_geoip_update_frequency }}
|
updateFrequency {{ caddy_geoip_update_frequency }}
|
||||||
@@ -38,22 +53,63 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
log waf {
|
log waf {
|
||||||
format json
|
format {{ caddy_sites_defaults.log_format }}
|
||||||
include "http.handlers.waf"
|
include "http.handlers.waf"
|
||||||
|
format append {
|
||||||
|
waf_id {{ caddy_my_name }}
|
||||||
|
}
|
||||||
|
{% if caddy_sites_defaults.log_to_file %}
|
||||||
output file {{ caddy_log_dir }}/waf.log
|
output file {{ caddy_log_dir }}/waf.log
|
||||||
|
{% else %}
|
||||||
|
output stdout
|
||||||
|
{% endif %}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 0=origin, 1=methods, 2=headers, 3=allow credentials, 4=max age, 5=vary, 6=expose headers
|
||||||
|
(cors) {
|
||||||
|
@match-cors-preflight-{args[0]} {
|
||||||
|
header Origin {args[0]}
|
||||||
|
method OPTIONS
|
||||||
|
}
|
||||||
|
header @match-cors-preflight-{args[0]} {
|
||||||
|
Access-Control-Allow-Origin "{args[0]}"
|
||||||
|
Access-Control-Allow-Methods "{args[1]}"
|
||||||
|
Access-Control-Allow-Headers "{args[2]}"
|
||||||
|
Access-Control-Allow-Credentials "{args[3]}"
|
||||||
|
Access-Control-Max-Age "{args[4]}"
|
||||||
|
Vary "{args[5]}"
|
||||||
|
}
|
||||||
|
handle @match-cors-preflight-{args[0]} {
|
||||||
|
respond "" 204
|
||||||
|
}
|
||||||
|
|
||||||
|
@match-cors-request-{args[0]} {
|
||||||
|
header Origin {args[0]}
|
||||||
|
not method OPTIONS
|
||||||
|
}
|
||||||
|
header @match-cors-request-{args[0]} {
|
||||||
|
>Access-Control-Allow-Origin "{args[0]}"
|
||||||
|
>Access-Control-Allow-Credentials "{args[3]}"
|
||||||
|
>Vary "{args[5]}"
|
||||||
|
>Access-Control-Expose-Headers "{args[6]}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(cors-deny) {
|
||||||
|
@cors-preflight-deny method OPTIONS
|
||||||
|
handle @cors-preflight-deny {
|
||||||
|
respond "" 403
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{% for site in caddy_sites %}
|
{% for site in caddy_sites %}
|
||||||
|
|
||||||
{% if (site.site_redirect_from_aliases | default(caddy_sites_defaults.site_redirect_from_aliases)) and (site.site_aliases | default([]) | length) > 0 %}
|
{% if (site.site_redirect_from_aliases | default(caddy_sites_defaults.site_redirect_from_aliases)) and (site.site_aliases | default([]) | length) > 0 %}
|
||||||
|
|
||||||
{{ site.site_aliases | join(', ') }} {
|
{{ site.site_aliases | join(', ') }} {
|
||||||
redir https://{{ site.name }}{uri}
|
redir https://{{ site.name }}{uri}
|
||||||
}
|
}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
{% for alias in site.site_aliases | default(caddy_sites_defaults.site_aliases) %}
|
{% for alias in site.site_aliases | default(caddy_sites_defaults.site_aliases) %}
|
||||||
{{ alias }},
|
{{ alias }},
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -67,19 +123,27 @@
|
|||||||
to {{ path.addrs | join(' ') }}
|
to {{ path.addrs | join(' ') }}
|
||||||
header_up X-Real-IP {remote}
|
header_up X-Real-IP {remote}
|
||||||
lb_policy {{ site.proxy_lb_policy | default(caddy_sites_defaults.proxy_lb_policy) }}
|
lb_policy {{ site.proxy_lb_policy | default(caddy_sites_defaults.proxy_lb_policy) }}
|
||||||
# Active checks
|
|
||||||
# health_uri /
|
{% if site.proxy_active_checks | default(caddy_sites_defaults.proxy_active_checks) %}
|
||||||
# health_interval 10s
|
health_uri {{ site.proxy_active_checks_uri | default(caddy_sites_defaults.proxy_active_checks_uri) }}
|
||||||
# health_timeout 5s
|
health_port {{ site.proxy_active_checks_port | default(caddy_sites_defaults.proxy_active_checks_port) }}
|
||||||
# health_status 200
|
health_interval {{ site.proxy_active_checks_interval | default(caddy_sites_defaults.proxy_active_checks_interval) }}
|
||||||
# Passive checks
|
health_timeout {{ site.proxy_active_checks_timeout | default(caddy_sites_defaults.proxy_active_checks_timeout) }}
|
||||||
fail_duration 30s
|
health_method {{ site.proxy_active_checks_method | default(caddy_sites_defaults.proxy_active_checks_method) }}
|
||||||
max_fails 3
|
health_status {{ site.proxy_active_checks_status | default(caddy_sites_defaults.proxy_active_checks_status) }}
|
||||||
unhealthy_latency 2000ms
|
{% if site.proxy_active_checks_body | default(caddy_sites_defaults.proxy_active_checks_body) != None %}
|
||||||
transport http {
|
health_body {{ site.proxy_active_checks_body | default(caddy_sites_defaults.proxy_active_checks_body) }}
|
||||||
# tls_server_name {host}
|
{% endif %}
|
||||||
# tls_insecure_skip_verify
|
{% endif %}
|
||||||
}
|
{% if site.proxy_passive_checks | default(caddy_sites_defaults.proxy_passive_checks) %}
|
||||||
|
fail_duration {{ site.proxy_passive_checks_fail_duration | default(caddy_sites_defaults.proxy_passive_checks_fail_duration) }}
|
||||||
|
max_fails {{ site.proxy_passive_checks_max_fails | default(caddy_sites_defaults.proxy_passive_checks_max_fails) }}
|
||||||
|
unhealthy_status {{ site.proxy_passive_checks_unhealthy_status | default(caddy_sites_defaults.proxy_passive_checks_unhealthy_status) }}
|
||||||
|
unhealthy_latency {{ site.proxy_passive_checks_unhealthy_latency | default(caddy_sites_defaults.proxy_passive_checks_unhealthy_latency) }}
|
||||||
|
{% if site.proxy_passive_checks_unhealthy_request_count | default(caddy_sites_defaults.proxy_passive_checks_unhealthy_request_count) != None %}
|
||||||
|
unhealthy_request_count {{ site.proxy_passive_checks_unhealthy_request_count | default(caddy_sites_defaults.proxy_passive_checks_unhealthy_request_count) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -103,33 +167,33 @@
|
|||||||
respond @geofilter "Access Denied" 403
|
respond @geofilter "Access Denied" 403
|
||||||
|
|
||||||
{% if site.geoip_debug | default(caddy_sites_defaults.geoip_debug) %}
|
{% if site.geoip_debug | default(caddy_sites_defaults.geoip_debug) %}
|
||||||
header geoip-is_anonymous "{geoip2.is_anonymous}"
|
header x-geoip-is-anonymous "{geoip2.is_anonymous}"
|
||||||
header geoip-is_anonymous_vpn "{geoip2.is_anonymous_vpn}"
|
header x-geoip-is-anonymous-vpn "{geoip2.is_anonymous_vpn}"
|
||||||
header geoip-is_hosting_provider "{geoip2.is_hosting_provider}"
|
header x-geoip-is-hosting-provider "{geoip2.is_hosting_provider}"
|
||||||
header geoip-is_public_proxy "{geoip2.is_public_proxy}"
|
header x-geoip-is-public-proxy "{geoip2.is_public_proxy}"
|
||||||
header geoip-is_residential_proxy "{geoip2.is_residential_proxy}"
|
header x-geoip-is-residential-proxy "{geoip2.is_residential_proxy}"
|
||||||
header geoip-is_tor_exit_node "{geoip2.is_tor_exit_node}"
|
header x-geoip-is-tor-exit-node "{geoip2.is_tor_exit_node}"
|
||||||
header geoip-connection_type "{geoip2.connection_type}"
|
header x-geoip-connection-type "{geoip2.connection_type}"
|
||||||
header geoip-domain "{geoip2.domain}"
|
header x-geoip-domain "{geoip2.domain}"
|
||||||
header geoip-country_code "{geoip2.country_code}"
|
header x-geoip-country-code "{geoip2.country_code}"
|
||||||
header geoip-country_confidence "{geoip2.country_confidence}"
|
# header x-geoip-country-confidence "{geoip2.country_confidence}"
|
||||||
header geoip-country_eu "{geoip2.country_eu}"
|
header x-geoip-country-eu "{geoip2.country_eu}"
|
||||||
header geoip-country_geoname_id "{geoip2.country_geoname_id}"
|
header x-geoip-country-geoname-id "{geoip2.country_geoname_id}"
|
||||||
header geoip-country_name "{geoip2.country_name}"
|
header x-geoip-country-name "{geoip2.country_name}"
|
||||||
header geoip-continent_code "{geoip2.continent_code}"
|
header x-geoip-continent-code "{geoip2.continent_code}"
|
||||||
header geoip-continent_geoname_id "{geoip2.continent_geoname_id}"
|
header x-geoip-continent-geoname-id "{geoip2.continent_geoname_id}"
|
||||||
header geoip-continent_name "{geoip2.continent_name}"
|
header x-geoip-continent-name "{geoip2.continent_name}"
|
||||||
header geoip-city_confidence "{geoip2.city_confidence}"
|
# header x-geoip-city-confidence "{geoip2.city_confidence}"
|
||||||
header geoip-city_geoname_id "{geoip2.city_geoname_id}"
|
header x-geoip-city-geoname-id "{geoip2.city_geoname_id}"
|
||||||
header geoip-city_name "{geoip2.city_name}"
|
header x-geoip-city-name "{geoip2.city_name}"
|
||||||
header geoip-location_time_zone "{geoip2.location_time_zone}"
|
header x-geoip-location-time-zone "{geoip2.location_time_zone}"
|
||||||
header geoip-autonomous_system_number "{geoip2.autonomous_system_number}"
|
header x-geoip-autonomous-system-number "{geoip2.autonomous_system_number}"
|
||||||
header geoip-autonomous_system_organization "{geoip2.autonomous_system_organization}"
|
header x-geoip-autonomous-system-organization "{geoip2.autonomous_system_organization}"
|
||||||
header geoip-isp "{geoip2.isp}"
|
header x-geoip-isp "{geoip2.isp}"
|
||||||
header geoip-mobile_country_code "{geoip2.mobile_country_code}"
|
header x-geoip-mobile-country-code "{geoip2.mobile_country_code}"
|
||||||
header geoip-mobile_network_code "{geoip2.mobile_network_code}"
|
header x-geoip-mobile-network-code "{geoip2.mobile_network_code}"
|
||||||
header geoip-organization "{geoip2.organization}"
|
header x-geoip-organization "{geoip2.organization}"
|
||||||
header geoip-ip_address "{geoip2.ip_address}"
|
header x-geoip-ip-address "{geoip2.ip_address}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -139,21 +203,22 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
|
|
||||||
{% if site.bot_barrier | default(caddy_sites_defaults.bot_barrier) %}
|
|
||||||
bot_barrier @not_whitelisted {
|
|
||||||
secret {{ site.bot_barrier_secret | default(caddy_sites_defaults.bot_barrier_secret) | mandatory }}
|
|
||||||
complexity {{ site.bot_barrier_complexity | default(caddy_sites_defaults.bot_barrier_complexity) }}
|
|
||||||
valid_for {{ site.bot_barrier_valid_for | default(caddy_sites_defaults.bot_barrier_valid_for) }}
|
|
||||||
seed_cookie_name __chall_{{ site.id }}_seed
|
|
||||||
solution_cookie_name __chall_{{ site.id }}_solution
|
|
||||||
mac_cookie_name __chall_{{ site.id }}_mac
|
|
||||||
template {{ caddy_config_dir }}/bot_barrier_template.html
|
|
||||||
}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if site.rate_limit | default(caddy_sites_defaults.rate_limit) %}
|
{% if site.rate_limit | default(caddy_sites_defaults.rate_limit) %}
|
||||||
rate_limit @not_whitelisted {
|
rate_limit @not_whitelisted {
|
||||||
# distributed
|
{% if caddy_consul %}
|
||||||
|
distributed
|
||||||
|
storage consul {
|
||||||
|
address "{{ caddy_consul_server }}"
|
||||||
|
token "{{ caddy_out_consul_token.token.SecretID }}"
|
||||||
|
timeout 10
|
||||||
|
prefix "caddy-{{ caddy_my_name }}-rl"
|
||||||
|
value_prefix "{{ caddy_my_name }}"
|
||||||
|
aes_key "{{ caddy_consul_aes_key }}"
|
||||||
|
tls_enabled "true"
|
||||||
|
tls_insecure "false"
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
log_key
|
||||||
zone remote_ip {
|
zone remote_ip {
|
||||||
key {remote.ip}
|
key {remote.ip}
|
||||||
events {{ site.rate_limit_events | default(caddy_sites_defaults.rate_limit_events) }}
|
events {{ site.rate_limit_events | default(caddy_sites_defaults.rate_limit_events) }}
|
||||||
@@ -166,23 +231,48 @@
|
|||||||
coraza_waf @not_whitelisted {
|
coraza_waf @not_whitelisted {
|
||||||
load_owasp_crs
|
load_owasp_crs
|
||||||
directives `
|
directives `
|
||||||
Include "{{ caddy_config_dir }}/sites/{{ site.id }}/coraza.conf"
|
Include "{{ caddy_sites_dir }}/{{ site.id }}/coraza.conf"
|
||||||
Include "{{ caddy_config_dir }}/sites/{{ site.id }}/crs-setup.conf"
|
Include "{{ caddy_sites_dir }}/{{ site.id }}/crs-setup.conf"
|
||||||
{% for plugin in site.crs_plugins | default(caddy_sites_defaults.crs_plugins) %}
|
{% for plugin in site.crs_plugins | default(caddy_sites_defaults.crs_plugins) %}
|
||||||
Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-config.conf"
|
Include "{{ caddy_crs_plugins_dir }}/{{ plugin }}-config.conf"
|
||||||
Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-before.conf"
|
Include "{{ caddy_crs_plugins_dir }}/{{ plugin }}-before.conf"
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
Include "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-request-before.conf"
|
Include "{{ caddy_sites_dir }}/{{ site.id }}/exclusions-request-before.conf"
|
||||||
Include "{{ caddy_config_dir }}/coreruleset-{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}/rules/*.conf"
|
Include "{{ caddy_config_dir }}/coreruleset-{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}/rules/*.conf"
|
||||||
Include "{{ caddy_config_dir }}/sites/{{ site.id }}/exclusions-response-after.conf"
|
Include "{{ caddy_sites_dir }}/{{ site.id }}/exclusions-response-after.conf"
|
||||||
{% for plugin in site.crs_plugins | default(caddy_sites_defaults.crs_plugins) %}
|
{% for plugin in site.crs_plugins | default(caddy_sites_defaults.crs_plugins) %}
|
||||||
Include "{{ caddy_config_dir }}/crs-plugins/{{ plugin }}-after.conf"
|
Include "{{ caddy_crs_plugins_dir }}/{{ plugin }}-after.conf"
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
SecRuleEngine On
|
SecRuleEngine On
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if site.cors | default(caddy_sites_defaults.cors) %}
|
||||||
|
{% for origin in site.cors_allowed_origins | mandatory %}
|
||||||
|
import cors https://{{ origin }} "{{
|
||||||
|
site.cors_allowed_methods | default(caddy_sites_defaults.cors_allowed_methods) | listadddel(site.cors_allowed_methods_add | default([]), site.cors_allowed_methods_del | default([])) | join(', ') }}" "{{
|
||||||
|
site.cors_allowed_headers | default(caddy_sites_defaults.cors_allowed_headers) | listadddel(site.cors_allowed_headers_add | default([]), site.cors_allowed_headers_del | default([])) | join(', ') }}" "{{
|
||||||
|
site.cors_allowed_credentials | default(caddy_sites_defaults.cors_allowed_credentials) | ternary('true', 'false') }}" "{{
|
||||||
|
site.cors_max_age | default(caddy_sites_defaults.cors_max_age) }}" "{{
|
||||||
|
site.cors_vary | default(caddy_sites_defaults.cors_vary) | listadddel(site.cors_vary_add | default([]), site.cors_vary_del | default([])) | join(', ') }}" "{{
|
||||||
|
site.cors_exposed_headers | default(caddy_sites_defaults.cors_exposed_headers) | listadddel(site.cors_exposed_headers_add | default([]), site.cors_exposed_headers_del | default([])) | join(', ') }}"
|
||||||
|
{% endfor %}
|
||||||
|
import cors-deny
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if site.bot_barrier | default(caddy_sites_defaults.bot_barrier) %}
|
||||||
|
bot_barrier @not_whitelisted {
|
||||||
|
secret {{ site.bot_barrier_secret | default(caddy_sites_defaults.bot_barrier_secret) | mandatory }}
|
||||||
|
complexity {{ site.bot_barrier_complexity | default(caddy_sites_defaults.bot_barrier_complexity) }}
|
||||||
|
valid_for {{ site.bot_barrier_valid_for | default(caddy_sites_defaults.bot_barrier_valid_for) }}
|
||||||
|
seed_cookie_name __chall_{{ site.id }}_seed
|
||||||
|
solution_cookie_name __chall_{{ site.id }}_solution
|
||||||
|
mac_cookie_name __chall_{{ site.id }}_mac
|
||||||
|
template {{ caddy_config_dir }}/bot_barrier_template.html
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
Content-Security-Policy "{{ caddy_sites_defaults.header_content_security_policy | combine(site.header_content_security_policy | default({})) | dict2str(sep1=' ', sep2='; ', sep3=';') }}"
|
Content-Security-Policy "{{ caddy_sites_defaults.header_content_security_policy | combine(site.header_content_security_policy | default({})) | dict2str(sep1=' ', sep2='; ', sep3=';') }}"
|
||||||
Cross-Origin-Embedder-Policy "{{ site.header_cross_origin_embedder_policy | default(caddy_sites_defaults.header_cross_origin_embedder_policy) }}"
|
Cross-Origin-Embedder-Policy "{{ site.header_cross_origin_embedder_policy | default(caddy_sites_defaults.header_cross_origin_embedder_policy) }}"
|
||||||
@@ -211,8 +301,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
log {
|
log {
|
||||||
format json
|
format {{ site.log_format | default(caddy_sites_defaults.log_format) }}
|
||||||
|
level INFO
|
||||||
|
format append {
|
||||||
|
waf_id {{ caddy_my_name }}
|
||||||
|
}
|
||||||
|
{% if site.log_to_file | default(caddy_sites_defaults.log_to_file) %}
|
||||||
output file {{ caddy_log_dir }}/site_{{ site.id }}.log
|
output file {{ caddy_log_dir }}/site_{{ site.id }}.log
|
||||||
|
{% else %}
|
||||||
|
output stdout
|
||||||
|
{% endif %}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
AccountID {{ caddy_geoip_account_id }}
|
|
||||||
LicenseKey {{ caddy_geoip_license_key }}
|
|
||||||
EditionIDs {{ caddy_geoip_edition_ids }}
|
|
||||||
@@ -1,19 +1,25 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=WAF {{ caddy_my_name }} (built with BYOW: Build Your Own WAF)
|
Description=WAF ({{ caddy_my_name }}) (built with BYOW: Build Your Own WAF)
|
||||||
After=network.target network-online.target
|
After=network.target network-online.target
|
||||||
Requires=network-online.target
|
Requires=network-online.target{% if caddy_consul %} consul.service{% endif %}
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=notify
|
Type=notify
|
||||||
User={{ caddy_system_user }}
|
User={{ caddy_system_user }}
|
||||||
Group={{ caddy_system_group }}
|
Group={{ caddy_system_group }}
|
||||||
ExecStart=/usr/local/bin/{{ caddy_my_name }} run --environ --config {{ caddy_config_dir }}/Caddyfile
|
ExecStart={{ caddy_binary }} run --environ --config {{ caddy_config_dir }}/Caddyfile
|
||||||
ExecReload=/usr/local/bin/{{ caddy_my_name }} reload --config {{ caddy_config_dir }}/Caddyfile --force
|
ExecReload={{ caddy_binary }} reload --config {{ caddy_config_dir }}/Caddyfile --force
|
||||||
TimeoutStopSec=15s
|
TimeoutStopSec=15s
|
||||||
LimitNOFILE=1048576
|
LimitNOFILE=1048576
|
||||||
PrivateTmp=true
|
PrivateTmp=true
|
||||||
ProtectSystem=full
|
ProtectSystem=full
|
||||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier={{ caddy_my_name }}
|
||||||
|
{% if caddy_consul %}
|
||||||
|
Environment="CONSUL_CLIENT_CERT={{ caddy_consul_client_cert }}" "CONSUL_CLIENT_KEY={{ caddy_consul_client_key }}"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# -- Rule engine initialization ----------------------------------------------
|
# -- Rule engine initialization ----------------------------------------------
|
||||||
|
# See: https://coraza.io/docs/seclang/directives/
|
||||||
|
|
||||||
# Enable Coraza, attaching it to every transaction. Use detection
|
# Enable Coraza, attaching it to every transaction. Use detection
|
||||||
# only to start with, because that minimises the chances of post-installation
|
# only to start with, because that minimises the chances of post-installation
|
||||||
@@ -78,7 +79,7 @@ SecResponseBodyAccess On
|
|||||||
# Which response MIME types do you want to inspect? You should adjust the
|
# Which response MIME types do you want to inspect? You should adjust the
|
||||||
# configuration below to catch documents but avoid static files
|
# configuration below to catch documents but avoid static files
|
||||||
# (e.g., images and archives).
|
# (e.g., images and archives).
|
||||||
SecResponseBodyMimeType text/plain text/html text/xml
|
SecResponseBodyMimeType text/plain text/html text/xml application/json
|
||||||
|
|
||||||
# Buffer response bodies of up to 512 KB in length.
|
# Buffer response bodies of up to 512 KB in length.
|
||||||
SecResponseBodyLimit 524288
|
SecResponseBodyLimit 524288
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.blocking_crs_paranoia_level={{ site.crs_paranoia_level | default(caddy_sites_defaults.crs_paranoia_level) }}"
|
setvar:tx.blocking_paranoia_level={{ site.crs_paranoia_level | default(caddy_sites_defaults.crs_paranoia_level) }}"
|
||||||
{% if site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) != None %}
|
{% if site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) != None %}
|
||||||
|
|
||||||
## Detection paranoia level
|
## Detection paranoia level
|
||||||
@@ -23,7 +23,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_detection_paranoia_level={{ site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) }}"
|
setvar:tx.detection_paranoia_level={{ site.crs_detection_paranoia_level | default(caddy_sites_defaults.crs_detection_paranoia_level) }}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
## Enforce Body Processor URLENCODED
|
## Enforce Body Processor URLENCODED
|
||||||
@@ -35,7 +35,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_enforce_bodyproc_urlencoded={{ site.crs_enforce_bodyproc_urlencoded | default(caddy_sites_defaults.crs_enforce_bodyproc_urlencoded) }}"
|
setvar:tx.enforce_bodyproc_urlencoded={{ site.crs_enforce_bodyproc_urlencoded | default(caddy_sites_defaults.crs_enforce_bodyproc_urlencoded) }}"
|
||||||
|
|
||||||
## Anomaly Scoring Mode Severity Levels
|
## Anomaly Scoring Mode Severity Levels
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -46,10 +46,10 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_critical_anomaly_score={{ site.crs_critical_anomaly_score | default(caddy_sites_defaults.crs_critical_anomaly_score) }},\
|
setvar:tx.critical_anomaly_score={{ site.crs_critical_anomaly_score | default(caddy_sites_defaults.crs_critical_anomaly_score) }},\
|
||||||
setvar:tx.crs_error_anomaly_score={{ site.crs_error_anomaly_score | default(caddy_sites_defaults.crs_error_anomaly_score) }},\
|
setvar:tx.error_anomaly_score={{ site.crs_error_anomaly_score | default(caddy_sites_defaults.crs_error_anomaly_score) }},\
|
||||||
setvar:tx.crs_warning_anomaly_score={{ site.crs_warning_anomaly_score | default(caddy_sites_defaults.crs_warning_anomaly_score) }},\
|
setvar:tx.warning_anomaly_score={{ site.crs_warning_anomaly_score | default(caddy_sites_defaults.crs_warning_anomaly_score) }},\
|
||||||
setvar:tx.crs_notice_anomaly_score={{ site.crs_notice_anomaly_score | default(caddy_sites_defaults.crs_notice_anomaly_score) }}"
|
setvar:tx.notice_anomaly_score={{ site.crs_notice_anomaly_score | default(caddy_sites_defaults.crs_notice_anomaly_score) }}"
|
||||||
|
|
||||||
## Anomaly Scoring Mode Blocking Threshold Levels
|
## Anomaly Scoring Mode Blocking Threshold Levels
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -60,8 +60,8 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_inbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_inbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_inbound_anomaly_score_threshold) }}{% endif %},\
|
setvar:tx.inbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_inbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_inbound_anomaly_score_threshold) }}{% endif %},\
|
||||||
setvar:tx.crs_outbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_outbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_outbound_anomaly_score_threshold) }}{% endif %}"
|
setvar:tx.outbound_anomaly_score_threshold={% if site.crs_log_only | default(caddy_sites_defaults.crs_log_only) %}1000{% else %}{{ site.crs_outbound_anomaly_score_threshold | default(caddy_sites_defaults.crs_outbound_anomaly_score_threshold) }}{% endif %}"
|
||||||
|
|
||||||
## Application Specific Rule Exclusions
|
## Application Specific Rule Exclusions
|
||||||
# FIXME
|
# FIXME
|
||||||
@@ -88,7 +88,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_reporting_level={{ site.crs_reporting_level | default(caddy_sites_defaults.crs_reporting_level) }}"
|
setvar:tx.reporting_level={{ site.crs_reporting_level | default(caddy_sites_defaults.crs_reporting_level) }}"
|
||||||
|
|
||||||
## Early Anomaly Scoring Mode Blocking
|
## Early Anomaly Scoring Mode Blocking
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -112,7 +112,7 @@ SecAction \
|
|||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.enable_default_collections=1"
|
setvar:tx.enable_default_collections=1"
|
||||||
|
|
||||||
## HTTP Policy Settings
|
## Allowed HTTP methods
|
||||||
SecAction \
|
SecAction \
|
||||||
"id:900200,\
|
"id:900200,\
|
||||||
phase:1,\
|
phase:1,\
|
||||||
@@ -121,7 +121,17 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:'tx.crs_allowed_methods={{ site.crs_allowed_methods | default(caddy_sites_defaults.crs_allowed_methods) | join(" ") }}'"
|
setvar:'tx.allowed_methods={{ site.crs_allowed_methods | default(caddy_sites_defaults.crs_allowed_methods) | listadddel(site.crs_allowed_methods_add | default([]), site.crs_allowed_methods_del | default([])) | join(" ") }}'"
|
||||||
|
|
||||||
|
## HTTP Method Override Parameter
|
||||||
|
SecAction \
|
||||||
|
"id:900210,\
|
||||||
|
phase:1,\
|
||||||
|
pass,\
|
||||||
|
nolog,\
|
||||||
|
tag:'OWASP_CRS',\
|
||||||
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
|
setvar:'tx.allow_method_override_parameter={{ site.crs_allow_method_override_parameter | default(caddy_sites_defaults.crs_allow_method_override_parameter) }}'"
|
||||||
|
|
||||||
## Content-Types that a client is allowed to send in a request
|
## Content-Types that a client is allowed to send in a request
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -132,7 +142,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:'tx.crs_allowed_request_content_type={{ site.crs_allowed_request_content_type | default(caddy_sites_defaults.crs_allowed_request_content_type) | join(" ") }}'"
|
setvar:'tx.allowed_request_content_type={{ site.crs_allowed_request_content_type | default(caddy_sites_defaults.crs_allowed_request_content_type) | listadddel(site.crs_allowed_request_content_type_add | default([]), site.crs_allowed_request_content_type_del | default([])) | join(" ") }}'"
|
||||||
|
|
||||||
## Allowed HTTP versions
|
## Allowed HTTP versions
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -143,7 +153,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:'tx.crs_allowed_http_versions={{ site.crs_allowed_http_versions | default(caddy_sites_defaults.crs_allowed_http_versions) | join(" ") }}'"
|
setvar:'tx.allowed_http_versions={{ site.crs_allowed_http_versions | default(caddy_sites_defaults.crs_allowed_http_versions) | listadddel(site.crs_allowed_http_versions_add | default([]), site.crs_allowed_http_versions_del | default([])) | join(" ") }}'"
|
||||||
|
|
||||||
## Forbidden file extensions
|
## Forbidden file extensions
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -154,7 +164,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:'tx.crs_restricted_extensions={{ site.crs_restricted_extensions | default(caddy_sites_defaults.crs_restricted_extensions) | join(" ") }}'"
|
setvar:'tx.restricted_extensions={{ site.crs_restricted_extensions | default(caddy_sites_defaults.crs_restricted_extensions) | listadddel(site.crs_restricted_extensions_add | default([]), site.crs_restricted_extensions_del | default([])) | join(" ") }}'"
|
||||||
|
|
||||||
## Restricted request headers
|
## Restricted request headers
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -165,7 +175,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:'tx.crs_restricted_headers_basic={{ site.crs_restricted_headers_basic | default(caddy_sites_defaults.crs_restricted_headers_basic) | join(" ") }}'"
|
setvar:'tx.restricted_headers_basic={{ site.crs_restricted_headers_basic | default(caddy_sites_defaults.crs_restricted_headers_basic) | listadddel(site.restricted_headers_basic_add | default([]), site.restricted_headers_basic_del | default([])) | join(" ") }}'"
|
||||||
|
|
||||||
## Extended restricted request headers (forbidden at a higher paranoia level)
|
## Extended restricted request headers (forbidden at a higher paranoia level)
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -176,7 +186,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:'tx.crs_restricted_headers_extended={{ site.crs_restricted_headers_extended | default(caddy_sites_defaults.crs_restricted_headers_extended) | join(" ") }}'"
|
setvar:'tx.restricted_headers_extended={{ site.crs_restricted_headers_extended | default(caddy_sites_defaults.crs_restricted_headers_extended) | listadddel(site.restricted_headers_extended_add | default([]), site.restricted_headers_extended_del | default([])) | join(" ") }}'"
|
||||||
|
|
||||||
## Content-Types charsets that a client is allowed to send in a request
|
## Content-Types charsets that a client is allowed to send in a request
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -187,7 +197,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:'tx.crs_allowed_request_content_type_charset={{ caddy_sites_defaults.crs_allowed_request_content_type_charset | default(caddy_sites_defaults.crs_allowed_request_content_type_charset) | join(" ") }}'"
|
setvar:'tx.allowed_request_content_type_charset={{ caddy_sites_defaults.crs_allowed_request_content_type_charset | default(caddy_sites_defaults.crs_allowed_request_content_type_charset) | listadddel(site.allowed_request_content_type_charset_add | default([]), site.allowed_request_content_type_charset_del | default([])) | join(" ") }}'"
|
||||||
|
|
||||||
## Block request if number of arguments is too high
|
## Block request if number of arguments is too high
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -198,7 +208,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_max_num_args={{ site.crs_max_num_args | default(caddy_sites_defaults.crs_max_num_args) }}"
|
setvar:tx.max_num_args={{ site.crs_max_num_args | default(caddy_sites_defaults.crs_max_num_args) }}"
|
||||||
|
|
||||||
## Block request if the length of any argument name is too high
|
## Block request if the length of any argument name is too high
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -209,7 +219,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_arg_name_length={{ site.crs_arg_name_length | default(caddy_sites_defaults.crs_arg_name_length) }}"
|
setvar:tx.name_length={{ site.crs_arg_name_length | default(caddy_sites_defaults.crs_arg_name_length) }}"
|
||||||
|
|
||||||
## Block request if the length of any argument value is too high
|
## Block request if the length of any argument value is too high
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -220,7 +230,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_arg_length={{ site.crs_arg_length | default(caddy_sites_defaults.crs_arg_length) }}"
|
setvar:tx.arg_length={{ site.crs_arg_length | default(caddy_sites_defaults.crs_arg_length) }}"
|
||||||
|
|
||||||
## Block request if the total length of all combined arguments is too high
|
## Block request if the total length of all combined arguments is too high
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -231,7 +241,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_total_arg_length={{ site.crs_total_arg_length | default(caddy_sites_defaults.crs_total_arg_length) }}"
|
setvar:tx.total_arg_length={{ site.crs_total_arg_length | default(caddy_sites_defaults.crs_total_arg_length) }}"
|
||||||
|
|
||||||
## Block request if the file size of any individual uploaded file is too high
|
## Block request if the file size of any individual uploaded file is too high
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -242,7 +252,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_max_file_size={{ site.crs_max_file_size | default(caddy_sites_defaults.crs_max_file_size) }}"
|
setvar:tx.max_file_size={{ site.crs_max_file_size | default(caddy_sites_defaults.crs_max_file_size) }}"
|
||||||
|
|
||||||
## Block request if the total size of all combined uploaded files is too high
|
## Block request if the total size of all combined uploaded files is too high
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -253,7 +263,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_combined_file_sizes={{ site.crs_combined_file_sizes | default(caddy_sites_defaults.crs_combined_file_sizes) }}"
|
setvar:tx.combined_file_sizes={{ site.crs_combined_file_sizes | default(caddy_sites_defaults.crs_combined_file_sizes) }}"
|
||||||
|
|
||||||
## Easing In / Sampling Percentage
|
## Easing In / Sampling Percentage
|
||||||
SecAction \
|
SecAction \
|
||||||
@@ -263,7 +273,7 @@ SecAction \
|
|||||||
nolog,\
|
nolog,\
|
||||||
tag:'OWASP_CRS',\
|
tag:'OWASP_CRS',\
|
||||||
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
ver:'OWASP_CRS/{{ site.crs_version | default(caddy_sites_defaults.crs_version) }}',\
|
||||||
setvar:tx.crs_sampling_percentage={{ site.crs_sampling_percentage | default(caddy_sites_defaults.crs_sampling_percentage) }}"
|
setvar:tx.sampling_percentage={{ site.crs_sampling_percentage | default(caddy_sites_defaults.crs_sampling_percentage) }}"
|
||||||
|
|
||||||
## Check UTF-8 encoding
|
## Check UTF-8 encoding
|
||||||
SecAction \
|
SecAction \
|
||||||
|
|||||||
@@ -5,8 +5,15 @@ caddy_global_sites_defaults:
|
|||||||
site_aliases: []
|
site_aliases: []
|
||||||
site_redirect_from_aliases: true
|
site_redirect_from_aliases: true
|
||||||
|
|
||||||
|
# Log settings
|
||||||
|
# If log_to_file is true, logs will go:
|
||||||
|
# - for each site, in: /var/log/<caddy_my_name>/site_<site id>.log
|
||||||
|
# - for WAF logs (Coraza), in /var/log/<caddy_my_name>/waf.log
|
||||||
|
log_to_file: false
|
||||||
|
log_format: "json"
|
||||||
|
|
||||||
# Proxy settings
|
# Proxy settings
|
||||||
|
# See: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#lb_policy
|
||||||
proxy_lb_policy: "ip_hash" # random
|
proxy_lb_policy: "ip_hash" # random
|
||||||
# random_choose <n>
|
# random_choose <n>
|
||||||
# first
|
# first
|
||||||
@@ -20,17 +27,68 @@ caddy_global_sites_defaults:
|
|||||||
# header [field]
|
# header [field]
|
||||||
# cookie [<name> [<secret>]]
|
# cookie [<name> [<secret>]]
|
||||||
|
|
||||||
|
# Upstreams active checks
|
||||||
|
# See: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#active-health-checks
|
||||||
|
proxy_active_checks: false
|
||||||
|
proxy_active_checks_uri: "/"
|
||||||
|
proxy_active_checks_port: 80
|
||||||
|
proxy_active_checks_interval: "30s"
|
||||||
|
proxy_active_checks_timeout: "5s"
|
||||||
|
proxy_active_checks_method: "GET"
|
||||||
|
proxy_active_checks_status: "2xx"
|
||||||
|
proxy_active_checks_body: null
|
||||||
|
|
||||||
# Custom TLS certificate
|
# Upstreams passive checks
|
||||||
custom_cert: false
|
# See: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#passive-health-checks
|
||||||
custom_cert_file: ""
|
proxy_passive_checks: false
|
||||||
custom_cert_key_file: ""
|
proxy_passive_checks_fail_duration: "30s"
|
||||||
|
proxy_passive_checks_max_fails: 1
|
||||||
|
proxy_passive_checks_unhealthy_status: "5xx"
|
||||||
|
proxy_passive_checks_unhealthy_latency: "2000ms"
|
||||||
|
proxy_passive_checks_unhealthy_request_count: null
|
||||||
|
|
||||||
# Filters
|
# Filters
|
||||||
filter_blacklist: [] # Superseeds filter_whitelist
|
filter_blacklist: [] # Superseeds filter_whitelist
|
||||||
filter_whitelist: ["127.0.0.1"]
|
filter_whitelist: ["127.0.0.1"]
|
||||||
|
|
||||||
|
# Custom TLS certificate
|
||||||
|
custom_cert: false
|
||||||
|
custom_cert_file: null # Mandatory if custum_cert is true
|
||||||
|
custom_cert_key_file: null # Mandatory if custum_cert is true
|
||||||
|
|
||||||
|
# CORS - Cross Origin Resource Sharing
|
||||||
|
cors: false
|
||||||
|
cors_allowed_origins: [] # Minimum 1 required
|
||||||
|
cors_allowed_methods:
|
||||||
|
# These variables can be used for adding and removing methods from the list:
|
||||||
|
# cors_allowed_methods_add: ["XXX"]
|
||||||
|
# cors_allowed_methods_del: ["YYY"]
|
||||||
|
- "GET"
|
||||||
|
- "HEAD"
|
||||||
|
- "POST"
|
||||||
|
- "OPTIONS"
|
||||||
|
cors_allowed_headers:
|
||||||
|
# These variables can be used for adding and removing headers from the list:
|
||||||
|
# cors_allowed_headers_add: ["Xxx"]
|
||||||
|
# cors_allowed_headers_del: ["Yyy"]
|
||||||
|
- "Cache-Control"
|
||||||
|
- "Content-Type"
|
||||||
|
- "If-Modified-Since"
|
||||||
|
- "Range"
|
||||||
|
- "User-Agent"
|
||||||
|
cors_max_age: 3600
|
||||||
|
cors_allowed_credentials: false
|
||||||
|
cors_vary:
|
||||||
|
# These variables can be used for adding and removing headers from the list:
|
||||||
|
# cors_vary_add: ["Xxx"]
|
||||||
|
# cors_vary_del: ["Yyy"]
|
||||||
|
- "Origin"
|
||||||
|
cors_exposed_headers:
|
||||||
|
# These variables can be used for adding and removing headers from the list:
|
||||||
|
# cors_exposed_headers_add: ["Xxx"]
|
||||||
|
# cors_exposed_headers_del: ["Yyy"]
|
||||||
|
- "Content-Length"
|
||||||
|
- "Content-Range"
|
||||||
|
|
||||||
# Security headers
|
# Security headers
|
||||||
header_content_security_policy:
|
header_content_security_policy:
|
||||||
@@ -213,20 +271,17 @@ caddy_global_sites_defaults:
|
|||||||
- name: "X-BYOW"
|
- name: "X-BYOW"
|
||||||
value: "🍷"
|
value: "🍷"
|
||||||
|
|
||||||
|
|
||||||
# caddy-ratelimit
|
# caddy-ratelimit
|
||||||
rate_limit: true
|
rate_limit: true
|
||||||
rate_limit_events: 1000
|
rate_limit_events: 1000
|
||||||
rate_limit_window: "1m"
|
rate_limit_window: "1m"
|
||||||
|
|
||||||
|
|
||||||
# steffenbusch/caddy-bot-barrier
|
# steffenbusch/caddy-bot-barrier
|
||||||
bot_barrier: false
|
bot_barrier: false
|
||||||
bot_barrier_secret: null # Required
|
bot_barrier_secret: null # Required
|
||||||
bot_barrier_complexity: 18
|
bot_barrier_complexity: 18
|
||||||
bot_barrier_valid_for: "60m"
|
bot_barrier_valid_for: "60m"
|
||||||
|
|
||||||
|
|
||||||
# corazawaf/coraza-caddy
|
# corazawaf/coraza-caddy
|
||||||
crs: true
|
crs: true
|
||||||
crs_version: "4.22.0"
|
crs_version: "4.22.0"
|
||||||
@@ -235,7 +290,7 @@ caddy_global_sites_defaults:
|
|||||||
crs_exceptions:
|
crs_exceptions:
|
||||||
before_request: []
|
before_request: []
|
||||||
after_response: []
|
after_response: []
|
||||||
crs_paranoia_level: 1
|
crs_paranoia_level: 4
|
||||||
crs_detection_paranoia_level: null
|
crs_detection_paranoia_level: null
|
||||||
crs_enforce_bodyproc_urlencoded: 1
|
crs_enforce_bodyproc_urlencoded: 1
|
||||||
crs_critical_anomaly_score: 5
|
crs_critical_anomaly_score: 5
|
||||||
@@ -252,21 +307,29 @@ caddy_global_sites_defaults:
|
|||||||
crs_max_file_size: 10485760 # 10 Mo
|
crs_max_file_size: 10485760 # 10 Mo
|
||||||
crs_combined_file_sizes: 20970520 # 20 Mo
|
crs_combined_file_sizes: 20970520 # 20 Mo
|
||||||
crs_sampling_percentage: 100
|
crs_sampling_percentage: 100
|
||||||
|
crs_allow_method_override_parameter: 0
|
||||||
crs_allowed_methods:
|
crs_allowed_methods:
|
||||||
|
# These variables can be used for adding and removing methods from the list:
|
||||||
|
# crs_allowed_methods_add: ["XXX"]
|
||||||
|
# crs_allowed_methods_del: ["YYY"]
|
||||||
- "GET"
|
- "GET"
|
||||||
- "HEAD"
|
- "HEAD"
|
||||||
- "POST"
|
- "POST"
|
||||||
- "OPTIONS"
|
- "OPTIONS"
|
||||||
crs_allowed_request_content_type:
|
crs_allowed_request_content_type:
|
||||||
- "|application/csp-report|"
|
# These variables can be used for adding and removing content types from the list:
|
||||||
|
# crs_allowed_request_content_type_add: ["|xxx/yyy|"]
|
||||||
|
# crs_allowed_request_content_type_del: ["|zzz/aaa|"]
|
||||||
- "|application/json|"
|
- "|application/json|"
|
||||||
- "|application/reports+json|"
|
|
||||||
- "|application/soap+xml|"
|
- "|application/soap+xml|"
|
||||||
- "|application/x-www-form-urlencoded|"
|
- "|application/x-www-form-urlencoded|"
|
||||||
- "|application/xml|"
|
- "|application/xml|"
|
||||||
- "|multipart/form-data|"
|
- "|multipart/form-data|"
|
||||||
- "|text/xml|"
|
- "|text/xml|"
|
||||||
crs_restricted_extensions:
|
crs_restricted_extensions:
|
||||||
|
# These variables can be used for adding and removing extensions from the list:
|
||||||
|
# crs_restricted_extensions_add: [".xxx/"]
|
||||||
|
# crs_restricted_extensions_del: [".yyy/"]
|
||||||
- ".ani/"
|
- ".ani/"
|
||||||
- ".asa/"
|
- ".asa/"
|
||||||
- ".asax/"
|
- ".asax/"
|
||||||
@@ -310,6 +373,7 @@ caddy_global_sites_defaults:
|
|||||||
- ".inc/"
|
- ".inc/"
|
||||||
- ".inf/"
|
- ".inf/"
|
||||||
- ".ini/"
|
- ".ini/"
|
||||||
|
- ".jks/"
|
||||||
- ".jse/"
|
- ".jse/"
|
||||||
- ".key/"
|
- ".key/"
|
||||||
- ".licx/"
|
- ".licx/"
|
||||||
@@ -342,9 +406,12 @@ caddy_global_sites_defaults:
|
|||||||
- ".sql/"
|
- ".sql/"
|
||||||
- ".sqlite/"
|
- ".sqlite/"
|
||||||
- ".sqlite3/"
|
- ".sqlite3/"
|
||||||
|
- ".swap/"
|
||||||
|
- ".swo/"
|
||||||
- ".swp/"
|
- ".swp/"
|
||||||
- ".sys/"
|
- ".sys/"
|
||||||
- ".temp/"
|
- ".temp/"
|
||||||
|
- ".tfstate/"
|
||||||
- ".tlb/"
|
- ".tlb/"
|
||||||
- ".tmp/"
|
- ".tmp/"
|
||||||
- ".vb/"
|
- ".vb/"
|
||||||
@@ -361,6 +428,9 @@ caddy_global_sites_defaults:
|
|||||||
- ".xsd/"
|
- ".xsd/"
|
||||||
- ".xsx/"
|
- ".xsx/"
|
||||||
crs_restricted_headers_basic:
|
crs_restricted_headers_basic:
|
||||||
|
# These variables can be used for adding and removing headers from the list:
|
||||||
|
# crs_restricted_headers_basic_add: ["/xxx/"]
|
||||||
|
# crs_restricted_headers_basic_del: ["/yyy/"]
|
||||||
- "/content-encoding/"
|
- "/content-encoding/"
|
||||||
- "/content-range/"
|
- "/content-range/"
|
||||||
- "/expect/"
|
- "/expect/"
|
||||||
@@ -372,8 +442,14 @@ caddy_global_sites_defaults:
|
|||||||
- "/x-method-override/"
|
- "/x-method-override/"
|
||||||
- "/x-middleware-subrequest/"
|
- "/x-middleware-subrequest/"
|
||||||
crs_restricted_headers_extended:
|
crs_restricted_headers_extended:
|
||||||
|
# These variables can be used for adding and removing headers from the list:
|
||||||
|
# crs_restricted_headers_extended_add: ["/xxx/"]
|
||||||
|
# crs_restricted_headers_extended_del: ["/yyy/"]
|
||||||
- "/accept-charset/"
|
- "/accept-charset/"
|
||||||
crs_allowed_http_versions:
|
crs_allowed_http_versions:
|
||||||
|
# These variables can be used for adding and removing protocols from the list:
|
||||||
|
# crs_allowed_http_versions_add: ["HTTP/x.x"]
|
||||||
|
# crs_allowed_http_versions_del: ["HTTP/y.y"]
|
||||||
- "HTTP/1.0"
|
- "HTTP/1.0"
|
||||||
- "HTTP/1.1"
|
- "HTTP/1.1"
|
||||||
- "HTTP/2"
|
- "HTTP/2"
|
||||||
@@ -381,17 +457,15 @@ caddy_global_sites_defaults:
|
|||||||
- "HTTP/3"
|
- "HTTP/3"
|
||||||
- "HTTP/3.0"
|
- "HTTP/3.0"
|
||||||
crs_allowed_request_content_type_charset:
|
crs_allowed_request_content_type_charset:
|
||||||
|
# These variables can be used for adding and removing charsets from the list:
|
||||||
|
# crs_allowed_request_content_type_charset_add: ["|xxx|"]
|
||||||
|
# crs_allowed_request_content_type_charset_del: ["|yyy|"]
|
||||||
- "|utf-8|"
|
- "|utf-8|"
|
||||||
- "|iso-8859-1|"
|
- "|iso-8859-1|"
|
||||||
- "|iso-8859-15|"
|
- "|iso-8859-15|"
|
||||||
- "|windows-1252|"
|
- "|windows-1252|"
|
||||||
|
|
||||||
|
|
||||||
# github.com/zhangjiayin/caddy-geoip2
|
# github.com/zhangjiayin/caddy-geoip2
|
||||||
geoip: false
|
geoip: false
|
||||||
geoip_debug: false
|
geoip_debug: false
|
||||||
geoip_filter_expression: '{geoip2.country_code} == "UNK"'
|
geoip_filter_expression: '{geoip2.country_code} == "UNK"'
|
||||||
# geoip_deny_countries: [] # ISO country codes (2 letters), "UNK" for unknown country
|
|
||||||
# geoip_allow_countries: [] # ISO country codes (2 letters), "UNK" for unknown country
|
|
||||||
# geopip_deny_asn: []
|
|
||||||
# geopip_allow_asn: []
|
|
||||||
|
|||||||
@@ -1,22 +1,34 @@
|
|||||||
# Required
|
# Required.
|
||||||
consul_datacenter: null
|
|
||||||
consul_domain: null
|
|
||||||
consul_secret_key: null
|
|
||||||
consul_server: false
|
consul_server: false
|
||||||
|
consul_datacenter: null
|
||||||
|
consul_secret_key: null # Generate with "consul keygen"
|
||||||
consul_servers: []
|
consul_servers: []
|
||||||
|
|
||||||
# Required for registering services
|
# Required if consul_server.
|
||||||
consul_services: []
|
consul_bootstrap_secret: null # Generate with "uuidgen"
|
||||||
|
|
||||||
# Defaults
|
# Required for activating UI.
|
||||||
consul_version: "1.22.2"
|
consul_ui_secret_id: null # Generate with "uuidgen"
|
||||||
consul_key_file: "/etc/ssl/private/server.{{ consul_datacenter }}.{{ consul_domain }}.key"
|
|
||||||
consul_cert_file: "/etc/ssl/certs/server.{{ consul_datacenter }}.{{ consul_domain }}.crt"
|
# Defaults.
|
||||||
consul_ca_file: "/etc/ssl/certs/local-ca.crt"
|
consul_domain: "consul"
|
||||||
consul_client_addr: "0.0.0.0"
|
consul_version: "1.22.3"
|
||||||
|
consul_client_addr: "127.0.0.1"
|
||||||
consul_bind_addr: "{{ ansible_default_ipv4.address }}"
|
consul_bind_addr: "{{ ansible_default_ipv4.address }}"
|
||||||
consul_advertise_addr: "{{ ansible_default_ipv4.address }}"
|
|
||||||
consul_default_check_interval: "15s"
|
consul_default_check_interval: "15s"
|
||||||
consul_default_check_timeout: "2s"
|
consul_default_check_timeout: "2s"
|
||||||
|
|
||||||
consul_acl_bootstraped: false
|
# Attributes for certificate must be:
|
||||||
|
# cn: server.<consul_datacenter>.<consul_domain>
|
||||||
|
# SANs: DNS:server.<consul_datacenter>.<consul_domain>
|
||||||
|
consul_key_file: "/etc/ssl/private/server.{{ consul_datacenter }}.{{ consul_domain }}.key"
|
||||||
|
consul_cert_file: "/etc/ssl/certs/server.{{ consul_datacenter }}.{{ consul_domain }}.crt"
|
||||||
|
consul_ca_file: "/etc/ssl/certs/local-ca.crt"
|
||||||
|
|
||||||
|
# Required for registering services.
|
||||||
|
consul_services: []
|
||||||
|
# - name: "www"
|
||||||
|
# port: 443
|
||||||
|
# check_tcp: ""
|
||||||
|
# check_http: "http://{{ ansible_default_ipv4.address }}:80/"
|
||||||
|
# scheme: "" (default "http")
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
- name: Restart Consul
|
- name: Restart Consul - Restart service
|
||||||
|
listen: "Restart Consul"
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
name: "consul"
|
name: "consul"
|
||||||
state: "restarted"
|
state: "restarted"
|
||||||
daemon_reload: true
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: Restart Consul - Wait a little
|
||||||
|
listen: "Restart Consul"
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
timeout: 5
|
||||||
|
|||||||
@@ -3,13 +3,6 @@
|
|||||||
name:
|
name:
|
||||||
- "unzip"
|
- "unzip"
|
||||||
|
|
||||||
# Not required for Ubuntu 24, was a test for Debian 13
|
|
||||||
- name: Disable IPv6 on all interfaces
|
|
||||||
ansible.posix.sysctl:
|
|
||||||
name: "net.ipv6.conf.all.disable_ipv6"
|
|
||||||
value: "1"
|
|
||||||
sysctl_set: true
|
|
||||||
|
|
||||||
- name: Create Consul directory
|
- name: Create Consul directory
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "/usr/local/consul-{{ consul_version }}"
|
path: "/usr/local/consul-{{ consul_version }}"
|
||||||
@@ -20,40 +13,34 @@
|
|||||||
ansible.builtin.unarchive:
|
ansible.builtin.unarchive:
|
||||||
src: "https://releases.hashicorp.com/consul/{{ consul_version }}/consul_{{ consul_version }}_linux_amd64.zip"
|
src: "https://releases.hashicorp.com/consul/{{ consul_version }}/consul_{{ consul_version }}_linux_amd64.zip"
|
||||||
dest: "/usr/local/consul-{{ consul_version }}"
|
dest: "/usr/local/consul-{{ consul_version }}"
|
||||||
|
creates: "/usr/local/consul-{{ consul_version }}/consul"
|
||||||
remote_src: true
|
remote_src: true
|
||||||
notify:
|
notify:
|
||||||
- "Restart Consul"
|
- "Restart Consul"
|
||||||
|
|
||||||
- name: Link Consul
|
- name: Create Consul system group
|
||||||
ansible.builtin.file:
|
|
||||||
src: "/usr/local/consul-{{ consul_version }}/consul"
|
|
||||||
dest: "/usr/local/bin/consul"
|
|
||||||
state: "link"
|
|
||||||
notify:
|
|
||||||
- "Restart Consul"
|
|
||||||
|
|
||||||
- name: Create consul system group
|
|
||||||
ansible.builtin.group:
|
ansible.builtin.group:
|
||||||
name: "consul"
|
name: "consul"
|
||||||
system: true
|
system: true
|
||||||
|
|
||||||
- name: Create consul system user
|
- name: Create Consul system user
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
name: "consul"
|
name: "consul"
|
||||||
group: "consul"
|
group: "consul"
|
||||||
groups: ["ssl-cert"]
|
groups: ["ssl-cert"]
|
||||||
password: "!"
|
password: "!"
|
||||||
system: true
|
system: true
|
||||||
|
shell: "/usr/sbin/nologin"
|
||||||
home: "/opt/consul"
|
home: "/opt/consul"
|
||||||
|
|
||||||
- name: Create consul config directory
|
- name: Create Consul config directory
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "/etc/consul"
|
path: "/etc/consul"
|
||||||
state: "directory"
|
state: "directory"
|
||||||
group: "consul"
|
group: "consul"
|
||||||
mode: "0750"
|
mode: "0750"
|
||||||
|
|
||||||
- name: Create consul log dir
|
- name: Create Consul log dir
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "/var/log/consul"
|
path: "/var/log/consul"
|
||||||
state: "directory"
|
state: "directory"
|
||||||
@@ -84,35 +71,162 @@
|
|||||||
enabled: true
|
enabled: true
|
||||||
daemon_reload: true
|
daemon_reload: true
|
||||||
|
|
||||||
# consul acl bootstrap -format=json
|
- name: Generate Consul ACL config
|
||||||
# {
|
when: "consul_server"
|
||||||
# "CreateIndex": 1042,
|
ansible.builtin.template:
|
||||||
# "ModifyIndex": 1042,
|
src: "templates/acl.json"
|
||||||
# "AccessorID": "50f8bfb6-b259-4c08-f9aa-2dc0eeb08e99",
|
dest: "/etc/consul/acl.json"
|
||||||
# "SecretID": "b7f16a8a-0b4f-4661-fea2-f79d95dd011b",
|
group: "consul"
|
||||||
# "Description": "Bootstrap Token (Global Management)",
|
mode: "0640"
|
||||||
# "Policies": [
|
notify:
|
||||||
# {
|
- "Restart Consul"
|
||||||
# "ID": "00000000-0000-0000-0000-000000000001",
|
|
||||||
# "Name": "global-management"
|
- name: Running handlers for restarting Consul if required
|
||||||
# }
|
ansible.builtin.meta: "flush_handlers"
|
||||||
# ],
|
|
||||||
# "Local": false,
|
- name: Bootstrap Consul ACL system
|
||||||
# "CreateTime": "2026-01-19T18:41:13.294800712+03:00",
|
when: "consul_server"
|
||||||
# "Hash": "X2AgaFhnQGRhSSF/h0m6qpX1wj/HJWbyXcxkEM/5GrY="
|
run_once: true
|
||||||
# }
|
community.general.consul_acl_bootstrap:
|
||||||
|
bootstrap_secret: "{{ consul_bootstrap_secret }}"
|
||||||
|
|
||||||
|
- name: Create/retrieve Consul node agent accessor_id
|
||||||
|
ansible.builtin.shell:
|
||||||
|
executable: "/usr/bin/bash"
|
||||||
|
cmd: |
|
||||||
|
set -o pipefail
|
||||||
|
if test -f /root/.consul_agent_accessor_id; then
|
||||||
|
echo OK
|
||||||
|
else
|
||||||
|
uuidgen > /root/.consul_agent_accessor_id
|
||||||
|
echo CHANGED
|
||||||
|
fi
|
||||||
|
cat /root/.consul_agent_accessor_id
|
||||||
|
register: "consul_out_agent_accessor_id"
|
||||||
|
changed_when: "consul_out_agent_accessor_id.stdout_lines[0] == 'CHANGED'"
|
||||||
|
|
||||||
|
- name: Create/retrieve Consul node agent token
|
||||||
|
community.general.consul_token:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
|
accessor_id: "{{ consul_out_agent_accessor_id.stdout_lines[1] }}"
|
||||||
|
description: "Node {{ ansible_fqdn }}"
|
||||||
|
node_identities:
|
||||||
|
- datacenter: "{{ consul_datacenter }}"
|
||||||
|
node_name: "{{ ansible_hostname }}"
|
||||||
|
register: "consul_out_agent_token"
|
||||||
|
|
||||||
|
- name: Create Consul policy for DNS agent
|
||||||
|
when: "consul_server"
|
||||||
|
run_once: true
|
||||||
|
community.general.consul_policy:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
|
name: "dns-access"
|
||||||
|
rules: |
|
||||||
|
node_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
{% for service in consul_services %}
|
||||||
|
service "{{ service.name }}" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
- name: Create/retrieve Consul DNS agent accessor_id
|
||||||
|
ansible.builtin.shell:
|
||||||
|
executable: "/usr/bin/bash"
|
||||||
|
cmd: |
|
||||||
|
set -o pipefail
|
||||||
|
if test -f /root/.consul_dns_accessor_id; then
|
||||||
|
echo OK
|
||||||
|
else
|
||||||
|
uuidgen > /root/.consul_dns_accessor_id
|
||||||
|
echo CHANGED
|
||||||
|
fi
|
||||||
|
cat /root/.consul_dns_accessor_id
|
||||||
|
register: "consul_out_dns_accessor_id"
|
||||||
|
changed_when: "consul_out_dns_accessor_id.stdout_lines[0] == 'CHANGED'"
|
||||||
|
|
||||||
|
- name: Create/retrieve Consul DNS agent token
|
||||||
|
when: "consul_server"
|
||||||
|
community.general.consul_token:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
|
accessor_id: "{{ consul_out_dns_accessor_id.stdout_lines[1] }}"
|
||||||
|
description: "DNS {{ ansible_fqdn }}"
|
||||||
|
policies:
|
||||||
|
- name: "dns-access"
|
||||||
|
register: "consul_out_dns_token"
|
||||||
|
|
||||||
|
- name: Generate Consul agent tokens config
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "templates/tokens.json"
|
||||||
|
dest: "/etc/consul/tokens.json"
|
||||||
|
group: "consul"
|
||||||
|
mode: "0640"
|
||||||
|
notify:
|
||||||
|
- "Restart Consul"
|
||||||
|
|
||||||
|
- name: Running handlers for restarting Consul if required
|
||||||
|
ansible.builtin.meta: "flush_handlers"
|
||||||
|
|
||||||
|
- name: Create Consul policy for UI
|
||||||
|
when: "consul_server and consul_ui_secret_id != None"
|
||||||
|
run_once: true
|
||||||
|
community.general.consul_policy:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
|
name: "ui-access"
|
||||||
|
rules: |
|
||||||
|
key_prefix "" {
|
||||||
|
policy = "write"
|
||||||
|
}
|
||||||
|
node_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
service_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Create/retrieve Consul UI accessor_id
|
||||||
|
when: "consul_server and consul_ui_secret_id != None and consul_servers[0] == ansible_hostname"
|
||||||
|
ansible.builtin.shell:
|
||||||
|
executable: "/usr/bin/bash"
|
||||||
|
cmd: |
|
||||||
|
set -o pipefail
|
||||||
|
if test -f /root/.consul_ui_accessor_id; then
|
||||||
|
echo OK
|
||||||
|
else
|
||||||
|
uuidgen > /root/.consul_ui_accessor_id
|
||||||
|
echo CHANGED
|
||||||
|
fi
|
||||||
|
cat /root/.consul_ui_accessor_id
|
||||||
|
register: "consul_out_ui_accessor_id"
|
||||||
|
changed_when: "consul_out_ui_accessor_id.stdout_lines[0] == 'CHANGED'"
|
||||||
|
|
||||||
|
- name: Create/retrieve Consul UI token
|
||||||
|
when: "consul_server and consul_ui_secret_id != None and consul_servers[0] == ansible_hostname"
|
||||||
|
community.general.consul_token:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
|
accessor_id: "{{ consul_out_ui_accessor_id.stdout_lines[1] }}"
|
||||||
|
secret_id: "{{ consul_ui_secret_id }}"
|
||||||
|
description: "UI"
|
||||||
|
policies:
|
||||||
|
- name: "ui-access"
|
||||||
|
|
||||||
- name: Register services to consul
|
- name: Register services to consul
|
||||||
loop: "{{ consul_services }}"
|
loop: "{{ consul_services }}"
|
||||||
community.general.consul_agent_service:
|
community.general.consul_agent_service:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
name: "{{ item.name }}"
|
name: "{{ item.name }}"
|
||||||
|
address: "{{ item.address | default(ansible_default_ipv4.address) }}"
|
||||||
service_port: "{{ item.port }}"
|
service_port: "{{ item.port }}"
|
||||||
tags: "{{ item.tags | default([]) }}"
|
tags: "{{ item.tags | default([]) }}"
|
||||||
|
# Because community.general.consul_agent_check is not idempotent:
|
||||||
|
register: "consul_out_register_services"
|
||||||
|
|
||||||
- name: Register HTTP checks to consul
|
- name: Register HTTP checks to consul
|
||||||
loop: "{{ consul_services }}"
|
loop: "{{ consul_services }}"
|
||||||
when: "item.check_http | default(None) != None"
|
when: "consul_out_register_services.changed and (item.check_http | default(None) != None)"
|
||||||
community.general.consul_agent_check:
|
community.general.consul_agent_check:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
name: "{{ item.name }}_check"
|
name: "{{ item.name }}_check"
|
||||||
service_id: "{{ item.name }}"
|
service_id: "{{ item.name }}"
|
||||||
interval: "{{ item.check_interval | default(consul_default_check_interval) }}"
|
interval: "{{ item.check_interval | default(consul_default_check_interval) }}"
|
||||||
@@ -122,8 +236,9 @@
|
|||||||
|
|
||||||
- name: Register TCP checks to consul
|
- name: Register TCP checks to consul
|
||||||
loop: "{{ consul_services }}"
|
loop: "{{ consul_services }}"
|
||||||
when: "item.check_tcp | default(None) != None"
|
when: "consul_out_register_services and (item.check_tcp | default(None) != None)"
|
||||||
community.general.consul_agent_check:
|
community.general.consul_agent_check:
|
||||||
|
token: "{{ consul_bootstrap_secret }}"
|
||||||
name: "{{ item.name }}_check"
|
name: "{{ item.name }}_check"
|
||||||
service_id: "{{ item.name }}"
|
service_id: "{{ item.name }}"
|
||||||
interval: "{{ item.check_interval | default(consul_default_check_interval) }}"
|
interval: "{{ item.check_interval | default(consul_default_check_interval) }}"
|
||||||
|
|||||||
9
seb4itik/byow/roles/consul/templates/acl.json
Normal file
9
seb4itik/byow/roles/consul/templates/acl.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"acl" : {
|
||||||
|
"enabled" : true,
|
||||||
|
{% if consul_server %}
|
||||||
|
"default_policy" : "deny",
|
||||||
|
{% endif %}
|
||||||
|
"down_policy" : "extend-cache"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,45 @@
|
|||||||
{
|
{
|
||||||
"log_level": "INFO",
|
"log_level": "INFO",
|
||||||
|
"enable_syslog": true,
|
||||||
|
"node_name": "{{ ansible_hostname }}",
|
||||||
"domain": "{{ consul_domain }}",
|
"domain": "{{ consul_domain }}",
|
||||||
"datacenter": "{{ consul_datacenter | mandatory }}",
|
"datacenter": "{{ consul_datacenter | mandatory }}",
|
||||||
"key_file": "{{ consul_key_file }}",
|
|
||||||
"cert_file": "{{ consul_cert_file }}",
|
|
||||||
"ca_file": "{{ consul_ca_file }}",
|
|
||||||
"verify_incoming": true,
|
|
||||||
"verify_outgoing": true,
|
|
||||||
"verify_server_hostname": true,
|
|
||||||
"encrypt": "{{ consul_secret_key }}",
|
"encrypt": "{{ consul_secret_key }}",
|
||||||
"data_dir": "/opt/consul",
|
"data_dir": "/opt/consul",
|
||||||
|
"retry_join": ["{{ consul_servers | join('", "') }}"],
|
||||||
|
"disable_coordinates": true,
|
||||||
|
"disable_remote_exec": true,
|
||||||
|
"disable_update_check": true,
|
||||||
|
"tls": {
|
||||||
|
"defaults": {
|
||||||
|
"ca_file": "{{ consul_ca_file }}",
|
||||||
|
"cert_file": "{{ consul_cert_file }}",
|
||||||
|
"key_file": "{{ consul_key_file }}",
|
||||||
|
"verify_incoming": true,
|
||||||
|
"verify_outgoing": true
|
||||||
|
},
|
||||||
|
"internal_rpc": {
|
||||||
|
"verify_server_hostname": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"addresses": {
|
||||||
|
"http": "127.0.0.1",
|
||||||
|
"https": "0.0.0.0"
|
||||||
|
},
|
||||||
|
"ports": {
|
||||||
|
"https": 8501
|
||||||
|
},
|
||||||
{% if consul_server %}
|
{% if consul_server %}
|
||||||
"node_name": "{{ ansible_hostname }}",
|
|
||||||
"server": true,
|
"server": true,
|
||||||
"ui": true,
|
|
||||||
"leave_on_terminate": true,
|
"leave_on_terminate": true,
|
||||||
"client_addr": "{{ consul_client_addr }}",
|
|
||||||
"bind_addr": "{{ consul_bind_addr }}",
|
"bind_addr": "{{ consul_bind_addr }}",
|
||||||
"advertise_addr": "{{ consul_advertise_addr }}",
|
"bootstrap_expect": {{ consul_servers | length }},
|
||||||
"bootstrap_expect": {{ (consul_servers | length) - 1 }},
|
"ui_config": {
|
||||||
"enable_syslog": true,
|
"enabled": {{ (consul_ui_secret_id != None) | ternary('true', 'false') }}
|
||||||
|
},
|
||||||
"performance": {
|
"performance": {
|
||||||
"raft_multiplier": 1
|
"raft_multiplier": 1
|
||||||
},
|
}
|
||||||
{% endif %}
|
{% else %}
|
||||||
"retry_join": ["{{ consul_servers | join('", "') }}"]
|
{% endif %}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ ConditionFileNotEmpty=/etc/consul/config.json
|
|||||||
Type=notify
|
Type=notify
|
||||||
User=consul
|
User=consul
|
||||||
Group=consul
|
Group=consul
|
||||||
ExecStart=/usr/local/bin/consul agent -config-file=/etc/consul/config.json
|
ExecStart=/usr/local/consul-{{ consul_version }}/consul agent -config-file=/etc/consul/
|
||||||
KillMode=process
|
KillMode=process
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
LimitNOFILE=65536
|
LimitNOFILE=65536
|
||||||
|
|||||||
10
seb4itik/byow/roles/consul/templates/tokens.json
Normal file
10
seb4itik/byow/roles/consul/templates/tokens.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"acl" : {
|
||||||
|
"tokens": {
|
||||||
|
{% if consul_server %}
|
||||||
|
"dns": "{{ consul_out_dns_token.token.SecretID }}",
|
||||||
|
{% endif %}
|
||||||
|
"default": "{{ consul_out_agent_token.token.SecretID }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Required
|
# Required
|
||||||
ovh_ldp_token: null
|
ovh_ldp_token: null # Jeton d'écriture
|
||||||
ovh_ldp_cluster: null
|
ovh_ldp_cluster: null
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
|
|||||||
2
seb4itik/byow/roles/squid/defaults/main.yml
Normal file
2
seb4itik/byow/roles/squid/defaults/main.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
squid_authorized_networks: ["127.0.0.1"]
|
||||||
|
squid_cache_size: 10240
|
||||||
4
seb4itik/byow/roles/squid/handlers/main.yml
Normal file
4
seb4itik/byow/roles/squid/handlers/main.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- name: Restart squid
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "squid"
|
||||||
|
state: "restarted"
|
||||||
23
seb4itik/byow/roles/squid/tasks/main.yml
Normal file
23
seb4itik/byow/roles/squid/tasks/main.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
- name: Install squid package
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: "squid"
|
||||||
|
notify:
|
||||||
|
- "Restart squid"
|
||||||
|
|
||||||
|
- name: Deploy squid configuration file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "templates/squid.conf"
|
||||||
|
dest: "/etc/squid/squid.conf"
|
||||||
|
owner: "root"
|
||||||
|
group: "root"
|
||||||
|
mode: "0644"
|
||||||
|
notify:
|
||||||
|
- "Restart squid"
|
||||||
|
|
||||||
|
- name: Enable squid
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "squid"
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
notify:
|
||||||
|
- "Restart squid"
|
||||||
9386
seb4itik/byow/roles/squid/templates/squid.conf
Normal file
9386
seb4itik/byow/roles/squid/templates/squid.conf
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,12 @@
|
|||||||
server:
|
server:
|
||||||
|
do-ip4: yes
|
||||||
|
do-ip6: no
|
||||||
|
do-udp: yes
|
||||||
|
do-tcp: yes
|
||||||
|
hide-identity: yes
|
||||||
|
hide-version: yes
|
||||||
|
harden-glue: yes
|
||||||
|
use-caps-for-id: yes
|
||||||
do-not-query-localhost: no
|
do-not-query-localhost: no
|
||||||
{% for interface in unbound_listen_interfaces %}
|
{% for interface in unbound_listen_interfaces %}
|
||||||
interface: {{ interface }}
|
interface: {{ interface }}
|
||||||
@@ -6,15 +14,18 @@ server:
|
|||||||
{% for access in unbound_access_control %}
|
{% for access in unbound_access_control %}
|
||||||
access-control: {{ access }}
|
access-control: {{ access }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for zone in unbound_stub_zones %}
|
|
||||||
|
|
||||||
|
# Consul ne supporte pas DNSSEC
|
||||||
|
# FIXME: domain-insecure: "consul"
|
||||||
|
|
||||||
|
{% for zone in unbound_stub_zones %}
|
||||||
stub-zone:
|
stub-zone:
|
||||||
name: "{{ zone.name }}"
|
name: "{{ zone.name }}"
|
||||||
stub-addr: {{ zone.stub_to }}
|
stub-addr: {{ zone.stub_to }}
|
||||||
stub-no-cache: {{ zone.no_cache | default('yes') }}
|
stub-no-cache: {{ zone.no_cache | default('yes') }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for zone in unbound_forward_zones %}
|
|
||||||
|
|
||||||
|
{% for zone in unbound_forward_zones %}
|
||||||
forward-zone:
|
forward-zone:
|
||||||
name: "{{ zone.name }}"
|
name: "{{ zone.name }}"
|
||||||
forward-addr: {{ zone.forward_to }}
|
forward-addr: {{ zone.forward_to }}
|
||||||
|
|||||||
Reference in New Issue
Block a user