first commit
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
.claude/settings.local.json
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = inventory/host.ini
|
||||||
|
host_key_checking = False
|
||||||
|
interpreter_python = auto_silent
|
||||||
|
vars = groups_vars/
|
||||||
|
|
||||||
|
[privilege_escalation]
|
||||||
|
become = True
|
||||||
|
become_method = sudo
|
||||||
|
become_user = root
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
---
|
||||||
|
# Durcissement CIS Ubuntu 24.04 — AIDE (integrite fichiers) installe + verification quotidienne
|
||||||
|
# (checks 35758, 35759)
|
||||||
|
#
|
||||||
|
# IMPORTANT : /var/lib/docker (images/layers/volumes), les donnees de bases de donnees
|
||||||
|
# (postgresql, redis), wazuh-indexer, clamav et /var/log/audit sont exclus AVANT le premier
|
||||||
|
# aideinit — sans ca, le scan initial serait tres long et generait des faux positifs
|
||||||
|
# quotidiens (ces donnees changent en permanence par nature, leur integrite est geree par
|
||||||
|
# leurs propres mecanismes, pas par un FIM au niveau fichier).
|
||||||
|
#
|
||||||
|
# `aideinit` peut prendre plusieurs minutes (hash de la quasi-totalite du systeme de
|
||||||
|
# fichiers) — pas de reboot necessaire, mais consommation CPU/IO notable pendant le scan.
|
||||||
|
#
|
||||||
|
# `serial: 1` + `any_errors_fatal` : un host a la fois, arret immediat si un host casse.
|
||||||
|
#
|
||||||
|
# Usage recommande : tester sur un host avant le rollout complet :
|
||||||
|
# ansible-playbook hardening/playbook-aide-hardening.yml --limit pre-prod-uber
|
||||||
|
|
||||||
|
- name: Durcissement AIDE - integrite fichiers (CIS Ubuntu 24.04)
|
||||||
|
hosts: prod,pre-prod,bdd-redis-prod,replica-prod,infra,infra-runner,infra-utils,load-balancer
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer aide et aide-common
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- aide
|
||||||
|
- aide-common
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Deployer les exclusions specifiques infra (avant le premier scan)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/72_aide_infra_excludes.j2
|
||||||
|
dest: /etc/aide/aide.conf.d/72_aide_infra_excludes
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Verifier si une base AIDE existe deja
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /var/lib/aide/aide.db
|
||||||
|
register: aide_db
|
||||||
|
|
||||||
|
- name: Initialiser la base AIDE (aideinit) — peut prendre plusieurs minutes
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: aideinit -y -f
|
||||||
|
when: not aide_db.stat.exists
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Activer et demarrer la verification quotidienne (dailyaidecheck.timer)
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "{{ item }}"
|
||||||
|
masked: false
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
loop:
|
||||||
|
- dailyaidecheck.service
|
||||||
|
- dailyaidecheck.timer
|
||||||
|
|
||||||
|
- name: Verifier l'etat final
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: systemctl show dailyaidecheck.timer -p LoadState,ActiveState
|
||||||
|
register: aide_timer_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >
|
||||||
|
'LoadState=loaded' not in aide_timer_check.stdout or
|
||||||
|
'ActiveState=active' not in aide_timer_check.stdout
|
||||||
|
|
||||||
|
- name: Confirmer le succes pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "✅ AIDE installé et vérification quotidienne active sur {{ inventory_hostname }}."
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
---
|
||||||
|
# Durcissement CIS Ubuntu 24.04 — AppArmor installe, active au boot, tous les profils enforcing
|
||||||
|
# (checks 35536-35539)
|
||||||
|
#
|
||||||
|
# CONTEXTE (verifie manuellement avant deploiement) : sur cette infra, apparmor_status montre
|
||||||
|
# des dizaines de profils en mode "unconfined"/"complain" qui correspondent tous a des paquets
|
||||||
|
# desktop jamais utilises sur des serveurs headless (navigateurs, Discord, Steam, transmission,
|
||||||
|
# runtimes conteneurs standalone comme runc/crun/podman non utilises directement — Docker confine
|
||||||
|
# deja ses containers via le profil "docker-default", separe et deja enforce). Aucun process
|
||||||
|
# reellement actif n'est concerne par le passage en enforce de ces profils inutilises.
|
||||||
|
#
|
||||||
|
# IMPORTANT GRUB : /etc/default/grub contient deja "audit=1 audit_backlog_limit=8192"
|
||||||
|
# (playbook-coredump-auditd-hardening.yml) — ce playbook AJOUTE apparmor=1 security=apparmor
|
||||||
|
# a la suite, ne remplace jamais la ligne existante.
|
||||||
|
#
|
||||||
|
# `aa-enforce /etc/apparmor.d/*` s'applique a chaud (pas de redemarrage necessaire pour le
|
||||||
|
# check CIS lui-meme), mais comme pour audit=1, le parametre GRUB apparmor=1/security=apparmor
|
||||||
|
# necessite un redemarrage pour etre reellement actif au niveau noyau (le check 35537 passe
|
||||||
|
# immediatement car il inspecte /etc/default/grub, pas l'etat runtime).
|
||||||
|
#
|
||||||
|
# `serial: 1` + `any_errors_fatal` : un host a la fois, arret immediat si un host casse.
|
||||||
|
#
|
||||||
|
# Usage recommande : tester sur un host avant le rollout complet :
|
||||||
|
# ansible-playbook hardening/playbook-apparmor-hardening.yml --limit pre-prod-uber
|
||||||
|
|
||||||
|
- name: Durcissement AppArmor (CIS Ubuntu 24.04)
|
||||||
|
hosts: prod,pre-prod,bdd-redis-prod,replica-prod,infra,infra-runner,infra-utils,load-balancer
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer apparmor et apparmor-utils
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- apparmor
|
||||||
|
- apparmor-utils
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Sauvegarder /etc/default/grub avant modification
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: /etc/default/grub
|
||||||
|
dest: /etc/default/grub.bak-cis-apparmor
|
||||||
|
remote_src: true
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Ajouter apparmor=1 security=apparmor a GRUB_CMDLINE_LINUX (sans ecraser audit=1 existant)
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -e
|
||||||
|
if ! grep -q 'apparmor=1' /etc/default/grub; then
|
||||||
|
sed -i 's/^\(GRUB_CMDLINE_LINUX="[^"]*\)"/\1 apparmor=1 security=apparmor"/' /etc/default/grub
|
||||||
|
echo CHANGED
|
||||||
|
fi
|
||||||
|
register: grub_conf
|
||||||
|
changed_when: "'CHANGED' in grub_conf.stdout"
|
||||||
|
|
||||||
|
- name: Regenerer grub.cfg si la config a change
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: update-grub
|
||||||
|
when: grub_conf.changed
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Forcer tous les profils AppArmor en mode enforce
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: aa-enforce /etc/apparmor.d/*
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Verifier l'etat final (apparmor_status)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: apparmor_status
|
||||||
|
register: aa_status
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >
|
||||||
|
'profiles are in complain mode' in aa_status.stdout and
|
||||||
|
not (aa_status.stdout | regex_search('^0\s*profiles are in complain mode', multiline=True))
|
||||||
|
|
||||||
|
- name: Confirmer le succes pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "✅ AppArmor durci sur {{ inventory_hostname }} — reboot requis pour apparmor=1/security=apparmor au niveau noyau."
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
# Regles d'audit detaillees restantes (CIS 6.2.3.4-6.2.3.19) — appliquees a chaud, pas de reboot
|
||||||
|
#
|
||||||
|
# PREREQUIS : hardening/playbook-coredump-auditd-hardening.yml (auditd) et
|
||||||
|
# hardening/playbook-audit-rules-sudo-omnex.yml deja appliques.
|
||||||
|
#
|
||||||
|
# Couvre : date/heure, environnement reseau, acces fichier echoues, user/group (identity),
|
||||||
|
# permissions DAC (chmod/chown/xattr), montages, sessions, login/logout, suppressions fichiers,
|
||||||
|
# politique MAC (AppArmor), commandes chcon/setfacl/chacl/usermod, modules noyau.
|
||||||
|
#
|
||||||
|
# UID_MIN lu dynamiquement depuis /etc/login.defs de chaque host (1000 sur cette infra, mais
|
||||||
|
# pas suppose en dur pour rester correct si un host differe).
|
||||||
|
#
|
||||||
|
# `augenrules --load` recharge a chaud : PAS de redemarrage necessaire tant que le mode
|
||||||
|
# immutable (-e 2, check 35749) n'est pas active — volontairement PAS fait par ce playbook.
|
||||||
|
#
|
||||||
|
# `serial: 1` + `any_errors_fatal` : un host a la fois, arret immediat si un host casse.
|
||||||
|
#
|
||||||
|
# Usage recommande : tester sur un host avant le rollout complet :
|
||||||
|
# ansible-playbook hardening/playbook-audit-rules-cis-rest.yml --limit pre-prod-uber
|
||||||
|
|
||||||
|
- name: Regles d'audit detaillees restantes CIS 6.2.3.x (Ubuntu 24.04)
|
||||||
|
hosts: prod,pre-prod,bdd-redis-prod,replica-prod,infra,infra-runner,infra-utils,load-balancer
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Lire UID_MIN depuis /etc/login.defs
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: awk '/^\s*UID_MIN/{print $2}' /etc/login.defs
|
||||||
|
register: uid_min_result
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Deployer les regles d'audit CIS restantes
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/audit-52-cis-rest.rules.j2
|
||||||
|
dest: /etc/audit/rules.d/52-cis-rest.rules
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0640"
|
||||||
|
vars:
|
||||||
|
uid_min: "{{ uid_min_result.stdout }}"
|
||||||
|
register: cis_rest_rules
|
||||||
|
|
||||||
|
- name: Charger les nouvelles regles d'audit (augenrules --load)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: augenrules --load
|
||||||
|
when: cis_rest_rules.changed
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Verifier que les cles principales sont actives (auditctl -l)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: auditctl -l
|
||||||
|
register: auditctl_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >
|
||||||
|
'time-change' not in auditctl_check.stdout or
|
||||||
|
'system-locale' not in auditctl_check.stdout or
|
||||||
|
'identity' not in auditctl_check.stdout or
|
||||||
|
'perm_mod' not in auditctl_check.stdout or
|
||||||
|
'mounts' not in auditctl_check.stdout or
|
||||||
|
'session' not in auditctl_check.stdout or
|
||||||
|
'logins' not in auditctl_check.stdout or
|
||||||
|
'delete' not in auditctl_check.stdout or
|
||||||
|
'MAC-policy' not in auditctl_check.stdout or
|
||||||
|
'perm_chng' not in auditctl_check.stdout or
|
||||||
|
'usermod' not in auditctl_check.stdout or
|
||||||
|
'kernel_modules' not in auditctl_check.stdout
|
||||||
|
|
||||||
|
- name: Confirmer le succes pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "✅ Règles d'audit CIS 6.2.3.x restantes actives sur {{ inventory_hostname }} (UID_MIN={{ uid_min_result.stdout }}, pas de reboot requis)."
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
---
|
||||||
|
# Regles d'audit detaillees (CIS 6.2.3.1-6.2.3.3) — surveillance sudo + surveillance dediee omnex
|
||||||
|
#
|
||||||
|
# PREREQUIS : necessite hardening/playbook-coredump-auditd-hardening.yml deja applique
|
||||||
|
# (auditd installe et actif).
|
||||||
|
#
|
||||||
|
# - Regles CIS standard : changements /etc/sudoers(.d), toute action "en tant qu'un autre
|
||||||
|
# utilisateur" (execve avec euid!=uid, couvre sudo/su), modifications de /var/log/sudo.log.
|
||||||
|
# - Regle custom omnex : capture TOUTE commande executee par omnex (execve filtre sur auid,
|
||||||
|
# qui persiste a travers sudo/su, donc suit omnex meme apres elevation) — uniquement sur
|
||||||
|
# les hosts ou l'utilisateur omnex existe (absent sur bdd-redis-prod/backup-mln, root direct).
|
||||||
|
# - `augenrules --load` recharge la config a chaud : PAS besoin de redemarrage ici (contrairement
|
||||||
|
# a audit=1 dans GRUB) tant que le mode immutable (-e 2) n'est pas active — volontairement pas
|
||||||
|
# configure par ce playbook (risque : plus aucune modif de regle possible sans reboot).
|
||||||
|
#
|
||||||
|
# `serial: 1` + `any_errors_fatal` : un host a la fois, arret immediat si un host casse.
|
||||||
|
#
|
||||||
|
# Usage recommande : tester sur un host avant le rollout complet :
|
||||||
|
# ansible-playbook hardening/playbook-audit-rules-sudo-omnex.yml --limit pre-prod-uber
|
||||||
|
|
||||||
|
- name: Regles d'audit detaillees - sudo + omnex (CIS Ubuntu 24.04)
|
||||||
|
hosts: prod,pre-prod,bdd-redis-prod,replica-prod,infra,infra-runner,infra-utils,load-balancer
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Deployer les regles d'audit sudo (CIS 6.2.3.1-6.2.3.3)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/audit-50-sudo.rules.j2
|
||||||
|
dest: /etc/audit/rules.d/50-sudo.rules
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0640"
|
||||||
|
register: sudo_rules
|
||||||
|
|
||||||
|
- name: Verifier si l'utilisateur omnex existe sur cet host
|
||||||
|
ansible.builtin.getent:
|
||||||
|
database: passwd
|
||||||
|
key: omnex
|
||||||
|
ignore_errors: true
|
||||||
|
register: omnex_getent
|
||||||
|
|
||||||
|
- name: Deployer la regle d'audit dediee omnex (uniquement si l'utilisateur existe)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/audit-51-omnex.rules.j2
|
||||||
|
dest: /etc/audit/rules.d/51-omnex.rules
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0640"
|
||||||
|
vars:
|
||||||
|
omnex_uid: "{{ ansible_facts.getent_passwd.omnex[1] }}"
|
||||||
|
when: omnex_getent is succeeded
|
||||||
|
register: omnex_rules
|
||||||
|
|
||||||
|
- name: Charger les nouvelles regles d'audit (augenrules --load)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: augenrules --load
|
||||||
|
when: sudo_rules.changed or (omnex_rules is defined and omnex_rules.changed)
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Verifier que les regles sudo sont bien actives (auditctl -l)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: auditctl -l
|
||||||
|
register: auditctl_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >
|
||||||
|
'scope' not in auditctl_check.stdout or
|
||||||
|
'user_emulation' not in auditctl_check.stdout or
|
||||||
|
'sudo_log_file' not in auditctl_check.stdout
|
||||||
|
|
||||||
|
- name: Verifier que la regle omnex est active (si applicable)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: auditctl -l
|
||||||
|
register: auditctl_omnex_check
|
||||||
|
changed_when: false
|
||||||
|
when: omnex_getent is succeeded
|
||||||
|
failed_when: "'omnex_actions' not in auditctl_omnex_check.stdout"
|
||||||
|
|
||||||
|
- name: Confirmer le succes pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: >-
|
||||||
|
✅ Règles d'audit sudo{{ ' + omnex' if omnex_getent is succeeded else '' }}
|
||||||
|
actives sur {{ inventory_hostname }} (auditctl -l vérifié, pas de reboot requis).
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
---
|
||||||
|
# Durcissement CIS Ubuntu 24.04 — core dumps restreints, Apport désactivé, auditd installé/actif
|
||||||
|
# (checks 35543, 35545, 35723-35726, 35756, 35757)
|
||||||
|
#
|
||||||
|
# IMPORTANT — REBOOT :
|
||||||
|
# - audit=1 et audit_backlog_limit=8192 sont ajoutés à /etc/default/grub puis `update-grub`
|
||||||
|
# régénère immédiatement /boot/grub/grub.cfg → les checks CIS 35725/35726 passent au VERT
|
||||||
|
# dès ce playbook exécuté (ils inspectent le fichier grub.cfg généré, pas le noyau en cours
|
||||||
|
# d'exécution).
|
||||||
|
# - MAIS la protection réelle (auditer les process qui démarrent avant auditd) ne prend effet
|
||||||
|
# qu'après un REDÉMARRAGE du serveur (le paramètre kernel n'est actif qu'au prochain boot).
|
||||||
|
# Ce playbook NE redémarre PAS automatiquement les serveurs — décision à prendre séparément,
|
||||||
|
# en fenêtre de maintenance, host par host (impact Docker/VPN/prod public à chaque reboot).
|
||||||
|
#
|
||||||
|
# - apport est PURGÉ (pas juste désactivé) : cohérent avec le choix déjà fait pour rsync/telnet/ftp
|
||||||
|
# dans ce même chantier. apport-core-dump-handler et python3-apport partent avec (dépendances),
|
||||||
|
# sans impact sur les services applicatifs de cette infra (aucun ne dépend d'apport).
|
||||||
|
#
|
||||||
|
# `serial: 1` + `any_errors_fatal` : un host a la fois, arret immediat si un host casse.
|
||||||
|
#
|
||||||
|
# Usage recommande : tester sur un host avant le rollout complet :
|
||||||
|
# ansible-playbook hardening/playbook-coredump-auditd-hardening.yml --limit pre-prod-uber
|
||||||
|
|
||||||
|
- name: Durcissement core dumps + apport + auditd (CIS Ubuntu 24.04)
|
||||||
|
hosts: prod,pre-prod,bdd-redis-prod,replica-prod,infra,infra-runner,infra-utils,load-balancer
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# --- 1.5.3 Core dumps restreints ---
|
||||||
|
- name: Deployer fs.suid_dumpable=0
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/60-cis-coredump-sysctl.conf.j2
|
||||||
|
dest: /etc/sysctl.d/60-cis-coredump-sysctl.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: coredump_sysctl
|
||||||
|
|
||||||
|
- name: Appliquer fs.suid_dumpable
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: sysctl --system
|
||||||
|
when: coredump_sysctl.changed
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Deployer la limite hard core 0
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/60-cis-coredump-limits.conf.j2
|
||||||
|
dest: /etc/security/limits.d/60-cis-coredump.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
# --- 1.5.5 Apport (Automatic Error Reporting) ---
|
||||||
|
- name: Purger apport (et ses dependances python3-apport, apport-core-dump-handler)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: apport
|
||||||
|
state: absent
|
||||||
|
purge: true
|
||||||
|
|
||||||
|
# --- 6.2.1.x auditd ---
|
||||||
|
- name: Installer auditd et audispd-plugins
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- auditd
|
||||||
|
- audispd-plugins
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Demasquer, activer et demarrer auditd
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: auditd
|
||||||
|
masked: false
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Verifier la presence de audit=1 dans GRUB_CMDLINE_LINUX
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/default/grub
|
||||||
|
regexp: '^GRUB_CMDLINE_LINUX='
|
||||||
|
line: 'GRUB_CMDLINE_LINUX="audit=1 audit_backlog_limit=8192"'
|
||||||
|
backup: true
|
||||||
|
register: grub_conf
|
||||||
|
|
||||||
|
- name: Regenerer grub.cfg si la config a change
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: update-grub
|
||||||
|
when: grub_conf.changed
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Verifier que audit=1 est bien present dans grub.cfg genere
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: grep -q 'audit=1' /boot/grub/grub.cfg
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
# --- 6.2.4.9 / 6.2.4.10 Ownership des outils d'audit ---
|
||||||
|
- name: Proprietaire/groupe root:root sur les outils d'audit
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
loop:
|
||||||
|
- /sbin/auditctl
|
||||||
|
- /sbin/aureport
|
||||||
|
- /sbin/ausearch
|
||||||
|
- /sbin/autrace
|
||||||
|
- /sbin/auditd
|
||||||
|
- /sbin/augenrules
|
||||||
|
ignore_errors: true # certains binaires peuvent etre des symlinks vers /usr/sbin selon la distro
|
||||||
|
|
||||||
|
- name: Confirmer le succes pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: >-
|
||||||
|
✅ Core dumps/apport/auditd appliqués sur {{ inventory_hostname }}.
|
||||||
|
REDÉMARRAGE requis pour que audit=1 protège les process pré-auditd (non fait par ce playbook).
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
# Durcissement CIS Ubuntu 24.04 — retrait rsync/telnet/ftp + permissions cron + cron.allow/at.allow
|
||||||
|
# (checks 35573, 35585, 35587, 35594-35601)
|
||||||
|
#
|
||||||
|
# IMPORTANT :
|
||||||
|
# - rsync/telnet/ftp verifies avant retrait sur cette infra : aucun daemon actif, aucun cron/script
|
||||||
|
# n'en dependait (grep sur les crontabs + scripts de backup). Purge sans risque constate.
|
||||||
|
# - Le paquet 'at' n'est PAS installe sur cette infra et ce playbook ne l'installe PAS : ajouter un
|
||||||
|
# service juste pour le verrouiller ensuite serait contre-productif (surface d'attaque en plus
|
||||||
|
# pour un compliance-checkbox). /etc/at.allow est quand meme cree en defense en profondeur, mais
|
||||||
|
# le check CIS 35601 restera en echec par ce choix assume tant que 'at' n'est pas installe.
|
||||||
|
# - /etc/cron.allow doit avoir owner:group EXACTEMENT root:root pour satisfaire le check automatise
|
||||||
|
# 35600 — la documentation CIS mentionne le groupe "crontab" comme alternative acceptable, mais la
|
||||||
|
# regex du check SCA (`r:^root root$`) n'accepte que root:root en pratique (verifie empiriquement).
|
||||||
|
#
|
||||||
|
# `serial: 1` + `any_errors_fatal` : un host a la fois, arret immediat si un host casse.
|
||||||
|
#
|
||||||
|
# Usage recommande : tester sur un host avant le rollout complet :
|
||||||
|
# ansible-playbook hardening/playbook-cron-packages-hardening.yml --limit pre-prod-uber
|
||||||
|
|
||||||
|
- name: Durcissement cron/at + retrait paquets insecurises (CIS Ubuntu 24.04)
|
||||||
|
hosts: prod,pre-prod,bdd-redis-prod,replica-prod,infra,infra-runner,infra-utils,load-balancer
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Purger rsync, telnet et ftp (clients/services insecurises)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- rsync
|
||||||
|
- telnet
|
||||||
|
- inetutils-telnet
|
||||||
|
- ftp
|
||||||
|
- tnftp
|
||||||
|
state: absent
|
||||||
|
purge: true
|
||||||
|
|
||||||
|
- name: Permissions /etc/crontab (0600 root:root)
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/crontab
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0600"
|
||||||
|
|
||||||
|
- name: Permissions repertoires cron (0700 root:root)
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0700"
|
||||||
|
loop:
|
||||||
|
- /etc/cron.hourly
|
||||||
|
- /etc/cron.daily
|
||||||
|
- /etc/cron.weekly
|
||||||
|
- /etc/cron.monthly
|
||||||
|
- /etc/cron.d
|
||||||
|
|
||||||
|
- name: Verifier si /etc/cron.deny existe
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /etc/cron.deny
|
||||||
|
register: cron_deny
|
||||||
|
|
||||||
|
- name: Creer /etc/cron.allow (crontab restreint aux utilisateurs autorises)
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/cron.allow
|
||||||
|
state: touch
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0640"
|
||||||
|
access_time: preserve
|
||||||
|
modification_time: preserve
|
||||||
|
when: not cron_deny.stat.exists
|
||||||
|
|
||||||
|
- name: Permissions /etc/cron.deny si present
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/cron.deny
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0640"
|
||||||
|
when: cron_deny.stat.exists
|
||||||
|
|
||||||
|
- name: Creer /etc/at.allow (defense en profondeur, meme si 'at' non installe)
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/at.allow
|
||||||
|
state: touch
|
||||||
|
owner: root
|
||||||
|
group: daemon
|
||||||
|
mode: "0640"
|
||||||
|
access_time: preserve
|
||||||
|
modification_time: preserve
|
||||||
|
|
||||||
|
- name: Confirmer le succes pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "✅ Durcissement cron/paquets appliqué sur {{ inventory_hostname }}"
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
# Durcissement CIS Ubuntu 24.04 — modules noyau reseau/filesystem inutilises + sysctl reseau
|
||||||
|
# (checks 35509, 35604-35607, 35608-35618)
|
||||||
|
#
|
||||||
|
# IMPORTANT :
|
||||||
|
# - net.ipv4.ip_forward est laisse ACTIF sur la plupart des hosts (Docker gere le NAT des ports
|
||||||
|
# publies, vpn-uber fait relais entre pairs WireGuard) — le desactiver casserait ces usages.
|
||||||
|
# Seul load-balancer (pas de Docker, pas de relais VPN) le desactive, via la variable
|
||||||
|
# `ip_forwarding_disabled` (group_vars, defaut false, true uniquement pour load-balancer).
|
||||||
|
# Le check CIS 35608 restera donc en echec par necessite fonctionnelle sur la plupart des hosts.
|
||||||
|
# - rp_filter est mis a 1 (strict) partout : verifie sans casse sur cette infra (Docker + WireGuard
|
||||||
|
# coexistent sans probleme de routage asymetrique ici), mais a re-tester si la topologie change.
|
||||||
|
# - Aucun des modules blacklistes n'est charge sur cette infra (verifie via lsmod avant deploiement) :
|
||||||
|
# zero impact fonctionnel attendu. Exception : fat/fuse sont compiles en dur dans le noyau Ubuntu
|
||||||
|
# (builtin) et resteront "disponibles" quoi qu'il arrive — check CIS 35509 restera en echec pour
|
||||||
|
# ces deux modules specifiquement, cas documente par la CIS elle-meme comme sans remediation
|
||||||
|
# possible ("if pre-compiled into the kernel, no remediation is necessary").
|
||||||
|
#
|
||||||
|
# `serial: 1` + `any_errors_fatal` : un host a la fois, arret immediat si un host casse.
|
||||||
|
#
|
||||||
|
# Usage recommande : tester sur un host avant le rollout complet :
|
||||||
|
# ansible-playbook hardening/playbook-kernel-sysctl-hardening.yml --limit pre-prod-uber
|
||||||
|
|
||||||
|
- name: Durcissement kernel modules + sysctl reseau (CIS Ubuntu 24.04)
|
||||||
|
hosts: prod,pre-prod,bdd-redis-prod,replica-prod,infra,infra-runner,infra-utils,load-balancer
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Deployer le blacklist des modules noyau inutilises
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/blacklist-unused-modules.conf.j2
|
||||||
|
dest: /etc/modprobe.d/cis-blacklist-unused.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Deployer le durcissement sysctl reseau
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/60-cis-network-hardening.conf.j2
|
||||||
|
dest: /etc/sysctl.d/60-cis-network-hardening.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: sysctl_conf
|
||||||
|
|
||||||
|
- name: Appliquer les parametres sysctl actifs
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: sysctl --system
|
||||||
|
when: sysctl_conf.changed
|
||||||
|
changed_when: true
|
||||||
|
register: sysctl_apply
|
||||||
|
|
||||||
|
- name: Verifier qu'aucune erreur n'est remontee par sysctl --system
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "Erreur sysctl --system sur {{ inventory_hostname }} : {{ sysctl_apply.stdout }}"
|
||||||
|
when: sysctl_apply is defined and sysctl_apply.stdout is defined and 'error' in sysctl_apply.stdout | lower
|
||||||
|
|
||||||
|
- name: Verifier la valeur effective de ip_forward
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: sysctl -n net.ipv4.ip_forward
|
||||||
|
register: ip_forward_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >
|
||||||
|
(not (ip_forwarding_disabled | default(false)) and ip_forward_check.stdout != "1") or
|
||||||
|
((ip_forwarding_disabled | default(false)) and ip_forward_check.stdout != "0")
|
||||||
|
|
||||||
|
- name: Confirmer le succes pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "✅ Durcissement kernel/sysctl appliqué sur {{ inventory_hostname }} — ip_forward={{ ip_forward_check.stdout }}"
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
---
|
||||||
|
# Durcissement PAM (CIS Ubuntu 24.04 — pam_faillock, pam_pwquality, pam_pwhistory)
|
||||||
|
#
|
||||||
|
# IMPORTANT — à lire avant d'exécuter :
|
||||||
|
# - Ce playbook touche l'authentification (sudo/su) sur TOUS les hosts ciblés.
|
||||||
|
# Une erreur dans un profil pam-auth-update peut casser sudo partout.
|
||||||
|
# - `serial: 1` traite un host à la fois : si un host casse, le run s'arrête
|
||||||
|
# avant de toucher les suivants (any_errors_fatal).
|
||||||
|
# - La dernière tâche force un reset du cache sudo (`sudo -K`) puis revalide
|
||||||
|
# un `become` réel, pour détecter une casse immédiatement plutôt que de la
|
||||||
|
# découvrir 15 min plus tard quand le cache sudo normal expire.
|
||||||
|
# - Volontairement AUCUNE expiration de mot de passe n'est appliquée sur les
|
||||||
|
# comptes existants (omnex/root) : ces comptes se connectent en SSH par clé
|
||||||
|
# (jamais par mot de passe), donc le mécanisme d'expiration PAM — qui ne se
|
||||||
|
# déclenche qu'au moment d'un prompt de mot de passe au login — ne se
|
||||||
|
# déclencherait jamais, et une expiration silencieuse casserait `sudo` sans
|
||||||
|
# aucun moyen interactif de le corriger à distance. PASS_MAX_DAYS n'est posé
|
||||||
|
# que dans /etc/login.defs (valeur par défaut pour les FUTURS comptes), pas
|
||||||
|
# rétroactivement via chage.
|
||||||
|
#
|
||||||
|
# Usage recommandé : tester d'abord sur UN seul host avant le rollout complet :
|
||||||
|
# ansible-playbook infra/playbook-pam-hardening.yml --limit pre-prod-uber
|
||||||
|
#
|
||||||
|
- name: Durcissement PAM (CIS Ubuntu 24.04)
|
||||||
|
hosts: bdd-redis-prod
|
||||||
|
become: true
|
||||||
|
serial: 1
|
||||||
|
any_errors_fatal: true
|
||||||
|
vars:
|
||||||
|
pam_faillock_deny: 5
|
||||||
|
pam_faillock_unlock_time: 900
|
||||||
|
pam_faillock_fail_interval: 900
|
||||||
|
pam_pwquality_minlen: 16
|
||||||
|
pam_pwquality_difok: 8
|
||||||
|
pam_pwhistory_remember: 24
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer libpam-pwquality
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: libpam-pwquality
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Sauvegarder l'état PAM actuel avant modification
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -e
|
||||||
|
BACKUP_DIR="/root/pam-backup-$(date +%Y%m%d%H%M%S)"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
cp -a /etc/pam.d "$BACKUP_DIR/"
|
||||||
|
cp -a /usr/share/pam-configs "$BACKUP_DIR/"
|
||||||
|
cp /etc/login.defs "$BACKUP_DIR/" 2>/dev/null || true
|
||||||
|
[ -f /etc/security/faillock.conf ] && cp /etc/security/faillock.conf "$BACKUP_DIR/" || true
|
||||||
|
[ -f /etc/security/pwquality.conf ] && cp /etc/security/pwquality.conf "$BACKUP_DIR/" || true
|
||||||
|
echo "$BACKUP_DIR"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
changed_when: false
|
||||||
|
register: pam_backup
|
||||||
|
|
||||||
|
- name: Afficher le chemin de sauvegarde (rollback manuel possible)
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Backup PAM : {{ pam_backup.stdout }}"
|
||||||
|
|
||||||
|
- name: Déployer le profil unix (retire nullok, garde use_authtok)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/pam-configs-unix.j2
|
||||||
|
dest: /usr/share/pam-configs/unix
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: pam_unix_profile
|
||||||
|
|
||||||
|
- name: Déployer le profil faillock (authfail)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/pam-configs-faillock.j2
|
||||||
|
dest: /usr/share/pam-configs/faillock
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: pam_faillock_profile
|
||||||
|
|
||||||
|
- name: Déployer le profil faillock_notify (preauth + account)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/pam-configs-faillock-notify.j2
|
||||||
|
dest: /usr/share/pam-configs/faillock_notify
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: pam_faillock_notify_profile
|
||||||
|
|
||||||
|
- name: Déployer le profil pwquality
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/pam-configs-pwquality.j2
|
||||||
|
dest: /usr/share/pam-configs/pwquality
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: pam_pwquality_profile
|
||||||
|
|
||||||
|
- name: Déployer le profil pwhistory
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/pam-configs-pwhistory.j2
|
||||||
|
dest: /usr/share/pam-configs/pwhistory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: pam_pwhistory_profile
|
||||||
|
|
||||||
|
- name: Déployer /etc/security/faillock.conf
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/faillock.conf.j2
|
||||||
|
dest: /etc/security/faillock.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Déployer /etc/security/pwquality.conf
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/pwquality.conf.j2
|
||||||
|
dest: /etc/security/pwquality.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Activer les profils PAM (regénère common-auth/common-account/common-password)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: pam-auth-update --enable faillock --enable faillock_notify --enable pwquality --enable pwhistory
|
||||||
|
when: >
|
||||||
|
pam_unix_profile.changed or pam_faillock_profile.changed or
|
||||||
|
pam_faillock_notify_profile.changed or pam_pwquality_profile.changed or
|
||||||
|
pam_pwhistory_profile.changed
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Configurer PASS_MAX_DAYS dans login.defs (nouveaux comptes uniquement)
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/login.defs
|
||||||
|
regexp: '^PASS_MAX_DAYS'
|
||||||
|
line: "PASS_MAX_DAYS\t365"
|
||||||
|
|
||||||
|
- name: Configurer PASS_MIN_DAYS dans login.defs
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/login.defs
|
||||||
|
regexp: '^PASS_MIN_DAYS'
|
||||||
|
line: "PASS_MIN_DAYS\t1"
|
||||||
|
|
||||||
|
- name: Configurer PASS_WARN_AGE dans login.defs
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/login.defs
|
||||||
|
regexp: '^PASS_WARN_AGE'
|
||||||
|
line: "PASS_WARN_AGE\t7"
|
||||||
|
|
||||||
|
- name: Verrouillage par défaut des comptes inactifs (nouveaux comptes)
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: useradd -D -f 30
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
# --- Vérification critique : la stack PAM fonctionne-t-elle toujours ? ---
|
||||||
|
# On invalide le cache sudo existant pour forcer une vraie ré-authentification
|
||||||
|
# PAM, sinon un sudo déjà "chaud" masquerait une stack cassée pendant 15 min.
|
||||||
|
- name: Invalider le cache sudo pour forcer une vraie revalidation PAM
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: sudo -K
|
||||||
|
become: false
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Vérifier que sudo fonctionne toujours avec la nouvelle stack PAM
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: whoami
|
||||||
|
register: pam_sudo_check
|
||||||
|
failed_when: pam_sudo_check.stdout != "root"
|
||||||
|
|
||||||
|
- name: Confirmer le succès pour cet host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "✅ PAM durci avec succès sur {{ inventory_hostname }} — sudo toujours fonctionnel."
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
- name: SSH HARDENNING
|
||||||
|
hosts: load-balancer
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
tasks:
|
||||||
|
- name: Créer le groupe ssh
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: ssh
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- ansible.builtin.user:
|
||||||
|
name: "{{ user_ssh }}"
|
||||||
|
shell: /bin/bash
|
||||||
|
groups:
|
||||||
|
- sudo
|
||||||
|
- ssh
|
||||||
|
append: true
|
||||||
|
state: present
|
||||||
|
password: "{{ password_user_ssh }}"
|
||||||
|
update_password: on_create
|
||||||
|
create_home: true
|
||||||
|
home: /home/omnex
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Check si la paire de clé SSH existe
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ playbook_dir }}/../../.ssh/{{ user_ssh }}"
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
register: ssh_key_check
|
||||||
|
tags: [key]
|
||||||
|
|
||||||
|
- name: Générer la paire de clés SSH localement
|
||||||
|
community.crypto.openssh_keypair:
|
||||||
|
path: "{{ playbook_dir }}/../../.ssh/{{ user_ssh }}"
|
||||||
|
type: ed25519
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
when: not ssh_key_check.stat.exists
|
||||||
|
run_once: true
|
||||||
|
tags: [key]
|
||||||
|
|
||||||
|
- ansible.posix.authorized_key:
|
||||||
|
user: "{{ user_ssh }}"
|
||||||
|
state: present
|
||||||
|
key: "{{ lookup('file', playbook_dir + '/../../.ssh/' + user_ssh + '.pub') }}"
|
||||||
|
|
||||||
|
- name: Déployer la config sshd durcie
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/ssh_harden_conf.j2
|
||||||
|
dest: /etc/ssh/sshd_config
|
||||||
|
mode: "0644"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
validate: /usr/sbin/sshd -t -f %s
|
||||||
|
notify: restart ssh
|
||||||
|
|
||||||
|
- name: Delete cloud ssh config if exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/ssh/sshd_config.d/60-cloudimg-settings.conf
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Déployer la config cloud-init durcie
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/cloud_harden.conf.j2
|
||||||
|
dest: /etc/ssh/sshd_config.d/60-cloudimg-settings.conf
|
||||||
|
mode: "0644"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
notify: restart ssh
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: restart ssh
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: ssh
|
||||||
|
state: restarted
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
- name: Génération du certificat SSL Let's Encrypt
|
||||||
|
hosts: infra
|
||||||
|
become: true
|
||||||
|
gather_facts: false
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer certbot et le plugin nginx
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- certbot
|
||||||
|
- python3-certbot-nginx
|
||||||
|
- nginx
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Déployer la config Nginx HTTP simple (ACME challenge)
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/nginx/sites-available/certbot
|
||||||
|
content: |
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name {{ domain_name }} {{ subdomains | join(' ') }};
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 200 'ok';
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Activer le site certbot
|
||||||
|
ansible.builtin.file:
|
||||||
|
src: /etc/nginx/sites-available/certbot
|
||||||
|
dest: /etc/nginx/sites-enabled/certbot
|
||||||
|
state: link
|
||||||
|
force: yes
|
||||||
|
|
||||||
|
- name: Désactiver le site par défaut
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/nginx/sites-enabled/default
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Tester la configuration Nginx
|
||||||
|
ansible.builtin.command: nginx -t
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Redémarrer Nginx
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: nginx
|
||||||
|
state: restarted
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Ouvrir les ports dans UFW
|
||||||
|
ansible.builtin.ufw:
|
||||||
|
rule: allow
|
||||||
|
port: "{{ item }}"
|
||||||
|
proto: tcp
|
||||||
|
loop:
|
||||||
|
- "22"
|
||||||
|
- "80"
|
||||||
|
- "443"
|
||||||
|
|
||||||
|
- name: Vérifier si le certificat existe déjà
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||||
|
register: cert_file
|
||||||
|
tags: [gen]
|
||||||
|
|
||||||
|
- name: Générer le certificat avec Certbot (domaine + sous-domaines)
|
||||||
|
ansible.builtin.command: >
|
||||||
|
certbot certonly --nginx
|
||||||
|
-d {{ domain_name }}
|
||||||
|
{{ subdomains | map('regex_replace', '^(.*)$', '-d \1') | join(' ') }}
|
||||||
|
--non-interactive
|
||||||
|
--agree-tos
|
||||||
|
--email admin@{{ domain_name }}
|
||||||
|
when: not cert_file.stat.exists
|
||||||
|
tags: [gen]
|
||||||
|
|
||||||
|
- name: Vérifier que le certificat a bien été généré
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||||
|
register: cert_check
|
||||||
|
|
||||||
|
- name: Afficher le résultat
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ 'Certificat généré : /etc/letsencrypt/live/' + domain_name + '/fullchain.pem' if cert_check.stat.exists else 'ERREUR : certificat non trouvé' }}"
|
||||||
|
|
||||||
|
- name: Vérifier le renouvellement automatique
|
||||||
|
ansible.builtin.command: certbot renew --dry-run
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
when: cert_check.stat.exists
|
||||||
|
|
||||||
|
- name: Créer le dossier docker/certs
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/nginx/certs"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0750"
|
||||||
|
tags: [create]
|
||||||
|
|
||||||
|
- name: Copier fullchain.pem dans docker/certs
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||||
|
dest: "{{ docker_dir }}/nginx/certs/fullchain.pem"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0644"
|
||||||
|
remote_src: yes
|
||||||
|
tags: [create]
|
||||||
|
|
||||||
|
- name: Copier privkey.pem dans docker/certs
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "/etc/letsencrypt/live/{{ domain_name }}/privkey.pem"
|
||||||
|
dest: "{{ docker_dir }}/nginx/certs/privkey.pem"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0640"
|
||||||
|
remote_src: yes
|
||||||
|
tags: [create]
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
---
|
||||||
|
- name: Installation et configuration du clamAV
|
||||||
|
hosts: infra
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
tasks:
|
||||||
|
- name: Vérifier si ClamAV existe dans les dépôts
|
||||||
|
ansible.builtin.command: apt-cache search ^clamav$
|
||||||
|
register: clamav_search
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Afficher résultat
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: clamav_search.stdout
|
||||||
|
|
||||||
|
- name: Installer ClamAV si disponible
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- clamav
|
||||||
|
- clamav-daemon
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
|
||||||
|
- name: Démarrer ClamAV
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: clamav-daemon
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
|
||||||
|
- name: Arrêter clamav-freshclam avant la mise à jour
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: clamav-freshclam
|
||||||
|
state: stopped
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
|
||||||
|
- name: Mettre à jour la base de données virale (freshclam)
|
||||||
|
ansible.builtin.command: freshclam
|
||||||
|
register: freshclam_result
|
||||||
|
changed_when: "'Database updated' in freshclam_result.stdout"
|
||||||
|
failed_when: freshclam_result.rc != 0
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
|
||||||
|
- name: Redémarrer clamav-freshclam après la mise à jour
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: clamav-freshclam
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
|
||||||
|
- name: Configurer ClamAV - activer la détection PUA
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/clamav/clamd.conf
|
||||||
|
regexp: "^#?DetectPUA"
|
||||||
|
line: "DetectPUA yes"
|
||||||
|
backup: true
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
notify: Redémarrer clamav-daemon
|
||||||
|
|
||||||
|
- name: Configurer ClamAV - activer les logs
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/clamav/clamd.conf
|
||||||
|
regexp: "^#?LogFile "
|
||||||
|
line: "LogFile /var/log/clamav/clamav.log"
|
||||||
|
backup: true
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
notify: Redémarrer clamav-daemon
|
||||||
|
|
||||||
|
- name: Configurer ClamAV - taille max des fichiers scannés
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/clamav/clamd.conf
|
||||||
|
regexp: "^#?MaxFileSize"
|
||||||
|
line: "MaxFileSize 100M"
|
||||||
|
backup: true
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
notify: Redémarrer clamav-daemon
|
||||||
|
|
||||||
|
- name: Planifier un scan quotidien via cron
|
||||||
|
ansible.builtin.cron:
|
||||||
|
name: "ClamAV daily scan"
|
||||||
|
minute: "30"
|
||||||
|
hour: "2"
|
||||||
|
job: >
|
||||||
|
ionice -c 3 nice -n 19
|
||||||
|
docker exec gestion-clamav
|
||||||
|
clamscan -r /home /tmp /app/uploads
|
||||||
|
--log=/var/log/clamav/daily_scan.log --quiet
|
||||||
|
user: root
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
|
||||||
|
- name: Afficher résultat final
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "ClamAV installé et configuré avec succès"
|
||||||
|
when: clamav_search.stdout != ""
|
||||||
|
|
||||||
|
- name: Afficher message si ClamAV non disponible
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "ClamAV n'est pas disponible dans les dépôts"
|
||||||
|
when: clamav_search.stdout == ""
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Redémarrer clamav-daemon
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: clamav-daemon
|
||||||
|
state: restarted
|
||||||
@@ -0,0 +1,332 @@
|
|||||||
|
---
|
||||||
|
- name: Installation et configuration du Gitea Act Runner
|
||||||
|
hosts: infra
|
||||||
|
become: false
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
act_runner_version: "0.2.11"
|
||||||
|
act_runner_binary: /usr/local/bin/act_runner
|
||||||
|
act_runner_workdir: /opt/gitea-runner
|
||||||
|
act_runner_config: /opt/gitea-runner/.runner
|
||||||
|
gitea_instance_url: "https://gitea.uber-stup.club"
|
||||||
|
runner_name: "{{ inventory_hostname }}-runner"
|
||||||
|
runner_labels: "ubuntu-latest:docker://catthehacker/ubuntu:act-22.04,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04"
|
||||||
|
|
||||||
|
# ── Utilisateur CI/CD ────────────────────────────────
|
||||||
|
ci_cd_user: "ci-cd"
|
||||||
|
ci_cd_user_shell: "/bin/bash"
|
||||||
|
ci_cd_user_groups:
|
||||||
|
- docker
|
||||||
|
ci_cd_ssh_pubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICJ4COozE+71IvOhzK7ijeQY5lmoDxYTA0+B0lEAO0tG xor_fakers@AsusXor" # ex: "ssh-ed25519 AAAAC3Nza... ci-cd@gitea"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# ── Verrou dpkg (unattended-upgrades / cloud-init au boot) ──
|
||||||
|
- name: Attendre la libération du verrou dpkg/apt
|
||||||
|
become: true
|
||||||
|
shell: |
|
||||||
|
while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 \
|
||||||
|
|| fuser /var/lib/dpkg/lock >/dev/null 2>&1 \
|
||||||
|
|| fuser /var/lib/apt/lists/lock >/dev/null 2>&1 \
|
||||||
|
|| fuser /var/cache/apt/archives/lock >/dev/null 2>&1; do
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
changed_when: false
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
tags: always
|
||||||
|
|
||||||
|
# ── Prérequis ──────────────────────────────────────────
|
||||||
|
- name: Installer les paquets requis
|
||||||
|
become: true
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- curl
|
||||||
|
- ca-certificates
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
register: apt_prereqs_result
|
||||||
|
until: apt_prereqs_result is succeeded
|
||||||
|
retries: 10
|
||||||
|
delay: 15
|
||||||
|
|
||||||
|
# ── Docker (requis pour exécuter les jobs) ─────────────
|
||||||
|
- name: Vérifier si Docker est installé
|
||||||
|
become: true
|
||||||
|
command: docker --version
|
||||||
|
register: docker_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Installer Docker si absent
|
||||||
|
become: true
|
||||||
|
block:
|
||||||
|
- name: Ajouter la clé GPG Docker
|
||||||
|
apt_key:
|
||||||
|
url: https://download.docker.com/linux/ubuntu/gpg
|
||||||
|
keyring: /etc/apt/keyrings/docker.gpg
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ajouter le dépôt Docker
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
|
||||||
|
- name: Installer Docker
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
register: apt_docker_result
|
||||||
|
until: apt_docker_result is succeeded
|
||||||
|
retries: 10
|
||||||
|
delay: 15
|
||||||
|
|
||||||
|
- name: Démarrer et activer Docker
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
when: docker_check.rc != 0
|
||||||
|
|
||||||
|
# ── Utilisateur dédié CI/CD ─────────────────────────────
|
||||||
|
- name: Vérifier que ci_cd_ssh_pubkey est fourni
|
||||||
|
fail:
|
||||||
|
msg: "La variable 'ci_cd_ssh_pubkey' est requise. Relancez avec : -e ci_cd_ssh_pubkey='ssh-ed25519 AAAA...'"
|
||||||
|
when: ci_cd_ssh_pubkey is not defined or ci_cd_ssh_pubkey == ""
|
||||||
|
tags: ["ci-cd-user"]
|
||||||
|
|
||||||
|
- name: Créer l'utilisateur CI/CD
|
||||||
|
become: true
|
||||||
|
user:
|
||||||
|
name: "{{ ci_cd_user }}"
|
||||||
|
shell: "{{ ci_cd_user_shell }}"
|
||||||
|
groups: "{{ ci_cd_user_groups }}"
|
||||||
|
append: true
|
||||||
|
create_home: true
|
||||||
|
state: present
|
||||||
|
tags: ["ci-cd-user"]
|
||||||
|
|
||||||
|
- name: Créer le répertoire .ssh de l'utilisateur CI/CD
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: "/home/{{ ci_cd_user }}/.ssh"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ ci_cd_user }}"
|
||||||
|
group: "{{ ci_cd_user }}"
|
||||||
|
mode: "0700"
|
||||||
|
tags: ["ci-cd-user"]
|
||||||
|
|
||||||
|
- name: Déployer la clé publique SSH de l'utilisateur CI/CD
|
||||||
|
become: true
|
||||||
|
authorized_key:
|
||||||
|
user: "{{ ci_cd_user }}"
|
||||||
|
key: "{{ ci_cd_ssh_pubkey }}"
|
||||||
|
state: present
|
||||||
|
exclusive: false
|
||||||
|
tags: ["ci-cd-user"]
|
||||||
|
|
||||||
|
- name: Autoriser l'utilisateur CI/CD à utiliser Docker sans mot de passe (sudo ciblé, optionnel)
|
||||||
|
become: true
|
||||||
|
copy:
|
||||||
|
dest: "/etc/sudoers.d/{{ ci_cd_user }}-docker"
|
||||||
|
content: "{{ ci_cd_user }} ALL=(ALL) NOPASSWD: /usr/bin/docker\n"
|
||||||
|
mode: "0440"
|
||||||
|
validate: "visudo -cf %s"
|
||||||
|
tags: ["ci-cd-user"]
|
||||||
|
|
||||||
|
# ── Téléchargement act_runner ──────────────────────────
|
||||||
|
- name: Vérifier si act_runner est déjà installé
|
||||||
|
become: true
|
||||||
|
stat:
|
||||||
|
path: "{{ act_runner_binary }}"
|
||||||
|
register: runner_bin
|
||||||
|
tags: ["runner", "register-runner"]
|
||||||
|
|
||||||
|
- name: Récupérer la version installée
|
||||||
|
become: true
|
||||||
|
command: "{{ act_runner_binary }} --version"
|
||||||
|
register: installed_version
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
when: runner_bin.stat.exists
|
||||||
|
tags: ["runner", "register-runner"]
|
||||||
|
|
||||||
|
- name: Télécharger act_runner v{{ act_runner_version }}
|
||||||
|
become: true
|
||||||
|
get_url:
|
||||||
|
url: "https://dl.gitea.com/act_runner/{{ act_runner_version }}/act_runner-{{ act_runner_version }}-linux-amd64"
|
||||||
|
dest: "{{ act_runner_binary }}"
|
||||||
|
mode: "0755"
|
||||||
|
force: yes
|
||||||
|
tags: ["runner", "register-runner"]
|
||||||
|
when: >
|
||||||
|
not (runner_bin.stat.exists | default(false)) or
|
||||||
|
(installed_version.stdout is defined and act_runner_version not in installed_version.stdout)
|
||||||
|
# ── Répertoire de travail ──────────────────────────────
|
||||||
|
- name: Créer le répertoire de travail
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: "{{ act_runner_workdir }}"
|
||||||
|
state: directory
|
||||||
|
mode: "0750"
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
# ── Enregistrement du runner ───────────────────────────
|
||||||
|
- name: Vérifier que gitea_runner_token est fourni
|
||||||
|
become: true
|
||||||
|
fail:
|
||||||
|
msg: "La variable 'gitea_runner_token' est requise. Relancez avec : -e gitea_runner_token=<token>"
|
||||||
|
when: gitea_runner_token is not defined or gitea_runner_token == ""
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Vérifier si le runner est déjà enregistré
|
||||||
|
become: true
|
||||||
|
stat:
|
||||||
|
path: "{{ act_runner_config }}"
|
||||||
|
register: runner_config
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Arrêter le service avant re-enregistrement
|
||||||
|
become: true
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: stopped
|
||||||
|
failed_when: false
|
||||||
|
when: gitea_runner_token is defined and runner_config.stat.exists
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Supprimer l'ancienne configuration du runner
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: "{{ act_runner_config }}"
|
||||||
|
state: absent
|
||||||
|
when: gitea_runner_token is defined and runner_config.stat.exists
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Enregistrer le runner auprès de Gitea
|
||||||
|
become: true
|
||||||
|
command: >
|
||||||
|
{{ act_runner_binary }} register
|
||||||
|
--instance {{ gitea_instance_url }}
|
||||||
|
--token {{ gitea_runner_token }}
|
||||||
|
--name {{ runner_name }}
|
||||||
|
--labels {{ runner_labels }}
|
||||||
|
--no-interactive
|
||||||
|
args:
|
||||||
|
chdir: "{{ act_runner_workdir }}"
|
||||||
|
no_log: true
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
# ── Service systemd ────────────────────────────────────
|
||||||
|
- name: Créer le service systemd gitea-runner
|
||||||
|
become: true
|
||||||
|
copy:
|
||||||
|
dest: /etc/systemd/system/gitea-runner.service
|
||||||
|
mode: "0644"
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Gitea Act Runner
|
||||||
|
After=network.target docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart={{ act_runner_binary }} daemon
|
||||||
|
WorkingDirectory={{ act_runner_workdir }}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
User=root
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
notify: Recharger systemd
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Activer et démarrer le service gitea-runner
|
||||||
|
become: true
|
||||||
|
systemd:
|
||||||
|
name: gitea-runner
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
daemon_reload: yes
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
# ── Vérification ───────────────────────────────────────
|
||||||
|
- name: Vérifier le statut du runner
|
||||||
|
become: true
|
||||||
|
command: systemctl status gitea-runner
|
||||||
|
register: runner_status
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Afficher le statut
|
||||||
|
become: true
|
||||||
|
debug:
|
||||||
|
msg: "{{ runner_status.stdout_lines }}"
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Check if swap is already active
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command: swapon --show
|
||||||
|
register: swap_status
|
||||||
|
changed_when: false
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Create swapfile
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command: "fallocate -l {{ swap_size }} {{ swap_file }}"
|
||||||
|
args:
|
||||||
|
creates: "{{ swap_file }}"
|
||||||
|
tags: ["register-runner"]
|
||||||
|
when: swap_status.stdout == ""
|
||||||
|
|
||||||
|
- name: Set swapfile permissions
|
||||||
|
become: true
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ swap_file }}"
|
||||||
|
mode: "0600"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Format swap
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command: mkswap {{ swap_file }}
|
||||||
|
tags: ["register-runner"]
|
||||||
|
when: swap_status.stdout == ""
|
||||||
|
|
||||||
|
- name: Enable swap
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command: swapon {{ swap_file }}
|
||||||
|
tags: ["register-runner"]
|
||||||
|
when: swap_status.stdout == ""
|
||||||
|
|
||||||
|
- name: Ensure swap in fstab
|
||||||
|
become: true
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/fstab
|
||||||
|
line: "{{ swap_file }} none swap sw 0 0"
|
||||||
|
state: present
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
- name: Set swappiness
|
||||||
|
become: true
|
||||||
|
ansible.builtin.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: "{{ swap_swappiness }}"
|
||||||
|
state: present
|
||||||
|
reload: yes
|
||||||
|
tags: ["register-runner"]
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Recharger systemd
|
||||||
|
become: true
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
---
|
||||||
|
- name: S3 backup pour la db de prod
|
||||||
|
hosts: infra
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- acl
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create directory for Docker GPG key
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add Docker GPG key
|
||||||
|
apt_key:
|
||||||
|
url: https://download.docker.com/linux/ubuntu/gpg
|
||||||
|
keyring: /etc/apt/keyrings/docker.gpg
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Get system architecture
|
||||||
|
command: dpkg --print-architecture
|
||||||
|
register: system_arch
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Get Ubuntu codename
|
||||||
|
command: lsb_release -cs
|
||||||
|
register: ubuntu_codename
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch={{ system_arch.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ubuntu_codename.stdout }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Update apt cache after adding repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Install Docker packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Ensure Docker service is started and enabled
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker group
|
||||||
|
group:
|
||||||
|
name: "{{ docker_group }}"
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker user
|
||||||
|
user:
|
||||||
|
name: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
create_home: yes
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add ansible user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
when: ansible_user is defined
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker installation
|
||||||
|
command: docker --version
|
||||||
|
register: docker_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker Compose installation
|
||||||
|
command: docker compose version
|
||||||
|
register: compose_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Display versions
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "{{ docker_version.stdout }}"
|
||||||
|
- "{{ compose_version.stdout }}"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Copy S3 project
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: ../monitoring/s3-backup/
|
||||||
|
dest: "{{ docker_dir }}/"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Ensure parent directory has correct permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set correct permissions for Docker files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
recurse: yes
|
||||||
|
tags: project
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
---
|
||||||
|
- name: Déploiement OTA & S3 pour les build
|
||||||
|
hosts: infra
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- acl
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create directory for Docker GPG key
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add Docker GPG key
|
||||||
|
apt_key:
|
||||||
|
url: https://download.docker.com/linux/ubuntu/gpg
|
||||||
|
keyring: /etc/apt/keyrings/docker.gpg
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Get system architecture
|
||||||
|
command: dpkg --print-architecture
|
||||||
|
register: system_arch
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Get Ubuntu codename
|
||||||
|
command: lsb_release -cs
|
||||||
|
register: ubuntu_codename
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch={{ system_arch.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ubuntu_codename.stdout }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Update apt cache after adding repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Install Docker packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Ensure Docker service is started and enabled
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker group
|
||||||
|
group:
|
||||||
|
name: "{{ docker_group }}"
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker user
|
||||||
|
user:
|
||||||
|
name: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
create_home: yes
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add ansible user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
when: ansible_user is defined
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker installation
|
||||||
|
command: docker --version
|
||||||
|
register: docker_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker Compose installation
|
||||||
|
command: docker compose version
|
||||||
|
register: compose_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Display versions
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "{{ docker_version.stdout }}"
|
||||||
|
- "{{ compose_version.stdout }}"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Copy S3 project
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: ../monitoring/s3/
|
||||||
|
dest: "{{ docker_dir }}/"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Ensure parent directory has correct permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set correct permissions for Docker files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
recurse: yes
|
||||||
|
tags: project
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
---
|
||||||
|
- name: Déploiement des solution de monitoring et de sécurité
|
||||||
|
hosts: infra
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- acl
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create directory for Docker GPG key
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add Docker GPG key
|
||||||
|
apt_key:
|
||||||
|
url: https://download.docker.com/linux/ubuntu/gpg
|
||||||
|
keyring: /etc/apt/keyrings/docker.gpg
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Get system architecture
|
||||||
|
command: dpkg --print-architecture
|
||||||
|
register: system_arch
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Get Ubuntu codename
|
||||||
|
command: lsb_release -cs
|
||||||
|
register: ubuntu_codename
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch={{ system_arch.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ubuntu_codename.stdout }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Update apt cache after adding repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Install Docker packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Ensure Docker service is started and enabled
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker group
|
||||||
|
group:
|
||||||
|
name: "{{ docker_group }}"
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker user
|
||||||
|
user:
|
||||||
|
name: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
create_home: yes
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add ansible user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
when: ansible_user is defined
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker installation
|
||||||
|
command: docker --version
|
||||||
|
register: docker_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker Compose installation
|
||||||
|
command: docker compose version
|
||||||
|
register: compose_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Display versions
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "{{ docker_version.stdout }}"
|
||||||
|
- "{{ compose_version.stdout }}"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Copy Docker project
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: ../monitoring/security/
|
||||||
|
dest: "{{ docker_dir }}/"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Ensure parent directory has correct permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set correct permissions for Docker files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
recurse: yes
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set permissions for .env file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/.env"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0640"
|
||||||
|
tags: project
|
||||||
|
ignore_errors: yes
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
- name: Mises à jour de sécurité automatiques (unattended-upgrades)
|
||||||
|
hosts: load-balancer
|
||||||
|
become: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer unattended-upgrades et jq (notification Discord)
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- unattended-upgrades
|
||||||
|
- jq
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Déployer la config des origines/exclusions (50unattended-upgrades)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/unattended-upgrades-50.j2
|
||||||
|
dest: /etc/apt/apt.conf.d/50unattended-upgrades
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Déployer la config d'activation périodique (20auto-upgrades)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/unattended-upgrades-20.j2
|
||||||
|
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Déployer le script de notification Discord
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/unattended-upgrades-notify.sh.j2
|
||||||
|
dest: /usr/local/bin/unattended-upgrades-notify.sh
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0750"
|
||||||
|
|
||||||
|
- name: Déployer le service systemd de notification
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/unattended-upgrades-notify.service.j2
|
||||||
|
dest: /etc/systemd/system/unattended-upgrades-notify.service
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify: Recharger systemd
|
||||||
|
|
||||||
|
- name: Déployer le timer systemd de notification
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: ../templates/unattended-upgrades-notify.timer.j2
|
||||||
|
dest: /etc/systemd/system/unattended-upgrades-notify.timer
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify: Recharger systemd
|
||||||
|
|
||||||
|
- name: Activer et démarrer le timer de notification
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: unattended-upgrades-notify.timer
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: Vérifier la config avec un dry-run
|
||||||
|
ansible.builtin.command: unattended-upgrade --dry-run --debug
|
||||||
|
register: dry_run_result
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Afficher le résultat du dry-run
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: dry_run_result.stdout_lines
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Recharger systemd
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
daemon_reload: true
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
---
|
||||||
|
- name: Configure WireGuard VPN Client
|
||||||
|
hosts: load-balancer
|
||||||
|
become: true
|
||||||
|
vars:
|
||||||
|
vpn_ip: "10.0.0.12"
|
||||||
|
vpn_private_key: "+E1pcelkLIr0x6FcOofnAWAFr6g5qHu8QHpG1sY6mG4="
|
||||||
|
vpn_server_pubkey: "VQa6g1foaXhJgYWbwyJ9R/EAmmXg0nOnhPhbIIPLlmg="
|
||||||
|
vpn_server_ip: "131.123.42.158"
|
||||||
|
vpn_server_port: "51820"
|
||||||
|
vpn_network: "10.0.0.0/24"
|
||||||
|
vpn_private_ip: "10.0.0.1"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Install WireGuard and tools
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- wireguard
|
||||||
|
- wireguard-tools
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create WireGuard config directory
|
||||||
|
file:
|
||||||
|
path: /etc/wireguard
|
||||||
|
state: directory
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Create WireGuard config
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
[Interface]
|
||||||
|
Address = {{ vpn_ip }}/32
|
||||||
|
ListenPort = 51821
|
||||||
|
PrivateKey = {{ vpn_private_key }}
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = {{ vpn_server_pubkey }}
|
||||||
|
Endpoint = {{ vpn_server_ip }}:{{ vpn_server_port }}
|
||||||
|
AllowedIPs = {{ vpn_network }}
|
||||||
|
PersistentKeepalive = 25
|
||||||
|
dest: /etc/wireguard/wg0.conf
|
||||||
|
mode: '0600'
|
||||||
|
register: wg_config
|
||||||
|
|
||||||
|
- name: Enable WireGuard service
|
||||||
|
systemd:
|
||||||
|
name: wg-quick@wg0
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Redémarrer WireGuard si la config a changé (state:started ne recharge pas seul)
|
||||||
|
systemd:
|
||||||
|
name: wg-quick@wg0
|
||||||
|
state: restarted
|
||||||
|
when: wg_config.changed
|
||||||
|
|
||||||
|
- name: Enregistrer le pair load-balancer sur le serveur VPN
|
||||||
|
hosts: vpn-uber
|
||||||
|
become: true
|
||||||
|
vars:
|
||||||
|
vpn_ip: "10.0.0.12"
|
||||||
|
vpn_private_key: "+E1pcelkLIr0x6FcOofnAWAFr6g5qHu8QHpG1sY6mG4="
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Calculer la clé publique du client à partir de sa clé privée
|
||||||
|
command: wg pubkey
|
||||||
|
args:
|
||||||
|
stdin: "{{ vpn_private_key }}"
|
||||||
|
delegate_to: localhost
|
||||||
|
become: false
|
||||||
|
register: client_pubkey
|
||||||
|
changed_when: false
|
||||||
|
no_log: true
|
||||||
|
tags: [vpn]
|
||||||
|
|
||||||
|
- name: Ajouter le pair dans wg0.conf
|
||||||
|
ansible.builtin.blockinfile:
|
||||||
|
path: /etc/wireguard/wg0.conf
|
||||||
|
marker: "# {mark} PEER load-balancer"
|
||||||
|
insertafter: EOF
|
||||||
|
block: |
|
||||||
|
[Peer]
|
||||||
|
PublicKey = {{ client_pubkey.stdout }}
|
||||||
|
AllowedIPs = {{ vpn_ip }}/32
|
||||||
|
register: peer_added
|
||||||
|
tags: [vpn]
|
||||||
|
|
||||||
|
|
||||||
|
- name: Appliquer la config sans couper les autres pairs
|
||||||
|
ansible.builtin.shell: wg syncconf wg0 <(wg-quick strip wg0)
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
when: peer_added.changed
|
||||||
|
tags: [vpn]
|
||||||
|
|
||||||
|
- name: Vérifier la connectivité VPN du load-balancer
|
||||||
|
hosts: load-balancer
|
||||||
|
become: true
|
||||||
|
vars:
|
||||||
|
vpn_ip: "10.0.0.12"
|
||||||
|
vpn_private_ip: "10.0.0.1"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Wait for VPN connection to establish
|
||||||
|
pause:
|
||||||
|
seconds: 3
|
||||||
|
|
||||||
|
- name: Check VPN connection
|
||||||
|
command: ip addr show wg0
|
||||||
|
register: wg_status
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Test VPN connectivity
|
||||||
|
command: ping -c 1 "{{ vpn_private_ip }}"
|
||||||
|
register: ping_result
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Display VPN status
|
||||||
|
debug:
|
||||||
|
msg: |
|
||||||
|
VPN Configuration Complete!
|
||||||
|
IP Address: {{ vpn_ip }}
|
||||||
|
WireGuard Status:
|
||||||
|
{{ wg_status.stdout }}
|
||||||
|
|
||||||
|
Ping result ({{ 'SUCCESS' if ping_result.rc == 0 else 'FAILED' }}):
|
||||||
|
{{ ping_result.stdout | default('Connection test deferred') }}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# ============================================================
|
||||||
|
# Variables de l'ancien déploiement natif (hosts demo-uber / uber-stup-web,
|
||||||
|
# playbooks playbook-backend.yml / playbook-frontend.yml / playbook-file.yml).
|
||||||
|
# Ces playbooks n'existent plus dans infra/, prod/ ou pre-prod/, et aucune de
|
||||||
|
# ces variables n'est référencée par un playbook actif.
|
||||||
|
# Conservées pour ne rien casser silencieusement — à confirmer puis supprimer.
|
||||||
|
# ============================================================
|
||||||
|
directory: "/home/ubuntu"
|
||||||
|
backend_dir: "/home/ubuntu/backend"
|
||||||
|
backend_binary: "/home/ubuntu/backend/main"
|
||||||
|
uploads_dir: "/home/ubuntu/backend/uploads"
|
||||||
|
frontend_port: 5173
|
||||||
|
user_web: "www-data"
|
||||||
|
discord_webhook_url: "REMPLACER_PAR_TON_WEBHOOK_DISCORD"
|
||||||
|
user_owner: "root"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Docker — utilisé par tous les playbooks qui installent Docker (prod, pre-prod, infra)
|
||||||
|
docker_user: "ubuntu"
|
||||||
|
docker_group: "docker"
|
||||||
|
docker_dir: "/home/ubuntu/docker"
|
||||||
|
|
||||||
|
# Notification Discord infra (unattended-upgrades, etc.) — infra/playbook-unattended-upgrades.yml
|
||||||
|
# Laisser vide désactive silencieusement l'envoi (voir unattended-upgrades-notify.sh.j2).
|
||||||
|
discord_infra_webhook_url: "https://discord.com/api/webhooks/1526937190410621032/EUxNm2AMFByTPa9sWmwiX1fDpl41eEKO1ssj9gJxCLkqAwQ4laRSDXNxMeToseLQROAc"
|
||||||
|
|
||||||
|
# CIS 3.3.1 (ip forwarding) — hardening/playbook-kernel-sysctl-hardening.yml
|
||||||
|
# Par défaut laissé actif (false = ne pas désactiver) : la plupart des hosts font tourner Docker
|
||||||
|
# (NAT des ports publiés) ou servent de relais VPN. Surchargé à true uniquement pour les hosts
|
||||||
|
# sans aucun rôle de forwarding (voir group_vars/load-balancer).
|
||||||
|
ip_forwarding_disabled: false
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# PostgreSQL
|
||||||
|
pg_version: "16"
|
||||||
|
db_user: admin_gestion_commande_db
|
||||||
|
db_name: gestion_commande_db
|
||||||
|
db_password: "1SWDxH20rV7K2Uc2PNlwCaCxfVZEtKomF0CK9OMh"
|
||||||
|
db_host: "localhost"
|
||||||
|
db_port: 5432
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
redis_bind: "127.0.0.1"
|
||||||
|
redis_port: 6379
|
||||||
|
redis_maxmemory: "1024mb"
|
||||||
|
redis_maxmemory_policy: "allkeys-lru"
|
||||||
|
redis_password: "k6UYX9RtuXJVV1HUeefbSukMcSwjvVgRsh2qJGPh"
|
||||||
|
|
||||||
|
# Nginx / backend
|
||||||
|
nginx_enable_firewall: true
|
||||||
|
backend_local_port: 8080
|
||||||
|
backend_port: 80
|
||||||
|
nginx_proxy_timeout: 60
|
||||||
|
nginx_max_body_size: "10M"
|
||||||
|
|
||||||
|
# Sauvegarde Postgres (Plakar) — prod/playbook-backup.yml
|
||||||
|
plakar_version: "1.1.4"
|
||||||
|
plakar_go_version: "1.24.0"
|
||||||
|
plakar_backup_user: plakar-backup
|
||||||
|
plakar_home_dir: /var/lib/plakar-backup
|
||||||
|
plakar_dump_dir: /var/lib/plakar-backup/dumps
|
||||||
|
plakar_config_dir: /etc/plakar-backup
|
||||||
|
plakar_passphrase_file: /etc/plakar-backup/passphrase
|
||||||
|
|
||||||
|
# Dépôt Plakar (Kloset) distant — stocké sur MinIO via S3
|
||||||
|
plakar_store_name: minio-backup
|
||||||
|
plakar_s3_endpoint: "10.0.0.4:8080"
|
||||||
|
plakar_s3_bucket: backup-db-prod-mln
|
||||||
|
plakar_s3_prefix: postgresql
|
||||||
|
plakar_s3_access_key: admin
|
||||||
|
plakar_s3_secret_key: "admin@12345"
|
||||||
|
plakar_s3_use_tls: true
|
||||||
|
plakar_email: "free6nk33@gmail.com"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Utilisé par infra/playbook-gitea-runner.yml (configuration du swap sur le runner CI)
|
||||||
|
swap_size: 4G
|
||||||
|
swap_file: /swapfile
|
||||||
|
swap_swappiness: 10
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Utilisé par infra/playbook-harden-ssh.yml
|
||||||
|
user_ssh: "omnex"
|
||||||
|
group_ssh: "ssh"
|
||||||
|
password_user_ssh: "$6$w6GBkTHgj8K84P7o$pToS4pRMGLKwfpRfnz6i.WpO72Lt5DLtFQWZJsKL2dKvQrdKdi2q8xRuWqq/W3ybFNLQapvAqN33HexVjajGw0" #aiQgIAcCVIy1E33ReRssfm414dm
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Utilisé par infra/playbook-harden-ssh.yml
|
||||||
|
user_ssh: "omnex"
|
||||||
|
group_ssh: "ssh"
|
||||||
|
password_user_ssh: "$6$w6GBkTHgj8K84P7o$pToS4pRMGLKwfpRfnz6i.WpO72Lt5DLtFQWZJsKL2dKvQrdKdi2q8xRuWqq/W3ybFNLQapvAqN33HexVjajGw0" #aiQgIAcCVIy1E33ReRssfm414dm
|
||||||
|
|
||||||
|
# CIS 3.3.1 — hardening/playbook-kernel-sysctl-hardening.yml
|
||||||
|
# load-balancer est un reverse proxy applicatif pur (pas de Docker, pas de relais VPN) :
|
||||||
|
# aucun besoin de forwarding kernel, peut être désactivé sans risque.
|
||||||
|
ip_forwarding_disabled: true
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Dossier source du projet Docker Compose copié sur l'hôte (pre-prod/playbook-pre-prod.yml)
|
||||||
|
# NOTE : ce dossier n'existe pas encore dans le repo (voir remarque précédente sur docker-pre-prod/ manquant)
|
||||||
|
compose_project_dir: "../docker-pre-prod/"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Dossier source du projet Docker Compose copié sur l'hôte (prod/playbook-prod.yml)
|
||||||
|
compose_project_dir: "../docker-prod/"
|
||||||
|
|
||||||
|
# Utilisé uniquement par prod/playbook-s3-img.yml (les autres playbooks du groupe utilisent ansible_user)
|
||||||
|
user_deploy: "ubuntu"
|
||||||
|
docker_group: "docker"
|
||||||
|
docker_dir: "/home/ubuntu/docker/s3-img"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Même stack que prod (prod/playbook-prod.yml cible désormais ce groupe)
|
||||||
|
compose_project_dir: "../../docker-prod/"
|
||||||
|
docker_group: "docker"
|
||||||
|
user_deploy: "ubuntu"
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
[prod]
|
||||||
|
prod-uber ansible_host=131.123.39.119 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.6 ansible_become_pass=aiQgIAcCVIy1E33ReRssfm414dm
|
||||||
|
|
||||||
|
[pre-prod]
|
||||||
|
pre-prod-uber ansible_host=131.123.39.112 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.7 ansible_become_pass=aiQgIAcCVIy1E33ReRssfm414dm
|
||||||
|
|
||||||
|
[bdd-redis-prod]
|
||||||
|
bdd-redis-prod ansible_host=132.243.162.62 ansible_user=root ansible_ssh_private_key_file=../.ssh/key_bdd_redis vpn_ip=10.0.0.5
|
||||||
|
|
||||||
|
[replica-prod]
|
||||||
|
replica-prod-uber ansible_host=132.243.162.161 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.9
|
||||||
|
|
||||||
|
[infra-monitoring-security]
|
||||||
|
monitoring-uber ansible_host=185.103.167.138 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.2
|
||||||
|
|
||||||
|
[infra-runner]
|
||||||
|
runner-uber ansible_host=185.103.164.200 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex
|
||||||
|
|
||||||
|
[infra-utils]
|
||||||
|
s3-uber ansible_host=80.96.58.164 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex ansible_become_pass=aiQgIAcCVIy1E33ReRssfm414dm
|
||||||
|
|
||||||
|
[vpn-uber]
|
||||||
|
vpn-uber ansible_host=131.123.42.158 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.1
|
||||||
|
|
||||||
|
[load-balancer]
|
||||||
|
load-balancer ansible_host=93.185.166.221 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex
|
||||||
|
|
||||||
|
[infra]
|
||||||
|
monitoring-uber ansible_host=185.103.167.138 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.2
|
||||||
|
vpn-uber ansible_host=131.123.42.158 ansible_user=omnex ansible_ssh_private_key_file=../.ssh/omnex vpn_ip=10.0.0.1
|
||||||
|
backup-mln ansible_host=85.121.176.241 ansible_user=root ansible_ssh_private_key_file=../.ssh/key_backup vpn_ip=10.0.0.4
|
||||||
|
|
||||||
|
[infra:children]
|
||||||
|
infra-monitoring-security
|
||||||
|
infra-runner
|
||||||
|
infra-utils
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Utilisé par infra/playbook-certbot.yml (certificat unique couvrant le domaine + sous-domaines)
|
||||||
|
# Valeurs héritées de l'ancien group_vars/all/vars.yml ("demo-uber.xyz") — ne correspondent
|
||||||
|
# pas au domaine réel du VPS monitoring documenté dans INFRA.md ("uber-stup.club").
|
||||||
|
# À CONFIRMER avant tout run de ce playbook, sous peine de générer un certificat pour le mauvais domaine.
|
||||||
|
domain_name: "demo-uber.xyz"
|
||||||
|
subdomains:
|
||||||
|
- wazuh.demo-uber.xyz
|
||||||
|
- dozzle.demo-uber.xyz
|
||||||
|
- beszel.demo-uber.xyz
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
---
|
||||||
|
- name: Déploiement de la pre-prod
|
||||||
|
hosts: pre-prod
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- acl
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create directory for Docker GPG key
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add Docker GPG key
|
||||||
|
apt_key:
|
||||||
|
url: https://download.docker.com/linux/ubuntu/gpg
|
||||||
|
keyring: /etc/apt/keyrings/docker.gpg
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Get system architecture
|
||||||
|
command: dpkg --print-architecture
|
||||||
|
register: system_arch
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Get Ubuntu codename
|
||||||
|
command: lsb_release -cs
|
||||||
|
register: ubuntu_codename
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch={{ system_arch.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ubuntu_codename.stdout }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Update apt cache after adding repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Install Docker packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Ensure Docker service is started and enabled
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker group
|
||||||
|
group:
|
||||||
|
name: "{{ docker_group }}"
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker user
|
||||||
|
user:
|
||||||
|
name: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
create_home: yes
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add ansible user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
when: ansible_user is defined
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker installation
|
||||||
|
command: docker --version
|
||||||
|
register: docker_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker Compose installation
|
||||||
|
command: docker compose version
|
||||||
|
register: compose_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Display versions
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "{{ docker_version.stdout }}"
|
||||||
|
- "{{ compose_version.stdout }}"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Copy Docker project
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ compose_project_dir }}"
|
||||||
|
dest: "{{ docker_dir }}/"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Ensure parent directory has correct permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set correct permissions for Docker files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
recurse: yes
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set permissions for .env file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/.env.example"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0640"
|
||||||
|
tags: project
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Set permissions for lbtelegram.env file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/lbtelegram.env"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0640"
|
||||||
|
tags: project
|
||||||
|
ignore_errors: yes
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
---
|
||||||
|
# ============================================
|
||||||
|
# PostgreSQL Installation (vm-postgres uniquement)
|
||||||
|
# ============================================
|
||||||
|
- name: Installation et configuration de PostgreSQL
|
||||||
|
hosts: bdd-redis-prod
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# ============================================================
|
||||||
|
# Dépendances requises
|
||||||
|
# ============================================================
|
||||||
|
- name: Installer les dépendances pour le dépôt APT
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- gnupg2
|
||||||
|
- curl
|
||||||
|
- ca-certificates
|
||||||
|
- lsb-release
|
||||||
|
- python3-psycopg2
|
||||||
|
- acl
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Ajout du dépôt officiel PostgreSQL
|
||||||
|
# ============================================================
|
||||||
|
- name: Ajouter la clé GPG du dépôt PostgreSQL
|
||||||
|
ansible.builtin.apt_key:
|
||||||
|
url: https://www.postgresql.org/media/keys/ACCC4CF8.asc
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ajouter le dépôt PostgreSQL 16
|
||||||
|
ansible.builtin.apt_repository:
|
||||||
|
repo: "deb http://apt.postgresql.org/pub/repos/apt {{ ansible_distribution_release }}-pgdg main"
|
||||||
|
state: present
|
||||||
|
filename: pgdg
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Installation PostgreSQL 16
|
||||||
|
# ============================================================
|
||||||
|
- name: Installer PostgreSQL 16
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- "postgresql-{{ pg_version }}"
|
||||||
|
- "postgresql-client-{{ pg_version }}"
|
||||||
|
- "postgresql-contrib-{{ pg_version }}"
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Démarrer et activer PostgreSQL
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: postgresql
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Configuration PostgreSQL
|
||||||
|
# ============================================================
|
||||||
|
- name: Configurer l'écoute sur localhost
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "/etc/postgresql/{{ pg_version }}/main/postgresql.conf"
|
||||||
|
regexp: "^#?listen_addresses"
|
||||||
|
line: "listen_addresses = 'localhost'"
|
||||||
|
notify: Restart postgresql
|
||||||
|
|
||||||
|
- name: Configurer le port
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "/etc/postgresql/{{ pg_version }}/main/postgresql.conf"
|
||||||
|
regexp: "^#?port"
|
||||||
|
line: "port = {{ db_port }}"
|
||||||
|
notify: Restart postgresql
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Locale requise
|
||||||
|
# ============================================================
|
||||||
|
- name: Générer la locale fr_FR.UTF-8
|
||||||
|
ansible.builtin.command: locale-gen fr_FR.UTF-8
|
||||||
|
register: locale_gen
|
||||||
|
changed_when: "'Generation complete' in locale_gen.stdout"
|
||||||
|
|
||||||
|
- name: Mettre à jour les locales
|
||||||
|
ansible.builtin.command: update-locale
|
||||||
|
when: locale_gen.changed
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Création de la base de données et configuration utilisateur
|
||||||
|
# ============================================================
|
||||||
|
- name: Définir le mot de passe de l'utilisateur postgres
|
||||||
|
become_user: postgres
|
||||||
|
ansible.builtin.postgresql_user:
|
||||||
|
name: "{{ db_user }}"
|
||||||
|
password: "{{ db_password }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Vérifier si la base de données existe
|
||||||
|
become_user: postgres
|
||||||
|
ansible.builtin.command: psql -tAc "SELECT 1 FROM pg_database WHERE datname='{{ db_name }}'"
|
||||||
|
register: db_exists
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Créer la base de données avec ICU
|
||||||
|
become_user: postgres
|
||||||
|
ansible.builtin.command: >
|
||||||
|
psql -c "CREATE DATABASE {{ db_name }}
|
||||||
|
OWNER {{ db_user }}
|
||||||
|
ENCODING 'UTF8'
|
||||||
|
LOCALE_PROVIDER icu
|
||||||
|
ICU_LOCALE 'fr-FR'
|
||||||
|
TEMPLATE template0"
|
||||||
|
when: db_exists.stdout != "1"
|
||||||
|
|
||||||
|
- name: Accorder tous les privilèges sur la base
|
||||||
|
become_user: postgres
|
||||||
|
ansible.builtin.postgresql_privs:
|
||||||
|
db: "{{ db_name }}"
|
||||||
|
role: "{{ db_user }}"
|
||||||
|
type: database
|
||||||
|
privs: ALL
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Authentification pg_hba.conf
|
||||||
|
# ============================================================
|
||||||
|
- name: Configurer l'authentification md5 pour les connexions locales
|
||||||
|
ansible.builtin.postgresql_pg_hba:
|
||||||
|
dest: "/etc/postgresql/{{ pg_version }}/main/pg_hba.conf"
|
||||||
|
contype: host
|
||||||
|
databases: "{{ db_name }}"
|
||||||
|
users: "{{ db_user }}"
|
||||||
|
source: "127.0.0.1/32"
|
||||||
|
method: md5
|
||||||
|
notify: Restart postgresql
|
||||||
|
|
||||||
|
- name: Configurer l'authentification md5 pour IPv6 local
|
||||||
|
ansible.builtin.postgresql_pg_hba:
|
||||||
|
dest: "/etc/postgresql/{{ pg_version }}/main/pg_hba.conf"
|
||||||
|
contype: host
|
||||||
|
databases: "{{ db_name }}"
|
||||||
|
users: "{{ db_user }}"
|
||||||
|
source: "::1/128"
|
||||||
|
method: md5
|
||||||
|
notify: Restart postgresql
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Vérification
|
||||||
|
# ============================================================
|
||||||
|
- name: Vérifier la version de PostgreSQL
|
||||||
|
become_user: postgres
|
||||||
|
ansible.builtin.command: psql --version
|
||||||
|
register: pg_version_check
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Afficher la version
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ pg_version_check.stdout }}"
|
||||||
|
|
||||||
|
- name: Vérifier que la base existe
|
||||||
|
become_user: postgres
|
||||||
|
ansible.builtin.command: psql -lqt
|
||||||
|
register: pg_databases
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Afficher les bases de données
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ pg_databases.stdout_lines }}"
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Restart postgresql
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: postgresql
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# Redis Installation (vm-redis uniquement)
|
||||||
|
# ============================================
|
||||||
|
- name: Installation et configuration de Redis
|
||||||
|
hosts: bdd-redis-prod
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Installer Redis
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- redis-server
|
||||||
|
- python3-redis
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Créer le répertoire de backup Redis
|
||||||
|
file:
|
||||||
|
path: /var/lib/redis/backup
|
||||||
|
state: directory
|
||||||
|
owner: redis
|
||||||
|
group: redis
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Configurer Redis - bind address (accepter connexions réseau)
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^bind"
|
||||||
|
line: "bind 127.0.0.1 {{ vpn_ip }}"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Configurer Redis - port
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^port"
|
||||||
|
line: "port {{ redis_port }}"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Configurer Redis - maxmemory
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^# ?maxmemory"
|
||||||
|
line: "maxmemory {{ redis_maxmemory }}"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Configurer Redis - maxmemory-policy
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^# ?maxmemory-policy"
|
||||||
|
line: "maxmemory-policy {{ redis_maxmemory_policy }}"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Configurer Redis - requirepass
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^# ?requirepass"
|
||||||
|
line: "requirepass {{ redis_password }}"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Activer AOF (Append Only File) pour Redis
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^appendonly"
|
||||||
|
line: "appendonly yes"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Configurer la fréquence de sync AOF
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^# ?appendfsync"
|
||||||
|
line: "appendfsync everysec"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Activer la persistance RDB (snapshots)
|
||||||
|
blockinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
block: |
|
||||||
|
save 900 1
|
||||||
|
save 300 10
|
||||||
|
save 60 10000
|
||||||
|
marker: "# {mark} ANSIBLE MANAGED RDB PERSISTENCE"
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Configurer le nom du fichier AOF
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^appendfilename"
|
||||||
|
line: 'appendfilename "appendonly.aof"'
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Désactiver le mode protégé Redis
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^protected-mode"
|
||||||
|
line: "protected-mode no"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Configurer le répertoire de travail Redis
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^dir"
|
||||||
|
line: "dir /var/lib/redis"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: Définir le niveau de log
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/redis/redis.conf
|
||||||
|
regexp: "^loglevel"
|
||||||
|
line: "loglevel notice"
|
||||||
|
state: present
|
||||||
|
notify: Redémarrer Redis
|
||||||
|
|
||||||
|
- name: S'assurer que Redis est démarré
|
||||||
|
systemd:
|
||||||
|
name: redis-server
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Redémarrer Redis
|
||||||
|
systemd:
|
||||||
|
name: redis-server
|
||||||
|
state: restarted
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
---
|
||||||
|
- name: Installation et configuration du frontend et backend
|
||||||
|
hosts: replica-prod
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- acl
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create directory for Docker GPG key
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add Docker GPG key
|
||||||
|
apt_key:
|
||||||
|
url: https://download.docker.com/linux/ubuntu/gpg
|
||||||
|
keyring: /etc/apt/keyrings/docker.gpg
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Get system architecture
|
||||||
|
command: dpkg --print-architecture
|
||||||
|
register: system_arch
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Get Ubuntu codename
|
||||||
|
command: lsb_release -cs
|
||||||
|
register: ubuntu_codename
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch={{ system_arch.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ubuntu_codename.stdout }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Update apt cache after adding repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Install Docker packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Ensure Docker service is started and enabled
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker group
|
||||||
|
group:
|
||||||
|
name: "{{ docker_group }}"
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker user
|
||||||
|
user:
|
||||||
|
name: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
create_home: yes
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add ansible user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
when: ansible_user is defined
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker installation
|
||||||
|
command: docker --version
|
||||||
|
register: docker_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker Compose installation
|
||||||
|
command: docker compose version
|
||||||
|
register: compose_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Display versions
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "{{ docker_version.stdout }}"
|
||||||
|
- "{{ compose_version.stdout }}"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Copy Docker project
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ compose_project_dir }}"
|
||||||
|
dest: "{{ docker_dir }}/"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Ensure parent directory has correct permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set correct permissions for Docker files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
recurse: yes
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set permissions for .env file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/.env.example"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0640"
|
||||||
|
tags: project
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Set permissions for lbtelegram.env file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/.env.lbtelegram"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0640"
|
||||||
|
tags: project
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Create certs folder
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/certs"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0750"
|
||||||
|
tags: project
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
---
|
||||||
|
- name: Installation et configuration du frontend et backend
|
||||||
|
hosts: bdd-redis-prod
|
||||||
|
become: true
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 3600
|
||||||
|
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- acl
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create directory for Docker GPG key
|
||||||
|
file:
|
||||||
|
path: /etc/apt/keyrings
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add Docker GPG key
|
||||||
|
apt_key:
|
||||||
|
url: https://download.docker.com/linux/ubuntu/gpg
|
||||||
|
keyring: /etc/apt/keyrings/docker.gpg
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Get system architecture
|
||||||
|
command: dpkg --print-architecture
|
||||||
|
register: system_arch
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Get Ubuntu codename
|
||||||
|
command: lsb_release -cs
|
||||||
|
register: ubuntu_codename
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch={{ system_arch.stdout }} signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ubuntu_codename.stdout }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Update apt cache after adding repo
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Install Docker packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Ensure Docker service is started and enabled
|
||||||
|
systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker group
|
||||||
|
group:
|
||||||
|
name: "{{ docker_group }}"
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Create docker user
|
||||||
|
user:
|
||||||
|
name: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
shell: /bin/bash
|
||||||
|
create_home: yes
|
||||||
|
state: present
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Add ansible user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ user_deploy }}"
|
||||||
|
groups: docker
|
||||||
|
append: yes
|
||||||
|
when: user_deploy is defined
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker installation
|
||||||
|
command: docker --version
|
||||||
|
register: docker_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Verify Docker Compose installation
|
||||||
|
command: docker compose version
|
||||||
|
register: compose_version
|
||||||
|
changed_when: false
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Display versions
|
||||||
|
debug:
|
||||||
|
msg:
|
||||||
|
- "{{ docker_version.stdout }}"
|
||||||
|
- "{{ compose_version.stdout }}"
|
||||||
|
tags: docker
|
||||||
|
|
||||||
|
- name: Copy Docker project
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: ../../monitoring/s3-img
|
||||||
|
dest: "{{ docker_dir }}/"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Ensure parent directory has correct permissions
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0755"
|
||||||
|
tags: project
|
||||||
|
|
||||||
|
- name: Set correct permissions for Docker files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
recurse: yes
|
||||||
|
tags: project-fin
|
||||||
|
|
||||||
|
- name: Set permissions for .env file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_dir }}/.env"
|
||||||
|
owner: "{{ docker_user }}"
|
||||||
|
group: "{{ docker_group }}"
|
||||||
|
mode: "0640"
|
||||||
|
tags: project
|
||||||
|
ignore_errors: yes
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# CIS Ubuntu 24.04 - core dumps restreints (1.5.3)
|
||||||
|
* hard core 0
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# CIS Ubuntu 24.04 - core dumps restreints (1.5.3)
|
||||||
|
fs.suid_dumpable = 0
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# CIS Ubuntu 24.04 - durcissement sysctl reseau (3.3.x)
|
||||||
|
net.ipv4.conf.all.send_redirects = 0
|
||||||
|
net.ipv4.conf.default.send_redirects = 0
|
||||||
|
net.ipv4.conf.all.accept_redirects = 0
|
||||||
|
net.ipv4.conf.default.accept_redirects = 0
|
||||||
|
net.ipv6.conf.all.accept_redirects = 0
|
||||||
|
net.ipv6.conf.default.accept_redirects = 0
|
||||||
|
net.ipv4.conf.all.secure_redirects = 0
|
||||||
|
net.ipv4.conf.default.secure_redirects = 0
|
||||||
|
net.ipv4.conf.all.accept_source_route = 0
|
||||||
|
net.ipv4.conf.default.accept_source_route = 0
|
||||||
|
net.ipv6.conf.all.accept_source_route = 0
|
||||||
|
net.ipv6.conf.default.accept_source_route = 0
|
||||||
|
net.ipv4.conf.all.log_martians = 1
|
||||||
|
net.ipv4.conf.default.log_martians = 1
|
||||||
|
net.ipv4.tcp_syncookies = 1
|
||||||
|
net.ipv6.conf.all.accept_ra = 0
|
||||||
|
net.ipv6.conf.default.accept_ra = 0
|
||||||
|
net.ipv4.conf.all.rp_filter = 1
|
||||||
|
net.ipv4.conf.default.rp_filter = 1
|
||||||
|
{% if ip_forwarding_disabled | default(false) %}
|
||||||
|
# ip_forward desactive : ce host ne fait tourner ni Docker (NAT de ports publies) ni de relais VPN.
|
||||||
|
net.ipv4.ip_forward = 0
|
||||||
|
net.ipv6.conf.all.forwarding = 0
|
||||||
|
{% else %}
|
||||||
|
# ip_forward laisse actif (defaut systeme = 1) : ce host heberge Docker et/ou fait relais VPN,
|
||||||
|
# le desactiver casserait le NAT des ports publies ou le routage entre pairs WireGuard.
|
||||||
|
# CIS 35608 restera donc en echec ici par necessite fonctionnelle, pas par oubli.
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Exclusions specifiques a cette infra (donnees volumineuses, evolution constante,
|
||||||
|
# integrite geree par leurs propres mecanismes — pas pertinent pour un check AIDE)
|
||||||
|
!/var/lib/docker$
|
||||||
|
!/var/lib/docker/.*
|
||||||
|
!/var/lib/wazuh-indexer$
|
||||||
|
!/var/lib/wazuh-indexer/.*
|
||||||
|
!/var/lib/postgresql$
|
||||||
|
!/var/lib/postgresql/.*
|
||||||
|
!/var/lib/redis$
|
||||||
|
!/var/lib/redis/.*
|
||||||
|
!/var/lib/clamav$
|
||||||
|
!/var/lib/clamav/.*
|
||||||
|
!/var/lib/beszel-agent$
|
||||||
|
!/var/lib/beszel-agent/.*
|
||||||
|
!/var/log/audit$
|
||||||
|
!/var/log/audit/.*
|
||||||
|
!/var/lib/containerd$
|
||||||
|
!/var/lib/containerd/.*
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# CIS Ubuntu 24.04 - regles d'audit detaillees : surveillance sudo (6.2.3.1-6.2.3.3)
|
||||||
|
|
||||||
|
# 6.2.3.1 - changements de perimetre d'administration (sudoers)
|
||||||
|
-w /etc/sudoers -p wa -k scope
|
||||||
|
-w /etc/sudoers.d -p wa -k scope
|
||||||
|
|
||||||
|
# 6.2.3.2 - toute action executee en tant qu'un autre utilisateur (sudo -u, su, etc.)
|
||||||
|
-a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k user_emulation
|
||||||
|
-a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S execve -k user_emulation
|
||||||
|
|
||||||
|
# 6.2.3.3 - modifications du fichier de log sudo
|
||||||
|
-w /var/log/sudo.log -p wa -k sudo_log_file
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Regle custom (hors CIS) - surveillance dediee de l'utilisateur omnex
|
||||||
|
# auid (login uid) persiste a travers tout sudo/su : capture donc TOUTES les commandes
|
||||||
|
# executees par omnex, meme apres elevation de privileges.
|
||||||
|
-a always,exit -F arch=b64 -F auid={{ omnex_uid }} -S execve -k omnex_actions
|
||||||
|
-a always,exit -F arch=b32 -F auid={{ omnex_uid }} -S execve -k omnex_actions
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
# CIS Ubuntu 24.04 - regles d'audit detaillees restantes (6.2.3.4-6.2.3.19)
|
||||||
|
# UID_MIN lu dynamiquement depuis /etc/login.defs sur cet host : {{ uid_min }}
|
||||||
|
|
||||||
|
# 6.2.3.4 - changements date/heure
|
||||||
|
-a always,exit -F arch=b64 -S adjtimex,settimeofday -k time-change
|
||||||
|
-a always,exit -F arch=b32 -S adjtimex,settimeofday -k time-change
|
||||||
|
-a always,exit -F arch=b64 -S clock_settime -F a0=0x0 -k time-change
|
||||||
|
-a always,exit -F arch=b32 -S clock_settime -F a0=0x0 -k time-change
|
||||||
|
-w /etc/localtime -p wa -k time-change
|
||||||
|
|
||||||
|
# 6.2.3.5 - changements environnement reseau du systeme
|
||||||
|
-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale
|
||||||
|
-a always,exit -F arch=b32 -S sethostname,setdomainname -k system-locale
|
||||||
|
-w /etc/issue -p wa -k system-locale
|
||||||
|
-w /etc/issue.net -p wa -k system-locale
|
||||||
|
-w /etc/hosts -p wa -k system-locale
|
||||||
|
-w /etc/networks -p wa -k system-locale
|
||||||
|
-w /etc/network/ -p wa -k system-locale
|
||||||
|
-w /etc/netplan/ -p wa -k system-locale
|
||||||
|
|
||||||
|
# 6.2.3.7 - tentatives d'acces fichier echouees
|
||||||
|
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ uid_min }} -F auid!=unset -k access
|
||||||
|
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ uid_min }} -F auid!=unset -k access
|
||||||
|
-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ uid_min }} -F auid!=unset -k access
|
||||||
|
-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ uid_min }} -F auid!=unset -k access
|
||||||
|
|
||||||
|
# 6.2.3.8 - modifications informations user/group
|
||||||
|
-w /etc/group -p wa -k identity
|
||||||
|
-w /etc/passwd -p wa -k identity
|
||||||
|
-w /etc/gshadow -p wa -k identity
|
||||||
|
-w /etc/shadow -p wa -k identity
|
||||||
|
-w /etc/security/opasswd -p wa -k identity
|
||||||
|
-w /etc/nsswitch.conf -p wa -k identity
|
||||||
|
-w /etc/pam.conf -p wa -k identity
|
||||||
|
-w /etc/pam.d -p wa -k identity
|
||||||
|
|
||||||
|
# 6.2.3.9 - modifications permissions discretionnaires (DAC)
|
||||||
|
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ uid_min }} -F auid!=unset -F key=perm_mod
|
||||||
|
-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ uid_min }} -F auid!=unset -F key=perm_mod
|
||||||
|
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ uid_min }} -F auid!=unset -F key=perm_mod
|
||||||
|
-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ uid_min }} -F auid!=unset -F key=perm_mod
|
||||||
|
-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ uid_min }} -F auid!=unset -F key=perm_mod
|
||||||
|
-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ uid_min }} -F auid!=unset -F key=perm_mod
|
||||||
|
|
||||||
|
# 6.2.3.10 - montages systeme de fichiers reussis
|
||||||
|
-a always,exit -F arch=b32 -S mount -F auid>={{ uid_min }} -F auid!=unset -k mounts
|
||||||
|
-a always,exit -F arch=b64 -S mount -F auid>={{ uid_min }} -F auid!=unset -k mounts
|
||||||
|
|
||||||
|
# 6.2.3.11 - informations d'initiation de session
|
||||||
|
-w /var/run/utmp -p wa -k session
|
||||||
|
-w /var/log/wtmp -p wa -k session
|
||||||
|
-w /var/log/btmp -p wa -k session
|
||||||
|
|
||||||
|
# 6.2.3.12 - evenements login/logout
|
||||||
|
-w /var/log/lastlog -p wa -k logins
|
||||||
|
-w /var/run/faillock -p wa -k logins
|
||||||
|
|
||||||
|
# 6.2.3.13 - suppressions de fichiers par les utilisateurs
|
||||||
|
-a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>={{ uid_min }} -F auid!=unset -F key=delete
|
||||||
|
-a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F auid>={{ uid_min }} -F auid!=unset -F key=delete
|
||||||
|
|
||||||
|
# 6.2.3.14 - modifications du controle d'acces obligatoire (AppArmor)
|
||||||
|
-w /etc/apparmor/ -p wa -k MAC-policy
|
||||||
|
-w /etc/apparmor.d/ -p wa -k MAC-policy
|
||||||
|
|
||||||
|
# 6.2.3.15-17 - commandes chcon / setfacl / chacl
|
||||||
|
-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ uid_min }} -F auid!=unset -k perm_chng
|
||||||
|
-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ uid_min }} -F auid!=unset -k perm_chng
|
||||||
|
-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ uid_min }} -F auid!=unset -k perm_chng
|
||||||
|
|
||||||
|
# 6.2.3.18 - commande usermod
|
||||||
|
-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ uid_min }} -F auid!=unset -k usermod
|
||||||
|
|
||||||
|
# 6.2.3.19 - chargement/dechargement/modification de modules noyau
|
||||||
|
-a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ uid_min }} -F auid!=unset -k kernel_modules
|
||||||
|
-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ uid_min }} -F auid!=unset -k kernel_modules
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# CIS Ubuntu 24.04 - modules noyau reseau et filesystem inutilises dans cette infra (3.2.1-3.2.4, 1.1.1.10)
|
||||||
|
install dccp /bin/false
|
||||||
|
blacklist dccp
|
||||||
|
install tipc /bin/false
|
||||||
|
blacklist tipc
|
||||||
|
install rds /bin/false
|
||||||
|
blacklist rds
|
||||||
|
install sctp /bin/false
|
||||||
|
blacklist sctp
|
||||||
|
install afs /bin/false
|
||||||
|
blacklist afs
|
||||||
|
install ceph /bin/false
|
||||||
|
blacklist ceph
|
||||||
|
install cifs /bin/false
|
||||||
|
blacklist cifs
|
||||||
|
install exfat /bin/false
|
||||||
|
blacklist exfat
|
||||||
|
install ext /bin/false
|
||||||
|
blacklist ext
|
||||||
|
# fat et fuse sont compiles en dur dans le noyau Ubuntu (builtin, pas de .ko) : cette entree
|
||||||
|
# ne change rien fonctionnellement et le check CIS 35509 restera en echec pour ces deux modules.
|
||||||
|
install fat /bin/false
|
||||||
|
blacklist fat
|
||||||
|
install fscache /bin/false
|
||||||
|
blacklist fscache
|
||||||
|
install fuse /bin/false
|
||||||
|
blacklist fuse
|
||||||
|
install gfs2 /bin/false
|
||||||
|
blacklist gfs2
|
||||||
|
install nfs_common /bin/false
|
||||||
|
blacklist nfs_common
|
||||||
|
install nfsd /bin/false
|
||||||
|
blacklist nfsd
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
PasswordAuthentication no
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Géré par Ansible (playbook-pam-hardening.yml) — CIS Ubuntu 24.04 (5.5.2/5.5.3)
|
||||||
|
deny = {{ pam_faillock_deny }}
|
||||||
|
unlock_time = {{ pam_faillock_unlock_time }}
|
||||||
|
fail_interval = {{ pam_faillock_fail_interval }}
|
||||||
|
even_deny_root
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
global
|
||||||
|
log stdout format raw local0
|
||||||
|
maxconn 4096
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode http
|
||||||
|
option httplog
|
||||||
|
option dontlognull
|
||||||
|
timeout connect 5s
|
||||||
|
timeout client 30s
|
||||||
|
timeout server 30s
|
||||||
|
timeout http-request 10s
|
||||||
|
retries 2
|
||||||
|
|
||||||
|
frontend fe_https
|
||||||
|
bind *:443 ssl crt /etc/haproxy/certs/mln-uber.club.pem
|
||||||
|
mode http
|
||||||
|
option forwardfor
|
||||||
|
http-request set-header X-Forwarded-Proto https
|
||||||
|
|
||||||
|
# /api/* et /uploads/* -> pool backend (Go), tout le reste -> pool frontend (SPA)
|
||||||
|
acl is_api path_beg /api/ /uploads/ /webhook/telegram /webhook/nowpayment
|
||||||
|
use_backend be_api if is_api
|
||||||
|
default_backend be_frontend
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Pool API — TODO : /api/health n'existe pas encore côté backend,
|
||||||
|
# ce check échouera tant que la route n'est pas ajoutée.
|
||||||
|
# ============================================================
|
||||||
|
backend be_api
|
||||||
|
mode http
|
||||||
|
option httpchk GET /api/health
|
||||||
|
http-check expect status 200
|
||||||
|
|
||||||
|
server prod-uber {{ hostvars['prod-uber']['vpn_ip'] }}:443 ssl verify none check inter 2s fall 3 rise 2
|
||||||
|
server replica-prod-uber {{ hostvars['replica-prod-uber']['vpn_ip'] | default('TODO-vpn_ip-manquant') }}:443 ssl verify none check inter 2s fall 3 rise 2 backup
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Pool frontend statique (SPA) — check sur "/" (toujours servi par nginx même si l'API est down)
|
||||||
|
# ============================================================
|
||||||
|
backend be_frontend
|
||||||
|
mode http
|
||||||
|
option httpchk GET /
|
||||||
|
http-check expect status 200
|
||||||
|
|
||||||
|
server prod-uber {{ hostvars['prod-uber']['vpn_ip'] }}:443 ssl verify none check inter 2s fall 3 rise 2
|
||||||
|
server replica-prod-uber {{ hostvars['replica-prod-uber']['vpn_ip'] | default('TODO-vpn_ip-manquant') }}:443 ssl verify none check inter 2s fall 3 rise 2 backup
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Name: Notify of failed login attempts and reset count upon success
|
||||||
|
Default: yes
|
||||||
|
Priority: 1024
|
||||||
|
Auth-Type: Primary
|
||||||
|
Auth:
|
||||||
|
requisite pam_faillock.so preauth
|
||||||
|
Account-Type: Primary
|
||||||
|
Account:
|
||||||
|
required pam_faillock.so
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Name: Enable pam_faillock to deny access
|
||||||
|
Default: yes
|
||||||
|
Priority: 0
|
||||||
|
Auth-Type: Primary
|
||||||
|
Auth:
|
||||||
|
[default=die] pam_faillock.so authfail
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Name: pwhistory password history checking
|
||||||
|
Default: yes
|
||||||
|
Priority: 1024
|
||||||
|
Password-Type: Primary
|
||||||
|
Password:
|
||||||
|
requisite pam_pwhistory.so remember={{ pam_pwhistory_remember }} enforce_for_root try_first_pass use_authtok
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Name: Pwquality password strength checking
|
||||||
|
Default: yes
|
||||||
|
Priority: 1024
|
||||||
|
Conflicts: cracklib
|
||||||
|
Password-Type: Primary
|
||||||
|
Password:
|
||||||
|
requisite pam_pwquality.so retry=3
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
Name: Unix authentication
|
||||||
|
Default: yes
|
||||||
|
Priority: 256
|
||||||
|
Auth-Type: Primary
|
||||||
|
Auth:
|
||||||
|
[success=end default=ignore] pam_unix.so try_first_pass
|
||||||
|
Auth-Initial:
|
||||||
|
[success=end default=ignore] pam_unix.so
|
||||||
|
Account-Type: Primary
|
||||||
|
Account:
|
||||||
|
[success=end new_authtok_reqd=done default=ignore] pam_unix.so
|
||||||
|
Account-Initial:
|
||||||
|
[success=end new_authtok_reqd=done default=ignore] pam_unix.so
|
||||||
|
Session-Type: Additional
|
||||||
|
Session:
|
||||||
|
required pam_unix.so
|
||||||
|
Session-Initial:
|
||||||
|
required pam_unix.so
|
||||||
|
Password-Type: Primary
|
||||||
|
Password:
|
||||||
|
[success=end default=ignore] pam_unix.so obscure use_authtok try_first_pass yescrypt
|
||||||
|
Password-Initial:
|
||||||
|
[success=end default=ignore] pam_unix.so obscure yescrypt
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Géré par Ansible (playbook-pam-hardening.yml) — CIS Ubuntu 24.04 (5.5.4)
|
||||||
|
minlen = {{ pam_pwquality_minlen }}
|
||||||
|
dcredit = -1
|
||||||
|
ucredit = -1
|
||||||
|
lcredit = -1
|
||||||
|
ocredit = -1
|
||||||
|
difok = {{ pam_pwquality_difok }}
|
||||||
|
enforce_for_root
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
|
||||||
|
# This is the sshd server system-wide configuration file. See
|
||||||
|
# sshd_config(5) for more information.
|
||||||
|
|
||||||
|
# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
|
||||||
|
|
||||||
|
# The strategy used for options in the default sshd_config shipped with
|
||||||
|
# OpenSSH is to specify options with their default value where
|
||||||
|
# possible, but leave them commented. Uncommented options override the
|
||||||
|
# default value.
|
||||||
|
|
||||||
|
Include /etc/ssh/sshd_config.d/*.conf
|
||||||
|
|
||||||
|
#Port 22
|
||||||
|
AddressFamily inet
|
||||||
|
#ListenAddress 0.0.0.0
|
||||||
|
#ListenAddress ::
|
||||||
|
|
||||||
|
#HostKey /etc/ssh/ssh_host_rsa_key
|
||||||
|
#HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||||
|
#HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
|
|
||||||
|
# Ciphers and keying
|
||||||
|
#RekeyLimit default none
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
#SyslogFacility AUTH
|
||||||
|
#LogLevel INFO
|
||||||
|
|
||||||
|
# Authentication:
|
||||||
|
AllowGroups {{ group_ssh }}
|
||||||
|
AllowUsers {{ user_ssh }}
|
||||||
|
#LoginGraceTime 2m
|
||||||
|
PermitRootLogin no
|
||||||
|
#StrictModes yes
|
||||||
|
MaxAuthTries 3
|
||||||
|
MaxSessions 2
|
||||||
|
|
||||||
|
PubkeyAuthentication yes
|
||||||
|
|
||||||
|
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
|
||||||
|
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
|
||||||
|
|
||||||
|
#AuthorizedPrincipalsFile none
|
||||||
|
|
||||||
|
#AuthorizedKeysCommand none
|
||||||
|
#AuthorizedKeysCommandUser nobody
|
||||||
|
|
||||||
|
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
|
||||||
|
#HostbasedAuthentication no
|
||||||
|
# Change to yes if you don't trust ~/.ssh/known_hosts for
|
||||||
|
# HostbasedAuthentication
|
||||||
|
#IgnoreUserKnownHosts no
|
||||||
|
# Don't read the user's ~/.rhosts and ~/.shosts files
|
||||||
|
#IgnoreRhosts yes
|
||||||
|
|
||||||
|
# To disable tunneled clear text passwords, change to no here!
|
||||||
|
PasswordAuthentication no
|
||||||
|
#PermitEmptyPasswords no
|
||||||
|
|
||||||
|
# Change to yes to enable challenge-response passwords (beware issues with
|
||||||
|
# some PAM modules and threads)
|
||||||
|
KbdInteractiveAuthentication no
|
||||||
|
|
||||||
|
# Kerberos options
|
||||||
|
#KerberosAuthentication no
|
||||||
|
#KerberosOrLocalPasswd yes
|
||||||
|
#KerberosTicketCleanup yes
|
||||||
|
#KerberosGetAFSToken no
|
||||||
|
|
||||||
|
# GSSAPI options
|
||||||
|
#GSSAPIAuthentication no
|
||||||
|
#GSSAPICleanupCredentials yes
|
||||||
|
#GSSAPIStrictAcceptorCheck yes
|
||||||
|
#GSSAPIKeyExchange no
|
||||||
|
|
||||||
|
# Set this to 'yes' to enable PAM authentication, account processing,
|
||||||
|
# and session processing. If this is enabled, PAM authentication will
|
||||||
|
# be allowed through the KbdInteractiveAuthentication and
|
||||||
|
# PasswordAuthentication. Depending on your PAM configuration,
|
||||||
|
# PAM authentication via KbdInteractiveAuthentication may bypass
|
||||||
|
# the setting of "PermitRootLogin without-password".
|
||||||
|
# If you just want the PAM account and session checks to run without
|
||||||
|
# PAM authentication, then enable this but set PasswordAuthentication
|
||||||
|
# and KbdInteractiveAuthentication to 'no'.
|
||||||
|
UsePAM yes
|
||||||
|
|
||||||
|
#AllowAgentForwarding yes
|
||||||
|
#AllowTcpForwarding yes
|
||||||
|
#GatewayPorts no
|
||||||
|
X11Forwarding no
|
||||||
|
#X11DisplayOffset 10
|
||||||
|
#X11UseLocalhost yes
|
||||||
|
#PermitTTY yes
|
||||||
|
PrintMotd no
|
||||||
|
#PrintLastLog yes
|
||||||
|
#TCPKeepAlive yes
|
||||||
|
#PermitUserEnvironment no
|
||||||
|
#Compression delayed
|
||||||
|
#ClientAliveInterval 0
|
||||||
|
#ClientAliveCountMax 3
|
||||||
|
#UseDNS no
|
||||||
|
#PidFile /run/sshd.pid
|
||||||
|
MaxStartups 10:30:60
|
||||||
|
PermitTunnel no
|
||||||
|
#ChrootDirectory none
|
||||||
|
#VersionAddendum none
|
||||||
|
|
||||||
|
# no default banner path
|
||||||
|
#Banner none
|
||||||
|
|
||||||
|
# Allow client to pass locale environment variables
|
||||||
|
AcceptEnv LANG LC_*
|
||||||
|
|
||||||
|
# override default of no subsystems
|
||||||
|
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||||
|
|
||||||
|
# Example of overriding settings on a per-user basis
|
||||||
|
#Match User anoncvs
|
||||||
|
# X11Forwarding no
|
||||||
|
# AllowTcpForwarding no
|
||||||
|
# PermitTTY no
|
||||||
|
# ForceCommand cvs server
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// Généré par ansible (infra/playbook-unattended-upgrades.yml) — ne pas éditer à la main.
|
||||||
|
APT::Periodic::Update-Package-Lists "1";
|
||||||
|
APT::Periodic::Download-Upgradeable-Packages "1";
|
||||||
|
APT::Periodic::AutocleanInterval "7";
|
||||||
|
APT::Periodic::Unattended-Upgrade "1";
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// Généré par ansible (infra/playbook-unattended-upgrades.yml) — ne pas éditer à la main.
|
||||||
|
|
||||||
|
Unattended-Upgrade::Origins-Pattern {
|
||||||
|
"origin=Debian,codename=${distro_codename},label=Debian-Security";
|
||||||
|
"origin=Ubuntu,archive=${distro_codename}-security";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Paquets sensibles exclus — mise à jour manuelle et review requises :
|
||||||
|
// - postgresql/redis : pas de tolérance à une régression sur la DB/cache
|
||||||
|
// - docker/containerd : un redémarrage du daemon peut interrompre les conteneurs en cours
|
||||||
|
// - wireguard : composant réseau critique du VPN inter-serveurs
|
||||||
|
Unattended-Upgrade::Package-Blacklist {
|
||||||
|
"postgresql*";
|
||||||
|
"redis*";
|
||||||
|
"docker-ce*";
|
||||||
|
"docker-ce-cli*";
|
||||||
|
"containerd.io";
|
||||||
|
"wireguard*";
|
||||||
|
};
|
||||||
|
|
||||||
|
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
|
||||||
|
Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
||||||
|
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
|
||||||
|
|
||||||
|
Unattended-Upgrade::Automatic-Reboot "true";
|
||||||
|
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
|
||||||
|
Unattended-Upgrade::Automatic-Reboot-Time "00:00";
|
||||||
|
|
||||||
|
// Pas d'email (host headless) — notification Telegram via le script/timer dédié.
|
||||||
|
Unattended-Upgrade::Mail "";
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Notification Telegram post unattended-upgrades
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/local/bin/unattended-upgrades-notify.sh
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Généré par ansible (infra/playbook-unattended-upgrades.yml) — ne pas éditer à la main.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
LOG="/var/log/unattended-upgrades/unattended-upgrades.log"
|
||||||
|
TODAY="$(date +%Y-%m-%d)"
|
||||||
|
HOSTNAME="$(hostname)"
|
||||||
|
WEBHOOK_URL="{{ discord_infra_webhook_url }}"
|
||||||
|
|
||||||
|
if [ -z "$WEBHOOK_URL" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
INSTALLED=""
|
||||||
|
if [ -f "$LOG" ]; then
|
||||||
|
INSTALLED=$(grep "^$TODAY" "$LOG" | grep -i "Packages that will be upgraded\|Packages that are upgraded" || true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
REBOOT_STATUS="Pas de redémarrage requis"
|
||||||
|
if [ -f /var/run/reboot-required ]; then
|
||||||
|
REBOOT_STATUS="⚠️ Redémarrage requis (programmé à 00:00 UTC)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$INSTALLED" ]; then
|
||||||
|
MESSAGE="🔒 [$HOSTNAME] Unattended-upgrades — aucun paquet de sécurité à installer aujourd'hui."
|
||||||
|
else
|
||||||
|
MESSAGE="🔒 [$HOSTNAME] Unattended-upgrades — paquets mis à jour aujourd'hui :
|
||||||
|
${INSTALLED}
|
||||||
|
|
||||||
|
${REBOOT_STATUS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PAYLOAD="$(jq -n --arg content "$MESSAGE" '{content: $content}')"
|
||||||
|
|
||||||
|
curl -s -X POST "$WEBHOOK_URL" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$PAYLOAD" \
|
||||||
|
> /dev/null
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Déclenche la notification Telegram post unattended-upgrades
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=*-*-* 00:30:00
|
||||||
|
Persistent=true
|
||||||
|
RandomizedDelaySec=120
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
Reference in New Issue
Block a user