Aller au contenu

Flux de sécurité

AKKO applique une défense à 4 couches qui propage l'identité de l'utilisateur du navigateur jusqu'au plan de données :

  1. Authentification — SSO Keycloak (source unique, 13 clients OAuth, 5 rôles).
  2. Autorisation — OPA (politiques fines et contextuelles synchronisées avec les groupes Keycloak).
  3. Application côté requête — row-filters + column-masks Trino via le plugin OPA.
  4. Audit — logs structurés (Loki) + événements Keycloak + query log Trino + decision log OPA.

Flux d'authentification de bout en bout

sequenceDiagram
    participant B as Navigateur
    participant T as Traefik (TLS)
    participant O2P as oauth2-proxy
    participant S as Service (Superset / JupyterHub)
    participant KC as Keycloak
    participant OPA as OPA
    participant TR as Trino
    participant OM as OpenMetadata

    B->>T: https://bi.akko.local
    T->>O2P: vérification ForwardAuth (services sans OIDC natif)
    O2P->>KC: redirection vers /auth (OIDC)
    B->>KC: login (utilisateur + mot de passe / MFA)
    KC-->>B: ID token + access token (claim roles)
    B->>S: requête avec bearer token
    S->>KC: validation JWT (JWKS)
    KC-->>S: ok
    S->>TR: SQL avec X-Trino-User + token
    TR->>OPA: POST /v1/data/trino/allow {user, roles, query, table, columns}
    OPA->>KC: récupération des groupes (cache sync)
    OPA-->>TR: allow + row_filters + column_masks
    TR->>OM: résolution tags PII (cache)
    TR->>TR: réécriture de la requête (filtres + masques)
    TR-->>S: lignes masquées
    S-->>B: graphique / table
    note over OPA,KC: OPA interroge Keycloak toutes les 60 s pour la synchro des groupes

Rôles et groupes

flowchart LR
    subgraph KC[Realm Keycloak akko]
        R1[akko-admin]
        R2[akko-engineer]
        R3[akko-analyst]
        R4[akko-user]
        R5[akko-viewer]
        G1[groupe: data-team]
        G2[groupe: finance]
        G3[groupe: svc-accounts]
    end
    subgraph LLDAP[LLDAP optionnel]
        L1[utilisateurs entreprise]
        L2[groupes entreprise]
    end
    LLDAP -.fédéré.-> KC
    R1 -->|mappe| OPA
    R2 -->|mappe| OPA
    R3 -->|mappe| OPA
    R4 -->|mappe| OPA
    R5 -->|mappe| OPA
    G1 -->|accès projet| OPA
    G2 -->|accès projet| OPA
    G3 -->|jetons machine| OPA

Row-Filter + Column-Mask Trino

Le plugin OPA réécrit chaque requête avant exécution.

# package trino — extrait
mask_email[columns] {
    columns = {"email", "phone", "ssn", "dob"}
    not roles[_] in {"akko-admin", "akko-engineer", "akko-analyst"}
}

row_filter[{"filter": f}] {
    input.context.identity.groups[_] == "finance"
    f := "region IN ('EU', 'APAC')"
}

Exemple : un utilisateur rôle akko-user exécute :

SELECT email, amount FROM iceberg.banking.transactions;

Trino réécrit en :

SELECT '***masked***' AS email, amount
FROM iceberg.banking.transactions
WHERE region IN ('EU', 'APAC');

Synchro des tags PII — OpenMetadata -> OPA

flowchart LR
    OM[OpenMetadata<br/>tags de colonnes: PII, GDPR.Personal] -->|ingestion nocturne| REG[cache de tags]
    REG -->|/policies/pii| OPA
    OPA -->|column_mask| TR[Trino]

Le sidecar opa-sync interroge OpenMetadata toutes les 5 minutes et pousse les tags de colonnes PII comme donnée OPA. Les nouvelles colonnes taguées PII sont masquées automatiquement — aucun redéploiement de politique requis.

ForwardAuth oauth2-proxy

Les services sans OIDC natif (MLflow, Grafana mode legacy, Harbor UI dans certains modes) sont filtrés via le middleware ForwardAuth de Traefik pointant sur oauth2-proxy.

sequenceDiagram
    participant B as Navigateur
    participant TR as Traefik
    participant O2 as oauth2-proxy
    participant MLF as MLflow

    B->>TR: https://experiments.akko.local
    TR->>O2: forward-auth
    alt pas de cookie valide
        O2-->>B: redirection Keycloak
        B->>O2: code + state
        O2-->>B: pose cookie
        B->>TR: nouvelle tentative
    end
    TR->>MLF: pass-through avec header X-Auth-User
    MLF-->>B: UI

Piste d'audit

Trois flux de logs corrélés 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 via console decision log {user, input, result, policy}
Query log Trino JSON via event-listener {queryId, user, sql, bytes_scanned, duration}
audit_log ADEN JSON vers Loki aden_query_received, aden_opa_denied, aden_pii_masked

Voir Guide d'audit et l'audit API Kubernetes pour la rétention et la corrélation complètes.

NetworkPolicies

Tous les namespaces appliquent des NetworkPolicies :

  • L'egress Internet est refusé par défaut.
  • Seul ollama-init a une allowlist vers le registre de modèles Ollama à l'installation (désactivé en mode air-gap).
  • Le trafic inter-services n'est autorisé qu'entre paires explicites (Trino <-> Polaris, Airflow <-> Trino, etc.).

Liens