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
168 lines
7 KiB
YAML
168 lines
7 KiB
YAML
---
|
|
# LA CONDITION EST ECRITE D'UN SEUL TENANT, ET C'EST DELIBERE.
|
|
#
|
|
# `scripts/verifier_intrants.py` lit les `assert` de la forme `var | length > 0` comme un
|
|
# CONTRAT : l'instance doit fournir cette valeur. Et il ignore volontairement les `when:`
|
|
# — un intrant exige sous condition reste un intrant exige.
|
|
#
|
|
# Ecrite en deux morceaux (`that: var | length > 0` + `when: actif`), cette garde
|
|
# promettait donc un secret pour une console FERMEE, et P32 le refusait a juste titre.
|
|
# Ecrite en une implication, elle dit ce qu'elle veut vraiment dire : SI la console est
|
|
# ouverte, ALORS un mot de passe. Ne pas la « simplifier » en la recoupant en deux.
|
|
- name: Exiger un secret si — et seulement si — la console d'administration est ouverte
|
|
ansible.builtin.assert:
|
|
that:
|
|
- not (serveur_collabora_admin_actif | bool) or (serveur_collabora_admin_mot_de_passe | length > 0)
|
|
fail_msg: >-
|
|
La console d'administration est ouverte mais son mot de passe est vide.
|
|
Le renseigner depuis la voûte de l'instance, ou refermer la console
|
|
(`serveur_collabora_admin_actif: false`).
|
|
|
|
- name: Assurer le repertoire des trousseaux apt
|
|
ansible.builtin.file:
|
|
path: /etc/apt/keyrings
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
|
|
# Récupérée UNE FOIS, comme la clé Smallstep : une plateforme souveraine ne recontacte pas
|
|
# un serveur étranger à chaque déploiement pour une clé déjà installée. Une rotation amont
|
|
# ne passe pas inaperçue pour autant — `apt` refuse alors le dépôt, bruyamment.
|
|
# UN FICHIER VIDE EXISTE (mesure du 2026-09-10).
|
|
#
|
|
# Cette garde demandait « ce fichier est-il la ? ». Un telechargement interrompu — un 503,
|
|
# un delai depasse, une coupure — laisse un fichier de ZERO octet, qui existe. La tache
|
|
# est donc sautee a tous les passages suivants, et la machine garde une ressource morte
|
|
# pour toujours, en silence.
|
|
#
|
|
# CE QUE CA A COUTE : `infra-mail-01` a garde une cle smallstep de 0 octet apres une
|
|
# epreuve hors ligne. Treize machines portaient 1022 octets, elle portait le vide :
|
|
#
|
|
# E: Le depot http://packages.smallstep.com/... n'est pas signe.
|
|
#
|
|
# Le meme jour, l'index `dists/trixie` du cache du site etait tombe de 140 416 a 4 332
|
|
# octets — meme famille, autre endroit. Un telechargement partiel ne se signale pas : il
|
|
# se fait passer pour un succes.
|
|
#
|
|
# On demande donc « est-il ENTIER ? » — a defaut de pouvoir demander « est-il JUSTE ? »,
|
|
# ce qui exigerait une empreinte de reference que l'amont ne publie pas toujours.
|
|
- name: Cette ressource est-elle deja recuperee ? (cle Collabora)
|
|
ansible.builtin.stat:
|
|
path: "{{ serveur_collabora_depot_cle_fichier }}"
|
|
register: serveur_collabora_cle_presente
|
|
|
|
# ... ET IL FAUT LE RETIRER, PAS SEULEMENT LE REDEMANDER (mesure du 2026-09-10).
|
|
#
|
|
# Laisser la garde autoriser la tache ne suffit PAS. `get_url` sur une destination qui
|
|
# existe emet une requete CONDITIONNELLE : l'amont repond « non modifie », le module rend
|
|
# `ok`, et le fichier corrompu reste en place. Mesure : la tache s'executait bien
|
|
# (`ok: [infra-mail-01]`), et la cle faisait toujours 0 octet au passage suivant. Un
|
|
# `force: yes` manuel l'a reparee en une seconde.
|
|
#
|
|
# On efface donc la ruine avant de reconstruire. `state: absent` ne mord que sur un
|
|
# fichier vide : une cle valide n'est jamais retiree, et la doctrine « on ne retelecharge
|
|
# pas ce qu'on possede deja » reste intacte.
|
|
- name: Retirer une ressource VIDE avant de la redemander
|
|
ansible.builtin.file:
|
|
path: "{{ serveur_collabora_depot_cle_fichier }}"
|
|
state: absent
|
|
when:
|
|
- serveur_collabora_cle_presente.stat.exists
|
|
- (serveur_collabora_cle_presente.stat.size | default(0)) == 0
|
|
|
|
- name: Telecharger la cle de signature Collabora
|
|
when: not (serveur_collabora_cle_presente.stat.exists and serveur_collabora_cle_presente.stat.size | default(0) > 0)
|
|
ansible.builtin.get_url:
|
|
url: "{{ serveur_collabora_depot_cle_url }}"
|
|
dest: "{{ serveur_collabora_depot_cle_fichier }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
timeout: 30
|
|
register: serveur_collabora_cle
|
|
retries: 5
|
|
delay: 6
|
|
until: serveur_collabora_cle is succeeded
|
|
# LA CLE PASSE PAR LE CACHE, ELLE AUSSI (mesure du 2026-09-10).
|
|
#
|
|
# `get_url` ignore la configuration d'apt : le mandataire pose dans
|
|
# `/etc/apt/apt.conf.d/` ne vaut que pour apt. Les cles de signature sortaient donc
|
|
# TOUJOURS en direct, meme apres que tous les depots soient passes par le cache — un
|
|
# trou reste ouvert derriere une porte qu'on croyait fermee.
|
|
#
|
|
# Et ce n'est pas theorique : depuis `collab-01`, la route directe vers
|
|
# `www.collaboraoffice.com` EXPIRE, quand le cache l'atteint sans peine.
|
|
#
|
|
# en direct grafana 200 collabora TIMEOUT
|
|
# via le cache collabora 200
|
|
#
|
|
# Le meme geste corrige donc les deux : plus rien ne sort, et la machine qui n'avait
|
|
# pas de route en trouve une.
|
|
#
|
|
# DEGRADE, JAMAIS DEVINE : sans cache d'amorcage declare, la valeur est VIDE et
|
|
# `get_url` sort en direct comme avant. On n'invente pas un mandataire.
|
|
environment:
|
|
http_proxy: >-
|
|
{{ ('http://' ~ artefacts_amorcage) if (artefacts_amorcage | default('') | string | length > 0) else '' }}
|
|
https_proxy: ""
|
|
|
|
# DEPOT PLAT : `Suites: ./`, aucun composant. Une source classique ne le trouverait pas.
|
|
- name: Ajouter le depot apt Collabora
|
|
ansible.builtin.template:
|
|
src: collabora.sources.j2
|
|
dest: /etc/apt/sources.list.d/collabora.sources
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
|
|
- name: Installer Collabora Online
|
|
when: not ansible_check_mode # dry-run : le depot n'est pas reellement ajoute
|
|
ansible.builtin.apt:
|
|
name: "{{ serveur_collabora_paquets }}"
|
|
state: present
|
|
update_cache: true
|
|
|
|
- name: Assurer le repertoire du fragment systemd
|
|
ansible.builtin.file:
|
|
path: "{{ serveur_collabora_fragment | dirname }}"
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
|
|
# LA CONFIGURATION DE SET-OPS TIENT EN UN FICHIER, et le coolwsd.xml du paquet reste
|
|
# intact. Voir defaults/main.yml pour le raisonnement.
|
|
- name: Deployer la surcharge Set-OPS
|
|
ansible.builtin.template:
|
|
src: setops.conf.j2
|
|
dest: "{{ serveur_collabora_fragment }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0640"
|
|
notify: Redemarrer Collabora
|
|
|
|
- name: Appliquer les redemarrages avant de verifier
|
|
ansible.builtin.meta: flush_handlers
|
|
|
|
- name: Activer et demarrer Collabora
|
|
when: not ansible_check_mode
|
|
ansible.builtin.systemd:
|
|
name: "{{ serveur_collabora_service }}"
|
|
enabled: true
|
|
state: started
|
|
daemon_reload: true
|
|
|
|
# ECRIRE, PUIS RELIRE (D-68). Un service « active » qui ne repond pas a `capabilities`
|
|
# est un vert sur un perimetre vide : Nextcloud le decouvrirait a la premiere ouverture
|
|
# de document, c'est-a-dire devant un usager.
|
|
- name: Collabora repond-il vraiment ?
|
|
when: not ansible_check_mode
|
|
ansible.builtin.uri:
|
|
url: "http://127.0.0.1:{{ serveur_collabora_port }}/hosting/capabilities"
|
|
status_code: [200]
|
|
timeout: 20
|
|
register: serveur_collabora_capacites
|
|
retries: 12
|
|
delay: 5
|
|
until: serveur_collabora_capacites is succeeded
|