docs/WORK_REPRODUCTION.md
Porter le même modèle de sécurité de Docker + Auth0 + OpenCode vers Kubernetes et un IdP d’entreprise (Entra ID / Okta / Auth0 Enterprise). Le JWT a la même forme — ce qui change, c’est l’environnement.
À garder identique
| Concept | Valeur du lab | Au travail |
|---|---|---|
| Protocole MCP | ORDS standalone /mcp | Identique (pas de Tomcat pour MCP) |
| Validation JWT | iss, aud, JWKS | Issuer d’entreprise + JWKS |
| Claim des rôles | roles2 (ou nom sûr) | Mapper des groupes → mêmes chaînes, ou changer le pointeur ORDS |
| Chaînes de rôle | POOL.HR, POOL.FIN | Rôles / groupes applicatifs stables |
| Scope MCP global | urn:oracle:dbtools:ords:mcpserver:all | Même chaîne sur l’API / le scope |
| Liaison pool | mcp.role + mcp.scope par pool | Un pool par vraie base de données |
| Client | OpenCode OAuth PKCE | OpenCode ou autre client MCP avec OAuth |
À faire changer
| Lab | Travail |
|---|---|
API Identifier / URL MCP http://127.0.0.1:8080/mcp | URL publique HTTPS, ex. https://ords-mcp.company.com/mcp (hôte dédié ; ne pas retirer /ords — voir reverse proxy) |
| Tenant Auth0 gratuit | Entra ID / Okta / Auth0 Enterprise |
| Un Oracle Free, deux schémas | N bases ; un pool MCP par base |
| Docker Compose | Deployment + Ingress + Secrets + NetworkPolicy |
Mots de passe d’exemple dans .env | Vault / External Secrets |
resource= égal à cette URL. MCP est à
/mcp sur l’hôte ORDS, pas sous /ords. Un mapping https://my-proxy/ords/ →
http://ords fait annoncer à ORDS https://my-proxy/mcp.
Déploiement suggéré
roles2 + permissions.POOL.* (ou renommer pools/rôles de façon cohérente).mcp.role, équipe propriétaire.DBTOOLS$MCP_LOG, module/action de session), jetons de courte durée.Depuis scripts/configure-mcp.sh / config courante :
feature.mcp = true
mcp.security.jwt.profile.issuer
mcp.security.jwt.profile.audience # = URL publique du MCP
mcp.security.jwt.profile.jwk.url
mcp.security.jwt.profile.authorization.server.url
mcp.security.jwt.profile.role.claim.name # /roles2 ou pointeur du claim entreprise
# par pool :
db.hostname, db.port, db.servicename, db.username
mcp.role, mcp.scope
db.password (wallet / secret)
Mapping IdP
| Auth0 (lab) | Exemple entreprise |
|---|---|
Rôle POOL.FIN | Rôle d’application ou groupe POOL.FIN |
Claim roles2 | Claim personnalisé (éviter les noms réservés par l’IdP) |
| Permission sur le rôle | Le rôle d’app inclut le scope/permission de l’API MCP |
| App Native + PKCE | Client public pour les postes des développeurs |
| Action post-login | Entra : optional claims / token configuration |
http://127.0.0.1:19876/mcp/oauth/callback).Socle de sécurité
Matrice de validation
| Test | Résultat attendu |
|---|---|
| Utilisateur avec POOL.FIN seulement | database_list = pool fin uniquement |
| Utilisateur avec POOL.HR seulement | pool hr uniquement |
| Utilisateur avec les deux | les deux pools |
| Jeton sans permission MCP | 403 / client en needs_auth |
| Jeton sans claim de rôle | 401 Missing Role Claim |
| Mauvaise audience | 401 |