This commit is contained in:
Dan Allaire 2026-03-09 18:23:06 -04:00
parent e3e344398f
commit ef98fd8a3f
177 changed files with 1110 additions and 0 deletions

7
archives/README.md Normal file
View file

@ -0,0 +1,7 @@
# Archives
Contient :
- legacy
- variantes remplacées
- artefacts déplacés pendant migration

16
docs/README.md Normal file
View file

@ -0,0 +1,16 @@
# Documentation canonique
Ce dossier contient la documentation de référence de l'Alliance Boréale.
Branches principales :
- fondements
- modele
- architecture
- gouvernance
- decisions
- politiques
- ecosystemes
- guides
- corpus-a-integrer
- diffusion

View file

Before

Width:  |  Height:  |  Size: 268 B

After

Width:  |  Height:  |  Size: 268 B

9
infrastructure/README.md Normal file
View file

@ -0,0 +1,9 @@
# Infrastructure
Contient l'implémentation opératoire :
- ansible
- opentofu
- cloud-init
- templates
- netbox

2
infrastructure/ansible/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.retry
.ansible/

View file

@ -0,0 +1,57 @@
# ansible/
Sous-arbre Ansible de l'Alliance Boréale pour la **mise en conformité post-provisionnement** des VMs.
## Responsabilités
Ce sous-arbre prend des VMs déjà créées et accessibles en SSH, puis applique :
- la baseline packages commune ;
- le hardening OS ;
- le pare-feu local ;
- les mises à jour de sécurité automatiques ;
- l'agent Icinga2 ;
- l'agent Wazuh en option.
## Hors périmètre
Ne relèvent **pas** de ce sous-arbre :
- la création des VMs ;
- le clonage de templates ;
- la gestion Proxmox ;
- la génération initiale des ressources cloud-init.
Ces responsabilités appartiennent au sous-arbre `opentofu/` du dépôt principal.
## Structure
```text
ansible/
├── ansible.cfg
├── requirements.yml
├── inventories/prod/
│ ├── hosts.yml
│ ├── group_vars/all.yml
│ └── host_vars/
├── playbooks/
│ ├── site.yml
│ ├── baseline.yml
│ └── hardening.yml
├── roles/
│ ├── baseline_common/
│ ├── hardening_common/
│ ├── firewall_nftables/
│ ├── monitoring_icinga_agent/
│ └── security_wazuh_agent/
└── docs/
```
## Démarrage
1. Laisser OpenTofu générer `inventories/prod/hosts.yml`.
2. Ajuster `inventories/prod/group_vars/all.yml`.
3. Vérifier les réseaux d'administration autorisés dans le firewall.
4. Lancer :
```bash
ansible-playbook playbooks/site.yml
```

View file

@ -0,0 +1,18 @@
[defaults]
inventory = inventories/prod/hosts.yml
roles_path = roles
host_key_checking = False
retry_files_enabled = False
interpreter_python = auto_silent
stdout_callback = yaml
bin_ansible_callbacks = True
timeout = 30
forks = 20
gathering = smart
fact_caching = jsonfile
fact_caching_connection = .ansible/facts
fact_caching_timeout = 7200
[ssh_connection]
pipelining = True
scp_if_ssh = True

View file

@ -0,0 +1,33 @@
# Rapport de convergence — sous-arbre ansible/
## Décision d'architecture
Le dépôt Ansible fusionné a été recentré pour jouer un rôle unique :
**configurer et durcir des VMs déjà provisionnées**.
La création des VMs, le template Debian 12, le clonage et l'écriture de l'inventaire relèvent désormais du dépôt OpenTofu.
## Ce qui a été retenu
- `baseline_common`
- `hardening_common`
- `firewall_nftables`
- `monitoring_icinga_agent`
- `security_wazuh_agent`
- inventaire YAML simple
- playbooks séparés `baseline`, `hardening`, `site`
## Ce qui a été retiré du chemin principal
- `proxmox_debian12_template`
- `proxmox_vm_clone`
- `playbooks/proxmox/*`
## Logique cible
Le sous-arbre `ansible/` vise une baseline VM commune :
1. petite ;
2. reproductible ;
3. fermée par défaut ;
4. compatible avec l'inventaire généré par OpenTofu ;
5. prête à recevoir ensuite les rôles applicatifs C2/C3/C4/C5.

View file

@ -0,0 +1,86 @@
---
# Paramètres globaux de la baseline commune Alliance Boréale
ab_domain: example.internal
ab_dns_servers:
- 192.0.2.10
- 192.0.2.20
ab_admin_networks:
- 192.0.2.0/24
ab_ntp_server: c2-opnsense-01.example.internal
ab_ansible_user: ansible
ab_ansible_ssh_key_path: ~/.ssh/id_ed25519_ansible
ab_timezone: America/Montreal
ab_enable_wazuh_agent: false
ansible_user: "{{ ab_ansible_user }}"
ansible_ssh_private_key_file: "{{ ab_ansible_ssh_key_path }}"
# Baseline commune
baseline_common_enabled: true
baseline_common_upgrade: true
baseline_common_remove_packages: []
baseline_common_packages:
- apt-listchanges
- unattended-upgrades
- needrestart
- debsecan
- ca-certificates
- curl
- jq
- vim
- less
- git
- sudo
- rsync
- python3
- python3-apt
- acl
- chrony
- qemu-guest-agent
- nftables
- apparmor
- apparmor-utils
- fail2ban
- debian-archive-keyring
a_baseline_common_manage_sources: false
# Hardening commun
hardening_common_enabled: true
hardening_common_fail2ban_enabled: true
hardening_common_unattended_upgrades_enabled: true
hardening_common_debsecan_enabled: true
hardening_common_apparmor_enabled: true
hardening_common_journald_enabled: true
hardening_common_journald_system_max_use: 512M
hardening_common_journald_runtime_max_use: 128M
hardening_common_ssh_port: 22
hardening_common_ssh_allow_groups:
- sudo
hardening_common_ssh_listen_addresses: []
hardening_common_fail2ban_sshd_enabled: true
# Pare-feu local
firewall_nftables_enabled: true
firewall_nftables_allow_ipv6: true
firewall_nftables_policy_input: drop
firewall_nftables_policy_forward: drop
firewall_nftables_policy_output: accept
firewall_nftables_allowed_tcp_in:
- dport: 22
src: 192.0.2.0/24
firewall_nftables_allowed_udp_in: []
firewall_nftables_allow_icmp: true
# Monitoring commun
monitoring_icinga_agent_enabled: true
monitoring_icinga_agent_master: c3-icinga-01.example.internal
monitoring_icinga_agent_parent_zone: master
monitoring_icinga_agent_zone: "{{ inventory_hostname }}"
# Wazuh optionnel
security_wazuh_agent_enabled: "{{ ab_enable_wazuh_agent }}"
security_wazuh_agent_manager: c3-wazuh-01.example.internal
security_wazuh_agent_registration_password: ""

View file

@ -0,0 +1,4 @@
all:
children:
boreale_all:
hosts: {}

View file

@ -0,0 +1,6 @@
---
- name: Baseline packages et services communs
hosts: boreale_all
become: true
roles:
- role: baseline_common

View file

@ -0,0 +1,9 @@
---
- name: Hardening commun Alliance Boréale
hosts: boreale_all
become: true
roles:
- role: hardening_common
- role: firewall_nftables
- role: monitoring_icinga_agent
- role: security_wazuh_agent

View file

@ -0,0 +1,10 @@
---
- name: Baseline complète Alliance Boréale
hosts: boreale_all
become: true
roles:
- role: baseline_common
- role: hardening_common
- role: firewall_nftables
- role: monitoring_icinga_agent
- role: security_wazuh_agent

View file

@ -0,0 +1,4 @@
---
collections:
- name: ansible.posix
- name: community.general

View file

@ -0,0 +1,8 @@
---
baseline_common_enabled: true
baseline_common_upgrade: true
baseline_common_packages: []
baseline_common_remove_packages: []
baseline_common_manage_chrony: true
baseline_common_manage_timezone: true
baseline_common_qemu_guest_agent_service: qemu-guest-agent

View file

@ -0,0 +1,12 @@
---
- name: Restart chrony
ansible.builtin.systemd:
name: chrony
state: restarted
- name: Restart systemd-timesyncd if present
ansible.builtin.systemd:
name: systemd-timesyncd
state: stopped
enabled: false
failed_when: false

View file

@ -0,0 +1,61 @@
---
- name: Gate
ansible.builtin.meta: end_host
when: not baseline_common_enabled | bool
- name: Mettre à jour le cache APT
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Installer les paquets communs
ansible.builtin.apt:
name: "{{ baseline_common_packages }}"
state: present
- name: Retirer les paquets explicitement exclus
ansible.builtin.apt:
name: "{{ baseline_common_remove_packages }}"
state: absent
purge: true
when: baseline_common_remove_packages | length > 0
- name: Appliquer les mises à jour de distribution
ansible.builtin.apt:
upgrade: dist
when: baseline_common_upgrade | bool
- name: Régler le fuseau horaire
community.general.timezone:
name: "{{ ab_timezone }}"
when: baseline_common_manage_timezone | bool
- name: Désactiver systemd-timesyncd si présent
ansible.builtin.systemd:
name: systemd-timesyncd
enabled: false
state: stopped
failed_when: false
when: baseline_common_manage_chrony | bool
- name: Déployer la configuration chrony
ansible.builtin.template:
src: chrony.conf.j2
dest: /etc/chrony/chrony.conf
mode: '0644'
when: baseline_common_manage_chrony | bool
notify: Restart chrony
- name: Activer chrony
ansible.builtin.systemd:
name: chrony
enabled: true
state: started
when: baseline_common_manage_chrony | bool
- name: Activer qemu-guest-agent si présent
ansible.builtin.systemd:
name: "{{ baseline_common_qemu_guest_agent_service }}"
enabled: true
state: started
failed_when: false

View file

@ -0,0 +1,12 @@
# Ansible managed: baseline_common
pool 2.debian.pool.ntp.org iburst maxsources 2
server {{ ab_ntp_server }} iburst prefer
{% for dns in ab_dns_servers | default([]) %}
# DNS interne disponible: {{ dns }}
{% endfor %}
driftfile /var/lib/chrony/chrony.drift
rtcsync
makestep 1 3
logdir /var/log/chrony

View file

@ -0,0 +1,9 @@
---
firewall_nftables_enabled: true
firewall_nftables_allow_ipv6: true
firewall_nftables_allow_icmp: true
firewall_nftables_policy_input: drop
firewall_nftables_policy_forward: drop
firewall_nftables_policy_output: accept
firewall_nftables_allowed_tcp_in: []
firewall_nftables_allowed_udp_in: []

View file

@ -0,0 +1,5 @@
---
- name: Reload nftables
ansible.builtin.systemd:
name: nftables
state: reloaded

View file

@ -0,0 +1,23 @@
---
- name: Gate
ansible.builtin.meta: end_host
when: not firewall_nftables_enabled | bool
- name: Installer nftables
ansible.builtin.apt:
name: nftables
state: present
update_cache: true
- name: Déployer nftables
ansible.builtin.template:
src: nftables.conf.j2
dest: /etc/nftables.conf
mode: '0644'
notify: Reload nftables
- name: Activer nftables
ansible.builtin.systemd:
name: nftables
enabled: true
state: started

View file

@ -0,0 +1,34 @@
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
policy {{ firewall_nftables_policy_input }};
iif lo accept
ct state established,related accept
{% if firewall_nftables_allow_icmp %}
ip protocol icmp accept
{% if firewall_nftables_allow_ipv6 %}
ip6 nexthdr icmpv6 accept
{% endif %}
{% endif %}
{% for rule in firewall_nftables_allowed_tcp_in %}
tcp dport {{ rule.dport }} ip saddr {{ rule.src }} accept
{% endfor %}
{% for rule in firewall_nftables_allowed_udp_in %}
udp dport {{ rule.dport }} ip saddr {{ rule.src }} accept
{% endfor %}
}
chain forward {
type filter hook forward priority 0;
policy {{ firewall_nftables_policy_forward }};
}
chain output {
type filter hook output priority 0;
policy {{ firewall_nftables_policy_output }};
}
}

View file

@ -0,0 +1,58 @@
---
hardening_common_enabled: true
hardening_common_fail2ban_enabled: true
hardening_common_fail2ban_sshd_enabled: true
hardening_common_unattended_upgrades_enabled: true
hardening_common_debsecan_enabled: true
hardening_common_apparmor_enabled: true
hardening_common_journald_enabled: true
hardening_common_journald_system_max_use: 512M
hardening_common_journald_runtime_max_use: 128M
hardening_common_ssh_port: 22
hardening_common_ssh_allow_groups: []
hardening_common_ssh_listen_addresses: []
hardening_common_sysctl:
fs.protected_fifos: 2
fs.protected_hardlinks: 1
fs.protected_regular: 2
fs.protected_symlinks: 1
kernel.dmesg_restrict: 1
kernel.kptr_restrict: 2
kernel.randomize_va_space: 2
kernel.sysrq: 0
net.ipv4.conf.all.accept_redirects: 0
net.ipv4.conf.default.accept_redirects: 0
net.ipv4.conf.all.accept_source_route: 0
net.ipv4.conf.default.accept_source_route: 0
net.ipv4.conf.all.log_martians: 1
net.ipv4.conf.default.log_martians: 1
net.ipv4.conf.all.rp_filter: 1
net.ipv4.conf.default.rp_filter: 1
net.ipv4.conf.all.send_redirects: 0
net.ipv4.conf.default.send_redirects: 0
net.ipv4.icmp_echo_ignore_broadcasts: 1
net.ipv4.ip_forward: 0
net.ipv4.tcp_syncookies: 1
net.ipv6.conf.all.accept_redirects: 0
net.ipv6.conf.default.accept_redirects: 0
net.ipv6.conf.all.accept_source_route: 0
net.ipv6.conf.default.accept_source_route: 0
hardening_common_sshd_settings:
PasswordAuthentication: 'no'
PermitRootLogin: 'no'
KbdInteractiveAuthentication: 'no'
ChallengeResponseAuthentication: 'no'
PubkeyAuthentication: 'yes'
X11Forwarding: 'no'
MaxAuthTries: '3'
LoginGraceTime: '30'
AllowAgentForwarding: 'no'
AllowTcpForwarding: 'no'
TCPKeepAlive: 'no'
ClientAliveInterval: '300'
ClientAliveCountMax: '2'
MaxSessions: '10'
MaxStartups: '10:30:60'
Protocol: '2'
Port: '22'
UsePAM: 'yes'

View file

@ -0,0 +1,15 @@
---
- name: Reload ssh
ansible.builtin.systemd:
name: ssh
state: reloaded
- name: Restart journald
ansible.builtin.systemd:
name: systemd-journald
state: restarted
- name: Restart fail2ban
ansible.builtin.systemd:
name: fail2ban
state: restarted

View file

@ -0,0 +1,86 @@
---
- name: Gate
ansible.builtin.meta: end_host
when: not hardening_common_enabled | bool
- name: Appliquer le socle sysctl
ansible.posix.sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present
sysctl_set: true
reload: true
loop: "{{ hardening_common_sysctl | dict2items }}"
- name: Déployer le drop-in SSH durci
ansible.builtin.template:
src: sshd_boreale_hardening.conf.j2
dest: /etc/ssh/sshd_config.d/99-boreale-hardening.conf
mode: '0644'
validate: '/usr/sbin/sshd -T -f %s'
notify: Reload ssh
- name: Déployer le drop-in journald
ansible.builtin.template:
src: journald-boreale.conf.j2
dest: /etc/systemd/journald.conf.d/99-boreale.conf
mode: '0644'
when: hardening_common_journald_enabled | bool
notify: Restart journald
- name: Installer fail2ban
ansible.builtin.apt:
name: fail2ban
state: present
when: hardening_common_fail2ban_enabled | bool
- name: Déployer la jail sshd fail2ban
ansible.builtin.template:
src: jail-sshd.local.j2
dest: /etc/fail2ban/jail.d/sshd.local
mode: '0644'
when:
- hardening_common_fail2ban_enabled | bool
- hardening_common_fail2ban_sshd_enabled | bool
notify: Restart fail2ban
- name: Activer fail2ban
ansible.builtin.systemd:
name: fail2ban
enabled: true
state: started
when: hardening_common_fail2ban_enabled | bool
- name: Déployer unattended-upgrades auto
ansible.builtin.copy:
dest: /etc/apt/apt.conf.d/20auto-upgrades
mode: '0644'
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
when: hardening_common_unattended_upgrades_enabled | bool
- name: Déployer unattended-upgrades de base
ansible.builtin.copy:
dest: /etc/apt/apt.conf.d/52unattended-upgrades-local
mode: '0644'
content: |
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
when: hardening_common_unattended_upgrades_enabled | bool
- name: Installer debsecan
ansible.builtin.apt:
name: debsecan
state: present
when: hardening_common_debsecan_enabled | bool
- name: Activer AppArmor
ansible.builtin.systemd:
name: apparmor
enabled: true
state: started
failed_when: false
when: hardening_common_apparmor_enabled | bool

View file

@ -0,0 +1,7 @@
[sshd]
enabled = true
port = {{ hardening_common_ssh_port }}
backend = systemd
maxretry = 4
findtime = 10m
bantime = 1h

Some files were not shown because too many files have changed in this diff Show more