Set-OPS-Public/roles/serveur_collabora/tasks/main.yml
Daniel Allaire a60b69f072 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

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