From b6952759f5e015ded427cbfdc8103bf9cef114a0 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Sat, 4 Jul 2026 17:30:13 -0400 Subject: [PATCH] =?UTF-8?q?Doc=20=C3=A0=20jour=20:=20unit=C3=A9=20wiki=20A?= =?UTF-8?q?utorisation=20&=20RBAC=20+=20le=C3=A7on=20renouvellement=20+=20?= =?UTF-8?q?runbooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fermeture des dettes de doc : - nouvelle unité wiki « Autorisation & RBAC » (authZ, exemple Grafana) ; - section « le renouvellement est un système » dans l'unité PKI ; - docs/runbooks-exploitation.md (cert expiré, RBAC Grafana, branding). 15 unités wiki. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 5 +++ docs/runbooks-exploitation.md | 66 ++++++++++++++++++++++++++++ wiki/Autorisation-et-RBAC.md | 81 +++++++++++++++++++++++++++++++++++ wiki/PKI-et-confiance.md | 27 +++++++++++- wiki/_Sidebar.md | 3 +- 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 docs/runbooks-exploitation.md create mode 100644 wiki/Autorisation-et-RBAC.md diff --git a/CHANGELOG.md b/CHANGELOG.md index bb964f1..aa4f27f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ l'incident : `systemctl reload nginx` sur l'edge. ### Ajouté +- **Doc à jour : unité wiki « Autorisation & RBAC », leçon renouvellement, runbooks.** Fermeture + des dettes de doc : nouvelle **unité wiki authZ/RBAC** (pendant d'*Identité & SSO*, avec l'exemple + Grafana), **section « le renouvellement est un système »** versée dans l'unité *PKI* (comparer cert + servi vs fichier ; recharger le consommateur), et **`docs/runbooks-exploitation.md`** (cert expiré, + RBAC Grafana, branding Forgejo). 15 unités wiki désormais. - **UI des logs Loki : dashboard Grafana provisionné.** Loki n'a pas d'UI ; son UI est Grafana. Ajout d'un **dashboard « Journaux de la flotte »** (dossier Set-OPS) : sélecteur d'hôte multi + filtre regex insensible à la casse + panneau logs + débit par hôte. Référence Loki par une diff --git a/docs/runbooks-exploitation.md b/docs/runbooks-exploitation.md new file mode 100644 index 0000000..f3f0992 --- /dev/null +++ b/docs/runbooks-exploitation.md @@ -0,0 +1,66 @@ +# Runbooks d'exploitation — Set-OPS + +Procédures courtes et concrètes pour les situations d'exploitation. Complète les *docs/* de +conception (le *pourquoi*) par le *comment faire*. Le wiki de formation en donne la version +pédagogique. + +--- + +## 1. Un certificat a expiré / le login SSO est cassé + +**Symptôme** : connexion à une app via le SSO échoue *après* le login ; log Grafana/app : +`tls: failed to verify certificate: x509: certificate has expired`. + +**Cause fréquente** : le cert step-ca a été **renouvelé sur disque** mais le service (nginx sur +l'edge) **n'a pas été rechargé** → il sert l'ancien cert en mémoire. + +**Diagnostic-réflexe** — comparer le cert *servi* au cert *fichier* : +```bash +# SERVI (en mémoire par nginx) +echo | openssl s_client -connect infra-edge-01…:443 -servername keycloak.lab… 2>/dev/null \ + | openssl x509 -noout -enddate +# FICHIER (sur disque) +openssl x509 -in /etc/step/certs/infra-edge-01….crt -noout -enddate +``` +Dates différentes (servi < fichier) ⇒ nginx sert un cert périmé. + +**Fix immédiat** : `systemctl reload nginx` sur l'edge (idem `postfix`/`dovecot`/`slapd` selon le +service touché). + +**Fix permanent (déjà en place)** : `client_pki_reload_services` recharge les vrais consommateurs +après chaque renouvellement — edge→nginx, mail→postfix/dovecot, annuaire→slapd. Vérifier : +`systemctl cat cert-renewer@$(hostname -f).service | grep ExecStartPost`. +Voir aussi l'unité wiki *PKI & confiance* (⑤ le renouvellement). + +--- + +## 2. Donner Explore/Editor à un opérateur dans Grafana (RBAC) + +Par défaut, un utilisateur SSO est **Viewer** (dashboards seulement, pas Explore). Pour l'élever : + +1. Déclarer l'assignation dans l'inventaire de l'instance (group_vars `serveur_keycloak`) : + ```yaml + serveur_keycloak_role_assignments: + - { user: , role: grafana-editor } # ou grafana-admin + ``` +2. Redéployer Keycloak (`make deployer` sur le nœud SSO) — kcadm **à chaud, sans coupure**. +3. L'utilisateur doit **se déconnecter/reconnecter** (Grafana applique le rôle à la connexion). + +Mapping (défaut du rôle grafana) : `grafana-admin`→Admin, `grafana-editor`→Editor, sinon Viewer +(`serveur_grafana_oidc_role_path`). Idéal souverain : piloter par un **groupe d'annuaire** plutôt +qu'un utilisateur explicite. Voir l'unité wiki *Autorisation & RBAC*. + +--- + +## 3. Brander une instance Forgejo (identité visuelle) + +Activer dans l'inventaire (group_vars `serveur_forgejo`) : +```yaml +serveur_forgejo_branding: true +serveur_forgejo_app_name: "Forge Chezlepro" +serveur_forgejo_theme: "forgejo-dark" +serveur_forgejo_meta_description: "…" +``` +Puis redéployer. Le rôle déploie le dossier `custom/` officiel (logo/favicon aurore, accent CSS par +variables, page d'accueil brandée) — léger, résistant aux MAJ (aucune classe interne touchée). +Note : ne s'applique qu'aux Forgejo **gérées par Set-OPS**. diff --git a/wiki/Autorisation-et-RBAC.md b/wiki/Autorisation-et-RBAC.md new file mode 100644 index 0000000..c628008 --- /dev/null +++ b/wiki/Autorisation-et-RBAC.md @@ -0,0 +1,81 @@ +# Autorisation & RBAC + +> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer. +> Le pendant naturel de **[Identité & SSO](Identité-et-SSO)** : celle-là dit *qui tu es*, celle-ci dit *ce que tu as le droit de faire*. + +--- + +## ① Le concept *(générique)* + +**Authentification (authN)** : *qui es-tu ?* — **Autorisation (authZ)** : *as-tu le droit ?* Deux +questions distinctes. Se connecter ne dit **rien** sur ce qu'on peut faire. + +**RBAC** (*Role-Based Access Control*) : on n'attribue pas des droits à chaque personne, mais des +**rôles** (Viewer, Editor, Admin…), et chaque rôle porte un ensemble de **permissions**. La personne +reçoit un rôle → hérite des droits. Simple, auditable, évolutif. + +**Où décider ?** Deux écoles : +- *local à l'app* : chaque service gère ses propres comptes/rôles (silos, à maintenir partout) ; +- *centralisé (piloté par le SSO/annuaire)* : le rôle voyage **dans le jeton** ; l'app le lit et + l'applique. Une seule source, cohérente partout. **Moindre privilège** par défaut. + +Mécanique OIDC : le fournisseur d'identité met un **claim** (ex. `roles`) dans le jeton ; l'app +**mappe** ce claim vers son niveau de droit interne. + +--- + +## ② Comment Set-OPS le fait — l'exemple Grafana + +Par défaut, un utilisateur SSO arrive en **Viewer** dans Grafana → il voit les tableaux de bord, +mais **pas Explore** (requêtes ad-hoc). Pour donner Explore aux opérateurs, sans l'ouvrir à tous : + +``` +Keycloak : rôle de realm 'grafana-editor' ──(assigné à testmail) + + mapper de rôles ──> claim "roles":["grafana-editor"] dans le jeton +Grafana : role_attribute_path ──> "grafana-editor" ⇒ Editor (⇒ Explore) + "grafana-admin" ⇒ Admin ; sinon Viewer +``` + +Déclaratif dans Set-OPS : `serveur_keycloak_realm_roles`, `_role_mapper_clients`, +`_role_assignments` (côté IdP) + `serveur_grafana_oidc_role_path` (côté app). kcadm **à chaud** : +**zéro coupure SSO**. Une identité (`testmail`), et c'est **le rôle** — pas la connexion — qui décide +d'Explore. + +> **Raffinement souverain** : ici le rôle est assigné *explicitement* à testmail. L'idéal est de le +> piloter par un **groupe d'annuaire** (LDAP → Keycloak → claim), pour que *l'appartenance* gouverne +> l'autorisation. C'est le vrai « l'annuaire gouverne l'accès ». + +--- + +## ③ Pourquoi c'est transférable + +| Set-OPS | Équivalents ailleurs | +|---|---| +| rôles de realm Keycloak → claim | claims/scopes OIDC de tout IdP (Okta, Entra…) | +| `role_attribute_path` Grafana | *role mapping* de n'importe quelle app OIDC | +| RBAC (rôles → permissions) | **Kubernetes RBAC** · IAM cloud (AWS/GCP) · SGBD (rôles SQL) | +| moindre privilège | principe **universel** de sécurité | + +Tu as appris **authZ vs authN, le RBAC, l'autorisation par claim, le moindre privilège** — pas +« Grafana ». + +--- + +## ④ À toi de jouer + +1. **Sens le défaut.** Avant tout rôle, un nouvel utilisateur SSO est **Viewer** dans Grafana : il + voit le dashboard *Journaux de la flotte*, mais **pas** l'icône Explore. +2. **Donne Editor.** `testmail` a le rôle `grafana-editor` → **déconnecte/reconnecte-le** (Grafana + applique le rôle *à la connexion*) → **Explore apparaît**. +3. **Observe le claim.** Dans Keycloak (console admin) → Clients → grafana → *Client scopes* → + *Evaluate* pour `testmail` : le jeton contient `"roles": ["grafana-editor"]`. C'est ② en vrai. +4. **Casse & répare.** Retire `grafana-editor` de testmail (ou renomme-le en `grafana-viewer`), + reconnecte : **Explore disparaît**. Remets-le : il revient. Tu *sens* que c'est **le rôle**, pas + l'identité, qui ouvre la porte. + +--- + +## Pour aller plus loin *(dépôt)* +- IdP : `roles/serveur_keycloak/tasks/rbac-oidc.yml` (rôles + mapper + assignations). +- App : `roles/serveur_grafana` (`serveur_grafana_oidc_role_path`). +- Le pendant *authentification* : unité **[Identité & SSO](Identité-et-SSO)**. diff --git a/wiki/PKI-et-confiance.md b/wiki/PKI-et-confiance.md index 5a2a6e4..1fde741 100644 --- a/wiki/PKI-et-confiance.md +++ b/wiki/PKI-et-confiance.md @@ -78,7 +78,32 @@ Encrypt, Vault, une AC d'entreprise : le schéma est **identique**. --- +## ⑤ Le renouvellement : un système à part entière *(leçon d'exploitation vécue)* + +Un certificat **expire**. Les certs internes de Set-OPS (step-ca) sont **courts** (~24 h) — c'est +plus sûr (une clé volée ne vaut pas longtemps), mais ça **exige un renouvellement automatique** +fiable. Et attention à un piège vécu en vrai : + +> **Renouveler le fichier ne suffit pas — il faut recharger le consommateur.** Un service (nginx, +> postfix, dovecot, slapd) charge son cert **en mémoire au démarrage**. Si le renouvellement +> réécrit le fichier mais **ne recharge pas** le service, celui-ci sert l'**ancien cert périmé** +> alors que le fichier sur disque est frais. Symptôme trompeur : `openssl x509 -in fichier` dit +> « valide », mais le service sert un cert **expiré**. + +Diagnostic-réflexe : **comparer le cert servi au cert fichier**. +```bash +echo | openssl s_client -connect EDGE:443 -servername keycloak.lab… 2>/dev/null | openssl x509 -noout -enddate # SERVI +openssl x509 -in /etc/step/certs/EDGE.crt -noout -enddate # FICHIER +``` +Dans Set-OPS, `client_pki_reload_services` (par nœud) fait recharger les **vrais** consommateurs +après chaque renouvellement — edge→nginx, mail→postfix/dovecot, annuaire→slapd. Fix d'urgence si +ça arrive : `systemctl reload nginx` sur l'edge. + +**Casse & répare** : sur l'edge, arrête le timer `cert-renewer@…`, laisse le cert expirer (ou +force une horloge), observe le login SSO casser (échec TLS de l'échange OIDC), puis recharge nginx +→ tout revient. Tu *sens* que la PKI ne vit que si le renouvellement **et** le rechargement tournent. + ## Pour aller plus loin *(dépôt)* -- Rôles : `roles/serveur_step_ca`, `roles/client_pki`. +- Rôles : `roles/serveur_step_ca`, `roles/client_pki` (`client_pki_reload_services`). - Le motif « pont de certificat » (renouvellement automatique) : voir les tâches `*-cert-sync` des rôles (Dovecot, Postfix, nginx…). - Tier 0 des sauvegardes (`/etc/step-ca`) : unité **Sauvegardes**. diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md index 2eb0cfa..bf6f86b 100644 --- a/wiki/_Sidebar.md +++ b/wiki/_Sidebar.md @@ -5,6 +5,7 @@ *Fondations* - [Identité & SSO](Identité-et-SSO) +- [Autorisation & RBAC](Autorisation-et-RBAC) - [PKI & confiance](PKI-et-confiance) - [DNS & résolution de noms](DNS-et-résolution) @@ -28,7 +29,7 @@ - [Liaisons (bindings)](Liaisons-bindings) **Opérations** -- Runbooks *(à venir)* +- Runbooks → dépôt `docs/runbooks-exploitation.md` **Repères** - Glossaire *(à venir)*