vigie : sa base dans tous les modes ; trois restes du site corrigés
- serveur_icingaweb2 : base de console résolue et utilisée en SSO comme en db (config_backend db) ; le badge de migrations la réclame sans condition - serveur_icingaweb2 : php8.4-fpm et nginx avant les paquets tiers ; apache2 retiré s'il part seul (apt-get -s purge) - serveur_nginx : ssl_protocols de Debian neutralisé (doublon à chaque reload) - site_inventaire : les hyperviseurs ne reçoivent plus le cache du site ni ses amorçages, qu'ils n'atteignent pas - exemple de voûte : vault_bd_icingaweb2 dans tous les modes ; CHANGELOG 64 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2f275d8a7d
commit
f11bb11ad7
8 changed files with 143 additions and 18 deletions
56
CHANGELOG.md
56
CHANGELOG.md
|
|
@ -1,5 +1,61 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-10-03 (64) — La vigie a sa base partout ; trois restes du site corrigés
|
||||
|
||||
**Demande de l'exploitant** : traiter les points 3 et 5 du rapport d'anomalies.
|
||||
|
||||
**3. Icinga Web sans base chez les locataires.** Depuis leur reconstruction, la vigie de
|
||||
Chezlepro journalisait 145 fois par heure, page ouverte, « Failed to load pending
|
||||
migrations : Please check if a db instance exists at all » ; Technolibre de même dès qu'on la
|
||||
regardait. Le site avait reçu sa base le 2026-09-15, mais seulement en mode `db` ; les
|
||||
locataires, en SSO, étaient restés en `config_backend = "ini"`. Lu dans le code
|
||||
d'Icinga Web : `ConfigMenu::createMigrationBadge` compte les migrations SANS condition de
|
||||
permission — aucun réglage de rôle ne le fait taire. **Fait** : `serveur_icingaweb2` résout
|
||||
et utilise sa base dans TOUS les modes (`config_backend = "db"`, ressource `icingaweb_db`,
|
||||
schéma chargé une fois) ; les comptes en base et le compte d'amorçage restent propres au
|
||||
mode `db`. Base `icingaweb2` ajoutée aux plans de Chezlepro, Technolibre, du lab et des
|
||||
deux modèles qui portent une vigie (`observabilite`, `integral`) ; `vault_bd_icingaweb2`
|
||||
aux gabarits de voûte et à l'exemple public. **Reste à l'exploitant** : la valeur réelle
|
||||
dans trois voûtes (l'écriture a été refusée à l'assistant), puis le déploiement chez les
|
||||
deux locataires (`serveur_postgresql`, `serveur_icingaweb2`, `serveur_ops_tenant` pour
|
||||
que le runner reçoive la voûte). Les préférences déjà rangées en fichiers ne sont pas
|
||||
reprises : ce ne sont que des réglages d'affichage.
|
||||
|
||||
**5a. Le cache du site donné aux hyperviseurs, qui ne l'atteignent pas.** Mesuré depuis
|
||||
asgard : `10.37.33.21:3142` injoignable. Or `artefacts_amorcage` leur était transmis par
|
||||
`communes` : un passage de `client_journal` aurait réécrit leur dépôt Grafana en `http://`
|
||||
par ce mandataire, et apt l'aurait perdu. **Fait** : `site_inventaire.py` ne leur donne plus
|
||||
ni `artefacts_amorcage`, ni `setops_depot_binaires`, ni `dns_amorcage` (son jumeau, P79) —
|
||||
amorçages d'une VM née du gabarit, qu'aucun rôle des hyperviseurs ne lit. Simulé : un passage
|
||||
de `client_journal` n'y change plus que la config Alloy.
|
||||
|
||||
**5b. apache2 sur `site-mon-01`.** Tiré par `libapache2-mod-php8.4`, dont plus rien ne
|
||||
dépendait : au site, les paquets d'Icinga viennent du cache du contrôleur et s'installaient
|
||||
AVANT `php8.4-fpm`, et apt prenait la première alternative PHP. Les locataires, en une seule
|
||||
transaction, n'avaient pas ce reste. **Fait** : `php8.4-fpm` et nginx posés avant les
|
||||
paquets tiers ; apache2 retiré seulement si `apt-get -s purge` confirme qu'il part seul.
|
||||
Appliqué : 0 paquet apache, port 80 fermé, vigie en 302.
|
||||
|
||||
**5c. Grafana Live sans WebSocket.** Chaque page de l'observatoire journalisait
|
||||
`GET /api/live/ws` en 400, au site comme chez les locataires : l'edge relayait sans
|
||||
`Upgrade`. Le mécanisme existait (Collabora) ; Grafana ne le déclarait pas. **Fait** :
|
||||
`websocket: true` sur `grafana` dans les six plans qui le portent (site, deux locataires,
|
||||
lab, deux modèles). Appliqué au site : la poignée WebSocket atteint Grafana (401 sans
|
||||
session, au lieu de 400).
|
||||
|
||||
**5d. `ssl_protocols` en double.** Le `nginx.conf` de Debian le déclare déjà ;
|
||||
`99-setops.conf` le répétait au même niveau — `duplicate value "TLSv1.3"` à chaque
|
||||
rechargement. **Fait** : la ligne de Debian est neutralisée, comme `server_tokens` avant
|
||||
elle. Appliqué au site : `nginx -t` sans avertissement.
|
||||
|
||||
**Validation** : `ansible-lint` (0 violation), `make verifier` conforme sur Chezlepro (83/83)
|
||||
et preuves conformes sur Technolibre (82 + 1 sautée, la voûte) ; `voute.py verifier` complet
|
||||
pour les deux. Au site : simulé puis appliqué, 0 échec.
|
||||
|
||||
**Fuite à signaler** : en lisant la config d'Icinga Web de Chezlepro, l'assistant a affiché
|
||||
en clair le mot de passe de liaison LDAP `cn=icingaweb2` (`bind_pw` n'était pas masqué). Il
|
||||
n'est écrit nulle part ailleurs que dans la conversation ; une rotation est recommandée.
|
||||
|
||||
## 2026-10-03 (63) — Les locataires mesurés et corrigés : même bruit, et le courriel en ajoute
|
||||
|
||||
**Demande de l'exploitant** : mesurer chez les deux locataires les défauts corrigés au site
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ vault_postgresql_keycloak: ""
|
|||
vault_bd_keycloak: ""
|
||||
vault_bd_forgejo: ""
|
||||
vault_bd_icingadb: ""
|
||||
# La base des COMPTES de la console (mode `db`) — distincte de celle du moteur.
|
||||
# La base de la console (vigie) dans tous les modes : comptes en mode `db`, préférences
|
||||
# et migrations partout — distincte de celle du moteur.
|
||||
vault_bd_icingaweb2: ""
|
||||
|
||||
# --- Forge (Forgejo) ---
|
||||
|
|
|
|||
|
|
@ -16,6 +16,19 @@ serveur_icingaweb2_paquets:
|
|||
- php8.4-mbstring
|
||||
- nginx
|
||||
|
||||
# INSTALLES AVANT LES PAQUETS TIERS, pour qu'apt ne choisisse pas apache2 (voir tasks).
|
||||
serveur_icingaweb2_web_prealables:
|
||||
- php8.4-fpm
|
||||
- nginx
|
||||
|
||||
# Ce qu'un ordre d'installation fautif a laisse, et que le role retire s'il part seul.
|
||||
serveur_icingaweb2_apache_restes:
|
||||
- apache2
|
||||
- apache2-bin
|
||||
- apache2-data
|
||||
- apache2-utils
|
||||
- libapache2-mod-php8.4
|
||||
|
||||
serveur_icingaweb2_php_fpm_service: "php8.4-fpm"
|
||||
serveur_icingaweb2_php_fpm_socket: "/run/php/php8.4-fpm.sock"
|
||||
serveur_icingaweb2_nginx_service: "nginx"
|
||||
|
|
|
|||
|
|
@ -52,7 +52,13 @@
|
|||
name: resoudre_base
|
||||
vars:
|
||||
resoudre_base_groupe: "icingaweb2"
|
||||
when: serveur_icingaweb2_auth == 'db'
|
||||
# DANS TOUS LES MODES (2026-10-03), plus seulement `db`. Le cadre de migration d'Icinga
|
||||
# Web 2 veut une base quoi qu'il arrive : sans elle, chaque page qui affiche le menu de
|
||||
# configuration journalise « Failed to load pending migrations : Please check if a db
|
||||
# instance exists at all » — 145 fois par heure chez Chezlepro, vigie ouverte, depuis
|
||||
# la reconstruction. Le site avait recu sa base le 2026-09-15 ; les locataires, en SSO,
|
||||
# etaient restes sans. Le badge est calcule sans condition de permission
|
||||
# (`ConfigMenu::createMigrationBadge`) : aucun reglage de role ne le fait taire.
|
||||
|
||||
- name: Adopter la base des comptes pour Icinga Web 2
|
||||
ansible.builtin.set_fact:
|
||||
|
|
@ -62,7 +68,6 @@
|
|||
serveur_icingaweb2_db_utilisateur: "{{ resoudre_base_entree.proprietaire }}"
|
||||
serveur_icingaweb2_db_motdepasse: "{{ resoudre_base_db_password }}"
|
||||
no_log: true
|
||||
when: serveur_icingaweb2_auth == 'db'
|
||||
|
||||
- name: Exiger un mot de passe pour le compte d'amorçage
|
||||
ansible.builtin.assert:
|
||||
|
|
@ -76,7 +81,7 @@
|
|||
|
||||
# LE SCHEMA NE SE CHARGE QU'UNE FOIS. Le rejouer sur une base deja peuplee echouerait sur
|
||||
# les objets existants — on lit donc d'abord si la table des comptes est la.
|
||||
- name: La base des comptes est-elle déjà en place ?
|
||||
- name: La base de la console est-elle déjà en place ?
|
||||
community.postgresql.postgresql_query:
|
||||
login_host: "{{ serveur_icingaweb2_db_host }}"
|
||||
login_user: "{{ serveur_icingaweb2_db_utilisateur }}"
|
||||
|
|
@ -89,10 +94,9 @@
|
|||
changed_when: false
|
||||
no_log: true
|
||||
when:
|
||||
- serveur_icingaweb2_auth == 'db'
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Charger le schéma des comptes
|
||||
- name: Charger le schéma de la console (comptes, préférences, migrations)
|
||||
community.postgresql.postgresql_script:
|
||||
login_host: "{{ serveur_icingaweb2_db_host }}"
|
||||
login_user: "{{ serveur_icingaweb2_db_utilisateur }}"
|
||||
|
|
@ -103,7 +107,6 @@
|
|||
path: "{{ serveur_icingaweb2_schema }}"
|
||||
no_log: true
|
||||
when:
|
||||
- serveur_icingaweb2_auth == 'db'
|
||||
- not ansible_check_mode
|
||||
- not (serveur_icingaweb2_schema_etat.query_result[0].presente | default(false))
|
||||
|
||||
|
|
@ -192,6 +195,18 @@
|
|||
# `Acquire::https::Proxy "DIRECT"` — ils CONTOURNENT donc le cache du site et sortent sur
|
||||
# Internet a chaque construction de VM. `make cacher-paquets` les tire une fois, versions
|
||||
# epinglees et empreintes verifiees ; ce role les depose depuis ce cache.
|
||||
# PHP-FPM ET NGINX AVANT LES PAQUETS TIERS (2026-10-03). Les paquets d'Icinga exigent
|
||||
# « un PHP pour le web », et apt choisit la PREMIERE alternative qu'aucun paquet present ne
|
||||
# satisfait : `libapache2-mod-php`, qui tire apache2. Chez les locataires, tout s'installe
|
||||
# en une transaction avec `php8.4-fpm`, et apt n'a pas a choisir. Au site, les paquets
|
||||
# tiers viennent du cache du controleur, SEULS, avant le reste : `site-mon-01` portait un
|
||||
# apache2 ecoutant sur le port 80 depuis le 2026-09-14, que rien n'utilisait.
|
||||
- name: Installer PHP-FPM et nginx avant les paquets tiers (sinon apt choisit apache2)
|
||||
ansible.builtin.apt:
|
||||
name: "{{ serveur_icingaweb2_web_prealables }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Poser les paquets tiers depuis le cache du controleur
|
||||
ansible.builtin.include_role:
|
||||
name: paquets_tiers
|
||||
|
|
@ -211,6 +226,27 @@
|
|||
when: (serveur_icingaweb2_paquets
|
||||
| difference((paquets_tiers_disponibles | default({})).keys() | list)) | length > 0
|
||||
|
||||
# LE RESTE D'UNE INSTALLATION DANS LE MAUVAIS ORDRE (voir plus haut). On ne le retire que
|
||||
# si apt confirme qu'il part SEUL : `state: absent` emporterait aussi tout paquet qui en
|
||||
# dependrait, et ce role n'a pas a decider de leur sort.
|
||||
- name: Simuler le retrait d'apache2 (rien d'autre ne doit partir)
|
||||
ansible.builtin.command:
|
||||
argv: "{{ ['apt-get', '-s', 'purge'] + serveur_icingaweb2_apache_restes }}"
|
||||
register: serveur_icingaweb2_apache_simulation
|
||||
changed_when: false
|
||||
check_mode: false
|
||||
|
||||
- name: Retirer apache2, que rien n'utilise
|
||||
ansible.builtin.apt:
|
||||
name: "{{ serveur_icingaweb2_apache_restes }}"
|
||||
state: absent
|
||||
purge: true
|
||||
when:
|
||||
- serveur_icingaweb2_apache_simulation.stdout_lines | select('match', '^(Purg|Remv) ') | list | length > 0
|
||||
- (serveur_icingaweb2_apache_simulation.stdout_lines | select('match', '^(Purg|Remv) ')
|
||||
| map('regex_replace', '^(?:Purg|Remv) (\\S+).*$', '\\1') | list)
|
||||
is subset(serveur_icingaweb2_apache_restes)
|
||||
|
||||
- name: Ajouter www-data au groupe icingaweb2 (lecture de la config)
|
||||
ansible.builtin.user:
|
||||
name: www-data
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
; Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main.
|
||||
[global]
|
||||
show_stacktraces = "0"
|
||||
{% if serveur_icingaweb2_auth == 'db' %}
|
||||
; LA CONSOLE RANGE SON PROPRE ETAT DANS SA PROPRE BASE (2026-09-15).
|
||||
; LA CONSOLE RANGE SON PROPRE ETAT DANS SA PROPRE BASE (2026-09-15 au site, 2026-10-03
|
||||
; partout : les locataires en SSO etaient restes en `ini`, avec la premiere erreur ci-dessous).
|
||||
;
|
||||
; `config_backend = "ini"` laissait les preferences en fichiers, et c'etait tenable — mais
|
||||
; le cadre de MIGRATION d'Icinga Web 2, lui, veut une instance de base quoi qu'il arrive.
|
||||
|
|
@ -19,9 +19,6 @@ show_stacktraces = "0"
|
|||
; d'un navigateur a l'autre, ce que des fichiers locaux ne font pas.
|
||||
config_backend = "db"
|
||||
config_resource = "icingaweb_db"
|
||||
{% else %}
|
||||
config_backend = "ini"
|
||||
{% endif %}
|
||||
|
||||
[logging]
|
||||
log = "syslog"
|
||||
|
|
|
|||
|
|
@ -18,11 +18,10 @@ charset = "UTF8"
|
|||
ssl_mode = "{{ serveur_icingaweb2_db_sslmode }}"
|
||||
ssl_ca = "{{ serveur_icingaweb2_db_sslrootcert }}"
|
||||
{% endif %}
|
||||
{% if serveur_icingaweb2_auth == 'db' %}
|
||||
|
||||
; LA BASE DES COMPTES DE LA CONSOLE — distincte d'`icingadb`, qui est celle du MOTEUR.
|
||||
; Meler les deux ferait disparaitre les comptes au premier passage des migrations du
|
||||
; moteur, sans que personne n'ait touche aux comptes.
|
||||
; LA BASE DE LA CONSOLE — distincte d'`icingadb`, qui est celle du MOTEUR. Dans tous les
|
||||
; modes : comptes en mode `db`, preferences et migrations partout. Meler les deux bases
|
||||
; ferait disparaitre les comptes au premier passage des migrations du moteur.
|
||||
[icingaweb_db]
|
||||
type = "db"
|
||||
db = "pgsql"
|
||||
|
|
@ -36,7 +35,6 @@ charset = "UTF8"
|
|||
ssl_mode = "{{ serveur_icingaweb2_db_sslmode }}"
|
||||
ssl_ca = "{{ serveur_icingaweb2_db_sslrootcert }}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if serveur_icingaweb2_auth not in ('db',) %}
|
||||
|
||||
[icingaweb_ldap]
|
||||
|
|
|
|||
|
|
@ -16,6 +16,18 @@
|
|||
replace: '\1# server_tokens gere par Set-OPS (conf.d/99-setops.conf)'
|
||||
notify: Valider et recharger nginx
|
||||
|
||||
# MEME CAS POUR `ssl_protocols` (2026-10-03), mais sans echec : nginx ACCEPTE la directive
|
||||
# deux fois au meme niveau, ajoute les valeurs, et avertit a chaque rechargement —
|
||||
# `duplicate value "TLSv1.3" in /etc/nginx/conf.d/99-setops.conf:3`, releve dans le journal
|
||||
# de `site-edge-01`. Un avertissement repete est un avertissement qu'on cesse de lire ; et
|
||||
# la politique TLS doit avoir UNE source, la notre.
|
||||
- name: Neutraliser le ssl_protocols par defaut de Debian
|
||||
ansible.builtin.replace:
|
||||
path: /etc/nginx/nginx.conf
|
||||
regexp: '^(\s*)ssl_protocols\s+[^;]+;.*$'
|
||||
replace: '\1# ssl_protocols gere par Set-OPS (conf.d/99-setops.conf)'
|
||||
notify: Valider et recharger nginx
|
||||
|
||||
- name: Deployer le durcissement de base nginx
|
||||
ansible.builtin.template:
|
||||
src: 99-setops.conf.j2
|
||||
|
|
|
|||
|
|
@ -962,7 +962,19 @@ def inventaire() -> dict:
|
|||
# sert pour l'identite de noeud du cluster.
|
||||
**({"client_journal_loki_url":
|
||||
f"http://{_ip_loki}:3100/loki/api/v1/push"} if _ip_loki else {}),
|
||||
**communes,
|
||||
# NI LE CACHE DU SITE NI SES AMORCAGES (2026-10-03). `communes` le donne a toute machine du
|
||||
# site ; un hyperviseur ne l'atteint pas — mesure depuis asgard :
|
||||
# `10.37.33.21:3142` injoignable, par la frontiere comme tout le reste. Avec
|
||||
# `artefacts_amorcage`, `client_journal` aurait reecrit sa source Grafana en
|
||||
# `http://` par ce mandataire, et apt aurait perdu le depot. Sans lui, la
|
||||
# source reste `https://apt.grafana.com`, celle qui marche. Le depot de
|
||||
# binaires passe par le meme cache : meme raison.
|
||||
#
|
||||
# `dns_amorcage` part avec eux, son jumeau (P79) : les deux amorcent la PREMIERE
|
||||
# mise en route d'une VM nee du gabarit, et un hyperviseur n'en nait pas. Aucun
|
||||
# role qu'il recoit ne le lit.
|
||||
**{k: v for k, v in communes.items()
|
||||
if k not in ("artefacts_amorcage", "setops_depot_binaires", "dns_amorcage")},
|
||||
}
|
||||
groupes.setdefault("hyperviseurs", []).append(_nom)
|
||||
# ON TIRE, ON NE POUSSE PAS — ET C'EST LA ROUTE GELEE QUI LE DECIDE (2026-09-10).
|
||||
|
|
|
|||
Loading…
Reference in a new issue