Set-OPS-Public/roles/common_packages/tasks/main.yml

140 lines
6.1 KiB
YAML
Raw Normal View History

---
# `lock_timeout` sur CHAQUE tache apt : au premier demarrage, l'image Debian lance ses
# propres mises a jour (apt-daily, unattended-upgrades) et tient le verrou dpkg par
# vagues. Sans attente, la premiere tache echoue sur un verrou — pas sur une vraie
# erreur — et le deploiement d'une VM neuve devient un tirage au sort.
#
# Attendre ici plutot que seulement avant le playbook : le verrou peut etre repris
# ENTRE deux taches, ce qu'une verification ponctuelle en amont ne peut pas empecher.
proxmox : le pare-feu ne s'arme que dans le SDN — et 45e preuve Le decoupage du site en quatre zones a revele un defaut qui dormait dans le moteur. `firewall=1` sur l'interface d'une VM fait passer tout le trafic ponte par conntrack. Sur un VNet SDN c'est sans consequence : en EVPN le routage inter-VNet se fait dans le VRF, SUR LE NOEUD, et le flux ne quitte jamais l'hyperviseur. Sur un pont classique route par une frontiere externe, deux VM du MEME noeud dans deux VLAN differents ne se parlent qu'en EPINGLE : la trame sort par le lien physique, la frontiere la route, elle revient sur le meme pont. La meme table conntrack voit alors les deux moities de la connexion, classe le retour INVALID, et PVEFW-FORWARD le jette. La mesure a tranche : ops(asgard) -> pki(asgard) 0/8 dns(gandalf) -> cache(gandalf) 0/8 ops(asgard) -> forge(vishnu) 6/8 dns(gandalf) -> pki(asgard) 6/8 ops(asgard) -> cache(gandalf) 8/8 dns(gandalf) -> forge(vishnu) 8/8 Toutes les paires intra-noeud echouent, toutes les paires inter-noeuds passent. Douze tentatives faisaient monter le compteur `ctstate INVALID` de +112 sur asgard et +116 sur gandalf ; `firewall=0` pose, il ne bouge plus — 0 sur les deux, pour le meme trafic. Le defaut se deguise en panne reseau : la poignee TCP ABOUTIT, et ce sont les paquets de DONNEES qui disparaissent. L'AC le disait dans son propre journal (`TLS handshake error ... i/o timeout` : elle accepte et attend un ClientHello qui n'arrive jamais). Ecartes un par un, par la mesure : regles identiques champ par champ, alias corrects, assignation des interfaces confirmee, ARP et routes saines, IPS desactive, shaper vide, NAT source limite a `wan`, MTU a 1500 de bout en bout — et la taille sans effet, 100 octets se perdant comme 1460. L'INTENTION DECLAREE NE SUFFIT PAS : un tenant declare `proxmox_clone_parefeu_interface: true` avec `proxmox_clone_pont: vmbr1` comme valeur PAR DEFAUT, chaque hote la remplacant par son VNet derive. L'hote qui retombe sur `vmbr1` naitrait arme sur un pont classique. `cloner_vm_debian.yml` croise donc l'intention avec le pont REELLEMENT utilise, et le dit quand il desarme — un desarmement muet serait le meme piege, en silence. P45 EVALUE l'expression du playbook sur quatre cas plutot que d'en lire le texte, dont un qui DOIT rendre vrai : sans lui, une expression constamment fausse passerait la preuve sans rien garantir. Controle negatif verifie — le drapeau remis a plat fait echouer la preuve. Ce commit emporte aussi le desarmement d'`unattended-upgrades` dans `common_packages`, jusqu'ici applique sur les machines mais pas versionne : le verrou dpkg tenu 48 minutes par une vague de maj automatiques a coute deux deploiements. Le site a revele ce defaut parce qu'il a ete le premier a porter plusieurs zones. Ce n'est pas une particularite du site : un tenant derive les siennes du meme principe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 19:50:53 -04:00
# DÉSARMER AVANT TOUTE OPÉRATION APT, ET NON APRÈS.
#
# Une tâche apt placée avant celle-ci attendrait le verrou que celle-ci doit justement
# libérer — l'ordre n'est pas cosmétique. `state: stopped` en plus de `masked` : masquer
# empêche un démarrage futur, pas celui qui est déjà en cours.
- name: Désarmer les mises à jour automatiques de Debian (Set-OPS les applique lui-même)
ansible.builtin.systemd_service:
name: "{{ item }}"
state: stopped
enabled: false
masked: true
loop: "{{ common_packages_unites_maj_auto }}"
when: common_packages_desarmer_maj_auto | bool
failed_when: false # une unite absente n'est pas une faute : elle est desarmee
audit + timers : deux services en echec sur les quinze machines, muets depuis toujours `make prouver` disait 15/15 a failed=0. Les machines, elles, portaient chacune trois unites systemd en echec. Le rapport d Ansible n est pas l etat d une machine. AUDITD : ONZE REGLES ARMEES, PERSONNE POUR COLLECTER. Deux fichiers de regles identiques cohabitaient — 99-chezlepro.rules et 99-setops.rules, vestige du renommage du role. augenrules CONCATENE rules.d/ : Error sending add rule data request (Rule exists) There was an error in line 16 of /etc/audit/audit.rules audit-rules echoue, et auditd ne demarre pas — c est sa dependance. Resultat : auditctl -l affiche onze regles, ce qui donne toutes les apparences d un audit qui fonctionne, et rien ne les enregistre. Meme mue que ssh_baseline, meme registre : auditd_fichiers_perimes. On n y ajoute que des noms qu on a REELLEMENT deposes un jour. Et `failed_when: false` cachait la panne : quinze machines a failed=0 avec auditd mort sur les quinze. Un service de securite qui ne demarre pas doit se VOIR. TIMERS APT-DAILY : UN ETAT D ECHEC RESIDUEL. Masquer le service pendant que son timer tourne lui fait perdre sa cible ; systemd le note et le GARDE (Unit to trigger vanished). `state: stopped` n efface pas un etat failed — seul reset-failed le fait. Ce n est pas cosmetique : une supervision qui compte les unites en echec compte ces deux-la pour toujours, et la vraie panne s y noiera. Meme defaut que le journal de la frontiere noye sous 982 000 entrees. DIAGNOSTIC FAUX, CORRIGE : j avais lu « masked enabled » dans list-unit-files comme un etat contradictoire, et construit une reparation pour le defaire. Ces colonnes sont ETAT puis PRESET — masque avec un prereglage constructeur active est normal. La reparation a ete annulee avant d etre livree. make verifier : vert. make prouver : CONFORME, 55 OK, 0 echec, 0 saute. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-31 16:16:13 -04:00
# EFFACER LA TRACE QUE LE DESARMEMENT LAISSE (mesure du 2026-08-30).
#
# Masquer le service pendant que son timer TOURNE lui fait perdre sa cible. systemd le
# note, et le garde :
#
# apt-daily.timer: Unit to trigger vanished.
# apt-daily.timer: Failed with result 'resources'.
#
# `state: stopped` n'efface pas un etat `failed` — seul `reset-failed` le fait. Sans lui,
# CHAQUE machine porte deux unites en echec permanent. Constate sur les quinze de
# Chezlepro : `systemctl list-units --state=failed` en rend deux partout.
#
# CE N'EST PAS COSMETIQUE. Une supervision qui compte les unites en echec compte ces
# deux-la pour toujours — et le jour ou une VRAIE panne s'ajoute, elle se noie dans un
# bruit qu'on a appris a ignorer. C'est le meme defaut que le journal de la frontiere
# noye sous 982 000 entrees : ce qui ment le plus n'est pas ce qui se tait, c'est ce qui
# crie sans raison.
- name: Effacer l'etat d'echec laisse par le desarmement
ansible.builtin.command:
argv: ["systemctl", "reset-failed", "{{ item }}"]
loop: "{{ common_packages_unites_maj_auto }}"
register: common_packages_reset
changed_when: false
failed_when: false # rien a effacer n'est pas une faute
when: common_packages_desarmer_maj_auto | bool
2026-09-11 19:02:10 -04:00
# REARMER NE SE DEDUIT PAS DE NE PLUS DESARMER (2026-09-11).
#
# Passer `common_packages_desarmer_maj_auto` a `false` SAUTE la tache de desarmement —
# il ne defait rien. Une machine deja masquee le resterait pour toujours, et le drapeau
# dirait le contraire de l'etat reel. Le desarmement laisse une trace ; il faut donc une
# tache qui la retire, et elle doit exister le jour meme ou l'on inverse la decision.
#
# L'ORDRE COMPTE, COMME POUR LE DESARMEMENT : on reamorce AVANT les operations apt de ce
# role. Un demarrage d'`apt-daily` declenche pendant nos propres taches se disputerait le
# verrou au pire moment ; declenche avant, il est attendu par `lock_timeout`.
# ON ARME, ON NE DECLENCHE PAS — ET LA NUANCE A COUTE DIX MACHINES (2026-09-11).
#
# La premiere version faisait `state: started` sur les trois unites. Demarrer
# `unattended-upgrades.service` apres des semaines de masquage lance son RATTRAPAGE
# immediatement — en plein deploiement. Il a pris le verrou dpkg et l'a garde plus
# longtemps que `lock_timeout` (300 s) :
#
# 'apt-get autoremove' failed: E: Could not get lock /var/lib/dpkg/lock-frontend.
# It is held by process 185135 (unattended-upgr)
#
# Exactement la course qui avait motive le desarmement en aout, rejouee par la tache
# censee le defaire. Dix machines sur vingt et une.
#
# LE TRAVAIL QUOTIDIEN NE PASSE PAS PAR CE SERVICE : `apt-daily-upgrade.timer` appelle
# `apt.systemd.daily`, qui invoque `unattended-upgrade` lui-meme. Le `.service` ne sert
# qu'aux passages de demarrage et d'extinction. L'ACTIVER suffit donc — il partira au
# prochain redemarrage, sur une machine au repos, et non pendant qu'Ansible tient apt.
#
# Demarrer les MINUTEURS, en revanche, est sans danger : armer un minuteur ne declenche
# pas sa cible, il la programme.
- name: Réarmer les mises à jour automatiques de Debian (sans les déclencher)
ansible.builtin.systemd_service:
name: "{{ item }}"
masked: false
enabled: true
state: "{{ 'started' if item.endswith('.timer') else omit }}"
loop: "{{ common_packages_unites_maj_auto }}"
when: not (common_packages_desarmer_maj_auto | bool)
failed_when: false # une unite absente sur cette image n'est pas une faute
- name: Mettre à jour le cache APT
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
lock_timeout: "{{ common_packages_lock_timeout }}"
- name: Appliquer les mises à jour disponibles
ansible.builtin.apt:
upgrade: full
lock_timeout: "{{ common_packages_lock_timeout }}"
- name: Installer les paquets communs
ansible.builtin.apt:
name: "{{ common_packages_list }}"
state: present
lock_timeout: "{{ common_packages_lock_timeout }}"
- name: Supprimer les dépendances devenues inutiles
ansible.builtin.apt:
autoremove: true
lock_timeout: "{{ common_packages_lock_timeout }}"
un fichier vide existe, et une sonde pour les correctifs LA GARDE FICHIER ENTIER, en deux corrections. Un telechargement interrompu laisse un fichier de zero octet QUI EXISTE, et toutes les gardes demandaient seulement s il etait la. infra-mail-01 a garde une cle smallstep de 0 octet apres l epreuve hors ligne. La premiere correction n a pas suffi. Ajouter le controle de taille faisait bien s executer la tache - et le fichier faisait toujours 0 octet au passage suivant. get_url sur une destination existante emet une requete CONDITIONNELLE : l amont repond non modifie, le module rend ok, la ruine reste. Le play etait vert et ne reparait rien. Il faut effacer avant de redemander. Controle negatif : 0 -> 1022 octets, 0 erreur apt. Cinq roles. LA SONDE CORRECTIFS, 23e. Set-OPS desarme unattended-upgrades et applique les correctifs au deploiement - choix defendable, le verrou dpkg a fait decrocher une machine d une reconstruction entiere le matin meme. Mais rien ne disait QUAND le geste etait du : une flotte pouvait deriver des mois en restant verte. Elle mesure les paquets de securite en attente ET depuis quand. Elle ne lance pas apt-get update - une sonde qui rafraichit l index toutes les quinze minutes deviendrait la cause de la panne qu elle surveille. Et le seuil de 72 h est un choix d exploitation, pas une derivation : le mecanisme qui applique les correctifs est un geste humain. P64 REFUSAIT UNE DECLARATION CORRECTE. serveur_debian et serveur_durci sont des roles de declaration pure, sans une tache ; le travail est fait par les roles que leur playbook applique. La preuve exigeait declaration et depot dans le meme role - vrai des vingt-deux premieres sondes, faux des qu une sonde appartient au socle. Une garde qui force a contourner ce qu elle protege est un defaut. Elle suit desormais le playbook du groupe. Mesure : 21/21 machines vertes, 65 preuves, 23 sondes, 0 echec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 17:26:35 -04:00
# LA SONDE SE DEPOSE ICI, ELLE SE DECLARE AILLEURS (`roles/serveur_debian/meta/`).
# Ce role est celui qui APPLIQUE les mises a jour ; il est donc le bon porteur. Mais la
# derivation des services d'Icinga croise les GROUPES, et `common_packages` n'en est pas
# un — d'ou la separation, expliquee dans la declaration.
- name: Assurer le repertoire des sondes de supervision
ansible.builtin.file:
path: /usr/local/lib/setops/sondes
state: directory
owner: root
group: root
mode: "0755"
- name: Assurer le repertoire d etat des sondes
ansible.builtin.file:
path: /var/lib/setops
state: directory
owner: root
group: root
mode: "0750"
- name: Deposer la sonde des correctifs de securite
ansible.builtin.template:
src: sonde-correctifs.sh.j2
dest: /usr/local/lib/setops/sondes/correctifs.sh
owner: root
group: root
mode: "0750"