Aller au contenu principal

Administration Keycloak

STOA utilise Keycloak comme fournisseur d'identité. Ce guide couvre la configuration du realm, la mise en place des clients OIDC, le mapping des rôles RBAC et le durcissement en production.

Vue d'Ensemble de l'Architecture

Configuration du Realm

Créer le Realm

  1. Connectez-vous à la Console d'Administration Keycloak (https://auth.<VOTRE_DOMAINE>/admin)
  2. Cliquez sur Créer un Realm
  3. Définissez le nom du realm : stoa

Paramètres du Realm

ParamètreValeurObjectif
Nom affichéSTOA IdentityAffiché sur la page de connexion
SSL requisexternal (prod) / none (dev)Application de TLS
Inscription autoriséefalseAccès sur invitation uniquement
Connexion avec emailtrueEmail comme nom d'utilisateur
Protection contre la force brutetrueDurcissement sécurité
Réinitialisation du mot de passetrueRécupération en libre-service

Durées de Vie des Tokens

ParamètreDevProductionObjectif
Durée de vie du token d'accès3600s (1h)300s (5min)Courte durée pour la sécurité
Inactivité de session SSO1800s (30min)900s (15min)Délai d'inactivité
Durée maximale de session SSO36000s (10h)28800s (8h)Session maximale

Rôles RBAC

Créez ces 4 rôles de realm dans Paramètres du Realm > Rôles :

RôleDescriptionPortée
cpi-adminAdministrateur complet de la plateforme, peut gérer tous les tenants et les paramètres systèmePlateforme entière
tenant-adminAdministrateur de tenant, peut gérer les APIs et utilisateurs de son propre tenantTenant spécifique
devopsIngénieur DevOps, peut déployer et promouvoir des APIsTenant spécifique
viewerAccès en lecture seule aux ressources du tenantTenant spécifique

Hiérarchie des Rôles

cpi-admin (plateforme entière)
└── tenant-admin (tenant spécifique)
└── devops (portée déploiement)
└── viewer (lecture seule)

Les rôles supérieurs héritent de toutes les permissions des rôles inférieurs. Voir Permissions RBAC pour la matrice complète des permissions.

Mapping Utilisateur-Tenant

Chaque utilisateur a besoin d'un attribut tenant pour délimiter son accès :

  1. Allez dans Utilisateurs > sélectionnez l'utilisateur > Attributs
  2. Ajoutez l'attribut : tenant = acme (le slug du tenant)

Le claim tenant est inclus dans les tokens via un protocol mapper (configuré par client).

Clients OIDC

1. Control Plane API (Backend)

Objectif : Authentification service-à-service pour le backend.

ParamètreValeur
Client IDcontrol-plane-api
Type de clientConfidentiel
Flux standardActivé
Accès directActivé
Comptes de serviceActivé
Authentification clientActivée (client secret)

URIs de Redirection :

  • Dev : http://localhost:8000/*
  • Prod : https://api.<VOTRE_DOMAINE>/*

2. Console UI (Console d'Administration)

Objectif : Console d'administration pour les fournisseurs d'APIs. Client public utilisant PKCE.

ParamètreValeur
Client IDcontrol-plane-ui
Type de clientPublic
Flux standardActivé
Accès directActivé

URIs de Redirection :

  • Dev : http://localhost:3000/*, http://localhost:5173/*
  • Prod : https://console.<VOTRE_DOMAINE>/*

Protocol mapper (requis) : Ajoutez un mapper Audience :

  • Nom : control-plane-api-audience
  • Type de mapper : Audience
  • Audience client incluse : control-plane-api
  • Ajouter au token ID : Oui
  • Ajouter au token d'accès : Oui

Cela garantit que le claim aud inclut control-plane-api, permettant au backend de valider les tokens.

3. Portail Développeur

Objectif : Portail développeur public pour les consommateurs d'APIs.

ParamètreValeur
Client IDstoa-portal
Type de clientPublic
Flux standardActivé
Accès directActivé

URIs de Redirection :

  • Dev : http://localhost:3001/*
  • Prod : https://portal.<VOTRE_DOMAINE>/*

Protocol mapper : Même mapper d'audience que la Console (control-plane-api-audience).

4. MCP Gateway

Objectif : Validation JWT du gateway et compte de service pour la découverte d'outils.

ParamètreValeur
Client IDstoa-mcp-gateway
Type de clientConfidentiel
Flux standardActivé
Accès directActivé
Comptes de serviceActivé

URIs de Redirection :

  • Dev : http://localhost:8081/*
  • Prod : https://mcp.<VOTRE_DOMAINE>/*

5. OpenSearch Dashboards (Optionnel)

Objectif : SSO OIDC pour l'interface d'exploitation des logs.

ParamètreValeur
Client IDopensearch-dashboards
Type de clientConfidentiel
Flux standardActivé

Protocol mappers :

  • tenant-mapper : Mapper attribut utilisateur, claim tenant_id depuis l'attribut utilisateur tenant
  • realm-roles-mapper : Mapper rôles realm, claim roles avec les rôles realm de l'utilisateur

URIs de Redirection :

  • Prod : https://opensearch.<VOTRE_DOMAINE>/*

6. Observabilité (Optionnel)

Objectif : SSO Grafana et proxy OAuth2 Prometheus.

ParamètreValeur
Client IDstoa-observability
Type de clientConfidentiel
Flux standardActivé

Protocol mapper : Mapper realm-roles ajoutant le claim roles.

URIs de Redirection :

  • Grafana : https://grafana.<VOTRE_DOMAINE>/login/generic_oauth
  • Prometheus : https://prometheus.<VOTRE_DOMAINE>/oauth2/callback

Récapitulatif des Clients

Client IDTypeCompte de ServiceMapper AudienceUtilisateurs
control-plane-apiConfidentielOui--Services backend
control-plane-uiPublicNoncontrol-plane-apiAdmins (Console)
stoa-portalPublicNoncontrol-plane-apiDéveloppeurs (Portail)
stoa-mcp-gatewayConfidentielOui--Service Gateway
opensearch-dashboardsConfidentielNon--Utilisateurs observabilité
stoa-observabilityConfidentielNon--Grafana/Prometheus

Durcissement Sécurité (Production)

En-têtes de Sécurité du Navigateur

Configurez dans Paramètres du Realm > Défenses de Sécurité > En-têtes :

En-têteValeur
Content-Security-Policyframe-src 'self'; frame-ancestors 'self' https://console.<VOTRE_DOMAINE>; object-src 'none';
X-Content-Type-Optionsnosniff
X-XSS-Protection1; mode=block
Strict-Transport-Securitymax-age=31536000; includeSubDomains
Referrer-Policyno-referrer

Protection contre la Force Brute

Activez dans Paramètres du Realm > Défenses de Sécurité > Détection Force Brute :

ParamètreValeur Recommandée
ActivéeOui
Échecs de connexion max5
Incrément d'attente (secondes)60
Attente maximale (secondes)900
Temps de réinitialisation des échecs (secondes)43200 (12h)

TOTP/2FA (Optionnel)

STOA prend en charge l'authentification renforcée avec TOTP pour les opérations sensibles :

ParamètreValeur
Type de politique OTPTOTP
AlgorithmeHmacSHA256
Chiffres6
Période30 secondes
Applications compatiblesGoogle Authenticator, Microsoft Authenticator, Authy, 1Password, FreeOTP

Activez via un flux d'authentification personnalisé (step-up-totp) qui exige l'OTP pour les opérations d'administration.

Export/Import du Realm

Export (Sauvegarde)

Configure your environment

The examples below use environment variables. Set them for your STOA instance:

export STOA_API_URL="https://api.gostoa.dev"       # Replace with your domain
export STOA_AUTH_URL="https://auth.gostoa.dev" # Keycloak OIDC provider
export STOA_GATEWAY_URL="https://mcp.gostoa.dev" # MCP Gateway endpoint

Self-hosted? Replace gostoa.dev with your domain.

# Exporter la configuration du realm (sans les secrets)
curl -s "${STOA_AUTH_URL}/admin/realms/stoa" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" | jq > stoa-realm-backup.json

Import (Amorçage)

Pour le déploiement initial, importez le realm de référence :

# Via le CLI Keycloak
/opt/keycloak/bin/kcadm.sh config credentials \
--server "${STOA_AUTH_URL}" \
--realm master \
--user admin \
--password "${KEYCLOAK_ADMIN_PASSWORD}"

/opt/keycloak/bin/kcadm.sh create realms \
-f stoa-realm.json

Ou via Docker Compose avec montage de volume :

keycloak:
image: quay.io/keycloak/keycloak:24.0
command: start-dev --import-realm
volumes:
- ./init/keycloak-realm.json:/opt/keycloak/data/import/stoa-realm.json

Intégration OIDC Grafana

Configurez Grafana pour utiliser le SSO Keycloak :

# Valeurs Helm (kube-prometheus-stack)
grafana:
grafana.ini:
auth.generic_oauth:
enabled: true
name: Keycloak
client_id: stoa-observability
client_secret: ${GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET}
auth_url: https://auth.<VOTRE_DOMAINE>/realms/stoa/protocol/openid-connect/auth
token_url: https://auth.<VOTRE_DOMAINE>/realms/stoa/protocol/openid-connect/token
api_url: https://auth.<VOTRE_DOMAINE>/realms/stoa/protocol/openid-connect/userinfo
scopes: openid profile email roles
role_attribute_path: "contains(roles[*], 'stoa:admin') && 'Admin' || 'Viewer'"

Ce mapping associe les rôles Keycloak aux rôles Grafana :

  • Les utilisateurs avec la portée stoa:admin obtiennent le rôle Grafana Admin
  • Tous les autres obtiennent le rôle Grafana Viewer

Dépannage

ProblèmeCauseSolution
Erreur invalid_grantToken expiré ou client secret incorrectRégénérer le client secret dans Keycloak
audience_mismatchMapper d'audience manquant sur le clientAjouter le protocol mapper control-plane-api-audience
unauthorized_clientMauvais type de grant activéActiver le Flux Standard et/ou l'Accès Direct
La page de connexion affiche le realm stoaComportement correctLes utilisateurs s'authentifient sur le realm stoa
Erreurs CORS depuis la ConsoleWeb Origins incorrectAjouter l'URL de la Console aux Web Origins du client
Token sans claim tenantL'utilisateur n'a pas d'attribut tenantAjouter l'attribut utilisateur tenant dans Keycloak
Grafana SSO affiche 403Claim roles manquantAjouter le protocol mapper realm-roles au client stoa-observability

Voir Aussi