Aller au contenu

Catalog Manager

AKKO Catalog Manager est le backend en libre-service et le module cockpit qui permettent aux admins de gérer les catalogues Trino à chaud. Il s'appuie sur la gestion dynamique des catalogues de Trino 481 (catalog.management=dynamic, catalog.store=file) : ajouter, éditer ou supprimer un catalogue se fait sans downtime et sans helm upgrade.

Refondu en 2026-06 (spec catalog-onboarding-refonte-2026-06). L'ancienne API /api/admin/catalogs et ses 4 surfaces cockpit superposées ont été retirées après la bascule ; l'API canonique est /api/catalogs et le cockpit n'expose qu'UNE surface : le module catalog-onboarding.

Connecteurs supportés

La liste des connecteurs est pilotée par les données : le formulaire cockpit rend ce que retourne GET /api/catalogs/connectors (pattern registry, extensible en YAML via CONNECTOR_SPECS_DIR sans modifier le code).

Catégorie Connecteurs
Relationnel (JDBC) PostgreSQL, MySQL, SQL Server, Oracle, ClickHouse, Redshift
Lakehouse Iceberg (REST / Polaris), Iceberg (HMS), Hive + Kerberos, Delta Lake
NoSQL / Streaming MongoDB, Cassandra, Elasticsearch, Kafka
Échappatoire Personnalisé (connector.name + propriétés brutes)

Architecture

Module cockpit pages/catalog-onboarding/ (MVC, surface unique)
    │ HTTPS + cookie SSO
nginx (akko-cockpit-react)  /api/catalog-manager/ → injecte le Bearer
Hôte FastAPI (akko-catalog-manager) + package catalog_manager
    │   1. vérifie le JWT → rôle akko-admin requis
    │   2. registry → builder par famille → propriétés (pattern Strategy)
    │   3. secrets → credential FILE sur le PVC catalogue partagé
    │      (jamais dans le SQL — Trino journalise le CREATE CATALOG)
    │   4. CREATE CATALOG via /v1/statement en svc-catalog-manager
    │      (OPA : identité machine catalog_admin, moindre privilège)
    │   5. saga avec compensation : tout échec annule proprement
    │   6. audit JSON corrélé structuré (secrets caviardés)
Trino 481 — coordinator RW + workers RO sur le PVC /etc/trino/catalog
            catalogues plateforme photographiés dans .baseline/ (restore)

Décisions clés :

  • Formulaire ⟷ SQL bidirectionnel : le cockpit affiche le CREATE CATALOG exact pendant la saisie, et re-parse vos éditions SQL vers le formulaire. Le SQL affiché est une projection — le submit envoie {connector, name, config} et le backend régénère le SQL : un drift d'affichage ne peut jamais exécuter autre chose.
  • Pas d'onglet permissions : l'onboarding enregistre le catalogue (visible des admins par défaut). QUI lit QUOI se gère dans le composant Accès aux données (RBAC plateforme ≠ accès data).
  • Édition = plan DROP + CREATE : Trino n'a pas d'ALTER CATALOG. Le module affiche le plan honnêtement et le backend restaure la définition précédente si le re-CREATE échoue. Les secrets ne sont jamais relus : ressaisissez-les à l'édition.
  • Suppression / restauration : les catalogues plateforme (provenance platform) sont photographiés dans un baseline sur le PVC. En supprimer un affiche une bannière de restauration ; POST /api/catalogs/restore recrée les manquants. Les catalogues client exigent une confirmation par saisie du nom (définitif).

Ajouter un catalogue (cockpit)

  1. Connectez-vous avec le rôle akko-admin.
  2. Barre latérale → Sources de données.
  3. + Ajouter une source → choisissez un connecteur, remplissez les champs (l'œil révèle le mot de passe) — ou éditez directement le SQL.
  4. ⚡ Tester la connexion lance une sonde TCP de pré-vol.
  5. Créer la source — Trino valide le connecteur au CREATE CATALOG ; le catalogue est actif sur tout le cluster en ~5 s.

Ajouter un catalogue (API)

curl -X POST https://cockpit.mon-entreprise.example/api/cockpit/catalog-manager/api/catalogs \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "connector": "postgresql",
    "name": "client_pg_01",
    "config": {
      "host": "db.client.example", "port": "5432",
      "database": "ventes", "user": "trino_readonly",
      "password": "<caviardé>"
    }
  }'
# → 201 {name, connector, provenance, sql}   (le sql ne contient AUCUN secret)

Les noms de catalogue sont des identifiants SQL Trino nus : ^[a-z][a-z0-9_]{0,40}$ (pas de tiret), system et information_schema sont réservés, et Trino n'a pas de IF NOT EXISTS — les doublons sont rejetés avant le CREATE.

API complète

Méthode · chemin Rôle
GET /api/catalogs/connectors registry des connecteurs (pilote le formulaire)
GET /api/catalogs/meta constantes plateforme pour le codec SQL frontend
GET /api/catalogs liste — live ∪ store ∪ baseline manquants (missing: true)
GET /api/catalogs/{name} détail, propriétés SANS secrets (pré-remplissage édition)
POST /api/catalogs/preview validation + SQL généré, aucun effet de bord
POST /api/catalogs création (saga, credential file, audit)
PUT /api/catalogs/{name} mise à jour = DROP+CREATE avec rollback automatique
DELETE /api/catalogs/{name} idempotent ; retourne restorable + leaky_connector
POST /api/catalogs/restore re-CREATE des catalogues plateforme manquants
POST /api/catalogs/test sonde TCP de pré-vol (timeout 3 s)
GET /api/catalogs/{name}/status compte SHOW SCHEMAS live
POST /api/catalogs/sql mode expert — accepte UNIQUEMENT CREATE/DROP CATALOG

Hive + Kerberos — comment le keytab arrive à Trino

Deux voies distinctes, toutes deux prouvées live :

Voie plateforme (gérée par le chart) — les catalogues de fédération livrés avec la plateforme (ex. la démo Cloudera) : le keytab vit dans un Secret Kubernetes monté sur les pods Trino par le chart ; krb5.conf et les confs hadoop sont des montages niveau JVM/plateforme. C'est ce qui fait tourner la fédération Cloudera (6,3 M de lignes).

Voie self-service (cockpit / API) — pour les catalogues créés à chaud :

  1. Sources de données → connecteur Hive → options avancées → activer Authentification Kerberos.
  2. Renseigner service principal + client principal.
  3. Coller le keytab en base64 dans le champ Keytab (base64) (base64 -w0 mon.keytab), ou envoyer config.keytab_b64 via POST /api/catalogs.

Mécanique backend : le base64 est décodé en binaire et écrit à côté des credential files sur le PVC catalogue partagé — le seul chemin lisible par le coordinator ET les workers (les workers ouvrent leurs propres connexions metastore/HDFS). Le SQL généré référence ce chemin mais ne contient jamais le keytab (Trino journalise chaque CREATE CATALOG en intégralité). Le set de propriétés émis est le miroir du catalogue de fédération prouvé live : auth KERBEROS metastore + fs.hadoop.enabled=true + hive.config.resources (confs hadoop montées plateforme, pilotées par env) + HDFS kerbérisé principal/keytab, impersonation désactivée.

Cycle de vie des tickets : la JVM Trino acquiert et renouvelle les tickets depuis le keytab automatiquement — aucune opération d'expiration à gérer.

Situations d'échec (toutes vérifiées contre le vrai metastore kerbérisé)

Situation Comportement
Mauvais client principal (absent du keytab) CREATE rejeté par Trino en ~1,5 s, saga annulée, zéro résidu, erreur affichée dans le formulaire
Kerberos activé sans keytab fourni même rejet immédiat + rollback
Base64 invalide dans le champ keytab 400 avant même d'atteindre Trino
Metastore injoignable la sonde TCP de pré-vol le signale avant le submit
Keytab + principals valides catalogue actif, schémas du metastore kerbérisé navigables dans le drill-down de la ligne

Couverture E2E (tests/e2e/playwright/test_e2e_catalogs_page.py) : test_26 crée un catalogue Hive+Kerberos via l'interface avec le VRAI keytab de la démo et prouve le handshake par le drill-down des schémas ; test_27 prouve le rejet immédiat + rollback sur mauvais principal. Le keytab est extrait du Secret du cluster au moment du run — jamais commité.

Voir demos/cloudera-simulation/bootstrap-akko-catalog.sh pour la variante API scriptée.

Modèle de sécurité

  • Les écritures exigent le rôle realm akko-admin (JWT vérifié contre le JWKS Keycloak avec discovery OIDC).
  • Les mots de passe JDBC vont dans un credential file référencé par credential-provider.type=FILE — jamais dans les propriétés du catalogue, jamais dans le CREATE CATALOG (journalisé intégralement).
  • Côté Trino, l'identité de service svc-catalog-manager est une identité machine catalog_admin: true UNIQUEMENT : elle gère le cycle de vie des catalogues mais ne peut lire aucune table (NIST AC-6). Elle est seedée via akko-init.opaSeedPolicies pour que la synchro Keycloak→OPA ne la perde jamais.
  • Audit : chaque opération émet du JSON structuré corrélé, secrets caviardés.

Dépannage

Symptôme Cause Correctif
422 trino_rejected Access Denied: Cannot create catalog OPA a perdu le seed svc-catalog-manager vérifier akko-init.opaSeedPolicies, relancer le Job opa-sync
500 Error loading catalogs on worker credential file illisible sur les workers PVC monté RO sur les workers ; fichiers 0644
coordinator en CrashLoop après changement de config catalog.config-dir / catalog.store.file.path posés AUCUN des deux n'est valide en Trino 481 — le dir du file store est toujours /etc/trino/catalog (symlink du launcher)
catalogue plateforme supprimé absent comportement attendu — restaurez-le bannière → Restaurer depuis le baseline ou POST /api/catalogs/restore