Set-OPS-Public/roles/serveur_dns_public/templates/sonde-zones-publiques.sh.j2
Daniel Allaire 712ad9f630 DNSSEC : le locataire signe, avec la cle de sa voute
Cle CSK ECDSA P-256 tiree dans la voute du locataire, importee par le role, DS calcule
sans la machine. Refus de changer la cle ou de retirer la signature tant qu'un DS est
publie. SOA-EDIT EPOCH : INCEPTION-EPOCH aurait laisse expirer les signatures du site.
CAA sur chezlepro.ca, sonde des signatures au site, P18 deplie vault_dnssec_<zone>.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 22:09:21 -04:00

62 lines
3 KiB
Django/Jinja

#!/bin/bash
# GENERE par Set-OPS (role serveur_dns_public). Ne pas editer a la main.
#
# SONDE « zones-publiques » — le serveur public sert-il TOUTES les zones qu'il doit servir ?
#
# Contrat : docs/supervision-conception.md (API des greffons Nagios) — une ligne, 0/1/2.
# Mise en defaut PAR PARAMETRE : `serveur_dns_public_sonde_attendu` (seuil impossible).
set -uo pipefail
ATTENDU={{ serveur_dns_public_sonde_attendu }}
ICI={{ serveur_dns_public_ecoute }}
systemctl is-active --quiet pdns || { echo "Le serveur DNS public (pdns) n'est pas actif."; exit 2; }
# ON INTERROGE CE QUE LE MONDE INTERROGERA : le SOA de chaque zone, sur l'adresse d'ecoute.
# Un secondaire qui n'a jamais recu sa zone repond REFUSED ou SERVFAIL — ce qui, vu d'un
# registraire, se lit « serveur de noms defaillant ».
servies=0
manquantes=()
{% for zone in serveur_dns_public_relations | map(attribute='zones') | flatten %}
if [[ -n "$(dig +short +time=3 +tries=1 @"${ICI}" -p {{ serveur_dns_public_port }} SOA {{ zone }} 2>/dev/null)" ]]; then
servies=$((servies + 1))
else
manquantes+=("{{ zone }}")
fi
{% endfor %}
# LES SIGNATURES DES ZONES SIGNEES (2026-09-16). Le primaire du locataire renouvelle ses
# signatures chaque semaine ; son serial servi est l'heure (SOA-EDIT EPOCH), et le site
# retire la zone a chaque rafraichissement. Si ce relais casse, rien ne tombe tout de suite :
# les signatures servies EXPIRENT, en 7 a 14 jours, et le domaine devient BOGUS d'un coup.
# Normalement il reste entre 7 et 14 jours ; on avertit sous 6, on alerte sous 3.
maintenant=$(date -u +%s)
alerte=()
avert=()
{% for zone in serveur_dns_public_relations | map(attribute='signees') | map('default', []) | flatten %}
exp=$(dig +dnssec +noall +answer +time=3 +tries=1 @"${ICI}" -p {{ serveur_dns_public_port }} SOA {{ zone }} 2>/dev/null | awk '$4 == "RRSIG" { print $9; exit }')
if [[ -z "$exp" ]]; then
alerte+=("{{ zone }} (non signee)")
else
jours=$(( ( $(date -u -d "${exp:0:8} ${exp:8:2}:${exp:10:2}:${exp:12:2}" +%s) - maintenant ) / 86400 ))
if (( jours < 3 )); then alerte+=("{{ zone }} (${jours} j)")
elif (( jours < 6 )); then avert+=("{{ zone }} (${jours} j)"); fi
fi
{% endfor %}
if (( servies < ATTENDU )); then
echo "Le serveur public ne sert que ${servies} zone(s) sur ${ATTENDU} : ${manquantes[*]:-?} — ces domaines ne resolvent plus depuis Internet.|zones=${servies};${ATTENDU};;0;"
exit 2
fi
{# `${#tableau[@]}` ouvrirait un commentaire Jinja : ces lignes sont rendues telles quelles. #}
{% raw %}
if (( ${#alerte[@]} > 0 )); then
echo "Signatures DNSSEC absentes ou sur le point d'expirer : ${alerte[*]} — ces domaines deviennent BOGUS pour les resolveurs validants.|zones=${servies};${ATTENDU};;0;"
exit 2
fi
if (( ${#avert[@]} > 0 )); then
echo "Signatures DNSSEC qui ne se renouvellent plus : ${avert[*]} — le primaire du locataire relaie-t-il encore ?|zones=${servies};${ATTENDU};;0;"
exit 1
fi
{% endraw %}
echo "Serveur public : ${servies} zone(s) servie(s) sur ${ATTENDU}, signatures a jour.|zones=${servies};${ATTENDU};;0;"