Private
Public Access
2
0
This commit is contained in:
2026-01-20 17:40:16 +03:00
parent cda556eec6
commit b78da80550
83 changed files with 108 additions and 82 deletions

4
example/ansible/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/ca/
/.vault_pass
/ansible_local.env
/known_hosts

View File

@@ -0,0 +1,8 @@
[defaults]
inventory = ./inventory/
gathering = smart
vault_password_file = ./.vault_pass
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=300s -o StrictHostKeyChecking=no -o UserKnownHostsFile=./known_hosts

View File

@@ -0,0 +1,19 @@
# Example of a ansible_local.env file that is used to customize the local
# operation of Ansible with environment variables.
# Usage:
# 1. Copy ansible/ansible_local.env.example to ansible/ansible_local.env or create a new version.
# 2. Customize the contents of the ansible_local.env file, there can only be definitions of environment variables.
# cf.: https://docs.ansible.com/ansible/latest/reference_appendices/config.html
# 3. The run_ansible.sh script will automatically source the ansible/ansible_local.env file if it exists before running ansible.
# The ansible_local.env file is ignored by Git (present in.gitignore).
# Example of using the ANSIBLE_STRATEGY_PLUGINS and ANSIBLE_STRATEGY environment variables to enable Mitogen (speeds up the execution of Ansible playbooks by a factor of 2 to 10).
# cf.: https://mitogen.networkgenomics.com/ansible_detailed.html
ANSIBLE_STRATEGY_PLUGINS=/home/seb/.local/share/pipx/venvs/ansible/lib/python3.13/site-packages/ansible_mitogen/plugins/strategy
export ANSIBLE_STRATEGY_PLUGINS
ANSIBLE_STRATEGY=mitogen_linear
export ANSIBLE_STRATEGY

View File

@@ -0,0 +1 @@
../../filter_plugins

View File

@@ -0,0 +1,31 @@
linux:
vars:
ansible_user: "root"
debian13:
vars:
ansible_python_interpreter: "/usr/bin/python3.13"
ubuntu24:
vars:
ansible_python_interpreter: "/usr/bin/python3.12"
waf:
hosts:
waf1:
waf2:
waf3:
mysql:
hosts:
sql1:
nfs:
hosts:
nfs1:
www:
hosts:
www1:
www2:
www3:

View File

@@ -0,0 +1,7 @@
#!/bin/sh
multipass list --format=json |jq '{
_meta: {hostvars: [.list[] | {(.name): {ansible_host: .ipv4[0]}}] | add},
linux: {hosts: [.list[].name]},
ubuntu24: {hosts: [.list[].name]},
}'

View File

@@ -0,0 +1,25 @@
- name: Web Application Firewalls (config)
hosts: waf
vars_files:
- "vars/common.yml"
- "vars/secrets.yml"
vars:
local_ca_certs_ca_passphrase: "{{ secrets.ca.passphrase }}"
local_ca_certs_default_country_name: "{{ common.certificates.country_name }}"
local_ca_certs_default_locality_name: "{{ common.certificates.locality_name }}"
local_ca_certs_default_organization_name: "{{ common.certificates.organization_name }}"
local_ca_certs_default_email_address: "{{ common.certificates.email_address }}"
local_ca_certs_list:
- cn: "test.lab"
domains:
- "DNS:test.lab"
- "DNS:{{ ansible_fqdn }}"
- "DNS:{{ ansible_hostname }}"
- "IP:{{ ansible_default_ipv4.address }}"
caddy_config_only: true
caddy_sites: "{{ common.sites }}"
roles:
- "local_ca_certs"
- "caddy"
tags:
- "waf"

View File

@@ -0,0 +1,229 @@
- name: Gather facts (implicit) and packages facts
hosts: all
tasks:
- name: Gather packages facts
ansible.builtin.package_facts:
tags:
- "always"
- name: Create local CA
hosts: all
gather_facts: false
vars_files:
- "vars/common.yml"
- "vars/secrets.yml"
vars:
local_ca_common_name: "Lab CA"
local_ca_passphrase: "{{ secrets.ca.passphrase }}"
local_ca_country_name: "{{ common.certificates.country_name }}"
local_ca_locality_name: "{{ common.certificates.locality_name }}"
local_ca_organization_name: "{{ common.certificates.organization_name }}"
local_ca_email_address: "{{ common.certificates.email_address }}"
roles:
- "local_ca"
tags:
- "local_ca"
- name: Common
hosts: all
gather_facts: false
vars_files:
- "vars/common.yml"
- "vars/secrets.yml"
vars:
common_default_packages:
- "net-tools"
- "htop"
- "aptitude"
- "screen"
- "tcpdump"
roles:
- "common"
tags:
- "common"
- name: Web Application Firewalls (install)
hosts: waf
gather_facts: false
vars_files:
- "vars/common.yml"
- "vars/secrets.yml"
vars:
local_ca_certs_ca_passphrase: "{{ secrets.ca.passphrase }}"
local_ca_certs_default_country_name: "{{ common.certificates.country_name }}"
local_ca_certs_default_locality_name: "{{ common.certificates.locality_name }}"
local_ca_certs_default_organization_name: "{{ common.certificates.organization_name }}"
local_ca_certs_default_email_address: "{{ common.certificates.email_address }}"
local_ca_certs_list:
# Consul
- cn: "server.{{ common.consul.datacenter }}.{{ common.consul.domain }}"
domains:
- "DNS:server.{{ common.consul.datacenter }}.{{ common.consul.domain }}"
# Sites
- cn: "test.lab"
domains:
- "DNS:test.lab"
- "DNS:{{ ansible_fqdn }}"
- "DNS:{{ ansible_hostname }}"
- "IP:{{ ansible_default_ipv4.address }}"
consul_domain: "{{ common.consul.domain }}"
consul_datacenter: "{{ common.consul.datacenter }}"
consul_secret_key: "{{ secrets.consul.secret_key }}"
consul_servers: ["waf1", "waf2", "waf3"]
consul_server: true
consul_services:
- name: "www"
port: 443
check_http: "http://{{ ansible_default_ipv4.address }}:80/"
# keepalived_script_user: "byow"
# keepalived_monitored_process: "caddy"
# keepalived_vrrp_password: "{{ secrets.keepalived.secret }}"
# keepalived_vrrp_ips:
# - master: "waf1"
# virtual_router_id: 251
# addr: "{{ ansible_default_ipv4.address | regex_replace('\\.[0-9]+$', '') }}.251/24"
# - master: "waf2"
# virtual_router_id: 252
# addr: "{{ ansible_default_ipv4.address | regex_replace('\\.[0-9]+$', '') }}.252/24"
# - master: "waf3"
# virtual_router_id: 253
# addr: "{{ ansible_default_ipv4.address | regex_replace('\\.[0-9]+$', '') }}.253/24"
# # Multipass network doesn't seem to support well multicast.
# keepalived_unicast_peers:
# - "{{ hostvars['waf1'].ansible_default_ipv4.address }}"
# - "{{ hostvars['waf2'].ansible_default_ipv4.address }}"
# - "{{ hostvars['waf3'].ansible_default_ipv4.address }}"
unbound_listen_interfaces:
- "{{ ansible_default_ipv4.address }}"
unbound_stub_zones:
- name: "{{ common.consul.datacenter }}.{{ common.consul.domain }}"
stub_to: "127.0.0.1@8600"
caddy_sites: "{{ common.sites }}"
ovh_ldp_cluster: "gra2.logs.ovh.com"
ovh_ldp_token: ¨{{ secrets.ovh_ldp.token }}
roles:
- "local_ca_certs"
- "consul"
- "caddy"
# - "keepalived"
- "unbound"
- "ovh_ldp"
tags:
- "waf"
- name: MySQL servers
hosts: mysql
gather_facts: false
vars_files:
- "vars/common.yml"
- "vars/secrets.yml"
vars:
local_ca_certs_ca_passphrase: "{{ secrets.ca.passphrase }}"
local_ca_certs_default_country_name: "{{ common.certificates.country_name }}"
local_ca_certs_default_locality_name: "{{ common.certificates.locality_name }}"
local_ca_certs_default_organization_name: "{{ common.certificates.organization_name }}"
local_ca_certs_default_email_address: "{{ common.certificates.email_address }}"
local_ca_certs_list:
- cn: "{{ ansible_fqdn }}"
domains:
- "DNS:{{ ansible_fqdn }}"
- "DNS:{{ ansible_hostname }}"
- "IP:{{ ansible_default_ipv4.address }}"
mysql_databases:
- "wordpress"
mysql_users:
- name: "wordpress"
password: "{{ secrets.wordpress.mysql_password }}"
priv: "wordpress.*:ALL"
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:
- "local_ca_certs"
- "mysql"
- "consul"
tags:
- "mysql"
- name: NFS servers
hosts: nfs
gather_facts: false
vars_files:
- "vars/common.yml"
- "vars/secrets.yml"
vars:
nfs_server_exports:
- path: "/srv/wordpress"
owner: 1001
group: 33
clients:
- address: "www1"
options: "rw,no_root_squash"
- address: "www2"
options: "rw,no_root_squash"
- address: "www3"
options: "rw,no_root_squash"
roles:
- "nfs_server"
tags:
- "nfs"
- name: HTTP Servers
hosts: www
gather_facts: false
vars_files:
- "vars/common.yml"
- "vars/secrets.yml"
vars:
local_ca_certs_ca_passphrase: "{{ secrets.ca.passphrase }}"
local_ca_certs_default_country_name: "{{ common.certificates.country_name }}"
local_ca_certs_default_locality_name: "{{ common.certificates.locality_name }}"
local_ca_certs_default_organization_name: "{{ common.certificates.organization_name }}"
local_ca_certs_default_email_address: "{{ common.certificates.email_address }}"
local_ca_certs_list:
- cn: "{{ ansible_fqdn }}"
domains:
- "DNS:{{ ansible_fqdn }}"
- "DNS:{{ ansible_hostname }}"
- "IP:{{ ansible_default_ipv4.address }}"
nfs_client_mounts:
- mount_point: "/var/www/wordpress"
server: "nfs1:/srv/wordpress"
owner: 1001
group: 33
wordpress_create_master: "www1"
wordpress_site: "test.lab"
wordpress_url: "test.lab"
wordpress_site_title: "Lab Test"
wordpress_admin_user: "spock"
wordpress_admin_password: "{{ secrets.wordpress.admin_password }}"
wordpress_admin_email: "seb@itik.fr"
wordpress_themes: ["twentytwentyfive"]
wordpress_active_theme: "twentytwentyfive"
wordpress_db_host: "sql1"
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:
- "local_ca_certs"
- "nfs_client"
- "wordpress"
- "consul"
tags:
- "www"

1
example/ansible/roles Symbolic link
View File

@@ -0,0 +1 @@
../../roles

21
example/ansible/run_ansible.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
ANSIBLE_CONFIG=./ansible.cfg
export ANSIBLE_CONFIG
PLAY="main"
if [ "$1" == "--play" ]; then
shift
PLAY="$1"
shift
fi
if [ -f "./ansible_local.env" ]; then
. ./ansible_local.env
fi
if [ -f "./requirements.yml" ]; then
ansible-galaxy install -r requirements.yml
fi
ansible-lint --strict --project-dir . play-${PLAY}.yml && time ansible-playbook play-${PLAY}.yml $*

View File

@@ -0,0 +1,41 @@
common:
certificates:
country_name: "FR"
locality_name: "Vannes"
organization_name: "iTik"
email_address: "ca@itik.fr"
consul:
domain: "itik.fr"
datacenter: "lab"
sites:
- name: "test"
site: "test.lab"
paths:
- addrs:
- "http://www1"
- "http://www2"
- "http://www3"
custom_cert: true
custom_cert_file: "/etc/ssl/certs/test.lab.crt"
custom_key_file: "/etc/ssl/private/test.lab.key"
crs_plugins:
- "wordpress-rule-exclusions"
crs_exceptions:
# Cf. https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v3.x)
# before_request:
# - 'SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" "id:1,nolog,ctl:ruleRemoveById=932260"'
after_response:
- 'SecRuleUpdateTargetById 932260 "!ARGS:tag-name"'
header_cross_origin_embedder_policy: "unsafe-none"
header_content_security_policy:
worker-src: "'self' blob:"
img-src: "'self' data: https://secure.gravatar.com/avatar/"
font-src: "'self' data:"
script-src: "'self' 'unsafe-eval'"
script-src-elem: "'self' 'unsafe-inline'"
style-src-attr: "'self' 'unsafe-inline'"
style-src-elem: "'self' 'unsafe-inline'"
frame-src: "'self' blob:"

View File

@@ -0,0 +1,24 @@
$ANSIBLE_VAULT;1.1;AES256
30356233646632316565363533613033376333306433626366623230633838356230363461383135
3834363137353762316262363134643763353632306362640a613538306235633565356563613532
64643862613431313666363130376338356538323035346532636331316637646235346236333331
6336313466313434640a316437343866343061383838383362633638363633363535363330333463
64616330333361643166663061306338616265316262646339663438306465623231336139653764
63353862303538636636306430333464383339316233326133623564613337306266353730616564
63366562626135626136663665353663323265346438346131363838383263663665653937393066
32353061396661346138386561633734353634363164663438656331383663323035613264653265
38646164633465363238623232393731633761393466326466653430316532633139636533613033
39303764363861353666356239306366633662643865663033383235336663623632373566383330
32363334653936393962633266666439623130616161373231313037343735616361303131383230
62333863313432353536363962623161383434363136316264663061343038633065316232313334
38653233356135623431343166356464666663636330373663303663326561363333633837303337
66616464393661653835636665353439353539393530623730656331316235643032336337616436
64373163373932653038613765633061306331363962333932383564333735353534646637303237
62376561303364386662343331373631343166326261636362623432323437643735663437333564
39323961626131616334323131393963323231626638393231326631306337306230666138323830
63373331636234646431666332633633353637313338353536663539303531663938336132356134
30323631646666396239323261366435656434623537343935393531633966643135633561633636
31626266366432613936643937646537636164646334316562396639363132313862616433653535
34666537653433663466323730373363363064393334386133366365383435616436623963626634
31376162306565623262663732356463616464376231356432316137373138356466393663653035
613336396164633836626637393036303336