Gouvernance — RBAC¶
AKKO applique un seul modèle RBAC qui circule depuis Keycloak via OPA jusqu'à chaque service qui touche la donnée. Cette page est la synthèse gouvernance. Pour le guide opérationnel complet (ajout d'utilisateurs, exemples Rego, scripts API, tests), voir Admin / RBAC.
Un modèle, quatre points d'application¶
flowchart LR
KC[Keycloak realm akko<br/>5 rôles realm + groupes] --> JWT[JWT avec claim groups]
JWT --> S1[Service OIDC<br/>Superset, Airflow, Grafana, JupyterHub, MLflow]
JWT --> OPA[OPA<br/>row filters + column masks]
JWT --> LLM[LiteLLM<br/>clés virtuelles par rôle]
OPA --> TR[Trino]
S1 --> TR
LLM --> OLL[Ollama]
Quatre points d'application consomment la même identité :
- Service OIDC — Superset, Airflow, Grafana, JupyterHub, MLflow mappent le claim
groupsvers leurs rôles internes. - OPA — Trino délègue l'autorisation, les row filters et les column masks.
- Règles fichier Trino — ACL catalogue/schéma/table rechargées toutes les 5 minutes.
- LiteLLM — clés API virtuelles scope-limitées par rôle, routage de modèles et rate limits qui suivent l'utilisateur.
Les six rôles effectifs¶
AKKO livre cinq rôles realm dans Keycloak, plus un rôle implicite service-account pour les identités non humaines. Chaque rôle est la source de vérité — mappé automatiquement vers chaque service aval.
| Rôle | Persona | Visibilité données | PII | Pouvoir SQL |
|---|---|---|---|---|
akko-admin |
SRE / propriétaire plateforme (Alice) | tous catalogues, tous schémas | clair | DDL, DML, SELECT |
akko-engineer |
Ingénieur data (Bob) | raw, staging, analytics, sandbox |
clair | DDL sur schémas désignés, INSERT, SELECT |
akko-analyst |
Analyste sénior (Carol) | lecture seule tous schémas | clair | SELECT uniquement |
akko-user |
Utilisateur standard / conformité (Eve) | lecture seule tous schémas | masqués (email, phone, ssn, dob, mrn) | SELECT uniquement |
akko-viewer |
Exécutif / visualiseur (Dave) | analytics, reporting, public |
masqués | SELECT, row-filtered |
| service-account | Jobs CI, dbt, DAGs Airflow | scope projet | par projet | selon token |
Mapping par service¶
| Service | akko-admin |
akko-engineer |
akko-analyst |
akko-user |
akko-viewer |
|---|---|---|---|---|---|
| Trino | DDL + DML | DDL sur raw/staging/analytics/sandbox |
SELECT | SELECT + mask PII | SELECT + row filter + mask PII |
| Superset | Admin | Alpha | Gamma | Gamma | Public |
| Airflow | Admin | User | Viewer | Viewer | Viewer |
| Grafana | Admin | Editor | Viewer | Viewer | Viewer |
| JupyterHub | admin panel + spawn | spawn | spawn | spawn | spawn |
| MLflow | total | total | total | total | total |
| LiteLLM | tous modèles, 1000 rpm | tous modèles, 200 rpm | tous modèles, 100 rpm | chat + embed, 50 rpm | chat + embed, 20 rpm |
| OpenMetadata | admin | navigation + édition | navigation + édition | navigation | navigation |
| MinIO | root | root | root | root | root |
MinIO, MLflow et Spark utilisent encore des credentials partagés ; l'application par utilisateur est tracée dans le Stream 19 de la roadmap.
OPA — row filters et column masks¶
OPA est l'autorité pour la sécurité ligne et le caviardage colonne au-dessus des ACL fichier Trino. Les politiques sont rechargées à chaud depuis une ConfigMap, sans redémarrage.
# package trino — extrait
default allow := false
allow if { "akko-admin" in input.context.identity.groups }
# akko-user : SELECT uniquement
allow if {
"akko-user" in input.context.identity.groups
input.action.operation in {
"ExecuteQuery","AccessCatalog","FilterCatalogs","FilterSchemas",
"FilterTables","FilterColumns","SelectFromColumns",
"ShowSchemas","ShowTables","ShowColumns","ShowStats"
}
}
# Column mask PII — s'applique à akko-user et akko-viewer
columnMask := {"expression": "'***MASKED***'", "identity": "mask_pii"} if {
input.action.resource.column.columnName in {"email","phone","ssn","medical_record_number"}
not "akko-admin" in input.context.identity.groups
not "akko-engineer" in input.context.identity.groups
not "akko-analyst" in input.context.identity.groups
}
# Row filter : viewers ne voient que les comptes actifs
rowFilters contains {"expression": "status = 'active'", "identity": "viewer_active_only"} if {
"akko-viewer" in input.context.identity.groups
input.action.resource.table.tableName == "accounts"
}
Synchronisation des tags PII depuis OpenMetadata¶
Un sidecar (opa-sync) interroge OpenMetadata toutes les 5 minutes et pousse les tags PII comme data OPA. Les nouvelles colonnes taguées PII sont masquées automatiquement sans redéploiement de politique. Voir Flux de sécurité.
RBAC LLM¶
LiteLLM applique des clés virtuelles, des routages et des rate limits par rôle. Voir Admin / RBAC LLM pour la matrice complète.
| Rôle | Modèles autorisés | Rate limit | Contexte max |
|---|---|---|---|
akko-admin |
tous | 1000 rpm | 128 k |
akko-engineer |
tous | 200 rpm | 64 k |
akko-analyst |
chat + embed | 100 rpm | 32 k |
akko-user |
chat + embed | 50 rpm | 16 k |
akko-viewer |
chat uniquement | 20 rpm | 8 k |
Fonctions AI Trino — application par UDF¶
Les 17 UDF ai_* exposées par le plugin Trino contournent la vérification
OPA native ExecuteFunction (les UDF de plugin ne passent pas par le SPI
d'access-control). Le RBAC est donc appliqué au niveau AI Service :
- Le plugin Trino propage
X-Trino-User+X-Akko-Ai-Function: ai_<nom>sur chaque appel HTTP. - AI Service résout le rôle realm de l'utilisateur forwarded via l'API Admin Keycloak (cache 5 min) puis vérifie la matrice par fonction.
- Les refus renvoient HTTP 403 → SQL
NULL(fail-closed) ; chaque décision est journalisée dans Loki (audit_type=AI_RBAC) et comptée dans Prometheus.
Matrice complète 17×5 : voir AI / Fonctions Trino.
Source de vérité : helm/akko/charts/akko-ai-service/values.yaml, alignée
avec helm/akko/charts/akko-opa/templates/configmap.yaml.
Fédération entreprise¶
Quand global.auth.mode=enterprise, les utilisateurs de démo sont désactivés et Keycloak fédère :
- un LDAP corporate (LLDAP ou externe),
- ou un fournisseur OIDC amont (Azure AD, Okta, Google Workspace, Keycloak, Authentik),
- ou SAML (ADFS, PingFederate).
Voir Admin / Fournisseur d'identité externe et Admin / Fédération entreprise.
Piste d'audit¶
Trois flux de logs atterrissent dans Grafana pour la revue forensique :
| Source | Format | Exemples |
|---|---|---|
| Événements Keycloak | JSON via keycloak-event-listener-http |
LOGIN, LOGOUT, UPDATE_PASSWORD, TOKEN_REFRESH |
| Decision log OPA | JSON console decision log | {user, input, result, policy} |
| Query log Trino | JSON event listener | {queryId, user, sql, bytes_scanned, duration} |
| audit_log ADEN | JSON vers Loki | aden_query_received, aden_opa_denied, aden_pii_masked |
Voir Admin / Playbook d'audit.
Dépannage (top 5)¶
| Symptôme | Vérification | Correctif |
|---|---|---|
| L'utilisateur ne voit aucune donnée dans Superset | claim groups dans le JWT, mapping de rôle Superset |
Se reconnecter ; vérifier l'assignation Keycloak |
| Colonne visible en clair | Rôle admin/engineer/analyst |
Attendu — le masquage ne s'applique qu'à user/viewer |
| OAuth2-Proxy rejette l'utilisateur | emailVerified à false |
Activer dans Keycloak |
| Rôle Airflow / Grafana bloqué après changement | Token caché 5 min | L'utilisateur doit se déconnecter et se reconnecter |
| Nouvelle règle OPA non prise en compte | ConfigMap pas synchronisée | kubectl rollout restart deploy/akko-akko-opa (rare) ou attendre 30 s |
Voir aussi¶
- Admin / RBAC — guide opérationnel complet, scripts API, tests
- Admin / Architecture de gouvernance
- Admin / RBAC LLM
- Admin / Fournisseur d'identité externe
- Architecture / Flux de sécurité