Les 33 roles serveur_* declarent maintenant une sonde. Les huit qui manquaient
sont ceux dont la verite ne ressemble pas a « ce service repond-il ».
Quatre marqueurs du site : ce que tasks/main.yml verifie UNE FOIS au deploiement
cesse d etre vrai sans que rien ne tombe. La racine du cache se retrouve chainee,
la forge du genome repond en n ayant plus rien dedans, un locataire n est plus
admis a resoudre, l isolation d un depot glisse.
serveur_ops_site ne sert rien : il detient un pouvoir. La sonde verifie que la
carte est la, que la voute du site est chiffree et que sa cle est en 0600 — sans
lire le contenu d aucun des trois.
serveur_icingaweb2 surveille la vitrine de la supervision elle-meme : si la
console meurt, tout reste vert et l exploitant est aveugle.
DEFAUT 1 — quatre gabarits qu Ansible aurait refuse de rendre. Jinja lit le
{# de ${#tableau[@]} comme un debut de commentaire. Le depot connaissait le
remede et l appliquait la ou quelqu un s etait fait prendre, nulle part ailleurs.
P76 rend desormais chaque gabarit de role, avec les delimiteurs qu Ansible en
tirerait — pas une recherche de motif.
DEFAUT 2 — la doctrine promettait 54 greffons et citait check_pgsql. La flotte a
monitoring-plugins-basic : 53, sans check_pgsql ni check_dns ni check_ldap. Le
paquet qui les porte traine samba et snmp sur chaque machine. Un greffon absent
sort en 127, qui n est pas un code Nagios.
21 controles negatifs sur les machines reelles du site. ansible-lint production
0/91, harnais 75 OK.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
63 lines
2.7 KiB
Django/Jinja
63 lines
2.7 KiB
Django/Jinja
#!/bin/bash
|
|
# GENERE par Set-OPS (role serveur_ops_site). Ne pas editer a la main.
|
|
#
|
|
# SONDE « pouvoir-materialiser » — le runner du site peut-il encore creer des VM, et son
|
|
# secret est-il toujours protege ?
|
|
#
|
|
# CE QU'ELLE NE FAIT PAS, ET C'EST LE PLUS IMPORTANT : elle ne lit le CONTENU d'aucun de
|
|
# ces fichiers. Un en-tete de 21 octets, un proprietaire, un mode. Le mot de passe de la
|
|
# voute du site est un pointeur qu'on ne suit jamais — y compris depuis une sonde qui
|
|
# tourne en root toutes les quinze minutes.
|
|
#
|
|
# AUCUN GREFFON NE SAIT CA. `check_file_age` dirait qu'un fichier est vieux ; aucun ne
|
|
# sait ce qu'est une voute Ansible, ni pourquoi un fichier en clair est ici une urgence.
|
|
set -uo pipefail
|
|
|
|
CARTE='{{ serveur_ops_site_racine }}/{{ serveur_ops_site_depot }}/underlay.yml'
|
|
VOUTE='{{ serveur_ops_site_racine }}/{{ serveur_ops_site_depot }}/underlay.vault.yml'
|
|
CLE='{{ serveur_ops_site_cle_destination }}'
|
|
UTILISATEUR='{{ serveur_ops_site_utilisateur }}'
|
|
|
|
# 1. LA CARTE DE LA FABRIC.
|
|
if [[ ! -s "${CARTE}" ]]; then
|
|
echo "La carte de la fabric manque : ${CARTE}. Le runner du site ne sait plus sur quoi il materialise — aucune VM ne peut naitre."
|
|
exit 2
|
|
fi
|
|
|
|
# 2. LA VOUTE, ET SON CHIFFREMENT.
|
|
#
|
|
# L'EN-TETE, PAS LE CONTENU. `$ANSIBLE_VAULT` tient dans les 21 premiers octets ; c'est
|
|
# exactement ce que relit `tasks/main.yml` apres la copie, et pour la meme raison : une
|
|
# copie sans `decrypt: false` dechiffre en transit, et le fichier pose est alors en clair.
|
|
if [[ ! -s "${VOUTE}" ]]; then
|
|
echo "La voute du SITE manque : ${VOUTE}. Le runner a la carte mais plus les justificatifs du cluster."
|
|
exit 2
|
|
fi
|
|
|
|
entete=$(head -c 21 "${VOUTE}" 2>/dev/null)
|
|
if [[ "${entete}" != *'$ANSIBLE_VAULT'* ]]; then
|
|
echo "LA VOUTE DU SITE N'EST PAS CHIFFREE : ${VOUTE}. Les justificatifs du cluster sont en clair sur disque — les considerer comme exposes."
|
|
exit 2
|
|
fi
|
|
|
|
# 3. LA CLE, ET SES PERMISSIONS.
|
|
#
|
|
# `serveur_ops_site_cle_deposer` peut valoir faux : un runner qu'on arme a la main est un
|
|
# etat legitime. On ne crie donc pas pour une cle absente — on le DIT, ce qui n'est pas la
|
|
# meme chose qu'un vert muet.
|
|
if [[ ! -e "${CLE}" ]]; then
|
|
echo "Carte et voute en place, voute chiffree. Aucune cle deposee a ${CLE} : ce runner s'arme autrement."
|
|
exit 0
|
|
fi
|
|
|
|
lu=$(stat -c '%U %a' "${CLE}" 2>/dev/null) || { echo "La cle de la voute du site est illisible : ${CLE}."; exit 2; }
|
|
proprietaire=${lu%% *}
|
|
mode=${lu##* }
|
|
|
|
if [[ "${proprietaire}" != "${UTILISATEUR}" || "${mode}" != "600" ]]; then
|
|
echo "La cle de la voute du site est exposee : ${CLE} appartient a « ${proprietaire} » en mode ${mode} (attendu ${UTILISATEUR}, 600). Qui la lit ouvre toute la fabric."
|
|
exit 2
|
|
fi
|
|
|
|
echo "Runner du site : carte en place, voute chiffree, cle a ${UTILISATEUR} en 600."
|
|
exit 0
|