diff --git a/CHANGELOG.md b/CHANGELOG.md index d73868f..e4d1b9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,17 @@ est **autoritatif, pas récursif** — pour que les nœuds *utilisent* ces A sans casser la résolution Internet, il faut un **récursif** (pdns-recursor : forward de la zone interne + récursion du reste) ou garder le plancher `/etc/hosts`. Ne PAS repointer naïvement `client_dns` vers l'autoritatif. +- **`hosts_statiques` — alias d'exposition dans le plancher `/etc/hosts` (résolution client, sûre).** + Le plancher pose désormais, sur **chaque nœud**, ` ` pour chaque `expose` + (dérivé de `domaines.edge`, même source que nginx/PowerDNS). Indépendant du DNS, aucun risque de + couper la résolution (choix retenu vs pdns-recursor). Chargement du plan **best-effort** + (`stat` **`delegate_to: localhost`** + `become: false` — les registres vivent sur le nœud de + contrôle ; ignoré si le plan est absent, ex. préparation du template). **Prouvé** : `/etc/hosts` + d'obs-01 régénéré avec `keycloak`/`grafana` → edge (ligne manuelle éliminée), `getent` OK, et le + **flux SSO Grafana fonctionne via la résolution du plancher** (`login: testmail`). Boucle Phase 3 + fermée : déclarer `expose` → **vhost + SAN cert + A PowerDNS + alias plancher**, tout dérivé. + Bugs corrigés en chemin : `serveur_loki` (groupe `loki` manquant), `stat` sur cible→contrôle, + `become` inutile sur le contrôle. - **Bindings — Phase 1 : résolveur de liens dans `instancier.py` (relations service→service déclaratives).** Une application déclare ses `liens: [{vers, role}]` dans `plan/applications.yml` ; chaque rôle décrit les liens qu'il accepte dans `meta/liens.yml` diff --git a/roles/hosts_statiques/defaults/main.yml b/roles/hosts_statiques/defaults/main.yml index f63ee06..073799a 100644 --- a/roles/hosts_statiques/defaults/main.yml +++ b/roles/hosts_statiques/defaults/main.yml @@ -3,3 +3,9 @@ # serveur DNS. Permet à tout l'écosystème de se résoudre par nom même DNS éteint. hosts_statiques_actif: true hosts_statiques_domaine: "{{ domaine_interne | default('') }}" + +# Alias d'exposition : poser pour chaque application qui 'expose' +# un FQDN (domaines.edge → l'edge qui le sert). Rend la résolution des services indépendante +# du DNS. Best-effort : ignoré si le plan n'est pas disponible (ex. préparation du template). +hosts_statiques_publier_expositions: true +hosts_statiques_expositions: [] diff --git a/roles/hosts_statiques/tasks/main.yml b/roles/hosts_statiques/tasks/main.yml index 0c02055..8dc585f 100644 --- a/roles/hosts_statiques/tasks/main.yml +++ b/roles/hosts_statiques/tasks/main.yml @@ -1,4 +1,43 @@ --- +# Alias d'exposition (best-effort) : dérivés du plan si celui-ci est disponible. +- name: Vérifier la présence des registres du plan (sur le nœud de contrôle) + ansible.builtin.stat: + path: "{{ item }}" + register: hosts_statiques_plan + delegate_to: localhost # les registres du plan vivent sur le nœud de contrôle + become: false # lire un fichier ne nécessite pas de privilèges + loop: + - "{{ setops_plan_dir }}/applications.yml" + - "{{ setops_plan_dir }}/domaines.yml" + loop_control: + label: "{{ item | basename }}" + when: + - hosts_statiques_actif | bool + - hosts_statiques_publier_expositions | bool + - setops_plan_dir is defined + +- name: Charger les registres applications et domaines (si présents) + ansible.builtin.include_vars: + file: "{{ item }}" + loop: + - "{{ setops_plan_dir }}/applications.yml" + - "{{ setops_plan_dir }}/domaines.yml" + loop_control: + label: "{{ item | basename }}" + when: + - hosts_statiques_actif | bool + - hosts_statiques_publier_expositions | bool + - (hosts_statiques_plan.results | default([]) | selectattr('stat.exists', 'defined') | selectattr('stat.exists') | list | length) == 2 + +- name: Dériver les alias d'exposition (FQDN exposés → edge qui les sert) + ansible.builtin.set_fact: + hosts_statiques_expositions: >- + {{ {'applications': applications | default({})} + | expositions_des_applications({'domaines_publics': domaines_publics | default({})}) }} + when: + - hosts_statiques_actif | bool + - hosts_statiques_publier_expositions | bool + - name: Générer /etc/hosts depuis l'inventaire (plancher de résolution, indépendant du DNS) ansible.builtin.template: src: hosts.j2 diff --git a/roles/hosts_statiques/templates/hosts.j2 b/roles/hosts_statiques/templates/hosts.j2 index 169cc48..7ccdae0 100644 --- a/roles/hosts_statiques/templates/hosts.j2 +++ b/roles/hosts_statiques/templates/hosts.j2 @@ -10,3 +10,13 @@ ff02::2 ip6-allrouters {% for h in fleet if hostvars[h].ansible_host is defined %} {{ "%-15s" | format(hostvars[h].ansible_host) }} {{ h }}{{ (' ' ~ h ~ '.' ~ hosts_statiques_domaine) if hosts_statiques_domaine else '' }} {% endfor %} +{% if hosts_statiques_publier_expositions | default(false) and hosts_statiques_expositions %} + +# --- Alias d'exposition (FQDN publics → l'edge qui les sert) --- +{% for expo in hosts_statiques_expositions %} +{% set edge_hosts = groups.get(expo.edge, []) %} +{% if edge_hosts and hostvars[edge_hosts[0]].ansible_host is defined %} +{{ "%-15s" | format(hostvars[edge_hosts[0]].ansible_host) }} {{ expo.fqdn }} +{% endif %} +{% endfor %} +{% endif %}