From b3b972fb5e404facefde56aa60c3b31c776b4ddd Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Fri, 3 Jul 2026 16:57:04 -0400 Subject: [PATCH] =?UTF-8?q?serveur=5Ficingaweb2=20:=20Icinga=20Web=202=20(?= =?UTF-8?q?UI=20+=20module=20IcingaDB)=20=E2=80=94=20=C3=A9prouv=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit App PHP (php8.4-fpm) + nginx local, exposée par l'edge (auto-dérivé). Config par fichiers .ini (config/resources/authentication/roles + module icingadb), pas d'assistant. Base IcingaDB via resoudre_base. Auth LDAP direct (client_pki sur sup-01) — pas d'OIDC natif (SSO-proxy = raffinement). Prouvé : testmail (LDAP) se connecte (/dashboard), module IcingaDB affiche la supervision (hôte icinga). Déploiement failed=0 (frictions dans le simulateur curl, pas le rôle). Reste : module BPM. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 10 +++ docs/catalogue-services.md | 6 +- playbooks/groupes/serveur_icingaweb2.yml | 15 ++++ roles/serveur_icingaweb2/defaults/main.yml | 45 ++++++++++ roles/serveur_icingaweb2/handlers/main.yml | 12 +++ roles/serveur_icingaweb2/meta/empreinte.yml | 6 ++ roles/serveur_icingaweb2/tasks/main.yml | 84 +++++++++++++++++++ .../templates/authentication.ini.j2 | 7 ++ .../templates/config.ini.j2 | 9 ++ .../templates/icingadb-config.ini.j2 | 3 + .../templates/icingadb-redis.ini.j2 | 4 + .../templates/nginx.conf.j2 | 27 ++++++ .../templates/resources.ini.j2 | 20 +++++ .../serveur_icingaweb2/templates/roles.ini.j2 | 4 + 14 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 playbooks/groupes/serveur_icingaweb2.yml create mode 100644 roles/serveur_icingaweb2/defaults/main.yml create mode 100644 roles/serveur_icingaweb2/handlers/main.yml create mode 100644 roles/serveur_icingaweb2/meta/empreinte.yml create mode 100644 roles/serveur_icingaweb2/tasks/main.yml create mode 100644 roles/serveur_icingaweb2/templates/authentication.ini.j2 create mode 100644 roles/serveur_icingaweb2/templates/config.ini.j2 create mode 100644 roles/serveur_icingaweb2/templates/icingadb-config.ini.j2 create mode 100644 roles/serveur_icingaweb2/templates/icingadb-redis.ini.j2 create mode 100644 roles/serveur_icingaweb2/templates/nginx.conf.j2 create mode 100644 roles/serveur_icingaweb2/templates/resources.ini.j2 create mode 100644 roles/serveur_icingaweb2/templates/roles.ini.j2 diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5e08a..2781d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,16 @@ ## 2026-07-03 ### Ajouté +- **Rôle `serveur_icingaweb2` — Icinga Web 2 (UI native) + module IcingaDB : éprouvé.** App PHP + (php8.4-fpm) servie par un **nginx local**, exposée par l'edge (`icinga.lab.chezlepro.internal`, + auto-dérivé : vhost + cert SAN + A PowerDNS + alias plancher). Config **par fichiers `.ini`** + (config/resources/authentication/roles + module `icingadb`), pas d'assistant de setup. Base + IcingaDB via `resoudre_base` (registre). **Auth LDAP direct** vers OpenLDAP (LDAPS, `client_pki` + sur `sup-01`) — icingaweb2 n'a pas d'OIDC natif ; SSO-par-proxy = raffinement futur. **Prouvé** : + `testmail` (LDAP) se connecte (`/dashboard`), et le **module IcingaDB affiche la supervision** + (hôte `icinga`). Déploiement `failed=0` (le rôle est bon ; les frictions étaient dans le + simulateur de login curl : contrôle de cookie `_checkCookie`, champs `uid`/`submit_login`, + valeur CSRF avant `name`). **Reste de la pile Icinga : le module BPM.** - **Cœur Icinga éprouvé (supervision active).** `serveur_icinga` (cœur : `icinga2` + `icingadb` + `icingadb-redis`) déployé sur `sup-01` (🔧→⭐), base `icingadb` PostgreSQL via le registre. **Prouvé** : 3 services actifs, et le moteur **supervise** — IcingaDB peuplée (1 hôte, 12 diff --git a/docs/catalogue-services.md b/docs/catalogue-services.md index 0b4a931..9f5b312 100644 --- a/docs/catalogue-services.md +++ b/docs/catalogue-services.md @@ -43,8 +43,10 @@ Chezlepro » prouvé : `testmail` LDAP → Keycloak → Grafana). Plus **`serveu sur `forge-01`, PostgreSQL via registre, **branché au SSO OIDC** — 2e app : `testmail` se connecte, compte auto-créé). Et **`serveur_redis`** (sur `data-sql-01`, cache réseau, auth obligatoire — SET/GET prouvé, accès sans mot de passe refusé). Et le **cœur `serveur_icinga`** (sur `sup-01` : -icinga2 + icingadb + redis dédié, base PostgreSQL via registre — supervise, IcingaDB peuplée ; -**Icinga Web 2 + BPM différés**). Restent « code non éprouvé » : `serveur_sendmail`. +icinga2 + icingadb + redis dédié, base PostgreSQL via registre — supervise, IcingaDB peuplée) + +**`serveur_icingaweb2`** (UI native, PHP/nginx local, module IcingaDB, **auth LDAP** — `testmail` +se connecte et voit la supervision ; **reste le module BPM**). Restent « code non éprouvé » : +`serveur_sendmail`. > **Lacunes connues sur Keycloak** (déployé mais pas complet) : la **fédération LDAP** (Keycloak > → OpenLDAP, modèle d'identité A) n'est **pas encore automatisée** dans le rôle ; l'**edge nginx** diff --git a/playbooks/groupes/serveur_icingaweb2.yml b/playbooks/groupes/serveur_icingaweb2.yml new file mode 100644 index 0000000..e629826 --- /dev/null +++ b/playbooks/groupes/serveur_icingaweb2.yml @@ -0,0 +1,15 @@ +--- +- name: Appliquer le groupe serveur_icingaweb2 + hosts: serveur_icingaweb2 + become: true + gather_facts: true + + pre_tasks: + - name: Vérifier que la cible est Debian + ansible.builtin.assert: + that: + - ansible_facts.distribution == "Debian" + fail_msg: "Ce playbook est prévu pour Debian." + + roles: + - serveur_icingaweb2 diff --git a/roles/serveur_icingaweb2/defaults/main.yml b/roles/serveur_icingaweb2/defaults/main.yml new file mode 100644 index 0000000..802278b --- /dev/null +++ b/roles/serveur_icingaweb2/defaults/main.yml @@ -0,0 +1,45 @@ +--- +# Icinga Web 2 (UI native Icinga) + module IcingaDB, sur le nœud de supervision. +# App PHP servie par nginx local + php-fpm ; l'edge nginx proxifie par nom. +# Auth LDAP direct (OpenLDAP) — icingaweb2 n'a pas d'OIDC natif ; SSO via proxy = raffinement. +serveur_icingaweb2_paquets: + - icingadb-web # module IcingaDB (tire icingaweb2 en dépendance) + - php8.4-fpm + - php8.4-cli + - php8.4-pgsql + - php8.4-ldap + - php8.4-intl + - php8.4-gd + - php8.4-curl + - php8.4-xml + - php8.4-mbstring + - nginx + +serveur_icingaweb2_php_fpm_service: "php8.4-fpm" +serveur_icingaweb2_php_fpm_socket: "/run/php/php8.4-fpm.sock" +serveur_icingaweb2_nginx_service: "nginx" + +# Publication : nginx LOCAL sur ce port ; l'edge proxifie icinga. ici. +serveur_icingaweb2_hostname: "icinga.{{ domaine_interne }}" +serveur_icingaweb2_http_port: 8080 +serveur_icingaweb2_docroot: "/usr/share/icingaweb2/public" +serveur_icingaweb2_config_dir: "/etc/icingaweb2" + +# Base IcingaDB (via le registre — même consommateur que le moteur). +serveur_icingaweb2_icinga_groupe: "serveur_icinga" +# Redis IcingaDB (local au nœud de supervision). +serveur_icingaweb2_redis_host: "127.0.0.1" +serveur_icingaweb2_redis_port: 6380 + +# Authentification LDAP (OpenLDAP, LDAPS via la confiance step_ca / client_pki). +serveur_icingaweb2_ldap_url: "ldaps://id-ldap-01.{{ domaine_interne }}" +serveur_icingaweb2_ldap_port: 636 +serveur_icingaweb2_ldap_base: "dc={{ domaine_interne.split('.') | join(',dc=') }}" +serveur_icingaweb2_ldap_users_dn: "ou=people,dc={{ domaine_interne.split('.') | join(',dc=') }}" +serveur_icingaweb2_ldap_bind_dn: "cn=admin,dc={{ domaine_interne.split('.') | join(',dc=') }}" +serveur_icingaweb2_ldap_bind_password: "{{ vault_openldap_admin | default('') }}" +serveur_icingaweb2_ldap_user_class: "inetOrgPerson" +serveur_icingaweb2_ldap_user_attr: "uid" + +# Qui reçoit le rôle Administrateur (liste d'uid séparés par des virgules). +serveur_icingaweb2_admins: "testmail" diff --git a/roles/serveur_icingaweb2/handlers/main.yml b/roles/serveur_icingaweb2/handlers/main.yml new file mode 100644 index 0000000..f6329f3 --- /dev/null +++ b/roles/serveur_icingaweb2/handlers/main.yml @@ -0,0 +1,12 @@ +--- +- name: Redémarrer php-fpm + ansible.builtin.systemd: + name: "{{ serveur_icingaweb2_php_fpm_service }}" + state: restarted + when: not ansible_check_mode + +- name: Recharger nginx + ansible.builtin.systemd: + name: "{{ serveur_icingaweb2_nginx_service }}" + state: reloaded + when: not ansible_check_mode diff --git a/roles/serveur_icingaweb2/meta/empreinte.yml b/roles/serveur_icingaweb2/meta/empreinte.yml new file mode 100644 index 0000000..d3d3433 --- /dev/null +++ b/roles/serveur_icingaweb2/meta/empreinte.yml @@ -0,0 +1,6 @@ +--- +# Empreinte ressources — Icinga Web 2 (PHP-FPM + nginx). Co-localisé au moteur Icinga. +setops_empreinte: + coeurs: 1 + memoire_mo: 512 + disque_go: 3 diff --git a/roles/serveur_icingaweb2/tasks/main.yml b/roles/serveur_icingaweb2/tasks/main.yml new file mode 100644 index 0000000..fe3e66e --- /dev/null +++ b/roles/serveur_icingaweb2/tasks/main.yml @@ -0,0 +1,84 @@ +--- +- name: Résoudre la base IcingaDB depuis le registre (rôle partagé) + ansible.builtin.include_role: + name: resoudre_base + vars: + resoudre_base_groupe: "{{ serveur_icingaweb2_icinga_groupe }}" + +- name: Installer Icinga Web 2 + module IcingaDB + PHP-FPM + nginx + ansible.builtin.apt: + name: "{{ serveur_icingaweb2_paquets }}" + state: present + update_cache: true + +- name: Ajouter www-data au groupe icingaweb2 (lecture de la config) + ansible.builtin.user: + name: www-data + groups: icingaweb2 + append: true + notify: Redémarrer php-fpm + +- name: Assurer le répertoire du module IcingaDB + ansible.builtin.file: + path: "{{ serveur_icingaweb2_config_dir }}/modules/icingadb" + state: directory + owner: root + group: icingaweb2 + mode: "0750" + +- name: Déployer la configuration icingaweb2 (.ini) + ansible.builtin.template: + src: "{{ item.s }}" + dest: "{{ serveur_icingaweb2_config_dir }}/{{ item.d }}" + owner: root + group: icingaweb2 + mode: "0640" + no_log: "{{ item.secret | default(false) }}" + loop: + - { s: config.ini.j2, d: config.ini } + - { s: resources.ini.j2, d: resources.ini, secret: true } + - { s: authentication.ini.j2, d: authentication.ini } + - { s: roles.ini.j2, d: roles.ini } + - { s: icingadb-config.ini.j2, d: modules/icingadb/config.ini } + - { s: icingadb-redis.ini.j2, d: modules/icingadb/redis.ini } + loop_control: + label: "{{ item.d }}" + notify: Redémarrer php-fpm + +- name: Activer le module IcingaDB + ansible.builtin.command: icingacli module enable icingadb + args: + creates: "{{ serveur_icingaweb2_config_dir }}/enabledModules/icingadb" + when: not ansible_check_mode + +- name: Déployer le vhost nginx local d'Icinga Web 2 + ansible.builtin.template: + src: nginx.conf.j2 + dest: /etc/nginx/sites-available/icingaweb2.conf + owner: root + group: root + mode: "0644" + notify: Recharger nginx + +- name: Activer le vhost Icinga Web 2 + ansible.builtin.file: + src: /etc/nginx/sites-available/icingaweb2.conf + dest: /etc/nginx/sites-enabled/icingaweb2.conf + state: link + notify: Recharger nginx + +- name: Retirer le site nginx par défaut + ansible.builtin.file: + path: /etc/nginx/sites-enabled/default + state: absent + notify: Recharger nginx + +- name: Activer et démarrer PHP-FPM et nginx + ansible.builtin.systemd: + name: "{{ item }}" + enabled: true + state: started + loop: + - "{{ serveur_icingaweb2_php_fpm_service }}" + - "{{ serveur_icingaweb2_nginx_service }}" + when: not ansible_check_mode diff --git a/roles/serveur_icingaweb2/templates/authentication.ini.j2 b/roles/serveur_icingaweb2/templates/authentication.ini.j2 new file mode 100644 index 0000000..39f9798 --- /dev/null +++ b/roles/serveur_icingaweb2/templates/authentication.ini.j2 @@ -0,0 +1,7 @@ +; Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main. +[icingaweb2] +backend = "ldap" +resource = "icingaweb_ldap" +user_class = "{{ serveur_icingaweb2_ldap_user_class }}" +user_name_attribute = "{{ serveur_icingaweb2_ldap_user_attr }}" +base_dn = "{{ serveur_icingaweb2_ldap_users_dn }}" diff --git a/roles/serveur_icingaweb2/templates/config.ini.j2 b/roles/serveur_icingaweb2/templates/config.ini.j2 new file mode 100644 index 0000000..0135f63 --- /dev/null +++ b/roles/serveur_icingaweb2/templates/config.ini.j2 @@ -0,0 +1,9 @@ +; Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main. +[global] +show_stacktraces = "0" +config_backend = "ini" + +[logging] +log = "syslog" +level = "ERROR" +application = "icingaweb2" diff --git a/roles/serveur_icingaweb2/templates/icingadb-config.ini.j2 b/roles/serveur_icingaweb2/templates/icingadb-config.ini.j2 new file mode 100644 index 0000000..72b928f --- /dev/null +++ b/roles/serveur_icingaweb2/templates/icingadb-config.ini.j2 @@ -0,0 +1,3 @@ +; Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main. +[icingadb] +resource = "icingadb" diff --git a/roles/serveur_icingaweb2/templates/icingadb-redis.ini.j2 b/roles/serveur_icingaweb2/templates/icingadb-redis.ini.j2 new file mode 100644 index 0000000..51faeb0 --- /dev/null +++ b/roles/serveur_icingaweb2/templates/icingadb-redis.ini.j2 @@ -0,0 +1,4 @@ +; Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main. +[redis1] +host = "{{ serveur_icingaweb2_redis_host }}" +port = "{{ serveur_icingaweb2_redis_port }}" diff --git a/roles/serveur_icingaweb2/templates/nginx.conf.j2 b/roles/serveur_icingaweb2/templates/nginx.conf.j2 new file mode 100644 index 0000000..a3526e6 --- /dev/null +++ b/roles/serveur_icingaweb2/templates/nginx.conf.j2 @@ -0,0 +1,27 @@ +# Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main. +# nginx LOCAL : sert Icinga Web 2 (PHP-FPM). L'edge nginx proxifie par nom vers ce port. +server { + listen {{ serveur_icingaweb2_http_port }}; + listen [::]:{{ serveur_icingaweb2_http_port }}; + server_name {{ serveur_icingaweb2_hostname }}; + + root {{ serveur_icingaweb2_docroot }}; + index index.php; + + location / { + try_files $uri $uri/ /index.php$is_args$args; + } + + location ~ ^/index\.php { + fastcgi_pass unix:{{ serveur_icingaweb2_php_fpm_socket }}; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME {{ serveur_icingaweb2_docroot }}/index.php; + fastcgi_param ICINGAWEB_CONFIGDIR {{ serveur_icingaweb2_config_dir }}; + fastcgi_param REMOTE_USER $remote_user; + } + + location ~ /\.ht { + deny all; + } +} diff --git a/roles/serveur_icingaweb2/templates/resources.ini.j2 b/roles/serveur_icingaweb2/templates/resources.ini.j2 new file mode 100644 index 0000000..b840d0e --- /dev/null +++ b/roles/serveur_icingaweb2/templates/resources.ini.j2 @@ -0,0 +1,20 @@ +; Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main. +[icingadb] +type = "db" +db = "pgsql" +host = "{{ resoudre_base_db_host }}" +port = "{{ resoudre_base_db_port }}" +dbname = "{{ resoudre_base_entree.base }}" +username = "{{ resoudre_base_entree.proprietaire }}" +password = "{{ resoudre_base_db_password }}" +charset = "UTF8" + +[icingaweb_ldap] +type = "ldap" +hostname = "{{ serveur_icingaweb2_ldap_url | regex_replace('^ldaps?://', '') }}" +port = "{{ serveur_icingaweb2_ldap_port }}" +encryption = "ldaps" +root_dn = "{{ serveur_icingaweb2_ldap_base }}" +bind_dn = "{{ serveur_icingaweb2_ldap_bind_dn }}" +bind_pw = "{{ serveur_icingaweb2_ldap_bind_password }}" +timeout = "5" diff --git a/roles/serveur_icingaweb2/templates/roles.ini.j2 b/roles/serveur_icingaweb2/templates/roles.ini.j2 new file mode 100644 index 0000000..a4f99e4 --- /dev/null +++ b/roles/serveur_icingaweb2/templates/roles.ini.j2 @@ -0,0 +1,4 @@ +; Géré par Set-OPS (rôle serveur_icingaweb2). Ne pas éditer à la main. +[Administrators] +users = "{{ serveur_icingaweb2_admins }}" +permissions = "*"