#jinja2: comment_start_string:'{=#', comment_end_string:'#=}' #!/bin/bash # (Le gabarit redefinit le delimiteur de commentaire Jinja : `${#tableau[@]}` contient # la sequence `{#`, que Jinja lirait comme un debut de commentaire. Le shell en a # besoin ; c'est donc Jinja qui cede. Meme geste que `client_sante/setops-sante.sh.j2` # et `serveur_nginx/sonde-edge.sh.j2`.) # GENERE par Set-OPS (role serveur_resolveur_site). Ne pas editer a la main. # # SONDE « resolution-locataires » — les locataires peuvent-ils encore resoudre ici ? # # PAS UNE ENVELOPPE DE GREFFON. Ce qu'on mesure ici n'a pas d'equivalent standard : « le # resolveur accepte-t-il encore de repondre AUX RESEAUX DES TENANTS », et « repond-il a # l'adresse ou ils frappent ». La mesurer depuis la machine elle-meme est le seul endroit # ou on peut la lire sans traverser la frontiere. set -uo pipefail # LA LISTE ATTENDUE EST DERIVEE DU PLAN DU SITE, pas ecrite ici. C'est le meme calcul que # l'assertion de `tasks/main.yml` — et c'est voulu : la sonde n'est pas un second avis, # c'est la MEME exigence, rejouee quand plus personne ne regarde. attendus=({% for s in serveur_resolveur_site_supernets_tenants | default([]) %}'{{ s }}' {% endfor %}) CONF={{ serveur_resolveur_site_sonde_config }} TEMOIN='{{ serveur_resolveur_site_sonde_nom }}' ADRESSE='{{ serveur_resolveur_site_sonde_adresse }}' if (( ${#attendus[@]} == 0 )); then # PAS UN SUCCES DEGUISE. Un site sans locataire declare est un etat legitime — mais le # dire est preferable a rendre un vert qui laisserait croire qu'on a verifie quelque # chose. echo "Aucun supernet de locataire declare au plan du site : rien a verifier ici." exit 0 fi # 1. CHAQUE SUPERNET DE LOCATAIRE EST-IL ENCORE ADMIS ? # # On lit la configuration POSEE, pas celle qu'on croit avoir posee. `unbound-control` ne # rend pas la liste d'acces ; les fichiers, si — et ce sont eux qu'Unbound a charges. manquants=() for reseau in "${attendus[@]}"; do grep -rhqE "^[[:space:]]*access-control:[[:space:]]+${reseau//./\\.}[[:space:]]+allow" "${CONF}" 2>/dev/null \ || manquants+=("${reseau}") done if (( ${#manquants[@]} > 0 )); then echo "Locataire(s) non admis a resoudre ici : ${manquants[*]}. Leur amorcage lira « Echec temporaire dans la resolution du nom » — le message d'un DNS mort." exit 2 fi # 2. ET REPOND-IL A L'ADRESSE OU LES LOCATAIRES FRAPPENT ? # # CE N'EST PAS LA SONDE `resolution` DE `serveur_resolveur` REJOUEE. Celle-la interroge # 127.0.0.1 : elle dit « unbound traduit ». Un locataire, lui, frappe l'adresse de # l'interface — et une ecoute peut changer sans que la boucle locale bouge. On l'a deja # paye ailleurs : un `reload` ne reapplique PAS un changement d'adresse d'ecoute, et le # service reste vert depuis sa propre machine. # # POURQUOI `dig` ET PAS `check_dns`. Le greffon existe, mais dans # `monitoring-plugins-standard` — et ce paquet traine samba, smbclient et une pile SNMP # sur CHAQUE machine de la flotte (mesure du 2026-09-14). `client_sante` installe # `monitoring-plugins-basic`, 53 greffons, qui ne contient pas `check_dns`. Un greffon # absent sort en 127, ce qui n'est pas un code Nagios : la sonde deviendrait illisible. # `dig` vient de `dnsutils`, deja present sur un resolveur, et c'est ce qu'emploie # `resolution.sh` a cote. if ! dig +short +time=5 +tries=2 "@${ADRESSE}" "${TEMOIN}" A 2>/dev/null | grep -qE '.'; then echo "Les ${#attendus[@]} locataires sont admis, mais rien ne se traduit a ${ADRESSE} — l'adresse ou ils frappent. La boucle locale peut tres bien repondre encore." exit 2 fi echo "Resolveur du site : ${#attendus[@]} supernet(s) de locataire admis, et « ${TEMOIN} » se resout a ${ADRESSE}." exit 0