premier commit
This commit is contained in:
commit
bd5947b5d7
68 changed files with 3782 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
*.retry
|
||||
*.log
|
||||
inventories/**/group_vars/vault.yml
|
||||
25
README.md
Normal file
25
README.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Chezlepro Ansible (nouveau dépôt)
|
||||
|
||||
Dépôt Ansible normalisé (inventaire + playbooks + rôles) pour l'écosystème Chezlepro.
|
||||
|
||||
## Démarrage rapide
|
||||
|
||||
1) Ajuster l'inventaire :
|
||||
- `inventories/prod/hosts.yml`
|
||||
- `inventories/prod/group_vars/all.yml`
|
||||
- (optionnel) `inventories/prod/group_vars/vault.yml` (Ansible Vault)
|
||||
|
||||
2) Exécuter :
|
||||
```bash
|
||||
ansible-playbook -i inventories/prod/hosts.yml playbooks/site.yml
|
||||
```
|
||||
|
||||
## Playbooks
|
||||
- `playbooks/site.yml` : orchestration globale (baseline + sécurité + services)
|
||||
- `playbooks/proxmox_deb12_cloudinit.yml` : provisioning Proxmox (template Debian 12 + clones)
|
||||
|
||||
## Rôles
|
||||
- Baseline : `baseline_packages`, `baseline_updates`
|
||||
- Sécurité : `security_hardening`, `firewall_nftables`
|
||||
- Services : `monitoring_icinga`, `dns_powerdns`, `reverse_proxy_traefik`
|
||||
- Proxmox : `proxmox_deb12_cloudinit`
|
||||
10
ansible.cfg
Normal file
10
ansible.cfg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[defaults]
|
||||
inventory = inventories/prod/hosts.yml
|
||||
stdout_callback = yaml
|
||||
interpreter_python = auto_silent
|
||||
host_key_checking = False
|
||||
retry_files_enabled = False
|
||||
forks = 10
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
36
docs/opnsense-changelog.md
Normal file
36
docs/opnsense-changelog.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# OPNsense — Journal des modifications
|
||||
|
||||
## Règles
|
||||
- 1 changement = 1 entrée
|
||||
- Toujours joindre un export de config **post-changement**
|
||||
- Écrire “rollback” possible en une phrase
|
||||
|
||||
---
|
||||
|
||||
## Format d’entrée
|
||||
- Date/heure :
|
||||
- Auteur :
|
||||
- Contexte :
|
||||
- Changement :
|
||||
- Impact attendu :
|
||||
- Validation effectuée :
|
||||
- Export config :
|
||||
- Rollback :
|
||||
|
||||
---
|
||||
|
||||
## Entrées
|
||||
|
||||
### YYYY-MM-DD HH:MM
|
||||
- Auteur :
|
||||
- Contexte :
|
||||
- Changement :
|
||||
- Impact attendu :
|
||||
- Validation effectuée :
|
||||
- [ ] Accès admin OK
|
||||
- [ ] DNS OK
|
||||
- [ ] NTP OK
|
||||
- [ ] LAN/WAN OK
|
||||
- [ ] Monitoring OK
|
||||
- Export config : `opnsense-<site>-<role>-YYYYMMDD-HHMM.xml`
|
||||
- Rollback : importer l’export précédent `...`
|
||||
178
docs/opnsense-runbook.md
Normal file
178
docs/opnsense-runbook.md
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# OPNsense — Runbook (générique)
|
||||
|
||||
## Objectif
|
||||
Ce document décrit une méthode simple et reproductible pour :
|
||||
- opérer un pare-feu OPNsense sans Infrastructure-as-Code,
|
||||
- garder une source de vérité,
|
||||
- restaurer rapidement en cas de panne,
|
||||
- limiter les erreurs humaines (drift, changements non documentés).
|
||||
|
||||
## Portée
|
||||
- OPNsense (pare-feu, routage, NAT, DHCP/DNS si applicable)
|
||||
- Sauvegarde/restauration de configuration
|
||||
- Cadre de gestion des changements
|
||||
- Vérifications post-changement
|
||||
- Intégration opérationnelle (monitoring, inventaire)
|
||||
|
||||
## Principes
|
||||
1. **UI = configuration** (source de vérité opérationnelle).
|
||||
2. **Chaque changement = export de config + note de changelog**.
|
||||
3. **Restauration testée** au moins 1 fois par trimestre (sur matériel de spare ou VM si possible).
|
||||
4. **Secrets** : jamais en clair dans Git; chiffrer ou stocker dans Nextcloud avec contrôle d’accès.
|
||||
|
||||
---
|
||||
|
||||
## Pré-requis (à compléter)
|
||||
- Modèle matériel : __________________________
|
||||
- Version OPNsense : _________________________
|
||||
- Mode HA (si applicable) : ___________________
|
||||
- Accès admin : ______________________________
|
||||
- Emplacement des exports : ___________________
|
||||
- Emplacement des backups chiffrés : __________
|
||||
|
||||
---
|
||||
|
||||
## Inventaire minimal (à maintenir)
|
||||
### Interfaces
|
||||
| Nom | Rôle | VLAN | IPv4/IPv6 | Notes |
|
||||
|---|---|---:|---|---|
|
||||
| WAN | Internet | - | - | - |
|
||||
| LAN | Interne | - | - | - |
|
||||
| OPTx | Réseau/VLAN | - | - | - |
|
||||
|
||||
### Réseaux / VLAN
|
||||
- LAN: ______________________
|
||||
- VLANs: _____________________
|
||||
- Réseaux de services (DNS/NTP/monitoring): _____________________
|
||||
|
||||
### Services activés
|
||||
- DHCP : oui/non (sur quels réseaux)
|
||||
- DNS (Unbound) : oui/non
|
||||
- NTP : oui/non
|
||||
- VPN : oui/non (type : WireGuard/OpenVPN/IPsec)
|
||||
- Captive portal : oui/non
|
||||
- IDS/IPS : oui/non (Suricata, etc.)
|
||||
|
||||
---
|
||||
|
||||
## Sauvegarde (backup) de configuration
|
||||
|
||||
### Quand sauvegarder
|
||||
- Après **tout changement** (immédiatement après validation).
|
||||
- Avant toute mise à jour majeure.
|
||||
- Sauvegarde planifiée : hebdo (recommandé).
|
||||
|
||||
### Comment sauvegarder (procédure manuelle)
|
||||
1. Se connecter à l’UI OPNsense.
|
||||
2. Aller dans **System → Configuration → Backups** (ou équivalent selon version).
|
||||
3. Exporter la configuration (format XML).
|
||||
4. Nommer le fichier :
|
||||
- `opnsense-<site>-<role>-YYYYMMDD-HHMM.xml`
|
||||
5. Stocker :
|
||||
- copie “opérations” (Nextcloud privé / stockage interne),
|
||||
- copie “reprise” (stockage secondaire hors site, chiffrée si possible).
|
||||
|
||||
### Convention de stockage recommandée
|
||||
- `backups/opnsense/<site>/<YYYY>/<MM>/opnsense-...xml`
|
||||
- Un index `backups/opnsense/README.md` expliquant où est la dernière version.
|
||||
|
||||
### Protection des backups
|
||||
- Restreindre l’accès (admin seulement).
|
||||
- Si Git est utilisé : **chiffrer** (ex. fichier chiffré + clé hors Git).
|
||||
|
||||
---
|
||||
|
||||
## Restauration (disaster recovery)
|
||||
|
||||
### Scénarios
|
||||
- Remplacement SSD / panne matérielle
|
||||
- Mauvaise configuration (lockout)
|
||||
- Mise à jour ratée
|
||||
- Migration vers nouveau matériel
|
||||
|
||||
### Procédure de restauration (standard)
|
||||
1. Installer OPNsense (version identique si possible).
|
||||
2. Configurer accès minimal (WAN/LAN + admin).
|
||||
3. Importer le fichier XML (System → Configuration → Restore).
|
||||
4. Redémarrer si requis.
|
||||
5. Vérifier :
|
||||
- interfaces / VLAN / gateways
|
||||
- DNS/NTP
|
||||
- règles firewall (ordre, alias)
|
||||
- NAT/port forward
|
||||
- VPN (si utilisé)
|
||||
6. Valider la connectivité “de bout en bout”.
|
||||
|
||||
### Procédure en cas de lockout
|
||||
- Avoir une méthode “console”/local :
|
||||
- accès clavier/écran ou IPMI (si disponible),
|
||||
- rollback via backup,
|
||||
- vérifier règle admin “allow” sur LAN de management.
|
||||
|
||||
---
|
||||
|
||||
## Gestion des changements
|
||||
|
||||
### Règle simple
|
||||
- Un changement = une intention = une entrée dans le changelog + un export post-changement.
|
||||
|
||||
### Processus recommandé (léger)
|
||||
1. Définir l’objectif (1 phrase).
|
||||
2. Appliquer dans l’UI.
|
||||
3. Vérifier (section “Vérifications post-changement”).
|
||||
4. Exporter la config.
|
||||
5. Écrire 1 entrée dans le changelog.
|
||||
|
||||
---
|
||||
|
||||
## Vérifications post-changement (checklist)
|
||||
### Accès / sécurité
|
||||
- [ ] Accès admin local (LAN management) OK
|
||||
- [ ] Accès distant (si applicable) OK
|
||||
- [ ] Aucune règle “allow any any” accidentelle
|
||||
- [ ] Journaux consultés (erreurs/deny inattendus)
|
||||
|
||||
### Réseau
|
||||
- [ ] Ping vers passerelle
|
||||
- [ ] Résolution DNS depuis LAN
|
||||
- [ ] NTP synchronisé
|
||||
- [ ] Routage inter-VLAN (si applicable)
|
||||
- [ ] NAT/port forward (si applicable)
|
||||
|
||||
### Services
|
||||
- [ ] DHCP délivre des baux (si activé)
|
||||
- [ ] DNS (Unbound) répond (si activé)
|
||||
- [ ] VPN up (si utilisé)
|
||||
- [ ] IDS/IPS stable (si activé)
|
||||
|
||||
### Monitoring
|
||||
- [ ] Checks externes (Icinga) au vert
|
||||
- [ ] Latence/perte dans les seuils
|
||||
|
||||
---
|
||||
|
||||
## Mises à jour (upgrade)
|
||||
### Avant
|
||||
- [ ] Export de config
|
||||
- [ ] Note dans changelog
|
||||
- [ ] Fenêtre de maintenance
|
||||
- [ ] Plan de rollback (version + backup)
|
||||
|
||||
### Après
|
||||
- [ ] Vérifications post-changement
|
||||
- [ ] Export de config (post-upgrade)
|
||||
|
||||
---
|
||||
|
||||
## Annexes (à compléter)
|
||||
### Alias (liste)
|
||||
- ALIAS_1 : ___________________
|
||||
- ALIAS_2 : ___________________
|
||||
|
||||
### NAT / Port forwards (intention)
|
||||
- Service A : ___________________
|
||||
- Service B : ___________________
|
||||
|
||||
### VPN (intention)
|
||||
- Site-to-site : ___________________
|
||||
- Remote access : ___________________
|
||||
21
inventories/prod/group_vars/all.yml
Normal file
21
inventories/prod/group_vars/all.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Global defaults / overrides
|
||||
|
||||
# Baseline
|
||||
baseline_packages_enabled: true
|
||||
baseline_updates_enabled: true
|
||||
|
||||
# Security
|
||||
security_hardening_enabled: true
|
||||
firewall_nftables_enabled: true
|
||||
|
||||
# Monitoring (unifié)
|
||||
monitoring_icinga_enabled: true
|
||||
monitoring_icinga_agent_enabled: true
|
||||
monitoring_icinga_plugins_enabled: false
|
||||
monitoring_icinga_director_enabled: false
|
||||
|
||||
# DNS (PowerDNS)
|
||||
dns_powerdns_enabled: false
|
||||
|
||||
# Reverse proxy (Traefik)
|
||||
reverse_proxy_traefik_enabled: false
|
||||
13
inventories/prod/hosts.yml
Normal file
13
inventories/prod/hosts.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
all:
|
||||
children:
|
||||
servers:
|
||||
hosts:
|
||||
# exemple:
|
||||
# srv1:
|
||||
# ansible_host: 192.168.15.10
|
||||
dns:
|
||||
hosts: {}
|
||||
proxy:
|
||||
hosts: {}
|
||||
proxmox:
|
||||
hosts: {}
|
||||
53
playbooks/legacy/dev_workspace_ansible.yml
Normal file
53
playbooks/legacy/dev_workspace_ansible.yml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
- name: Kernel hardening - sysctl
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Configure sysctl settings for kernel hardening
|
||||
sysctl:
|
||||
name: "{{ item.key }}"
|
||||
value: "{{ item.value }}"
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
reload: yes
|
||||
loop:
|
||||
- { key: fs.suid_dumpable, value: 0 }
|
||||
- { key: kernel.core_uses_pid, value: 1 }
|
||||
- { key: kernel.dmesg_restrict, value: 1 }
|
||||
- { key: kernel.kptr_restrict, value: 2 }
|
||||
- { key: kernel.sysrq, value: 0 }
|
||||
# - { key: net.ipv4.conf.all.forwarding, value: 0 }
|
||||
- { key: net.ipv4.conf.all.log_martians, value: 1 }
|
||||
- { key: net.ipv4.conf.all.rp_filter, value: 1 }
|
||||
- { key: net.ipv4.conf.all.send_redirects, value: 0 }
|
||||
- { key: net.ipv4.conf.default.accept_redirects, value: 0 }
|
||||
- { key: net.ipv4.conf.default.accept_source_route, value: 0 }
|
||||
- { key: net.ipv4.conf.default.log_martians, value: 1 }
|
||||
- { key: net.ipv6.conf.all.accept_redirects, value: 0 }
|
||||
- { key: net.ipv6.conf.default.accept_redirects, value: 0 }
|
||||
|
||||
- name: Ensure settings are persistent in /etc/sysctl.conf or drop-in
|
||||
copy:
|
||||
dest: "/etc/sysctl.d/99-hardening.conf"
|
||||
content: |
|
||||
fs.suid_dumpable = 0
|
||||
kernel.core_uses_pid = 1
|
||||
kernel.dmesg_restrict = 1
|
||||
kernel.kptr_restrict = 2
|
||||
kernel.sysrq = 0
|
||||
#net.ipv4.conf.all.forwarding = 0
|
||||
net.ipv4.conf.all.log_martians = 1
|
||||
net.ipv4.conf.all.rp_filter = 1
|
||||
net.ipv4.conf.all.send_redirects = 0
|
||||
net.ipv4.conf.default.accept_redirects = 0
|
||||
net.ipv4.conf.default.accept_source_route = 0
|
||||
net.ipv4.conf.default.log_martians = 1
|
||||
net.ipv6.conf.all.accept_redirects = 0
|
||||
net.ipv6.conf.default.accept_redirects = 0
|
||||
mode: '0644'
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Reload sysctl to apply new settings
|
||||
command: sysctl --system
|
||||
112
playbooks/legacy/docker-compose.yml
Normal file
112
playbooks/legacy/docker-compose.yml
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
##########################################################
|
||||
# 1) STEPCA - Autorité de certification ACME interne
|
||||
##########################################################
|
||||
stepca:
|
||||
image: smallstep/step-ca:latest
|
||||
container_name: stepca
|
||||
environment:
|
||||
STEPPATH: /home/step
|
||||
volumes:
|
||||
- ./step_data:/home/step
|
||||
expose:
|
||||
- '9000' # Port interne (ACME / API)
|
||||
networks:
|
||||
- back_net
|
||||
|
||||
##########################################################
|
||||
# 2) KEYCLOAK
|
||||
##########################################################
|
||||
keycloak:
|
||||
image: quay.io/keycloak/keycloak:latest
|
||||
container_name: keycloak
|
||||
environment:
|
||||
KEYCLOAK_ADMIN: admin
|
||||
KEYCLOAK_ADMIN_PASSWORD: admin
|
||||
command: >
|
||||
start-dev
|
||||
--http-relative-path /auth
|
||||
expose:
|
||||
- '8080'
|
||||
networks:
|
||||
- back_net
|
||||
|
||||
##########################################################
|
||||
# 3) ERPLibre : MySQL (erplibre_db) + PHP-FPM (erplibre_php)
|
||||
##########################################################
|
||||
erplibre_db:
|
||||
image: mysql:5.7
|
||||
container_name: erplibre_db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: erplibre
|
||||
MYSQL_USER: erplibre
|
||||
MYSQL_PASSWORD: erplibre
|
||||
command: >
|
||||
--default-authentication-plugin=mysql_native_password
|
||||
--collation-server=utf8mb4_unicode_ci
|
||||
--character-set-server=utf8mb4
|
||||
volumes:
|
||||
- ./erplibre_db_data:/var/lib/mysql
|
||||
networks:
|
||||
- back_net
|
||||
|
||||
erplibre_php:
|
||||
# Dans l'idéal, tu construis l'image depuis le code ERPLibre (backend).
|
||||
# Sinon, s'ils fournissent une image Docker "prête à l'emploi", utilise-la ici.
|
||||
build:
|
||||
context: ./backend
|
||||
container_name: erplibre_php
|
||||
environment:
|
||||
DB_HOST: erplibre_db
|
||||
DB_DATABASE: erplibre
|
||||
DB_USERNAME: erplibre
|
||||
DB_PASSWORD: erplibre
|
||||
expose:
|
||||
- "9000"
|
||||
depends_on:
|
||||
- erplibre_db
|
||||
networks:
|
||||
- back_net
|
||||
|
||||
##########################################################
|
||||
# 4) CERTBOT - pour récupérer des certs depuis StepCA
|
||||
##########################################################
|
||||
certbot:
|
||||
image: certbot/certbot:latest
|
||||
container_name: certbot
|
||||
volumes:
|
||||
- ./certs:/etc/letsencrypt
|
||||
networks:
|
||||
- back_net
|
||||
# Pas d'expose: on l'invoque manuellement ou via cron
|
||||
|
||||
##########################################################
|
||||
# 5) NGINX - Reverse Proxy unique pour tout
|
||||
##########################################################
|
||||
nginx:
|
||||
image: nginx:latest
|
||||
container_name: nginx_proxy
|
||||
depends_on:
|
||||
- stepca
|
||||
- keycloak
|
||||
- erplibre_php
|
||||
- erplibre_db
|
||||
ports:
|
||||
- '80:80'
|
||||
- '443:443'
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./certs:/etc/nginx/certs
|
||||
networks:
|
||||
- front_net
|
||||
- back_net
|
||||
|
||||
networks:
|
||||
front_net:
|
||||
driver: bridge
|
||||
back_net:
|
||||
driver: bridge
|
||||
|
||||
42
playbooks/legacy/docker_keycloak.yml
Normal file
42
playbooks/legacy/docker_keycloak.yml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
- name: Déployer Keycloak dans Docker
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Télécharger l'image Docker Keycloak
|
||||
docker_image:
|
||||
name: quay.io/keycloak/keycloak
|
||||
tag: latest
|
||||
source: pull
|
||||
|
||||
- name: Créer un répertoire pour les données de Keycloak
|
||||
file:
|
||||
path: /opt/keycloak
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Exécuter le conteneur Keycloak
|
||||
docker_container:
|
||||
name: keycloak
|
||||
image: quay.io/keycloak/keycloak:latest
|
||||
state: started
|
||||
restart_policy: always
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "8443:8443"
|
||||
volumes:
|
||||
- /opt/keycloak:/opt/keycloak/data
|
||||
env:
|
||||
KEYCLOAK_ADMIN: "admin"
|
||||
KEYCLOAK_ADMIN_PASSWORD: "admin"
|
||||
command: start-dev
|
||||
|
||||
- name: Afficher l'état du conteneur Keycloak en cours d'exécution
|
||||
command: docker ps
|
||||
register: docker_ps_output
|
||||
|
||||
- name: Imprimer l'état de Keycloak
|
||||
debug:
|
||||
var: docker_ps_output.stdout
|
||||
|
||||
39
playbooks/legacy/docker_smallStepCA.yml
Normal file
39
playbooks/legacy/docker_smallStepCA.yml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
- name: Déployer Smallstep CA dans Docker
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Télécharger l'image Docker Smallstep CA
|
||||
docker_image:
|
||||
name: smallstep/step-ca
|
||||
tag: latest
|
||||
source: pull
|
||||
|
||||
- name: Créer un répertoire pour les données de Smallstep CA
|
||||
file:
|
||||
path: /opt/smallstep-ca
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Exécuter le conteneur Smallstep CA
|
||||
docker_container:
|
||||
name: smallstep-ca
|
||||
image: smallstep/step-ca:latest
|
||||
state: started
|
||||
restart_policy: always
|
||||
ports:
|
||||
- "9000:9000"
|
||||
volumes:
|
||||
- /opt/smallstep-ca:/home/step
|
||||
env:
|
||||
STEP_CA_PASSWORD: "changeit"
|
||||
|
||||
- name: Afficher l'état du conteneur Smallstep CA en cours d'exécution
|
||||
command: docker ps
|
||||
register: docker_ps_output
|
||||
|
||||
- name: Imprimer l'état de Smallstep CA
|
||||
debug:
|
||||
var: docker_ps_output.stdout
|
||||
|
||||
57
playbooks/legacy/docker_smallStepCA_v2.yml
Normal file
57
playbooks/legacy/docker_smallStepCA_v2.yml
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
- name: Deploy Smallstep CA with Docker Compose
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
tasks:
|
||||
- name: Create the directory for Docker Compose
|
||||
file:
|
||||
path: /opt/smallstep
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create the secrets directory for Smallstep
|
||||
file:
|
||||
path: /opt/smallstep/secrets
|
||||
state: directory
|
||||
mode: '0700'
|
||||
|
||||
- name: Create the password file for Smallstep CA
|
||||
copy:
|
||||
dest: /opt/smallstep/secrets/password
|
||||
content: "T0rp1n0uch3."
|
||||
mode: '0600'
|
||||
|
||||
- name: Create docker-compose.yml for Smallstep CA
|
||||
copy:
|
||||
dest: /opt/smallstep/docker-compose.yml
|
||||
content: |
|
||||
version: '3.8'
|
||||
services:
|
||||
step-ca:
|
||||
image: smallstep/step-ca:latest
|
||||
container_name: step-ca
|
||||
ports:
|
||||
- "443:443"
|
||||
environment:
|
||||
DOCKER_STEPCA_INIT_NAME: "MoiJeLConnais"
|
||||
DOCKER_STEPCA_INIT_DNS_NAMES: "example.com,api.example.com"
|
||||
DOCKER_STEPCA_INIT_PASSWORD_FILE: "/home/step/secrets/password"
|
||||
DOCKER_STEPCA_INIT_PROVISIONER_NAME: "admin"
|
||||
DOCKER_STEPCA_INIT_PROVISIONER_PASSWORD_FILE: "/home/step/secrets/password"
|
||||
volumes:
|
||||
- "/opt/smallstep/data:/home/step"
|
||||
- "/opt/smallstep/secrets:/home/step/secrets"
|
||||
restart: always
|
||||
mode: '0644'
|
||||
|
||||
- name: Install Docker Compose (if not already installed)
|
||||
apt:
|
||||
name: docker-compose
|
||||
state: present
|
||||
when: ansible_facts['os_family'] == "Debian"
|
||||
|
||||
- name: Start Smallstep CA with Docker Compose
|
||||
command: docker-compose up -d
|
||||
args:
|
||||
chdir: /opt/smallstep
|
||||
|
||||
11
playbooks/legacy/download_updates.yml
Normal file
11
playbooks/legacy/download_updates.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
- name: Exécuter apt upgrade sur tous les serveurs
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
- name: Mettre à jour la liste des paquets APT
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
|
||||
567
playbooks/legacy/durcissement_se.yml
Normal file
567
playbooks/legacy/durcissement_se.yml
Normal file
|
|
@ -0,0 +1,567 @@
|
|||
---
|
||||
- name: Apply security hardening based on Linys recommendations
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
tasks:
|
||||
- name: Ensure UFW is installed
|
||||
apt:
|
||||
name: ufw
|
||||
state: present
|
||||
|
||||
- name: Allow SSH immediately
|
||||
command: ufw allow 22/tcp
|
||||
|
||||
- name: Set default policy to deny incoming traffic
|
||||
command: ufw default deny incoming
|
||||
|
||||
- name: Set default policy to allow outgoing traffic
|
||||
command: ufw default allow outgoing
|
||||
|
||||
- name: Allow HTTP and HTTPS
|
||||
command: ufw allow {{ item }}/tcp
|
||||
loop:
|
||||
- 80
|
||||
- 443
|
||||
|
||||
- name: Allow ICINGA2 ports
|
||||
command: ufw allow 5665/tcp
|
||||
|
||||
- name: Allow OpenVPN port
|
||||
command: ufw allow 1194/udp
|
||||
|
||||
- name: Enable UFW without confirmation
|
||||
command: echo "y" | ufw enable
|
||||
|
||||
- name: Verify UFW rules
|
||||
command: ufw status verbose
|
||||
register: ufw_status
|
||||
changed_when: false
|
||||
|
||||
- name: Display UFW configuration
|
||||
debug:
|
||||
msg: "{{ ufw_status.stdout }}"
|
||||
|
||||
# 4. Installation des mises à jour & des rustines
|
||||
- name: Mettre à jour la liste des paquets APT
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Mettre à jour uniquement les paquets installés
|
||||
apt:
|
||||
upgrade: yes
|
||||
|
||||
|
||||
# 5. Ensure correct file permissions on sensitive files
|
||||
- name: Set permissions on /etc/passwd
|
||||
file:
|
||||
path: /etc/passwd
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Set permissions on /etc/shadow
|
||||
file:
|
||||
path: /etc/shadow
|
||||
owner: root
|
||||
group: shadow
|
||||
mode: '0640'
|
||||
|
||||
- name: Set permissions on /etc/group
|
||||
file:
|
||||
path: /etc/group
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Set permissions on /etc/gshadow
|
||||
file:
|
||||
path: /etc/gshadow
|
||||
owner: root
|
||||
group: shadow
|
||||
mode: '0640'
|
||||
|
||||
# 6. Disable core dumps (to prevent information leakage)
|
||||
- name: Disable core dumps
|
||||
lineinfile:
|
||||
path: /etc/security/limits.conf
|
||||
line: '* hard core 0'
|
||||
state: present
|
||||
|
||||
- name: Ensure core dumps are disabled via sysctl
|
||||
sysctl:
|
||||
name: fs.suid_dumpable
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
# 7. Restrict cron jobs
|
||||
- name: Restrict cron jobs to root and authorized users
|
||||
file:
|
||||
path: /etc/cron.deny
|
||||
state: absent
|
||||
|
||||
- name: Ensure /etc/cron.allow exists and has correct permissions
|
||||
file:
|
||||
path: /etc/cron.allow
|
||||
state: touch
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0640'
|
||||
|
||||
# 7. Améliorer la sécurité des répertoires temporaires
|
||||
- name: Install libpam-tmpdir and apt-listbugs
|
||||
apt:
|
||||
name:
|
||||
- libpam-tmpdir
|
||||
state: present
|
||||
|
||||
# 8. Disable IPv6 if not in use
|
||||
- name: Disable IPv6 via sysctl
|
||||
sysctl:
|
||||
name: net.ipv6.conf.all.disable_ipv6
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
reload: yes
|
||||
|
||||
# Adjust kernel and sysctl parameters for hardening
|
||||
- name: Disable TTY line discipline autoload
|
||||
sysctl:
|
||||
name: dev.tty.ldisc_autoload
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Use PID in core dump filenames
|
||||
sysctl:
|
||||
name: kernel.core_uses_pid
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
# ATTENTION !!! IRRÉVERSIBLE !!! PAS TOUCHE AVANT SNAPSHOT !!!
|
||||
#- name: Disable loading of kernel modules after boot
|
||||
# sysctl:
|
||||
# name: kernel.modules_disabled
|
||||
# value: '1'
|
||||
# state: present
|
||||
# sysctl_set: yes
|
||||
|
||||
- name: Disable unprivileged BPF
|
||||
sysctl:
|
||||
name: kernel.unprivileged_bpf_disabled
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Restrict ptrace to parent processes only
|
||||
sysctl:
|
||||
name: kernel.yama.ptrace_scope
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Harden BPF JIT compilation
|
||||
sysctl:
|
||||
name: net.core.bpf_jit_harden
|
||||
value: '2'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Enable reverse path filtering for IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.all.rp_filter
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Disable sending of ICMP redirects for IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.all.send_redirects
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Disable accepting of ICMP redirects by default for IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.default.accept_redirects
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Enable logging of suspicious packets for default IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.default.log_martians
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Disable accepting of ICMP redirects by default for IPv6
|
||||
sysctl:
|
||||
name: net.ipv6.conf.default.accept_redirects
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
# 9. Ensure auditing is configured (auditd)
|
||||
- name: Install auditd
|
||||
apt:
|
||||
name: auditd
|
||||
state: present
|
||||
|
||||
- name: Ensure auditd service is enabled and running
|
||||
service:
|
||||
name: auditd
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
# 12. Enable AppArmor (or SELinux on supported systems)
|
||||
- name: Ensure AppArmor is enabled and running
|
||||
service:
|
||||
name: apparmor
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
# 13. Create a banner for unauthorized access
|
||||
- name: Create a message of the day (MOTD) banner
|
||||
copy:
|
||||
dest: /etc/motd
|
||||
content: |
|
||||
|
||||
********************** AVERTISSEMENT ***********************
|
||||
|
||||
Ce système est strictement réservé aux utilisateurs autorisés
|
||||
Toute tentative d'accès non autorisé est interdite et peut
|
||||
être signalée aux autorités compétentes.
|
||||
|
||||
Votre activité peut être surveillée et enregistrée.
|
||||
En continuant, vous acceptez ces conditions.
|
||||
|
||||
|
||||
************************ WARNING ***************************
|
||||
|
||||
This system is strictly for authorized users only.
|
||||
Any unauthorized access attempts are prohibited and may
|
||||
be reported to the appropriate authorities.
|
||||
|
||||
Your activity may be monitored and logged.
|
||||
By proceeding, you accept these terms.
|
||||
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
# 14. Apply SSH hardening configuration
|
||||
|
||||
- name: Backup the current sshd_config
|
||||
copy:
|
||||
src: /etc/ssh/sshd_config
|
||||
dest: /etc/ssh/sshd_config.bak
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
remote_src: yes
|
||||
backup: yes
|
||||
|
||||
- name: Ensure banner is displayed on SSH login
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?Banner'
|
||||
line: 'Banner /etc/motd'
|
||||
state: present
|
||||
|
||||
- name: Backup the current sshd_config
|
||||
copy:
|
||||
src: /etc/ssh/sshd_config
|
||||
dest: /etc/ssh/sshd_config.bak
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
remote_src: yes
|
||||
backup: yes
|
||||
|
||||
- name: Ensure the PermitRootLogin is set to no (disable root login)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitRootLogin'
|
||||
line: 'PermitRootLogin no'
|
||||
state: present
|
||||
|
||||
- name: Ensure PasswordAuthentication is set to no (force key-based authentication)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PasswordAuthentication'
|
||||
line: 'PasswordAuthentication no'
|
||||
state: present
|
||||
|
||||
- name: Disable empty passwords
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitEmptyPasswords'
|
||||
line: 'PermitEmptyPasswords no'
|
||||
state: present
|
||||
|
||||
- name: Set MaxAuthTries to 3 (limit authentication attempts)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?MaxAuthTries'
|
||||
line: 'MaxAuthTries 3'
|
||||
state: present
|
||||
|
||||
- name: Set MaxSessions to 2 (limit open sessions)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?MaxSessions'
|
||||
line: 'MaxSessions 2'
|
||||
state: present
|
||||
|
||||
- name: Disable X11 forwarding
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?X11Forwarding'
|
||||
line: 'X11Forwarding no'
|
||||
state: present
|
||||
|
||||
- name: Disable TCP forwarding
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?AllowTcpForwarding'
|
||||
line: 'AllowTcpForwarding no'
|
||||
state: present
|
||||
|
||||
- name: Disable agent forwarding
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?AllowAgentForwarding'
|
||||
line: 'AllowAgentForwarding no'
|
||||
state: present
|
||||
|
||||
- name: Set ClientAliveInterval to 300 seconds (5 minutes)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?ClientAliveInterval'
|
||||
line: 'ClientAliveInterval 300'
|
||||
state: present
|
||||
|
||||
- name: Set ClientAliveCountMax to 0 (disconnect inactive sessions)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?ClientAliveCountMax'
|
||||
line: 'ClientAliveCountMax 0'
|
||||
state: present
|
||||
|
||||
- name: Set LoginGraceTime to 30 seconds
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?LoginGraceTime'
|
||||
line: 'LoginGraceTime 30'
|
||||
state: present
|
||||
|
||||
- name: Set UsePAM to yes
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?UsePAM'
|
||||
line: 'UsePAM yes'
|
||||
state: present
|
||||
|
||||
- name: Disable SSH version 1 (only use version 2)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?Protocol'
|
||||
line: 'Protocol 2'
|
||||
state: present
|
||||
|
||||
- name: Disable DNS lookup for SSH (improve performance)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?UseDNS'
|
||||
line: 'UseDNS no'
|
||||
state: present
|
||||
|
||||
- name: Restart SSH service to apply changes
|
||||
service:
|
||||
name: sshd
|
||||
state: restarted
|
||||
|
||||
# - name: Ensure apt-listbugs is installed
|
||||
# apt:
|
||||
# name: apt-listbugs
|
||||
# state: present
|
||||
|
||||
- name: Ensure debsums is installed
|
||||
apt:
|
||||
name: debsums
|
||||
state: present
|
||||
|
||||
- name: Ensure needrestart is installed
|
||||
apt:
|
||||
name: needrestart
|
||||
state: present
|
||||
|
||||
# 14. Ensure log rotation is enabled and configured
|
||||
- name: Ensure rsyslog is installed
|
||||
apt:
|
||||
name: rsyslog
|
||||
state: present
|
||||
|
||||
- name: Ensure logrotate is installed
|
||||
apt:
|
||||
name: logrotate
|
||||
state: present
|
||||
|
||||
- name: Create logrotate configuration for rsyslog
|
||||
copy:
|
||||
dest: /etc/logrotate.d/rsyslog
|
||||
content: |
|
||||
/var/log/syslog
|
||||
{
|
||||
rotate 7
|
||||
daily
|
||||
missingok
|
||||
notifempty
|
||||
delaycompress
|
||||
compress
|
||||
postrotate
|
||||
/usr/lib/rsyslog/rsyslog-rotate > /dev/null 2>&1 || true
|
||||
endscript
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Verify logrotate configuration
|
||||
shell: logrotate -d /etc/logrotate.conf
|
||||
register: logrotate_test
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Debug logrotate output
|
||||
debug:
|
||||
var: logrotate_test.stdout
|
||||
|
||||
# 1. Update sysctl parameters
|
||||
- name: Apply recommended sysctl settings
|
||||
sysctl:
|
||||
name: "{{ item.key }}"
|
||||
value: "{{ item.value }}"
|
||||
state: present
|
||||
reload: yes
|
||||
with_items:
|
||||
- { key: "fs.protected_fifos", value: "2" }
|
||||
- { key: "kernel.kptr_restrict", value: "2" }
|
||||
- { key: "kernel.sysrq", value: "0" }
|
||||
- { key: "net.ipv4.conf.all.accept_redirects", value: "0" }
|
||||
- { key: "net.ipv4.conf.all.log_martians", value: "1" }
|
||||
- { key: "net.ipv4.tcp_syncookies", value: "1" }
|
||||
- { key: "net.ipv6.conf.all.accept_redirects", value: "0" }
|
||||
|
||||
# 5. Install fail2ban
|
||||
- name: Install fail2ban
|
||||
package:
|
||||
name: fail2ban
|
||||
state: present
|
||||
|
||||
- name: Ensure fail2ban service is running
|
||||
service:
|
||||
name: fail2ban
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
# 6. Install and configure Chkrootkit
|
||||
- name: Ensure chkrootkit is installed
|
||||
apt:
|
||||
name: chkrootkit
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Create directory for chkrootkit logs
|
||||
file:
|
||||
path: /var/log/chkrootkit
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create chkrootkit daily scan script
|
||||
copy:
|
||||
dest: /etc/cron.daily/chkrootkit
|
||||
content: |
|
||||
#!/bin/bash
|
||||
LOGFILE="/var/log/chkrootkit/chkrootkit.log"
|
||||
echo "Chkrootkit scan on $(date)" > "$LOGFILE"
|
||||
chkrootkit >> "$LOGFILE" 2>&1
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Run immediate chkrootkit scan
|
||||
command: chkrootkit
|
||||
register: chkrootkit_scan
|
||||
|
||||
- name: Debug chkrootkit scan results
|
||||
debug:
|
||||
var: chkrootkit_scan.stdout
|
||||
|
||||
# 5. Install lynis & auditer la machine
|
||||
- name: Installer Lynis
|
||||
apt:
|
||||
name: lynis
|
||||
state: present
|
||||
|
||||
- name: Exécuter un audit de sécurité
|
||||
command: lynis audit system
|
||||
register: lynis_output
|
||||
|
||||
- name: Afficher le résultat de l'audit Lynis
|
||||
debug:
|
||||
var: lynis_output.stdout
|
||||
|
||||
# 6. Full AIDE setup from scratch
|
||||
|
||||
- name: Install AIDE package
|
||||
ansible.builtin.package:
|
||||
name: aide
|
||||
state: present
|
||||
|
||||
- name: Deploy AIDE configuration file
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
database=file:/var/lib/aide/aide.db.gz
|
||||
database_out=file:/var/lib/aide/aide.db.new.gz
|
||||
gzip_dbout=yes
|
||||
|
||||
# Define groups for rules
|
||||
NORMAL = p+i+n+u+g+s+m+c+acl+selinux+sha256
|
||||
F = sha256+ftype
|
||||
|
||||
# Directories and files to monitor
|
||||
/etc NORMAL
|
||||
/bin NORMAL
|
||||
/sbin NORMAL
|
||||
/usr/bin NORMAL
|
||||
/usr/sbin NORMAL
|
||||
/var/log F
|
||||
dest: /etc/aide/aide.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Remove any existing AIDE database (if any)
|
||||
ansible.builtin.file:
|
||||
path: /var/lib/aide/aide.db.gz
|
||||
state: absent
|
||||
|
||||
- name: Initialize AIDE database
|
||||
command: aide --init --config=/etc/aide/aide.conf
|
||||
args:
|
||||
creates: /var/lib/aide/aide.db.new.gz
|
||||
|
||||
- name: Replace old AIDE database with the new one
|
||||
command: mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
|
||||
args:
|
||||
creates: /var/lib/aide/aide.db.gz
|
||||
|
||||
- name: Schedule AIDE periodic checks with cron
|
||||
ansible.builtin.cron:
|
||||
name: "AIDE periodic integrity check"
|
||||
user: root
|
||||
job: "/usr/bin/aide --check --config=/etc/aide/aide.conf"
|
||||
special_time: daily
|
||||
|
||||
68
playbooks/legacy/icinga.services.configAudit.yml
Normal file
68
playbooks/legacy/icinga.services.configAudit.yml
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
- name: Add grouped Python plugins as CheckCommands in Icinga Director
|
||||
hosts: leChoixDuSysadmin
|
||||
gather_facts: no
|
||||
vars:
|
||||
# Grouped plugins by functionality
|
||||
plugin_groups:
|
||||
security_network:
|
||||
- name: "001_ensure_ufw_is_installed"
|
||||
path: "/usr/lib/nagios/plugins/001_ensure_ufw_is_installed.py"
|
||||
- name: "002_allow_ssh_immediately"
|
||||
path: "/usr/lib/nagios/plugins/002_allow_ssh_immediately.py"
|
||||
- name: "003_set_default_policy_to_deny_incoming_traffic"
|
||||
path: "/usr/lib/nagios/plugins/003_set_default_policy_to_deny_incoming_traffic.py"
|
||||
permissions_access:
|
||||
- name: "013_set_permissions_on_etc_passwd"
|
||||
path: "/usr/lib/nagios/plugins/013_set_permissions_on_etc_passwd.py"
|
||||
- name: "014_set_permissions_on_etc_shadow"
|
||||
path: "/usr/lib/nagios/plugins/014_set_permissions_on_etc_shadow.py"
|
||||
ssh_config:
|
||||
- name: "040_ensure_the_permitrootlogin_is_set_to_no_disable_root_login"
|
||||
path: "/usr/lib/nagios/plugins/040_ensure_the_permitrootlogin_is_set_to_no_disable_root_login.py"
|
||||
- name: "041_ensure_passwordauthentication_is_set_to_no_force_key_based_authentication"
|
||||
path: "/usr/lib/nagios/plugins/041_ensure_passwordauthentication_is_set_to_no_force_key_based_authentication.py"
|
||||
audits_logs:
|
||||
- name: "033_install_auditd"
|
||||
path: "/usr/lib/nagios/plugins/033_install_auditd.py"
|
||||
- name: "034_ensure_auditd_service_is_enabled_and_running"
|
||||
path: "/usr/lib/nagios/plugins/034_ensure_auditd_service_is_enabled_and_running.py"
|
||||
system_settings:
|
||||
- name: "011_mettre_jour_la_liste_des_paquets_apt"
|
||||
path: "/usr/lib/nagios/plugins/011_mettre_jour_la_liste_des_paquets_apt.py"
|
||||
- name: "012_mettre_jour_uniquement_les_paquets_install_s"
|
||||
path: "/usr/lib/nagios/plugins/012_mettre_jour_uniquement_les_paquets_install_s.py"
|
||||
backups_banners:
|
||||
- name: "036_create_a_message_of_the_day_motd_banner"
|
||||
path: "/usr/lib/nagios/plugins/036_create_a_message_of_the_day_motd_banner.py"
|
||||
- name: "037_backup_the_current_sshd_config"
|
||||
path: "/usr/lib/nagios/plugins/037_backup_the_current_sshd_config.py"
|
||||
security_integrity:
|
||||
- name: "061_install_fail2ban"
|
||||
path: "/usr/lib/nagios/plugins/061_install_fail2ban.py"
|
||||
- name: "062_ensure_fail2ban_service_is_running"
|
||||
path: "/usr/lib/nagios/plugins/062_ensure_fail2ban_service_is_running.py"
|
||||
|
||||
tasks:
|
||||
- name: Add CheckCommands for each group of plugins
|
||||
uri:
|
||||
url: "https://adm-kbr.delaviorne.net/api/v1/checkcommand"
|
||||
method: POST
|
||||
headers:
|
||||
Accept: "application/json"
|
||||
Authorization: "Bearer your_api_token"
|
||||
body:
|
||||
object_name: "{{ item.name }}"
|
||||
attrs:
|
||||
command: "{{ item.path }}"
|
||||
templates: ["configAudit"]
|
||||
vars.agent: true
|
||||
body_format: json
|
||||
validate_certs: no
|
||||
with_items: "{{ plugin_groups | combine }}"
|
||||
register: results
|
||||
|
||||
- name: Debug results
|
||||
debug:
|
||||
var: results
|
||||
|
||||
37
playbooks/legacy/install_autogrow.yml
Normal file
37
playbooks/legacy/install_autogrow.yml
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
- name: Deploy and configure autogrow service on Debian 12.9
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
tasks:
|
||||
|
||||
- name: Ensure /usr/local/bin directory exists
|
||||
file:
|
||||
path: /usr/local/bin
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Copy autogrow script to /usr/local/bin
|
||||
copy:
|
||||
src: fichiers/autogrow.sh
|
||||
dest: /usr/local/bin/autogrow.sh
|
||||
mode: '0755'
|
||||
|
||||
- name: Copy autogrow systemd service file
|
||||
copy:
|
||||
src: fichiers/autogrow.service
|
||||
dest: /etc/systemd/system/autogrow.service
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload systemd daemon
|
||||
command: systemctl daemon-reload
|
||||
|
||||
- name: Enable autogrow service
|
||||
systemd:
|
||||
name: autogrow.service
|
||||
enabled: yes
|
||||
|
||||
- name: Start autogrow service
|
||||
systemd:
|
||||
name: autogrow.service
|
||||
state: started
|
||||
|
||||
55
playbooks/legacy/install_docker.yml
Normal file
55
playbooks/legacy/install_docker.yml
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
- name: Install Docker on Debian 12
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Update the package index
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Install required packages for Docker
|
||||
apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- software-properties-common
|
||||
state: present
|
||||
|
||||
- name: Add Docker GPG key
|
||||
ansible.builtin.shell: |
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
args:
|
||||
creates: /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
|
||||
- name: Add Docker repository
|
||||
ansible.builtin.copy:
|
||||
content: "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian bookworm stable\n"
|
||||
dest: /etc/apt/sources.list.d/docker.list
|
||||
|
||||
- name: Update the package index after adding Docker repository
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Install Docker packages
|
||||
apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
state: present
|
||||
|
||||
- name: Ensure Docker service is enabled and running
|
||||
systemd:
|
||||
name: docker
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Add current user to Docker group (optional)
|
||||
ansible.builtin.user:
|
||||
name: "{{ ansible_user }}"
|
||||
groups: docker
|
||||
append: yes
|
||||
state: present
|
||||
|
||||
23
playbooks/legacy/install_easypki.yml
Normal file
23
playbooks/legacy/install_easypki.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
- name: Installer easy-rsa, copier le script easypki et créer la PKI Projet_KBR
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
tasks:
|
||||
- name: Assurer que le paquet easy-rsa est installé
|
||||
apt:
|
||||
name: easy-rsa
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Copier le script easypki vers /usr/sbin
|
||||
copy:
|
||||
src: ../pki/easypki
|
||||
dest: /usr/sbin/easypki
|
||||
mode: '0755'
|
||||
|
||||
- name: Créer la PKI Projet_KBR dans /var/lib si elle n'existe pas déjà
|
||||
command: "/usr/sbin/easypki Projet_KBR"
|
||||
args:
|
||||
chdir: /var/lib
|
||||
creates: /var/lib/Projet_KBR
|
||||
|
||||
152
playbooks/legacy/install_iptables.yml
Normal file
152
playbooks/legacy/install_iptables.yml
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
---
|
||||
- name: Configure Firewall with iptables securely
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
vars_files:
|
||||
- iptables_config.yml
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Installer iptables-persistent et auditd
|
||||
apt:
|
||||
name:
|
||||
- iptables-persistent
|
||||
- auditd
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Appliquer les règles INPUT
|
||||
iptables:
|
||||
chain: INPUT
|
||||
protocol: "{{ item.protocol }}"
|
||||
destination_port: "{{ item.port }}"
|
||||
source: "{{ item.source | default(omit) }}"
|
||||
jump: "{{ item.action }}"
|
||||
loop: "{{ rules_input }}"
|
||||
|
||||
- name: Appliquer les règles FORWARD
|
||||
iptables:
|
||||
chain: FORWARD
|
||||
source: "{{ item.source }}"
|
||||
destination: "{{ item.destination }}"
|
||||
jump: "{{ item.action }}"
|
||||
loop: "{{ rules_forward }}"
|
||||
|
||||
- name: Appliquer les règles OUTPUT
|
||||
iptables:
|
||||
chain: OUTPUT
|
||||
protocol: "{{ item.protocol }}"
|
||||
destination_port: "{{ item.port }}"
|
||||
jump: "{{ item.action }}"
|
||||
loop: "{{ rules_output }}"
|
||||
|
||||
- name: Activer le NAT pour Docker (Masquerading)
|
||||
iptables:
|
||||
table: nat
|
||||
chain: POSTROUTING
|
||||
source: "{{ item.source }}"
|
||||
destination: "{{ item.destination }}"
|
||||
jump: "{{ item.action }}"
|
||||
loop: "{{ rules_nat_masquerade }}"
|
||||
|
||||
- name: Ajouter les règles de port forwarding (DNAT)
|
||||
iptables:
|
||||
table: nat
|
||||
chain: PREROUTING
|
||||
protocol: "{{ item.proto }}"
|
||||
destination_port: "{{ item.ext_port }}"
|
||||
to_destination: "{{ item.int_ip }}:{{ item.int_port }}"
|
||||
jump: DNAT
|
||||
loop: "{{ rules_nat_dnat }}"
|
||||
|
||||
# 🔐 Protection contre brute-force SSH
|
||||
- name: Limiter les connexions SSH à 3 tentatives par minute
|
||||
iptables:
|
||||
chain: INPUT
|
||||
protocol: tcp
|
||||
destination_port: 22
|
||||
match: limit
|
||||
limit: "3/min"
|
||||
jump: ACCEPT
|
||||
|
||||
# 🔐 Protection SYN Flood (DDoS)
|
||||
- name: Protection SYN Flood
|
||||
iptables:
|
||||
chain: INPUT
|
||||
protocol: tcp
|
||||
match: limit
|
||||
limit: "10/s"
|
||||
limit_burst: 20
|
||||
jump: ACCEPT
|
||||
|
||||
- name: Autoriser le trafic loopback
|
||||
iptables:
|
||||
chain: INPUT
|
||||
in_interface: lo
|
||||
jump: ACCEPT
|
||||
|
||||
- name: Autoriser le trafic loopback (OUTPUT)
|
||||
iptables:
|
||||
chain: OUTPUT
|
||||
out_interface: lo
|
||||
jump: ACCEPT
|
||||
|
||||
- name: Autoriser les connexions déjà établies
|
||||
iptables:
|
||||
chain: "{{ item }}"
|
||||
match: conntrack
|
||||
ctstate: RELATED,ESTABLISHED
|
||||
jump: ACCEPT
|
||||
loop:
|
||||
- INPUT
|
||||
- FORWARD
|
||||
- OUTPUT
|
||||
|
||||
# 📢 LOGGING 🔥
|
||||
- name: Loguer le trafic bloqué en INPUT
|
||||
iptables:
|
||||
chain: INPUT
|
||||
jump: LOG
|
||||
log_prefix: "INPUT DROP: "
|
||||
log_level: 4
|
||||
|
||||
- name: Loguer le trafic bloqué en FORWARD
|
||||
iptables:
|
||||
chain: FORWARD
|
||||
jump: LOG
|
||||
log_prefix: "FORWARD DROP: "
|
||||
log_level: 4
|
||||
|
||||
- name: Loguer le trafic bloqué en OUTPUT
|
||||
iptables:
|
||||
chain: OUTPUT
|
||||
jump: LOG
|
||||
log_prefix: "OUTPUT DROP: "
|
||||
log_level: 4
|
||||
|
||||
# 🚫 BLOQUER TOUT LE RESTE
|
||||
- name: Bloquer tout autre trafic entrant
|
||||
iptables:
|
||||
chain: INPUT
|
||||
jump: DROP
|
||||
|
||||
- name: Bloquer tout autre trafic forward
|
||||
iptables:
|
||||
chain: FORWARD
|
||||
jump: DROP
|
||||
|
||||
- name: Bloquer tout autre trafic sortant
|
||||
iptables:
|
||||
chain: OUTPUT
|
||||
jump: DROP
|
||||
|
||||
# 🔍 Surveillance des modifications d'iptables
|
||||
#- name: Activer l’audit des modifications d’iptables
|
||||
# shell: "auditctl -w /sbin/iptables -p x -k firewall_change"
|
||||
|
||||
- name: Sauvegarder les règles iptables
|
||||
shell: iptables-save > /etc/iptables/rules.v4
|
||||
|
||||
- name: Rendre les règles persistantes
|
||||
command: netfilter-persistent save
|
||||
|
||||
116
playbooks/legacy/install_mailcow.yml
Normal file
116
playbooks/legacy/install_mailcow.yml
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
- name: Installation et configuration de Mailcow sur Debian 12.9
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
vars:
|
||||
mailcow_dir: "/opt/mailcow"
|
||||
mailcow_domain: "mail.exemple.com"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Mettre à jour le système
|
||||
apt:
|
||||
update_cache: yes
|
||||
upgrade: dist
|
||||
|
||||
- name: Installer les dépendances nécessaires
|
||||
apt:
|
||||
name:
|
||||
- curl
|
||||
- git
|
||||
- sudo
|
||||
- ufw
|
||||
- unzip
|
||||
- wget
|
||||
- bash-completion
|
||||
- dnsutils
|
||||
- python3-pip
|
||||
state: present
|
||||
|
||||
- name: Désactiver systemd-resolved
|
||||
systemd:
|
||||
name: systemd-resolved
|
||||
enabled: no
|
||||
state: stopped
|
||||
|
||||
- name: Supprimer resolv.conf et définir un nouveau DNS
|
||||
file:
|
||||
path: /etc/resolv.conf
|
||||
state: absent
|
||||
|
||||
- name: Configurer un DNS de secours
|
||||
copy:
|
||||
dest: /etc/resolv.conf
|
||||
content: "nameserver 8.8.8.8\n"
|
||||
|
||||
- name: Vérifier si Mailcow est déjà installé
|
||||
stat:
|
||||
path: "{{ mailcow_dir }}/docker-compose.yml"
|
||||
register: mailcow_installed
|
||||
|
||||
- name: Cloner le dépôt Mailcow
|
||||
git:
|
||||
repo: "https://github.com/mailcow/mailcow-dockerized.git"
|
||||
dest: "{{ mailcow_dir }}"
|
||||
version: "master"
|
||||
when: not mailcow_installed.stat.exists
|
||||
|
||||
# - name: Générer le fichier de configuration Mailcow
|
||||
# command:
|
||||
# cmd: "./generate_config.sh"
|
||||
# chdir: "{{ mailcow_dir }}"
|
||||
|
||||
# - name: Vérifier si le fichier mailcow.conf existe
|
||||
# stat:
|
||||
# path: "{{ mailcow_dir }}/mailcow.conf"
|
||||
# register: mailcow_config
|
||||
|
||||
# - name: Créer le fichier mailcow.conf s'il n'existe pas
|
||||
# copy:
|
||||
# dest: "{{ mailcow_dir }}/mailcow.conf"
|
||||
# content: "MAILCOW_HOSTNAME={{ mailcow_domain }}\nDISABLE_IPV6=y\n"
|
||||
# when: not mailcow_config.stat.exists
|
||||
|
||||
- name: Télécharger les images Docker Mailcow
|
||||
command:
|
||||
cmd: "docker compose pull"
|
||||
chdir: "{{ mailcow_dir }}"
|
||||
|
||||
- name: Démarrer Mailcow avec Docker Compose
|
||||
command:
|
||||
cmd: "docker compose up -d"
|
||||
chdir: "{{ mailcow_dir }}"
|
||||
|
||||
- name: Ouvrir les ports nécessaires avec UFW
|
||||
ufw:
|
||||
rule: leChoixDuSysadminow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- "22"
|
||||
- "80"
|
||||
- "443"
|
||||
- "25"
|
||||
- "465"
|
||||
- "587"
|
||||
- "993"
|
||||
- "995"
|
||||
|
||||
- name: Activer UFW
|
||||
ufw:
|
||||
state: enabled
|
||||
|
||||
- name: Redémarrer le conteneur acme-mailcow pour générer les certificats SSL
|
||||
command:
|
||||
cmd: "docker compose restart acme-mailcow"
|
||||
chdir: "{{ mailcow_dir }}"
|
||||
|
||||
- name: Générer la clé DKIM et afficher la configuration DNS
|
||||
command:
|
||||
cmd: "docker compose exec -T rspamd-mailcow rspamadm dkim_keygen -d {{ mailcow_domain }}"
|
||||
chdir: "{{ mailcow_dir }}"
|
||||
register: dkim_output
|
||||
|
||||
- name: Afficher la clé DKIM à ajouter dans le DNS
|
||||
debug:
|
||||
msg: "{{ dkim_output.stdout }}"
|
||||
|
||||
65
playbooks/legacy/install_nginx.yml
Normal file
65
playbooks/legacy/install_nginx.yml
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
- name: Installer et configurer NGINX avec Certbot
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes # Exécution avec sudo
|
||||
vars:
|
||||
domain_name: "change.me" # À remplacer par votre domaine
|
||||
email: "someone@somewhere.lol" # Adresse e-mail pour Let's Encrypt
|
||||
nginx_conf_path: "/etc/nginx/sites-available/{{ domain_name }}"
|
||||
nginx_conf_link: "/etc/nginx/sites-enabled/{{ domain_name }}"
|
||||
|
||||
tasks:
|
||||
- name: Mettre à jour la liste des paquets
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Installer NGINX et Certbot
|
||||
apt:
|
||||
name:
|
||||
- nginx
|
||||
- certbot
|
||||
- python3-certbot-nginx
|
||||
state: present
|
||||
|
||||
- name: Créer un répertoire pour le site web
|
||||
file:
|
||||
path: "/var/www/{{ domain_name }}"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0755'
|
||||
|
||||
- name: Déployer la configuration NGINX
|
||||
template:
|
||||
src: templates/nginx_vhost.conf.j2
|
||||
dest: "{{ nginx_conf_path }}"
|
||||
notify: Redémarrer NGINX
|
||||
|
||||
- name: Activer le site en créant un lien symbolique
|
||||
file:
|
||||
src: "{{ nginx_conf_path }}"
|
||||
dest: "{{ nginx_conf_link }}"
|
||||
state: link
|
||||
notify: Redémarrer NGINX
|
||||
|
||||
# - name: Vérifier que NGINX fonctionne avant la demande de certificat
|
||||
#uri:
|
||||
#url: "http://{{ domain_name }}"
|
||||
#status_code: 200
|
||||
#register: web_status
|
||||
#until: web_status.status == 200
|
||||
#retries: 5
|
||||
#delay: 5
|
||||
|
||||
- name: Obtenir un certificat SSL avec Certbot
|
||||
command: "certbot --nginx -d {{ domain_name }} --email {{ email }} --non-interactive --agree-tos"
|
||||
args:
|
||||
creates: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||
notify: Redémarrer NGINX
|
||||
|
||||
handlers:
|
||||
- name: Redémarrer NGINX
|
||||
systemd:
|
||||
name: nginx
|
||||
state: restarted
|
||||
enabled: yes
|
||||
77
playbooks/legacy/install_openvpn.yml
Normal file
77
playbooks/legacy/install_openvpn.yml
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
- name: Installer les prérequis pour OpenVPN et Easy-RSA
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
tasks:
|
||||
|
||||
- name: Mettre à jour la liste des paquets
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Installer OpenVPN et Easy-RSA
|
||||
apt:
|
||||
name:
|
||||
- openvpn
|
||||
- easy-rsa
|
||||
state: present
|
||||
|
||||
- name: Vérifier l'existence du script Easy-RSA
|
||||
stat:
|
||||
path: /usr/share/easy-rsa/easyrsa
|
||||
register: easyrsa_stat
|
||||
|
||||
- name: Créer le répertoire Easy-RSA dans OpenVPN
|
||||
file:
|
||||
path: /etc/openvpn/easy-rsa
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Supprimer l'ancien fichier vars s'il existe
|
||||
file:
|
||||
path: /etc/openvpn/easy-rsa/vars
|
||||
state: absent
|
||||
|
||||
- name: Initialiser l'environnement PKI sans confirmation
|
||||
command: "echo yes | /usr/share/easy-rsa/easyrsa init-pki"
|
||||
args:
|
||||
chdir: /etc/openvpn/easy-rsa
|
||||
when: easyrsa_stat.stat.exists
|
||||
|
||||
- name: Générer le CA
|
||||
command: "echo yes | /usr/share/easy-rsa/easyrsa build-ca nopass"
|
||||
args:
|
||||
chdir: /etc/openvpn/easy-rsa
|
||||
when: easyrsa_stat.stat.exists
|
||||
|
||||
- name: Générer la clé Diffie-Hellman
|
||||
command: "echo yes | /usr/share/easy-rsa/easyrsa gen-dh"
|
||||
args:
|
||||
chdir: /etc/openvpn/easy-rsa
|
||||
when: easyrsa_stat.stat.exists
|
||||
|
||||
- name: Créer un fichier de configuration serveur
|
||||
copy:
|
||||
dest: /etc/openvpn/server.conf
|
||||
content: |
|
||||
port 1194
|
||||
proto udp
|
||||
dev tun
|
||||
ca /etc/openvpn/easy-rsa/pki/ca.crt
|
||||
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
|
||||
key /etc/openvpn/easy-rsa/pki/private/server.key
|
||||
dh /etc/openvpn/easy-rsa/pki/dh.pem
|
||||
server 10.8.0.0 255.255.255.0
|
||||
keepalive 10 120
|
||||
persist-key
|
||||
persist-tun
|
||||
status /var/log/openvpn-status.log
|
||||
verb 3
|
||||
|
||||
- name: Activer et démarrer OpenVPN
|
||||
systemd:
|
||||
name: openvpn
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
515
playbooks/legacy/install_protections.yml
Normal file
515
playbooks/legacy/install_protections.yml
Normal file
|
|
@ -0,0 +1,515 @@
|
|||
---
|
||||
- name: Apply security hardening based on Linys recommendations
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
tasks:
|
||||
|
||||
# 4. Installation des mises à jour & des rustines
|
||||
- name: Mettre à jour la liste des paquets APT
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Mettre à jour uniquement les paquets installés
|
||||
apt:
|
||||
upgrade: yes
|
||||
|
||||
|
||||
# 5. Ensure correct file permissions on sensitive files
|
||||
- name: Set permissions on /etc/passwd
|
||||
file:
|
||||
path: /etc/passwd
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Set permissions on /etc/shadow
|
||||
file:
|
||||
path: /etc/shadow
|
||||
owner: root
|
||||
group: shadow
|
||||
mode: '0640'
|
||||
|
||||
- name: Set permissions on /etc/group
|
||||
file:
|
||||
path: /etc/group
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Set permissions on /etc/gshadow
|
||||
file:
|
||||
path: /etc/gshadow
|
||||
owner: root
|
||||
group: shadow
|
||||
mode: '0640'
|
||||
|
||||
# 6. Disable core dumps (to prevent information leakage)
|
||||
- name: Disable core dumps
|
||||
lineinfile:
|
||||
path: /etc/security/limits.conf
|
||||
line: '* hard core 0'
|
||||
state: present
|
||||
|
||||
- name: Ensure core dumps are disabled via sysctl
|
||||
sysctl:
|
||||
name: fs.suid_dumpable
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
# 7. Restrict cron jobs
|
||||
- name: Restrict cron jobs to root and authorized users
|
||||
file:
|
||||
path: /etc/cron.deny
|
||||
state: absent
|
||||
|
||||
- name: Ensure /etc/cron.allow exists and has correct permissions
|
||||
file:
|
||||
path: /etc/cron.allow
|
||||
state: touch
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0640'
|
||||
|
||||
# 7. Améliorer la sécurité des répertoires temporaires
|
||||
- name: Install libpam-tmpdir and apt-listbugs
|
||||
apt:
|
||||
name:
|
||||
- libpam-tmpdir
|
||||
state: present
|
||||
|
||||
# 8. Disable IPv6 if not in use
|
||||
- name: Disable IPv6 via sysctl
|
||||
sysctl:
|
||||
name: net.ipv6.conf.all.disable_ipv6
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
reload: yes
|
||||
|
||||
# Adjust kernel and sysctl parameters for hardening
|
||||
- name: Disable TTY line discipline autoload
|
||||
sysctl:
|
||||
name: dev.tty.ldisc_autoload
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Use PID in core dump filenames
|
||||
sysctl:
|
||||
name: kernel.core_uses_pid
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
# ATTENTION !!! IRRÉVERSIBLE !!! PAS TOUCHE AVANT SNAPSHOT !!!
|
||||
#- name: Disable loading of kernel modules after boot
|
||||
# sysctl:
|
||||
# name: kernel.modules_disabled
|
||||
# value: '1'
|
||||
# state: present
|
||||
# sysctl_set: yes
|
||||
|
||||
- name: Disable unprivileged BPF
|
||||
sysctl:
|
||||
name: kernel.unprivileged_bpf_disabled
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Restrict ptrace to parent processes only
|
||||
sysctl:
|
||||
name: kernel.yama.ptrace_scope
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Harden BPF JIT compilation
|
||||
sysctl:
|
||||
name: net.core.bpf_jit_harden
|
||||
value: '2'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Enable reverse path filtering for IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.all.rp_filter
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Disable sending of ICMP redirects for IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.all.send_redirects
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Disable accepting of ICMP redirects by default for IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.default.accept_redirects
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Enable logging of suspicious packets for default IPv4
|
||||
sysctl:
|
||||
name: net.ipv4.conf.default.log_martians
|
||||
value: '1'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
- name: Disable accepting of ICMP redirects by default for IPv6
|
||||
sysctl:
|
||||
name: net.ipv6.conf.default.accept_redirects
|
||||
value: '0'
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
|
||||
# 9. Ensure auditing is configured (auditd)
|
||||
- name: Install auditd
|
||||
apt:
|
||||
name: auditd
|
||||
state: present
|
||||
|
||||
- name: Ensure auditd service is enabled and running
|
||||
service:
|
||||
name: auditd
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
# 12. Enable AppArmor (or SELinux on supported systems)
|
||||
- name: Ensure AppArmor is enabled and running
|
||||
service:
|
||||
name: apparmor
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
# 13. Create a banner for unauthorized access
|
||||
- name: Create a message of the day (MOTD) banner
|
||||
copy:
|
||||
dest: /etc/motd
|
||||
content: |
|
||||
|
||||
********************** AVERTISSEMENT ***********************
|
||||
|
||||
Ce système est strictement réservé aux utilisateurs autorisés
|
||||
Toute tentative d'accès non autorisé est interdite et peut
|
||||
être signalée aux autorités compétentes.
|
||||
|
||||
Votre activité peut être surveillée et enregistrée.
|
||||
En continuant, vous acceptez ces conditions.
|
||||
|
||||
|
||||
************************ WARNING ***************************
|
||||
|
||||
This system is strictly for authorized users only.
|
||||
Any unauthorized access attempts are prohibited and may
|
||||
be reported to the appropriate authorities.
|
||||
|
||||
Your activity may be monitored and logged.
|
||||
By proceeding, you accept these terms.
|
||||
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
# 14. Apply SSH hardening configuration
|
||||
|
||||
- name: Backup the current sshd_config
|
||||
copy:
|
||||
src: /etc/ssh/sshd_config
|
||||
dest: /etc/ssh/sshd_config.bak
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
remote_src: yes
|
||||
backup: yes
|
||||
|
||||
- name: Ensure banner is displayed on SSH login
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?Banner'
|
||||
line: 'Banner /etc/motd'
|
||||
state: present
|
||||
|
||||
- name: Backup the current sshd_config
|
||||
copy:
|
||||
src: /etc/ssh/sshd_config
|
||||
dest: /etc/ssh/sshd_config.bak
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
remote_src: yes
|
||||
backup: yes
|
||||
|
||||
- name: Ensure the PermitRootLogin is set to no (disable root login)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitRootLogin'
|
||||
line: 'PermitRootLogin no'
|
||||
state: present
|
||||
|
||||
- name: Ensure PasswordAuthentication is set to no (force key-based authentication)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PasswordAuthentication'
|
||||
line: 'PasswordAuthentication no'
|
||||
state: present
|
||||
|
||||
- name: Disable empty passwords
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?PermitEmptyPasswords'
|
||||
line: 'PermitEmptyPasswords no'
|
||||
state: present
|
||||
|
||||
- name: Set MaxAuthTries to 3 (limit authentication attempts)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?MaxAuthTries'
|
||||
line: 'MaxAuthTries 3'
|
||||
state: present
|
||||
|
||||
- name: Set MaxSessions to 2 (limit open sessions)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?MaxSessions'
|
||||
line: 'MaxSessions 2'
|
||||
state: present
|
||||
|
||||
- name: Disable X11 forwarding
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?X11Forwarding'
|
||||
line: 'X11Forwarding no'
|
||||
state: present
|
||||
|
||||
- name: Disable TCP forwarding
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?AllowTcpForwarding'
|
||||
line: 'AllowTcpForwarding no'
|
||||
state: present
|
||||
|
||||
- name: Disable agent forwarding
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?AllowAgentForwarding'
|
||||
line: 'AllowAgentForwarding no'
|
||||
state: present
|
||||
|
||||
- name: Set ClientAliveInterval to 300 seconds (5 minutes)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?ClientAliveInterval'
|
||||
line: 'ClientAliveInterval 300'
|
||||
state: present
|
||||
|
||||
- name: Set ClientAliveCountMax to 0 (disconnect inactive sessions)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?ClientAliveCountMax'
|
||||
line: 'ClientAliveCountMax 0'
|
||||
state: present
|
||||
|
||||
- name: Set LoginGraceTime to 30 seconds
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?LoginGraceTime'
|
||||
line: 'LoginGraceTime 30'
|
||||
state: present
|
||||
|
||||
- name: Set UsePAM to yes
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?UsePAM'
|
||||
line: 'UsePAM yes'
|
||||
state: present
|
||||
|
||||
- name: Disable SSH version 1 (only use version 2)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?Protocol'
|
||||
line: 'Protocol 2'
|
||||
state: present
|
||||
|
||||
- name: Disable DNS lookup for SSH (improve performance)
|
||||
lineinfile:
|
||||
path: /etc/ssh/sshd_config
|
||||
regexp: '^#?UseDNS'
|
||||
line: 'UseDNS no'
|
||||
state: present
|
||||
|
||||
- name: Restart SSH service to apply changes
|
||||
service:
|
||||
name: sshd
|
||||
state: restarted
|
||||
|
||||
# 14. Ensure log rotation is enabled and configured
|
||||
- name: Ensure rsyslog is installed
|
||||
apt:
|
||||
name: rsyslog
|
||||
state: present
|
||||
|
||||
- name: Ensure logrotate is installed
|
||||
apt:
|
||||
name: logrotate
|
||||
state: present
|
||||
|
||||
- name: Create logrotate configuration for rsyslog
|
||||
copy:
|
||||
dest: /etc/logrotate.d/rsyslog
|
||||
content: |
|
||||
/var/log/syslog
|
||||
{
|
||||
rotate 7
|
||||
daily
|
||||
missingok
|
||||
notifempty
|
||||
delaycompress
|
||||
compress
|
||||
postrotate
|
||||
/usr/lib/rsyslog/rsyslog-rotate > /dev/null 2>&1 || true
|
||||
endscript
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Verify logrotate configuration
|
||||
shell: logrotate -d /etc/logrotate.conf
|
||||
register: logrotate_test
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Debug logrotate output
|
||||
debug:
|
||||
var: logrotate_test.stdout
|
||||
|
||||
# 1. Update sysctl parameters
|
||||
- name: Apply recommended sysctl settings
|
||||
sysctl:
|
||||
name: "{{ item.key }}"
|
||||
value: "{{ item.value }}"
|
||||
state: present
|
||||
reload: yes
|
||||
with_items:
|
||||
- { key: "fs.protected_fifos", value: "2" }
|
||||
- { key: "kernel.kptr_restrict", value: "2" }
|
||||
- { key: "kernel.sysrq", value: "0" }
|
||||
- { key: "net.ipv4.conf.all.accept_redirects", value: "0" }
|
||||
- { key: "net.ipv4.conf.all.log_martians", value: "1" }
|
||||
- { key: "net.ipv4.tcp_syncookies", value: "1" }
|
||||
- { key: "net.ipv6.conf.all.accept_redirects", value: "0" }
|
||||
|
||||
# 5. Install fail2ban
|
||||
- name: Install fail2ban
|
||||
package:
|
||||
name: fail2ban
|
||||
state: present
|
||||
|
||||
- name: Ensure fail2ban service is running
|
||||
service:
|
||||
name: fail2ban
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
# 6. Install and configure Chkrootkit
|
||||
- name: Ensure chkrootkit is installed
|
||||
apt:
|
||||
name: chkrootkit
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Create directory for chkrootkit logs
|
||||
file:
|
||||
path: /var/log/chkrootkit
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Create chkrootkit daily scan script
|
||||
copy:
|
||||
dest: /etc/cron.daily/chkrootkit
|
||||
content: |
|
||||
#!/bin/bash
|
||||
LOGFILE="/var/log/chkrootkit/chkrootkit.log"
|
||||
echo "Chkrootkit scan on $(date)" > "$LOGFILE"
|
||||
chkrootkit >> "$LOGFILE" 2>&1
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Run immediate chkrootkit scan
|
||||
command: chkrootkit
|
||||
register: chkrootkit_scan
|
||||
|
||||
- name: Debug chkrootkit scan results
|
||||
debug:
|
||||
var: chkrootkit_scan.stdout
|
||||
|
||||
# 5. Install lynis & auditer la machine
|
||||
- name: Installer Lynis
|
||||
apt:
|
||||
name: lynis
|
||||
state: present
|
||||
|
||||
- name: Exécuter un audit de sécurité
|
||||
command: lynis audit system
|
||||
register: lynis_output
|
||||
|
||||
- name: Afficher le résultat de l'audit Lynis
|
||||
debug:
|
||||
var: lynis_output.stdout
|
||||
|
||||
# 6. Full AIDE setup from scratch
|
||||
|
||||
- name: Install AIDE package
|
||||
ansible.builtin.package:
|
||||
name: aide
|
||||
state: present
|
||||
|
||||
- name: Deploy AIDE configuration file
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
database=file:/var/lib/aide/aide.db.gz
|
||||
database_out=file:/var/lib/aide/aide.db.new.gz
|
||||
gzip_dbout=yes
|
||||
|
||||
# Define groups for rules
|
||||
NORMAL = p+i+n+u+g+s+m+c+acl+selinux+sha256
|
||||
F = sha256+ftype
|
||||
|
||||
# Directories and files to monitor
|
||||
/etc NORMAL
|
||||
/bin NORMAL
|
||||
/sbin NORMAL
|
||||
/usr/bin NORMAL
|
||||
/usr/sbin NORMAL
|
||||
/var/log F
|
||||
dest: /etc/aide/aide.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Remove any existing AIDE database (if any)
|
||||
ansible.builtin.file:
|
||||
path: /var/lib/aide/aide.db.gz
|
||||
state: absent
|
||||
|
||||
- name: Initialize AIDE database
|
||||
command: aide --init --config=/etc/aide/aide.conf
|
||||
args:
|
||||
creates: /var/lib/aide/aide.db.new.gz
|
||||
|
||||
- name: Replace old AIDE database with the new one
|
||||
command: mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
|
||||
args:
|
||||
creates: /var/lib/aide/aide.db.gz
|
||||
|
||||
- name: Schedule AIDE periodic checks with cron
|
||||
ansible.builtin.cron:
|
||||
name: "AIDE periodic integrity check"
|
||||
user: root
|
||||
job: "/usr/bin/aide --check --config=/etc/aide/aide.conf"
|
||||
special_time: daily
|
||||
|
||||
130
playbooks/legacy/install_stepca.yml
Normal file
130
playbooks/legacy/install_stepca.yml
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
- name: Installation et Configuration de Step-CA
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
vars:
|
||||
stepca_user: step
|
||||
stepca_group: step
|
||||
stepca_home: /home/step
|
||||
stepca_data_dir: /home/step/.step
|
||||
stepca_service: step-ca
|
||||
stepca_port: 9000
|
||||
stepca_domain: "certificats.delaviorne.net"
|
||||
stepca_init_password: "ChangeMe123!" # À CHANGER
|
||||
stepca_provisioner: "admin"
|
||||
|
||||
tasks:
|
||||
##################################################################
|
||||
# 1️⃣ Installation de Step-CA et Step-CLI
|
||||
##################################################################
|
||||
- name: Télécharger et installer Step-CLI et Step-CA (Ubuntu/Debian)
|
||||
apt:
|
||||
deb: "{{ item }}"
|
||||
with_items:
|
||||
- "https://dl.smallstep.com/cli/docs-ca-install/latest/step-cli_amd64.deb"
|
||||
- "https://dl.smallstep.com/certificates/docs-ca-install/latest/step-ca_amd64.deb"
|
||||
when: ansible_os_family == "Debian"
|
||||
|
||||
- name: Télécharger et installer Step-CLI et Step-CA (CentOS/RHEL)
|
||||
yum:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- "https://dl.smallstep.com/gh-release/certificates/pkg/latest/step-cli_amd64.rpm"
|
||||
- "https://dl.smallstep.com/gh-release/certificates/pkg/latest/step-ca_amd64.rpm"
|
||||
when: ansible_os_family == "RedHat"
|
||||
|
||||
- name: Vérifier l'installation de Step-CA et Step-CLI
|
||||
command: step version
|
||||
register: step_version
|
||||
changed_when: false
|
||||
|
||||
##################################################################
|
||||
# 2️⃣ Création de l'utilisateur Step-CA
|
||||
##################################################################
|
||||
- name: Créer l'utilisateur Step-CA
|
||||
user:
|
||||
name: "{{ stepca_user }}"
|
||||
comment: "Utilisateur pour Step-CA"
|
||||
home: "{{ stepca_home }}"
|
||||
shell: /bin/false
|
||||
createhome: yes
|
||||
|
||||
- name: Créer le dossier de configuration Step-CA
|
||||
file:
|
||||
path: "{{ stepca_data_dir }}"
|
||||
state: directory
|
||||
owner: "{{ stepca_user }}"
|
||||
group: "{{ stepca_group }}"
|
||||
mode: '0755'
|
||||
|
||||
##################################################################
|
||||
# 3️⃣ Initialisation de Step-CA
|
||||
##################################################################
|
||||
- name: Vérifier si Step-CA est déjà initialisé
|
||||
stat:
|
||||
path: "{{ stepca_data_dir }}/ca.json"
|
||||
register: ca_json
|
||||
|
||||
- name: Initialiser Step-CA (si nécessaire)
|
||||
command: step ca init --name "My Internal CA" --dns "{{ stepca_domain }}" --address ":{{ stepca_port }}" --provisioner "{{ stepca_provisioner }}" --password-file /tmp/stepca_pass
|
||||
args:
|
||||
creates: "{{ stepca_data_dir }}/ca.json"
|
||||
become_user: "{{ stepca_user }}"
|
||||
when: not ca_json.stat.exists
|
||||
|
||||
- name: Supprimer le fichier de mot de passe temporaire
|
||||
file:
|
||||
path: /tmp/stepca_pass
|
||||
state: absent
|
||||
|
||||
##################################################################
|
||||
# 4️⃣ Création du service systemd
|
||||
##################################################################
|
||||
- name: Configurer Step-CA comme un service systemd
|
||||
copy:
|
||||
dest: "/etc/systemd/system/{{ stepca_service }}.service"
|
||||
mode: '0644'
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Step CA Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/step-ca {{ stepca_data_dir }}/ca.json
|
||||
Restart=always
|
||||
User={{ stepca_user }}
|
||||
Group={{ stepca_group }}
|
||||
Environment=STEPPATH={{ stepca_data_dir }}
|
||||
WorkingDirectory={{ stepca_data_dir }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
- name: Recharger systemd
|
||||
command: systemctl daemon-reload
|
||||
|
||||
- name: Activer et démarrer Step-CA
|
||||
systemd:
|
||||
name: "{{ stepca_service }}"
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
##################################################################
|
||||
# 5️⃣ Vérification du service
|
||||
##################################################################
|
||||
- name: Vérifier que Step-CA tourne bien
|
||||
shell: "systemctl is-active {{ stepca_service }}"
|
||||
register: stepca_status
|
||||
failed_when: stepca_status.stdout != "active"
|
||||
changed_when: false
|
||||
|
||||
- name: Tester si Step-CA répond sur le port {{ stepca_port }}
|
||||
uri:
|
||||
url: "https://localhost:{{ stepca_port }}/acme/acme-directory"
|
||||
method: GET
|
||||
status_code: 200
|
||||
validate_certs: no
|
||||
register: stepca_test
|
||||
failed_when: stepca_test.status != 200
|
||||
changed_when: false
|
||||
|
||||
140
playbooks/legacy/install_stepca2.yml
Normal file
140
playbooks/legacy/install_stepca2.yml
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
- name: Installation et Configuration de Step-CA
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
vars:
|
||||
stepca_user: step
|
||||
stepca_group: step
|
||||
stepca_home: /home/step
|
||||
stepca_data_dir: /home/step/.step
|
||||
stepca_tmp_dir: /var/tmp/.ansible_tmp
|
||||
stepca_service: step-ca
|
||||
stepca_port: 9000
|
||||
stepca_domain: "certificats.delaviorne.net"
|
||||
stepca_init_password: "T0rp1n0uch3." # À CHANGER
|
||||
stepca_provisioner: "admin"
|
||||
|
||||
tasks:
|
||||
##################################################################
|
||||
# 1️⃣ Création des répertoires nécessaires
|
||||
##################################################################
|
||||
- name: Créer le répertoire temporaire d’Ansible (si `noexec` sur /tmp)
|
||||
file:
|
||||
path: "{{ stepca_tmp_dir }}"
|
||||
state: directory
|
||||
mode: '1777'
|
||||
|
||||
- name: Créer l'utilisateur Step-CA s'il n'existe pas
|
||||
user:
|
||||
name: "{{ stepca_user }}"
|
||||
comment: "Utilisateur pour Step-CA"
|
||||
home: "{{ stepca_home }}"
|
||||
shell: /bin/bash
|
||||
createhome: yes
|
||||
|
||||
- name: Créer le répertoire de configuration Step-CA
|
||||
file:
|
||||
path: "{{ stepca_data_dir }}"
|
||||
state: directory
|
||||
owner: "{{ stepca_user }}"
|
||||
group: "{{ stepca_group }}"
|
||||
mode: '0755'
|
||||
|
||||
- name: Assurer que Step-CA peut écrire dans son dossier
|
||||
command: chown -R {{ stepca_user }}:{{ stepca_group }} {{ stepca_data_dir }}
|
||||
|
||||
##################################################################
|
||||
# 2️⃣ Installation de Step-CA et Step-CLI
|
||||
##################################################################
|
||||
- name: Télécharger et installer Step-CLI et Step-CA (Ubuntu/Debian)
|
||||
apt:
|
||||
deb: "{{ item }}"
|
||||
with_items:
|
||||
- "https://dl.smallstep.com/cli/docs-ca-install/latest/step-cli_amd64.deb"
|
||||
- "https://dl.smallstep.com/certificates/docs-ca-install/latest/step-ca_amd64.deb"
|
||||
when: ansible_os_family == "Debian"
|
||||
|
||||
- name: Vérifier l'installation de Step-CA et Step-CLI
|
||||
command: step version
|
||||
register: step_version
|
||||
changed_when: false
|
||||
|
||||
##################################################################
|
||||
# 3️⃣ Initialisation de Step-CA (si nécessaire)
|
||||
##################################################################
|
||||
- name: Vérifier si Step-CA est déjà initialisé
|
||||
stat:
|
||||
path: "{{ stepca_data_dir }}/config/ca.json"
|
||||
register: ca_json
|
||||
|
||||
- name: Créer le fichier de mot de passe temporaire pour Step-CA
|
||||
copy:
|
||||
dest: "/tmp/stepca_pass"
|
||||
content: "{{ stepca_init_password }}"
|
||||
mode: '0644'
|
||||
|
||||
- name: Initialiser Step-CA (si nécessaire)
|
||||
shell: sudo -u {{ stepca_user }} step ca init --name "My Internal CA" \
|
||||
--dns "{{ stepca_domain }}" \
|
||||
--address ":{{ stepca_port }}" \
|
||||
--provisioner "{{ stepca_provisioner }}" \
|
||||
--password-file /tmp/stepca_pass
|
||||
args:
|
||||
creates: "{{ stepca_data_dir }}/config/ca.json"
|
||||
when: not ca_json.stat.exists
|
||||
|
||||
- name: Supprimer le fichier de mot de passe temporaire
|
||||
file:
|
||||
path: /tmp/stepca_pass
|
||||
state: absent
|
||||
|
||||
##################################################################
|
||||
# 4️⃣ Création du service systemd
|
||||
##################################################################
|
||||
- name: Configurer Step-CA comme un service systemd
|
||||
copy:
|
||||
dest: "/etc/systemd/system/{{ stepca_service }}.service"
|
||||
mode: '0644'
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Step CA Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/step-ca {{ stepca_data_dir }}/config/ca.json
|
||||
Restart=always
|
||||
User={{ stepca_user }}
|
||||
Group={{ stepca_group }}
|
||||
Environment=STEPPATH={{ stepca_data_dir }}
|
||||
WorkingDirectory={{ stepca_data_dir }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
- name: Recharger systemd
|
||||
command: systemctl daemon-reload
|
||||
|
||||
- name: Activer et démarrer Step-CA
|
||||
systemd:
|
||||
name: "{{ stepca_service }}"
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
##################################################################
|
||||
# 5️⃣ Vérification du service
|
||||
##################################################################
|
||||
- name: Vérifier que Step-CA tourne bien
|
||||
shell: "systemctl is-active {{ stepca_service }}"
|
||||
register: stepca_status
|
||||
failed_when: stepca_status.stdout != "active"
|
||||
changed_when: false
|
||||
|
||||
- name: Tester si Step-CA répond sur le port {{ stepca_port }}
|
||||
uri:
|
||||
url: "https://localhost:{{ stepca_port }}/acme/acme-directory"
|
||||
method: GET
|
||||
status_code: 200
|
||||
validate_certs: no
|
||||
register: stepca_test
|
||||
failed_when: stepca_test.status != 200
|
||||
changed_when: false
|
||||
|
||||
15
playbooks/legacy/install_updates.yml
Normal file
15
playbooks/legacy/install_updates.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
- name: Exécuter apt upgrade sur tous les serveurs
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
- name: Mettre à jour la liste des paquets APT
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
- name: Mettre à jour uniquement les paquets installés
|
||||
apt:
|
||||
upgrade: yes
|
||||
|
||||
|
||||
55
playbooks/legacy/integrations.yml
Normal file
55
playbooks/legacy/integrations.yml
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
- name: Ajouter les agents
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
tasks:
|
||||
|
||||
- name: Installer GPG si manquant
|
||||
apt:
|
||||
name: gnupg
|
||||
state: present
|
||||
|
||||
# 1. Ajouter la clé publique du dépôt Icinga
|
||||
- name: Ajouter la clé GPG du dépôt Icinga
|
||||
apt_key:
|
||||
url: https://packages.icinga.com/icinga.key
|
||||
state: present
|
||||
|
||||
# 2. Ajouter le dépôt Icinga (Debian/Ubuntu)
|
||||
- name: Ajouter le dépôt Icinga pour Debian/Ubuntu
|
||||
apt_repository:
|
||||
repo: "deb https://packages.icinga.com/{{ ansible_distribution | lower }} icinga-{{ ansible_distribution_release | lower }} main"
|
||||
state: present
|
||||
|
||||
# 3. Mettre à jour le cache APT
|
||||
- name: Mettre à jour le cache APT
|
||||
apt:
|
||||
update_cache: yes
|
||||
|
||||
# 4. Installer les paquets nécessaires d'Icinga
|
||||
- name: Installer les paquets Icinga
|
||||
apt:
|
||||
name:
|
||||
- icinga2
|
||||
- monitoring-plugins
|
||||
state: latest
|
||||
|
||||
- name: Install QEMU Guest Agent
|
||||
apt:
|
||||
name: qemu-guest-agent
|
||||
state: present
|
||||
|
||||
- name: Enable and start QEMU Guest Agent
|
||||
systemd:
|
||||
name: qemu-guest-agent
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Verify QEMU Guest Agent is running
|
||||
shell: systemctl is-active qemu-guest-agent
|
||||
register: qemu_status
|
||||
changed_when: false
|
||||
|
||||
- name: Display QEMU Guest Agent status
|
||||
debug:
|
||||
msg: "QEMU Guest Agent is {{ qemu_status.stdout }}"
|
||||
28
playbooks/legacy/iptables_config.yml
Normal file
28
playbooks/legacy/iptables_config.yml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
rules_input:
|
||||
- { port: "22", action: "ACCEPT", protocol: "tcp" } # SSH
|
||||
- { port: "1194", action: "ACCEPT", protocol: "udp" } # RPV-SYMBA
|
||||
- { port: "1195", action: "ACCEPT", protocol: "udp" } # RPV-SYSADMIN
|
||||
- { port: "8069", action: "ACCEPT", protocol: "tcp", ctstate: "NEW" }
|
||||
- { port: "8071", action: "ACCEPT", protocol: "tcp", ctstate: "NEW" }
|
||||
- { port: "8072", action: "ACCEPT", protocol: "tcp", ctstate: "NEW" }
|
||||
-
|
||||
rules_forward:
|
||||
- { source: "0.0.0.0/0", destination: "10.10.10.10/32", action: "ACCEPT" } # Autoriser le trafic vers les conteneurs
|
||||
- { source: "0.0.0.0/0", destination: "172.17.0.0/16", action: "ACCEPT" } # Autoriser le trafic vers les conteneurs
|
||||
- { source: "172.17.0.0/16", destination: "0.0.0.0/0", action: "ACCEPT" } # Autoriser les conteneurs à sortir
|
||||
|
||||
rules_output:
|
||||
- { port: "53", action: "ACCEPT", protocol: "udp" } # Autoriser DNS sortant
|
||||
- { port: "80", action: "ACCEPT", protocol: "tcp" } # Autoriser HTTP sortant
|
||||
- { port: "443", action: "ACCEPT", protocol: "tcp" } # Autoriser HTTPS sortant
|
||||
- { port: "123", action: "ACCEPT", protocol: "udp" } # Autoriser NTP sortant
|
||||
- { port: "8069", action: "ACCEPT", protocol: "tcp" }
|
||||
- { port: "8071", action: "ACCEPT", protocol: "tcp" }
|
||||
- { port: "8072", action: "ACCEPT", protocol: "tcp" }
|
||||
-
|
||||
rules_nat_masquerade:
|
||||
- { source: "172.17.0.0/16", destination: "0.0.0.0/0", action: "MASQUERADE" } # Docker NAT
|
||||
|
||||
rules_nat_dnat:
|
||||
- { proto: "tcp", ext_port: "8080", int_port: "80", int_ip: "172.17.0.2", action: "DNAT" } # Redirection HTTP vers un conteneur
|
||||
- { proto: "tcp", ext_port: "8443", int_port: "443", int_ip: "172.17.0.3", action: "DNAT" } # Redirection HTTPS vers un autre conteneur
|
||||
19
playbooks/legacy/maxdevsda1.yml
Normal file
19
playbooks/legacy/maxdevsda1.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
- name: Étendre la partition root avec growpart et resize2fs
|
||||
hosts: leChoixDuSysadmin
|
||||
become: yes
|
||||
tasks:
|
||||
|
||||
- name: Installer cloud-utils (nécessaire pour growpart)
|
||||
apt:
|
||||
name: cloud-guest-utils
|
||||
state: present
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Étendre la partition root avec growpart
|
||||
command: "growpart /dev/sda 1"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Étendre le système de fichiers ext4
|
||||
command: "resize2fs /dev/sda1"
|
||||
ignore_errors: yes
|
||||
|
||||
19
playbooks/legacy/plugins-chezlepro.yml
Normal file
19
playbooks/legacy/plugins-chezlepro.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
- name: Installer les plugins de Chezlepro
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Créer le répertoire /usr/lib/nagios/plugins/chezlepro s'il n'existe pas
|
||||
ansible.builtin.file:
|
||||
path: /usr/lib/nagios/plugins/chezlepro
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Synchroniser les plugins personnalisés
|
||||
ansible.builtin.copy:
|
||||
src: ./plugins/
|
||||
dest: /usr/lib/nagios/plugins/chezlepro/
|
||||
mode: "0755"
|
||||
owner: root
|
||||
group: root
|
||||
161
playbooks/legacy/sys-kbr-base.yml
Normal file
161
playbooks/legacy/sys-kbr-base.yml
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
---
|
||||
- name: Setup Docker and deploy containers for Smallstep CA, NGINX+Certbot, and Keycloak
|
||||
hosts: leChoixDuSysadmin
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Install required packages
|
||||
apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- software-properties-common
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Add Docker GPG key
|
||||
command: >
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
|
||||
- name: Add Docker repository
|
||||
copy:
|
||||
content: "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable\n"
|
||||
dest: /etc/apt/sources.list.d/docker.list
|
||||
|
||||
- name: Install Docker
|
||||
apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
state: latest
|
||||
update_cache: yes
|
||||
|
||||
- name: Start and enable Docker service
|
||||
systemd:
|
||||
name: docker
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Install Docker Compose
|
||||
get_url:
|
||||
url: "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)"
|
||||
dest: /usr/local/bin/docker-compose
|
||||
mode: "0755"
|
||||
|
||||
- name: Create directory for Docker Compose setup
|
||||
file:
|
||||
path: /opt/docker-setup
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Deploy Docker Compose file
|
||||
copy:
|
||||
dest: /opt/docker-setup/docker-compose.yml
|
||||
content: |
|
||||
version: '3.8'
|
||||
services:
|
||||
step-ca:
|
||||
image: smallstep/step-ca:latest
|
||||
container_name: step-ca
|
||||
ports:
|
||||
- "9000:9000"
|
||||
volumes:
|
||||
- step-ca-data:/home/step
|
||||
environment:
|
||||
- STEP_CA_PASSWORD=T1l0u!
|
||||
|
||||
keycloak:
|
||||
image: quay.io/keycloak/keycloak:latest
|
||||
container_name: keycloak
|
||||
command: start-dev
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- KEYCLOAK_ADMIN=admin
|
||||
- KEYCLOAK_ADMIN_PASSWORD=T1l0u!
|
||||
|
||||
nginx:
|
||||
image: nginx:latest
|
||||
container_name: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- nginx-config:/etc/nginx/sites-available
|
||||
- nginx-enabled:/etc/nginx/sites-enabled
|
||||
- nginx-certbot:/etc/letsencrypt
|
||||
depends_on:
|
||||
- step-ca
|
||||
- keycloak
|
||||
|
||||
certbot:
|
||||
image: certbot/certbot:latest
|
||||
container_name: certbot
|
||||
entrypoint: ["/bin/bash", "-c", "trap exit TERM; while :; do sleep 6h & wait; done;"]
|
||||
volumes:
|
||||
- nginx-certbot:/etc/letsencrypt
|
||||
- certbot-config:/var/lib/letsencrypt
|
||||
|
||||
volumes:
|
||||
step-ca-data:
|
||||
nginx-config:
|
||||
nginx-enabled:
|
||||
nginx-certbot:
|
||||
certbot-config:
|
||||
|
||||
- name: Start Docker Compose services
|
||||
command: docker-compose up -d
|
||||
args:
|
||||
chdir: /opt/docker-setup
|
||||
|
||||
- name: Configure NGINX for Smallstep CA
|
||||
copy:
|
||||
dest: /opt/docker-setup/sites-available/step-ca.conf
|
||||
content: |
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name step-ca.your_domain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/step-ca.kbr.net/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/step-ca.kbr.net/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://step-ce.kbr.net:9000/;
|
||||
}
|
||||
}
|
||||
|
||||
- name: Configure NGINX for Keycloak
|
||||
copy:
|
||||
dest: /opt/docker-setup/sites-available/keycloak.conf
|
||||
content: |
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name keycloak.kbr.net;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/keycloak.kbr.net/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/keycloak.kbr.net/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://keycloak.kbr.net:8080/;
|
||||
}
|
||||
}
|
||||
|
||||
- name: Link site configurations
|
||||
file:
|
||||
src: /etc/nginx/sites-available/{{ item }}
|
||||
dest: /etc/nginx/sites-enabled/{{ item }}
|
||||
state: link
|
||||
with_items:
|
||||
- step-ca.conf
|
||||
- keycloak.conf
|
||||
|
||||
- name: Test NGINX configuration
|
||||
command: nginx -t
|
||||
|
||||
- name: Restart NGINX
|
||||
systemd:
|
||||
name: nginx
|
||||
state: restarted
|
||||
|
||||
7
playbooks/proxmox_deb12_cloudinit.yml
Normal file
7
playbooks/proxmox_deb12_cloudinit.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
- name: Proxmox · Debian 12 cloud-init · template + clones
|
||||
hosts: proxmox
|
||||
become: true
|
||||
gather_facts: false
|
||||
roles:
|
||||
- proxmox_deb12_cloudinit
|
||||
32
playbooks/site.yml
Normal file
32
playbooks/site.yml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
- name: Baseline
|
||||
hosts: servers
|
||||
become: true
|
||||
roles:
|
||||
- baseline_packages
|
||||
- baseline_updates
|
||||
|
||||
- name: Security
|
||||
hosts: servers
|
||||
become: true
|
||||
roles:
|
||||
- security_hardening
|
||||
- firewall_nftables
|
||||
|
||||
- name: Monitoring
|
||||
hosts: servers
|
||||
become: true
|
||||
roles:
|
||||
- monitoring_icinga
|
||||
|
||||
- name: DNS authoritative
|
||||
hosts: dns
|
||||
become: true
|
||||
roles:
|
||||
- dns_powerdns
|
||||
|
||||
- name: Reverse proxy
|
||||
hosts: proxy
|
||||
become: true
|
||||
roles:
|
||||
- reverse_proxy_traefik
|
||||
8
roles/baseline_packages/defaults/main.yml
Normal file
8
roles/baseline_packages/defaults/main.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
baseline_packages_enabled: true
|
||||
baseline_packages_list:
|
||||
- ca-certificates
|
||||
- curl
|
||||
- vim
|
||||
- git
|
||||
- chrony
|
||||
- qemu-guest-agent
|
||||
17
roles/baseline_packages/tasks/main.yml
Normal file
17
roles/baseline_packages/tasks/main.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
- name: Gate
|
||||
ansible.builtin.meta: end_host
|
||||
when: not baseline_packages_enabled | bool
|
||||
|
||||
- name: Install baseline packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ baseline_packages_list }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Enable qemu-guest-agent (if present)
|
||||
ansible.builtin.systemd:
|
||||
name: qemu-guest-agent
|
||||
enabled: true
|
||||
state: started
|
||||
ignore_errors: true
|
||||
2
roles/baseline_updates/defaults/main.yml
Normal file
2
roles/baseline_updates/defaults/main.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
baseline_updates_enabled: true
|
||||
baseline_updates_upgrade: true
|
||||
14
roles/baseline_updates/tasks/main.yml
Normal file
14
roles/baseline_updates/tasks/main.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
- name: Gate
|
||||
ansible.builtin.meta: end_host
|
||||
when: not baseline_updates_enabled | bool
|
||||
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Upgrade packages
|
||||
ansible.builtin.apt:
|
||||
upgrade: "yes"
|
||||
when: baseline_updates_upgrade | bool
|
||||
24
roles/dns_powerdns/defaults/main.yml
Normal file
24
roles/dns_powerdns/defaults/main.yml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
dns_powerdns_enabled: false
|
||||
|
||||
pdns_backend: "sqlite3"
|
||||
pdns_sqlite_db_path: "/var/lib/powerdns/pdns.sqlite3"
|
||||
|
||||
pdns_api_enabled: true
|
||||
pdns_api_key: "{{ vault_pdns_api_key | default('') }}"
|
||||
pdns_webserver_address: "127.0.0.1"
|
||||
pdns_webserver_port: 8081
|
||||
|
||||
pdns_zones: []
|
||||
# Example:
|
||||
# pdns_zones:
|
||||
# - name: "chezlepro.ca"
|
||||
# kind: "Native"
|
||||
# soa:
|
||||
# ns: "ns1.chezlepro.ca."
|
||||
# hostmaster: "hostmaster.chezlepro.ca."
|
||||
# refresh: 10800
|
||||
# retry: 3600
|
||||
# expire: 604800
|
||||
# minimum: 3600
|
||||
# nameservers:
|
||||
# - "ns1.chezlepro.ca."
|
||||
5
roles/dns_powerdns/handlers/main.yml
Normal file
5
roles/dns_powerdns/handlers/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
- name: Restart pdns
|
||||
ansible.builtin.systemd:
|
||||
name: pdns
|
||||
state: restarted
|
||||
55
roles/dns_powerdns/tasks/main.yml
Normal file
55
roles/dns_powerdns/tasks/main.yml
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
- name: Gate
|
||||
ansible.builtin.meta: end_host
|
||||
when: not dns_powerdns_enabled | bool
|
||||
|
||||
- name: Install PowerDNS and backend deps
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- pdns-server
|
||||
- sqlite3
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure db dir exists (sqlite)
|
||||
ansible.builtin.file:
|
||||
path: "{{ pdns_sqlite_db_path | dirname }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
when: pdns_backend == "sqlite3"
|
||||
|
||||
- name: Deploy pdns.conf
|
||||
ansible.builtin.template:
|
||||
src: pdns.conf.j2
|
||||
dest: /etc/powerdns/pdns.conf
|
||||
mode: "0644"
|
||||
notify: Restart pdns
|
||||
|
||||
- name: Enable and start pdns
|
||||
ansible.builtin.systemd:
|
||||
name: pdns
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Create zones + SOA (pdnsutil)
|
||||
ansible.builtin.command: >
|
||||
pdnsutil create-zone {{ item.name }}
|
||||
{% if item.soa is defined %}
|
||||
{{ item.soa.ns }} {{ item.soa.hostmaster }}
|
||||
{% endif %}
|
||||
args:
|
||||
creates: "/var/lib/powerdns/zones/{{ item.name }}"
|
||||
loop: "{{ pdns_zones }}"
|
||||
when: pdns_zones | length > 0
|
||||
register: pdns_create_zone
|
||||
changed_when: pdns_create_zone.rc == 0
|
||||
failed_when: pdns_create_zone.rc not in [0, 1]
|
||||
|
||||
- name: Ensure NS records exist
|
||||
ansible.builtin.command: >
|
||||
pdnsutil add-record {{ item.0.name }} @ NS {{ item.1 }}
|
||||
loop: "{{ pdns_zones | subelements('nameservers', skip_missing=True) }}"
|
||||
register: pdns_add_ns
|
||||
changed_when: "'Added record' in (pdns_add_ns.stdout | default(''))"
|
||||
failed_when: pdns_add_ns.rc != 0
|
||||
when: pdns_zones | length > 0
|
||||
16
roles/dns_powerdns/templates/pdns.conf.j2
Normal file
16
roles/dns_powerdns/templates/pdns.conf.j2
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Managed by Ansible
|
||||
|
||||
launch={{ pdns_backend }}
|
||||
{% if pdns_backend == "sqlite3" %}
|
||||
gsqlite3-database={{ pdns_sqlite_db_path }}
|
||||
{% endif %}
|
||||
|
||||
{% if pdns_api_enabled %}
|
||||
api=yes
|
||||
api-key={{ pdns_api_key }}
|
||||
webserver=yes
|
||||
webserver-address={{ pdns_webserver_address }}
|
||||
webserver-port={{ pdns_webserver_port }}
|
||||
{% else %}
|
||||
api=no
|
||||
{% endif %}
|
||||
14
roles/firewall_nftables/defaults/main.yml
Normal file
14
roles/firewall_nftables/defaults/main.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
firewall_nftables_enabled: true
|
||||
firewall_nftables_flush_ruleset: false
|
||||
|
||||
firewall_nftables_allowed_tcp_in:
|
||||
- { dport: 22, src: "0.0.0.0/0" }
|
||||
|
||||
firewall_nftables_allowed_udp_in: []
|
||||
|
||||
firewall_nftables_allow_established: true
|
||||
firewall_nftables_allow_loopback: true
|
||||
|
||||
firewall_nftables_policy_input: drop
|
||||
firewall_nftables_policy_forward: drop
|
||||
firewall_nftables_policy_output: accept
|
||||
6
roles/firewall_nftables/handlers/main.yml
Normal file
6
roles/firewall_nftables/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: Reload nftables
|
||||
ansible.builtin.systemd:
|
||||
name: nftables
|
||||
state: reloaded
|
||||
ignore_errors: true
|
||||
23
roles/firewall_nftables/tasks/main.yml
Normal file
23
roles/firewall_nftables/tasks/main.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
- name: Gate
|
||||
ansible.builtin.meta: end_host
|
||||
when: not firewall_nftables_enabled | bool
|
||||
|
||||
- name: Install nftables
|
||||
ansible.builtin.apt:
|
||||
name: nftables
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Deploy nftables config
|
||||
ansible.builtin.template:
|
||||
src: nftables.conf.j2
|
||||
dest: /etc/nftables.conf
|
||||
mode: "0644"
|
||||
notify: Reload nftables
|
||||
|
||||
- name: Enable and start nftables
|
||||
ansible.builtin.systemd:
|
||||
name: nftables
|
||||
enabled: true
|
||||
state: started
|
||||
42
roles/firewall_nftables/templates/nftables.conf.j2
Normal file
42
roles/firewall_nftables/templates/nftables.conf.j2
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/sbin/nft -f
|
||||
|
||||
{% if firewall_nftables_flush_ruleset %}
|
||||
flush ruleset
|
||||
{% endif %}
|
||||
|
||||
table inet filter {
|
||||
chain input {
|
||||
type filter hook input priority 0;
|
||||
policy {{ firewall_nftables_policy_input }};
|
||||
|
||||
{% if firewall_nftables_allow_loopback %}
|
||||
iif "lo" accept
|
||||
{% endif %}
|
||||
|
||||
{% if firewall_nftables_allow_established %}
|
||||
ct state established,related accept
|
||||
{% endif %}
|
||||
|
||||
# ICMP / ICMPv6 minimal
|
||||
ip protocol icmp accept
|
||||
ip6 nexthdr icmpv6 accept
|
||||
|
||||
{% for r in firewall_nftables_allowed_tcp_in %}
|
||||
ip saddr {{ r.src }} tcp dport {{ r.dport }} accept
|
||||
{% endfor %}
|
||||
|
||||
{% for r in firewall_nftables_allowed_udp_in %}
|
||||
ip saddr {{ r.src }} udp dport {{ r.dport }} 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 }};
|
||||
}
|
||||
}
|
||||
14
roles/monitoring_icinga/defaults/main.yml
Normal file
14
roles/monitoring_icinga/defaults/main.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
monitoring_icinga_enabled: true
|
||||
monitoring_icinga_agent_enabled: true
|
||||
monitoring_icinga_plugins_enabled: false
|
||||
monitoring_icinga_director_enabled: false
|
||||
|
||||
monitoring_icinga_agent_pkg: "icinga2"
|
||||
monitoring_icinga_agent_service: "icinga2"
|
||||
|
||||
monitoring_icinga_plugins_dest_dir: "/usr/lib/nagios/plugins"
|
||||
|
||||
monitoring_icinga_director_api_url: ""
|
||||
monitoring_icinga_director_api_token: ""
|
||||
monitoring_icinga_director_validate_certs: false
|
||||
monitoring_icinga_director_objects: []
|
||||
6
roles/monitoring_icinga/handlers/main.yml
Normal file
6
roles/monitoring_icinga/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: Restart Icinga2
|
||||
ansible.builtin.systemd:
|
||||
name: icinga2
|
||||
state: restarted
|
||||
ignore_errors: true
|
||||
12
roles/monitoring_icinga/tasks/agent.yml
Normal file
12
roles/monitoring_icinga/tasks/agent.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
- name: Install Icinga2
|
||||
ansible.builtin.apt:
|
||||
name: "{{ monitoring_icinga_agent_pkg }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Enable and start Icinga2
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ monitoring_icinga_agent_service }}"
|
||||
enabled: true
|
||||
state: started
|
||||
20
roles/monitoring_icinga/tasks/director.yml
Normal file
20
roles/monitoring_icinga/tasks/director.yml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
- name: Validate Director settings
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- monitoring_icinga_director_api_url | length > 0
|
||||
- monitoring_icinga_director_api_token | length > 0
|
||||
fail_msg: "Set monitoring_icinga_director_api_url/token when monitoring_icinga_director_enabled=true"
|
||||
|
||||
- name: Push Director objects
|
||||
ansible.builtin.uri:
|
||||
url: "{{ monitoring_icinga_director_api_url }}"
|
||||
method: POST
|
||||
headers:
|
||||
Accept: "application/json"
|
||||
Authorization: "Bearer {{ monitoring_icinga_director_api_token }}"
|
||||
body_format: json
|
||||
validate_certs: "{{ monitoring_icinga_director_validate_certs | bool }}"
|
||||
body: "{{ item }}"
|
||||
loop: "{{ monitoring_icinga_director_objects }}"
|
||||
no_log: true
|
||||
19
roles/monitoring_icinga/tasks/main.yml
Normal file
19
roles/monitoring_icinga/tasks/main.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
- name: Gate
|
||||
ansible.builtin.meta: end_host
|
||||
when: not monitoring_icinga_enabled | bool
|
||||
|
||||
- name: Agent
|
||||
ansible.builtin.import_tasks: agent.yml
|
||||
when: monitoring_icinga_agent_enabled | bool
|
||||
tags: [monitoring, icinga, agent]
|
||||
|
||||
- name: Plugins
|
||||
ansible.builtin.import_tasks: plugins.yml
|
||||
when: monitoring_icinga_plugins_enabled | bool
|
||||
tags: [monitoring, icinga, plugins]
|
||||
|
||||
- name: Director
|
||||
ansible.builtin.import_tasks: director.yml
|
||||
when: monitoring_icinga_director_enabled | bool
|
||||
tags: [monitoring, icinga, director]
|
||||
13
roles/monitoring_icinga/tasks/plugins.yml
Normal file
13
roles/monitoring_icinga/tasks/plugins.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
- name: Ensure plugins dir
|
||||
ansible.builtin.file:
|
||||
path: "{{ monitoring_icinga_plugins_dest_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Deploy Chezlepro plugins (if provided)
|
||||
ansible.builtin.copy:
|
||||
src: "plugins/"
|
||||
dest: "{{ monitoring_icinga_plugins_dest_dir }}/"
|
||||
mode: "0755"
|
||||
notify: Restart Icinga2
|
||||
26
roles/proxmox_deb12_cloudinit/defaults/main.yml
Normal file
26
roles/proxmox_deb12_cloudinit/defaults/main.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Proxmox (adapter à votre environnement)
|
||||
pve_node: "asgard"
|
||||
pve_storage: "CephNVMe"
|
||||
pve_cloudinit_storage: "CephNVMe"
|
||||
pve_snippets_storage: "cephFS"
|
||||
|
||||
# Template Debian 12
|
||||
deb12_template_id: 1681501
|
||||
deb12_template_name: "debian12-genericcloud"
|
||||
deb12_cloud_image_url: "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2"
|
||||
deb12_template_bridge: "vmbr1"
|
||||
deb12_template_machine: "q35"
|
||||
deb12_template_cpu: "host"
|
||||
|
||||
# Cloud-init user-data
|
||||
ci_user: "ansible"
|
||||
ci_lock_passwd: true
|
||||
ci_ssh_pwauth: false
|
||||
ci_password_hash: "" # idéalement via vault
|
||||
ci_authorized_keys: [] # liste de clés publiques
|
||||
ci_nameserver_default: "1.1.1.1"
|
||||
ci_searchdomain_default: ""
|
||||
apt_proxy_url: ""
|
||||
|
||||
# VMs à cloner
|
||||
vms: []
|
||||
26
roles/proxmox_deb12_cloudinit/tasks/00_snippets.yml
Normal file
26
roles/proxmox_deb12_cloudinit/tasks/00_snippets.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
# Active 'snippets' sur le storage ciblé et dépose le cloud-config
|
||||
- name: Activer le type 'snippets' sur {{ pve_snippets_storage }}
|
||||
command: >
|
||||
pvesm set {{ pve_snippets_storage }}
|
||||
--content snippets,iso,vztmpl,backup
|
||||
changed_when: false
|
||||
|
||||
- name: Déterminer le dossier snippets selon le storage
|
||||
set_fact:
|
||||
snippets_dir: >-
|
||||
{{ '/var/lib/vz/snippets'
|
||||
if pve_snippets_storage == 'local'
|
||||
else '/mnt/pve/' + pve_snippets_storage + '/snippets' }}
|
||||
|
||||
- name: Créer le dossier snippets
|
||||
file:
|
||||
path: "{{ snippets_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Déposer le #cloud-config Chezlepro
|
||||
template:
|
||||
src: "chezlepro-user-data.yml.j2"
|
||||
dest: "{{ snippets_dir }}/chezlepro-user-data.yml"
|
||||
mode: "0644"
|
||||
87
roles/proxmox_deb12_cloudinit/tasks/10_template.yml
Normal file
87
roles/proxmox_deb12_cloudinit/tasks/10_template.yml
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
- name: Préparer le dossier temporaire d’images
|
||||
file:
|
||||
path: "/var/lib/vz/template/tmp"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Chemin local de l'image cloud
|
||||
set_fact:
|
||||
deb12_img_path: "/var/lib/vz/template/tmp/debian-12-genericcloud-amd64.qcow2"
|
||||
|
||||
- name: Vérifier si l'image est déjà présente
|
||||
stat:
|
||||
path: "{{ deb12_img_path }}"
|
||||
register: deb12_img
|
||||
|
||||
- name: Télécharger l'image cloud Debian 12 (si absente)
|
||||
get_url:
|
||||
url: "{{ deb12_cloud_image_url }}"
|
||||
dest: "{{ deb12_img_path }}"
|
||||
mode: "0644"
|
||||
when: not deb12_img.stat.exists
|
||||
|
||||
# Defaults "safe"
|
||||
- name: Définir les valeurs par défaut du template (si non définies)
|
||||
set_fact:
|
||||
deb12_template_bridge: "{{ deb12_template_bridge | default('vmbr1') }}"
|
||||
# deb12_template_machine: "{{ deb12_template_machine | default('q35') }}"
|
||||
deb12_template_cpu: "{{ deb12_template_cpu | default('host') }}"
|
||||
|
||||
- name: Vérifier si le template existe déjà
|
||||
command: "qm status {{ deb12_template_id }}"
|
||||
register: tmpl_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Créer le template cloud-init (si absent)
|
||||
shell: |
|
||||
set -euo pipefail
|
||||
|
||||
# 1) Créer la VM si absente (en imposant q35 + cpu host dès le départ)
|
||||
qm create {{ deb12_template_id }} \
|
||||
--name {{ deb12_template_name }} \
|
||||
--memory 1024 --cores 2 \
|
||||
--cpu {{ deb12_template_cpu }} \
|
||||
--ostype l26 \
|
||||
--net0 virtio,bridge={{ deb12_template_bridge }} \
|
||||
--agent enabled=1
|
||||
|
||||
# 2) Disque OS (qcow2 importé)
|
||||
qm set {{ deb12_template_id }} --scsihw virtio-scsi-pci
|
||||
qm importdisk {{ deb12_template_id }} {{ deb12_img_path }} {{ pve_storage }} --format qcow2
|
||||
qm set {{ deb12_template_id }} --scsi0 {{ pve_storage }}:vm-{{ deb12_template_id }}-disk-0
|
||||
|
||||
# 3) Cloud-init
|
||||
qm set {{ deb12_template_id }} --ide2 {{ pve_cloudinit_storage }}:cloudinit
|
||||
qm set {{ deb12_template_id }} --boot c --bootdisk scsi0
|
||||
|
||||
# 5) Convertir en template
|
||||
qm template {{ deb12_template_id }}
|
||||
args:
|
||||
executable: /bin/bash
|
||||
when: tmpl_status.rc != 0
|
||||
|
||||
# IMPORTANT : pour un template déjà existant, on force machine/cpu, MAIS on ne retouche PAS net0 (évite tout changement de MAC).
|
||||
- name: Assurer machine q35 sur template existant
|
||||
command: "qm set {{ deb12_template_id }} --machine {{ deb12_template_machine }}"
|
||||
when: tmpl_status.rc == 0
|
||||
changed_when: true
|
||||
|
||||
- name: Assurer CPU host sur template existant
|
||||
command: "qm set {{ deb12_template_id }} --cpu {{ deb12_template_cpu }}"
|
||||
when: tmpl_status.rc == 0
|
||||
changed_when: true
|
||||
|
||||
- name: Assurer agent
|
||||
command: "qm set {{ deb12_template_id }} --agent enabled=1"
|
||||
when: tmpl_status.rc == 0
|
||||
changed_when: true
|
||||
|
||||
- name: Afficher le template
|
||||
command: "qm config {{ deb12_template_id }}"
|
||||
register: tmplcfg
|
||||
changed_when: false
|
||||
|
||||
- debug:
|
||||
var: tmplcfg.stdout_lines
|
||||
46
roles/proxmox_deb12_cloudinit/tasks/10_template.yml.old
Normal file
46
roles/proxmox_deb12_cloudinit/tasks/10_template.yml.old
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
- name: Préparer le dossier temporaire d’images
|
||||
file:
|
||||
path: "/var/lib/vz/template/tmp"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Chemin local de l'image cloud
|
||||
set_fact:
|
||||
deb12_img_path: "/var/lib/vz/template/tmp/debian-12-genericcloud-amd64.qcow2"
|
||||
|
||||
- name: Vérifier si l'image est déjà présente
|
||||
stat:
|
||||
path: "{{ deb12_img_path }}"
|
||||
register: deb12_img
|
||||
|
||||
- name: Télécharger l'image cloud Debian 12 (si absente)
|
||||
get_url:
|
||||
url: "{{ deb12_cloud_image_url }}"
|
||||
dest: "{{ deb12_img_path }}"
|
||||
mode: "0644"
|
||||
when: not deb12_img.stat.exists
|
||||
|
||||
- name: Créer le template cloud-init (si absent)
|
||||
shell: |
|
||||
set -e
|
||||
if ! qm status {{ deb12_template_id }} >/dev/null 2>&1; then
|
||||
qm create {{ deb12_template_id }} --name {{ deb12_template_name }} --memory 1024 --cores 2 \
|
||||
--net0 virtio,bridge=vmbr0 --agent enabled=1
|
||||
qm set {{ deb12_template_id }} --scsihw virtio-scsi-pci
|
||||
qm importdisk {{ deb12_template_id }} {{ deb12_img_path }} {{ pve_storage }} --format qcow2
|
||||
qm set {{ deb12_template_id }} --scsi0 {{ pve_storage }}:vm-{{ deb12_template_id }}-disk-0
|
||||
qm set {{ deb12_template_id }} --ide2 {{ pve_cloudinit_storage }}:cloudinit
|
||||
qm set {{ deb12_template_id }} --boot c --bootdisk scsi0
|
||||
qm template {{ deb12_template_id }}
|
||||
fi
|
||||
args:
|
||||
executable: /bin/bash
|
||||
|
||||
- name: Afficher le template créé
|
||||
shell: "qm config {{ deb12_template_id }}"
|
||||
register: tmplcfg
|
||||
changed_when: false
|
||||
|
||||
- debug:
|
||||
var: tmplcfg.stdout_lines
|
||||
10
roles/proxmox_deb12_cloudinit/tasks/20_clones.yml
Normal file
10
roles/proxmox_deb12_cloudinit/tasks/20_clones.yml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
- name: Provisionner les VMs depuis le template
|
||||
include_tasks: 21_clone_one.yml
|
||||
loop: "{{ vms }}"
|
||||
loop_control:
|
||||
loop_var: vm
|
||||
label: "{{ vm.name }}"
|
||||
vars:
|
||||
ci_nameserver: "{{ nameserver | default('1.1.1.1') }}"
|
||||
ci_searchdomain: "{{ searchdomain | default('') }}"
|
||||
101
roles/proxmox_deb12_cloudinit/tasks/21_clone_one.yml
Normal file
101
roles/proxmox_deb12_cloudinit/tasks/21_clone_one.yml
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# ============================================================================
|
||||
# Création/Configuration VM depuis template Debian 12 genericcloud
|
||||
# Objectif: q35 + MAC stable + ipconfig0 stable (Ansible-only)
|
||||
# ============================================================================
|
||||
|
||||
- name: Cloner la VM (si absente)
|
||||
shell: |
|
||||
set -euo pipefail
|
||||
if ! qm status {{ vm.id }} >/dev/null 2>&1; then
|
||||
qm clone {{ deb12_template_id }} {{ vm.id }} --name {{ vm.name }} --full 1 --target {{ pve_node }}
|
||||
fi
|
||||
args: { executable: /bin/bash }
|
||||
|
||||
# --- Lecture config actuelle -------------------------------------------------
|
||||
|
||||
- name: Lire la config Proxmox de la VM
|
||||
command: "qm config {{ vm.id }}"
|
||||
register: vm_cfg
|
||||
changed_when: false
|
||||
|
||||
- name: Lire le statut de la VM
|
||||
command: "qm status {{ vm.id }}"
|
||||
register: vm_status
|
||||
changed_when: false
|
||||
|
||||
# --- Appliquer hardware VM (host + cores/mem) -----------
|
||||
|
||||
- name: Appliquer CPU host + cores/memory stable
|
||||
command: >
|
||||
qm set {{ vm.id }}
|
||||
--cpu host
|
||||
--cores {{ vm.cores }}
|
||||
--memory {{ vm.memory }}
|
||||
changed_when: true
|
||||
|
||||
# --- Disque -----------------------------------------------------------------
|
||||
|
||||
- name: Redimensionner le disque système (idempotence simple)
|
||||
command: "qm resize {{ vm.id }} scsi0 {{ vm.disk_gb }}G"
|
||||
register: resize_out
|
||||
failed_when: >
|
||||
resize_out.rc != 0 and
|
||||
('no need to resize' not in (resize_out.stderr | lower)) and
|
||||
('shrinking' not in (resize_out.stderr | lower))
|
||||
changed_when: resize_out.rc == 0
|
||||
|
||||
# --- Cloud-init : sshkeys + réseau + DNS + hostname via meta-data -----------
|
||||
|
||||
- name: Créer le dossier pour les clés (si absent)
|
||||
file:
|
||||
path: /root/.cache/ansible
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Déposer la clé SSH publique de {{ vm.name }}
|
||||
copy:
|
||||
content: "{{ vm.sshkeys }}"
|
||||
dest: "/root/.cache/ansible/qm-sshkeys-{{ vm.id }}.pub"
|
||||
mode: "0600"
|
||||
|
||||
- name: Paramétrer cloud-init (user, sshkeys, réseau, DNS)
|
||||
command: >
|
||||
qm set {{ vm.id }}
|
||||
--ciuser {{ vm.ciuser | default('ansible') }}
|
||||
--sshkeys /root/.cache/ansible/qm-sshkeys-{{ vm.id }}.pub
|
||||
--ipconfig0 {{ vm.ipconfig0 }}
|
||||
--nameserver {{ ci_nameserver }}{{ (' --searchdomain ' + ci_searchdomain) if ci_searchdomain else '' }}
|
||||
--ciupgrade 1
|
||||
changed_when: true
|
||||
|
||||
# --- Hostname via meta-data NoCloud ----------------------------------------
|
||||
|
||||
- name: Générer le meta-data (hostname) pour {{ vm.name }}
|
||||
copy:
|
||||
dest: "{{ snippets_dir }}/meta-{{ vm.id }}.yml"
|
||||
mode: "0644"
|
||||
content: |
|
||||
instance-id: {{ vm.id }}
|
||||
local-hostname: {{ vm.name }}
|
||||
|
||||
- name: Associer user-data + meta-data via cicustom
|
||||
command: >
|
||||
qm set {{ vm.id }}
|
||||
--cicustom "user={{ pve_snippets_storage }}:snippets/chezlepro-user-data.yml,meta={{ pve_snippets_storage }}:snippets/meta-{{ vm.id }}.yml"
|
||||
changed_when: true
|
||||
|
||||
- name: Régénérer le disque cloud-init
|
||||
command: "qm cloudinit update {{ vm.id }}"
|
||||
changed_when: true
|
||||
|
||||
# --- Démarrage --------------------------------------------------------------
|
||||
|
||||
- name: Start VM (tolerate already running)
|
||||
command: "qm start {{ vm.id }}"
|
||||
register: vm_start
|
||||
failed_when: >
|
||||
vm_start.rc != 0 and
|
||||
('already running' not in (vm_start.stderr | lower))
|
||||
changed_when: vm_start.rc == 0
|
||||
76
roles/proxmox_deb12_cloudinit/tasks/21_clone_one.yml.old
Normal file
76
roles/proxmox_deb12_cloudinit/tasks/21_clone_one.yml.old
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
- name: Cloner la VM (si absente)
|
||||
shell: |
|
||||
set -e
|
||||
if ! qm status {{ vm.id }} >/dev/null 2>&1; then
|
||||
qm clone {{ deb12_template_id }} {{ vm.id }} --name {{ vm.name }} --full 1 --target {{ pve_node }}
|
||||
fi
|
||||
args: { executable: /bin/bash }
|
||||
|
||||
- name: Configurer CPU/RAM/NIC (+ VLAN tag si défini)
|
||||
shell: |
|
||||
set -e
|
||||
qm set {{ vm.id }} --cores {{ vm.cores }} --memory {{ vm.memory }} \
|
||||
--net0 virtio,bridge={{ vm.bridge }}{{ (',tag=' + vm.tag|string) if (vm.tag is defined) else '' }}
|
||||
args: { executable: /bin/bash }
|
||||
|
||||
- name: Redimensionner le disque système
|
||||
shell: "qm resize {{ vm.id }} scsi0 {{ vm.disk_gb }}G"
|
||||
args: { executable: /bin/bash }
|
||||
|
||||
- name: Créer le dossier pour les clés (si absent)
|
||||
file:
|
||||
path: /root/.cache/ansible
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Déposer la clé SSH publique de {{ vm.name }}
|
||||
copy:
|
||||
content: "{{ vm.sshkeys }}"
|
||||
dest: "/root/.cache/ansible/qm-sshkeys-{{ vm.id }}.pub"
|
||||
mode: "0600"
|
||||
|
||||
- name: Paramétrer cloud-init (user, ssh, réseau, DNS)
|
||||
shell: |
|
||||
set -e
|
||||
qm set {{ vm.id }} --ipconfig0 "{{ vm.ipconfig0 }}"
|
||||
qm set {{ vm.id }} --nameserver {{ ci_nameserver }}{{ (' --searchdomain ' + ci_searchdomain) if ci_searchdomain else '' }}
|
||||
qm set {{ vm.id }} --ciupgrade 1
|
||||
args: { executable: /bin/bash }
|
||||
|
||||
# --- Nouveau : hostname via meta-data NoCloud -------------------------------
|
||||
|
||||
- name: Générer le meta-data (hostname) pour {{ vm.name }}
|
||||
copy:
|
||||
dest: "{{ snippets_dir }}/meta-{{ vm.id }}.yml"
|
||||
mode: "0644"
|
||||
content: |
|
||||
instance-id: {{ vm.id }}
|
||||
local-hostname: {{ vm.name }}
|
||||
|
||||
- name: Associer user-data + meta-data via cicustom
|
||||
shell: |
|
||||
set -e
|
||||
qm set {{ vm.id }} --cicustom "user={{ pve_snippets_storage }}:snippets/chezlepro-user-data.yml,meta={{ pve_snippets_storage }}:snippets/meta-{{ vm.id }}.yml"
|
||||
args: { executable: /bin/bash }
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
- name: Régénérer le disque cloud-init
|
||||
shell: "qm cloudinit update {{ vm.id }}"
|
||||
args: { executable: /bin/bash }
|
||||
|
||||
- name: Start VM (tolerate already running)
|
||||
ansible.builtin.command: qm start {{ vm.id }}
|
||||
register: vm_start
|
||||
failed_when: >
|
||||
vm_start.rc != 0 and
|
||||
('already running' not in vm_start.stderr | lower)
|
||||
changed_when: >
|
||||
vm_start.rc == 0
|
||||
|
||||
#- name: Démarrer la VM
|
||||
# shell: "qm start {{ vm.id }}"
|
||||
# args: { executable: /bin/bash }
|
||||
4
roles/proxmox_deb12_cloudinit/tasks/main.yml
Normal file
4
roles/proxmox_deb12_cloudinit/tasks/main.yml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
- import_tasks: 00_snippets.yml
|
||||
- import_tasks: 10_template.yml
|
||||
- import_tasks: 20_clones.yml
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#cloud-config
|
||||
users:
|
||||
- name: {{ ci_user }}
|
||||
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
||||
lock_passwd: {{ 'true' if ci_lock_passwd else 'false' }}
|
||||
ssh_pwauth: {{ 'true' if ci_ssh_pwauth else 'false' }}
|
||||
{% if ci_password_hash|length > 0 %}
|
||||
passwd: "{{ ci_password_hash }}"
|
||||
{% endif %}
|
||||
ssh_authorized_keys:
|
||||
{% for k in ci_authorized_keys %}
|
||||
- {{ k }}
|
||||
{% endfor %}
|
||||
|
||||
package_update: true
|
||||
packages:
|
||||
- qemu-guest-agent
|
||||
- chrony
|
||||
|
||||
runcmd:
|
||||
- systemctl enable --now qemu-guest-agent
|
||||
- systemctl enable --now chrony
|
||||
- apt-get -y autoremove
|
||||
22
roles/reverse_proxy_traefik/defaults/main.yml
Normal file
22
roles/reverse_proxy_traefik/defaults/main.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
reverse_proxy_traefik_enabled: false
|
||||
|
||||
traefik_user: "traefik"
|
||||
traefik_group: "traefik"
|
||||
|
||||
traefik_version: "v3.0.0"
|
||||
traefik_arch: "linux_amd64"
|
||||
traefik_download_base: "https://github.com/traefik/traefik/releases/download"
|
||||
|
||||
traefik_bin_path: "/usr/local/bin/traefik"
|
||||
traefik_config_dir: "/etc/traefik"
|
||||
traefik_data_dir: "/var/lib/traefik"
|
||||
|
||||
traefik_listen_http: 80
|
||||
traefik_listen_https: 443
|
||||
|
||||
traefik_dashboard_enabled: false
|
||||
traefik_log_level: "INFO"
|
||||
|
||||
traefik_acme_enabled: false
|
||||
traefik_acme_email: ""
|
||||
traefik_acme_storage: "/var/lib/traefik/acme.json"
|
||||
5
roles/reverse_proxy_traefik/handlers/main.yml
Normal file
5
roles/reverse_proxy_traefik/handlers/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
- name: Restart traefik
|
||||
ansible.builtin.systemd:
|
||||
name: traefik
|
||||
state: restarted
|
||||
73
roles/reverse_proxy_traefik/tasks/main.yml
Normal file
73
roles/reverse_proxy_traefik/tasks/main.yml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
- name: Gate
|
||||
ansible.builtin.meta: end_host
|
||||
when: not reverse_proxy_traefik_enabled | bool
|
||||
|
||||
- name: Create traefik group
|
||||
ansible.builtin.group:
|
||||
name: "{{ traefik_group }}"
|
||||
system: true
|
||||
|
||||
- name: Create traefik user
|
||||
ansible.builtin.user:
|
||||
name: "{{ traefik_user }}"
|
||||
group: "{{ traefik_group }}"
|
||||
system: true
|
||||
create_home: false
|
||||
shell: /usr/sbin/nologin
|
||||
|
||||
- name: Create directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ traefik_user }}"
|
||||
group: "{{ traefik_group }}"
|
||||
mode: "0755"
|
||||
loop:
|
||||
- "{{ traefik_config_dir }}"
|
||||
- "{{ traefik_config_dir }}/dynamic"
|
||||
- "{{ traefik_data_dir }}"
|
||||
|
||||
- name: Download traefik
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ traefik_download_base }}/{{ traefik_version }}/traefik_{{ traefik_version }}_{{ traefik_arch }}.tar.gz"
|
||||
dest: "/tmp/traefik_{{ traefik_version }}.tar.gz"
|
||||
mode: "0644"
|
||||
|
||||
- name: Extract traefik binary
|
||||
ansible.builtin.unarchive:
|
||||
src: "/tmp/traefik_{{ traefik_version }}.tar.gz"
|
||||
dest: "/tmp/traefik_{{ traefik_version }}"
|
||||
remote_src: true
|
||||
creates: "/tmp/traefik_{{ traefik_version }}/traefik"
|
||||
|
||||
- name: Install traefik binary
|
||||
ansible.builtin.copy:
|
||||
src: "/tmp/traefik_{{ traefik_version }}/traefik"
|
||||
dest: "{{ traefik_bin_path }}"
|
||||
mode: "0755"
|
||||
remote_src: true
|
||||
notify: Restart traefik
|
||||
|
||||
- name: Deploy traefik static config
|
||||
ansible.builtin.template:
|
||||
src: traefik.yml.j2
|
||||
dest: "{{ traefik_config_dir }}/traefik.yml"
|
||||
owner: "{{ traefik_user }}"
|
||||
group: "{{ traefik_group }}"
|
||||
mode: "0644"
|
||||
notify: Restart traefik
|
||||
|
||||
- name: Deploy systemd service
|
||||
ansible.builtin.template:
|
||||
src: traefik.service.j2
|
||||
dest: /etc/systemd/system/traefik.service
|
||||
mode: "0644"
|
||||
notify: Restart traefik
|
||||
|
||||
- name: Enable and start traefik
|
||||
ansible.builtin.systemd:
|
||||
name: traefik
|
||||
daemon_reload: true
|
||||
enabled: true
|
||||
state: started
|
||||
17
roles/reverse_proxy_traefik/templates/traefik.service.j2
Normal file
17
roles/reverse_proxy_traefik/templates/traefik.service.j2
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[Unit]
|
||||
Description=Traefik
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
User={{ traefik_user }}
|
||||
Group={{ traefik_group }}
|
||||
ExecStart={{ traefik_bin_path }} --configFile={{ traefik_config_dir }}/traefik.yml
|
||||
Restart=on-failure
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
NoNewPrivileges=true
|
||||
LimitNOFILE=1048576
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
27
roles/reverse_proxy_traefik/templates/traefik.yml.j2
Normal file
27
roles/reverse_proxy_traefik/templates/traefik.yml.j2
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
log:
|
||||
level: {{ traefik_log_level }}
|
||||
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":{{ traefik_listen_http }}"
|
||||
websecure:
|
||||
address: ":{{ traefik_listen_https }}"
|
||||
|
||||
api:
|
||||
dashboard: {{ 'true' if traefik_dashboard_enabled else 'false' }}
|
||||
insecure: false
|
||||
|
||||
providers:
|
||||
file:
|
||||
directory: "{{ traefik_config_dir }}/dynamic"
|
||||
watch: true
|
||||
|
||||
{% if traefik_acme_enabled %}
|
||||
certificatesResolvers:
|
||||
le:
|
||||
acme:
|
||||
email: "{{ traefik_acme_email }}"
|
||||
storage: "{{ traefik_acme_storage }}"
|
||||
httpChallenge:
|
||||
entryPoint: web
|
||||
{% endif %}
|
||||
18
roles/security_hardening/defaults/main.yml
Normal file
18
roles/security_hardening/defaults/main.yml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
security_hardening_enabled: true
|
||||
|
||||
security_sysctl:
|
||||
net.ipv4.ip_forward: 0
|
||||
net.ipv4.conf.all.accept_redirects: 0
|
||||
net.ipv4.conf.default.accept_redirects: 0
|
||||
net.ipv4.conf.all.send_redirects: 0
|
||||
net.ipv4.conf.default.send_redirects: 0
|
||||
net.ipv4.conf.all.rp_filter: 1
|
||||
net.ipv4.conf.default.rp_filter: 1
|
||||
|
||||
security_ssh_hardening_enabled: true
|
||||
security_sshd_settings:
|
||||
PasswordAuthentication: "no"
|
||||
PermitRootLogin: "no"
|
||||
ChallengeResponseAuthentication: "no"
|
||||
UsePAM: "yes"
|
||||
X11Forwarding: "no"
|
||||
6
roles/security_hardening/handlers/main.yml
Normal file
6
roles/security_hardening/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: Reload ssh
|
||||
ansible.builtin.systemd:
|
||||
name: ssh
|
||||
state: reloaded
|
||||
ignore_errors: true
|
||||
24
roles/security_hardening/tasks/main.yml
Normal file
24
roles/security_hardening/tasks/main.yml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
- name: Gate
|
||||
ansible.builtin.meta: end_host
|
||||
when: not security_hardening_enabled | bool
|
||||
|
||||
- name: Apply sysctl hardening
|
||||
ansible.posix.sysctl:
|
||||
name: "{{ item.key }}"
|
||||
value: "{{ item.value }}"
|
||||
state: present
|
||||
sysctl_set: true
|
||||
reload: true
|
||||
loop: "{{ security_sysctl | dict2items }}"
|
||||
|
||||
- name: SSH hardening (drop-in)
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/ssh/sshd_config.d/99-chezlepro-hardening.conf
|
||||
mode: "0644"
|
||||
content: |
|
||||
{% for k,v in security_sshd_settings.items() %}
|
||||
{{ k }} {{ v }}
|
||||
{% endfor %}
|
||||
when: security_ssh_hardening_enabled | bool
|
||||
notify: Reload ssh
|
||||
Loading…
Reference in a new issue