Recette d'acceptation : make valider (phase 4, v1)
Vérifie que les services FONCTIONNENT, pas juste qu'ils sont déployés — complète les *-verifier (statiques, sur le plan) par une recette fonctionnelle vivante. playbooks/valider.yml (lecture seule) : - Prometheus : toutes les cibles de supervision UP (API /targets) - Edge : les vhosts HTTPS exposés répondent (server_name réels filtrés sur domaine_interne, statut sain 200/301/302/401/403) Éprouvé sur la flotte : 7 cibles UP, 8 vhosts OK (sous pare-feu actif). À venir : courriel bout-en-bout (envoi->IMAP), restauration de sauvegarde. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f05f505b88
commit
77dcc72aa6
3 changed files with 80 additions and 0 deletions
|
|
@ -3,6 +3,12 @@
|
||||||
## 2026-07-07
|
## 2026-07-07
|
||||||
|
|
||||||
### Ajouté
|
### Ajouté
|
||||||
|
- **`make valider` — recette d'acceptation fonctionnelle (phase 4, v1).** Vérifie que les services
|
||||||
|
*fonctionnent*, pas juste qu'ils sont déployés (complète les `*-verifier` statiques). `playbooks/valider.yml`,
|
||||||
|
lecture seule : **cibles Prometheus toutes UP** (API `/targets`) + **vhosts HTTPS exposés répondent**
|
||||||
|
(dérivés des `server_name` réels de l'edge, filtrés sur `domaine_interne` — générique). Éprouvé sur la
|
||||||
|
flotte vivante : 7 cibles UP, 8 vhosts OK (via l'edge, sous pare-feu actif). À venir : courriel
|
||||||
|
bout-en-bout (envoi→IMAP), restauration de sauvegarde.
|
||||||
- **Pare-feu nftables activé sur TOUTE la flotte (14 nœuds, activation prudente).** Les 14 hôtes
|
- **Pare-feu nftables activé sur TOUTE la flotte (14 nœuds, activation prudente).** Les 14 hôtes
|
||||||
actifs tournent sous `policy drop` avec leur ruleset **résolu moindre-privilège** (flux est-ouest
|
actifs tournent sous `policy drop` avec leur ruleset **résolu moindre-privilège** (flux est-ouest
|
||||||
déclarés autorisés par source, reste refusé). Vérifié en conditions réelles : flux déclarés OPEN
|
déclarés autorisés par source, reste refusé). Vérifié en conditions réelles : flux déclarés OPEN
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -308,6 +308,10 @@ flux: ansible-runtime
|
||||||
flux-verifier:
|
flux-verifier:
|
||||||
python3 scripts/resoudre_flux.py verifier
|
python3 scripts/resoudre_flux.py verifier
|
||||||
|
|
||||||
|
.PHONY: valider
|
||||||
|
valider: ansible-runtime
|
||||||
|
ansible-playbook -i $(INVENTAIRE_PRODUCTION) playbooks/valider.yml
|
||||||
|
|
||||||
.PHONY: wiki-publier
|
.PHONY: wiki-publier
|
||||||
wiki-publier:
|
wiki-publier:
|
||||||
@set -e; \
|
@set -e; \
|
||||||
|
|
|
||||||
70
playbooks/valider.yml
Normal file
70
playbooks/valider.yml
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
# make valider — RECETTE D'ACCEPTATION : les services FONCTIONNENT (pas juste déployés).
|
||||||
|
# Lecture seule / faible impact. Complète les *-verifier (statiques, sur le plan)
|
||||||
|
# et verifier-hote (niveau hôte) par une vérif FONCTIONNELLE de bout en bout.
|
||||||
|
#
|
||||||
|
# v1 : cibles Prometheus UP + endpoints HTTPS exposés répondent.
|
||||||
|
# À venir : courriel bout-en-bout (envoi→IMAP), restauration de sauvegarde.
|
||||||
|
|
||||||
|
- name: "Recette — Prometheus : toutes les cibles de supervision UP"
|
||||||
|
hosts: serveur_prometheus
|
||||||
|
gather_facts: false
|
||||||
|
become: false
|
||||||
|
tasks:
|
||||||
|
- name: Interroger l'API des cibles actives
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: "http://localhost:9090/api/v1/targets?state=active"
|
||||||
|
return_content: true
|
||||||
|
register: prom_targets
|
||||||
|
|
||||||
|
- name: Analyser up / down
|
||||||
|
vars:
|
||||||
|
cibles: "{{ (prom_targets.content | from_json).data.activeTargets }}"
|
||||||
|
en_panne: "{{ cibles | rejectattr('health', 'equalto', 'up') | list }}"
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
recette_prom_total: "{{ cibles | length }}"
|
||||||
|
recette_prom_down: "{{ en_panne | map(attribute='labels.instance') | list }}"
|
||||||
|
|
||||||
|
- name: "✔ Prometheus"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: "recette_prom_down | length == 0"
|
||||||
|
success_msg: "OK — {{ recette_prom_total }} cibles, toutes UP."
|
||||||
|
fail_msg: "ÉCHEC — cibles DOWN : {{ recette_prom_down }}"
|
||||||
|
|
||||||
|
- name: "Recette — Edge : les vhosts HTTPS exposés répondent"
|
||||||
|
hosts: serveur_nginx
|
||||||
|
gather_facts: false
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Lister les valeurs de la directive server_name (première colonne exacte)
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: >-
|
||||||
|
nginx -T 2>/dev/null | awk '$1=="server_name"{for(i=2;i<=NF;i++){gsub(/;/,"",$i);
|
||||||
|
print $i}}' | sort -u
|
||||||
|
register: recette_server_names
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Retenir les vhosts du domaine interne (exclut défauts/placeholders)
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
recette_fqdns: >-
|
||||||
|
{{ recette_server_names.stdout_lines
|
||||||
|
| select('search', '\.' ~ (domaine_interne | regex_escape) ~ '$') | list }}
|
||||||
|
|
||||||
|
- name: Interroger chaque vhost exposé en HTTPS (via l'edge)
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: "https://{{ item }}/"
|
||||||
|
validate_certs: false
|
||||||
|
status_code: [200, 301, 302, 401, 403]
|
||||||
|
follow_redirects: none
|
||||||
|
timeout: 10
|
||||||
|
loop: "{{ recette_fqdns }}"
|
||||||
|
register: recette_http
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: "✔ Endpoints HTTPS"
|
||||||
|
vars:
|
||||||
|
echecs: "{{ recette_http.results | rejectattr('status', 'in', [200, 301, 302, 401, 403]) | list }}"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: "echecs | length == 0"
|
||||||
|
success_msg: "OK — {{ recette_http.results | length }} vhosts répondent : {{ recette_fqdns }}"
|
||||||
|
fail_msg: "ÉCHEC — vhosts KO : {{ echecs | map(attribute='item') | list }} (statuts {{ echecs | map(attribute='status') | list }})"
|
||||||
Loading…
Reference in a new issue