feat(iam): migrate MCM from Keycloak to Ory (Hydra + Kratos + Keto + Oathkeeper)#202
Draft
kirgene wants to merge 3 commits into
Draft
feat(iam): migrate MCM from Keycloak to Ory (Hydra + Kratos + Keto + Oathkeeper)#202kirgene wants to merge 3 commits into
kirgene wants to merge 3 commits into
Conversation
Replace Keycloak with the Ory stack for MCM IAM: - HydraService: per-DFSP OAuth2 clients (client_credentials) for PM4ML - KratosService: per-admin identities + recovery-flow invitation, Keto role assignment incl. hub-admin subject_set transitivity and identity cleanup - CredentialsService + PkiService onboarding routed through Hydra/Kratos - AuthMiddleware trusts Oathkeeper headers (X-User/X-Email/X-DFSP-ID/X-Roles); session/token validation and /auth endpoints removed - KetoClient read-side queries for membership/cleanup - docker-compose: Hydra + Kratos + Keto + Mailpit + Kratos self-service UI; Vault switched to file-backend server mode with init/unseal - mcm-test-setup CLI driven by Kratos + Hydra - Integration tests for Hydra/Kratos/DFSP-IAM; Keycloak tests removed
# Conflicts: # .env-example # .nvmrc # docker-compose.yaml # docker/keycloak/dfsps-realm.json # docker/vault/docker-entrypoint.sh # package-lock.json # package.json # src/appLoader.js # test/.env-func # test/int/test-env-setup.js
c8e12db to
02beecc
Compare
…ation flow
Realign the Ory migration to the Hub/Dfsp Keto OPL so MCM does no runtime
authorization: it only provisions IAM at DFSP onboarding, and the Oathkeeper
gateway enforces every request against Keto.
- Rewrite KetoClient to the Hub/Dfsp/User relation-tuple model
- Add DfspIamService: the single facade that knows Hydra/Kratos/Keto exist;
business code (PkiService, CredentialsService) calls it and nothing else
- Drop all in-app authorization; list endpoints scope rows from the
gateway-supplied X-Roles header (hub-admin sees all, dfsp:{id} members
see their own; multi-DFSP supported)
- permissions/oathkeeper-rules.yml: per-route Keto checks (MCM owns the
route<->permission contract; deployments render the placeholders)
- Keto loads the OPL; iam-bootstrap seeds Hub:mojaloop#admins
- Kratos invitation via recovery magic-link + branded courier templates;
password-only completion; self-registration disabled
- Configurable hub object / role names (no hardcoded mojaloop/hub-admin)
- docker-compose: Oathkeeper gateway, OPL mount, Ory config rendering;
drop Keycloak/legacy PKI/vault/kubernetes assets
02beecc to
ed92641
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Story: mojaloop/project#4478 · DA: mojaloop/project#4472
Draft / WIP. Opening early for visibility on the architecture and to get feedback while the test suites and a few follow-ups are finished.
What this does
Migrates MCM's IAM from Keycloak to the Ory stack, following the Hub/Dfsp Keto OPL in #193 and the Oathkeeper rules in mojaloop/helm#804.
The guiding rule: MCM does no runtime authorization. It provisions IAM resources when a DFSP is onboarded and does nothing else with Ory. Every request is authenticated and authorized by the Oathkeeper gateway against Keto before it reaches the API, and MCM trusts the identity headers the gateway injects.
Provisioning (onboarding only)
DfspIamServiceis the one module that knows Hydra, Kratos and Keto exist. The business code (PkiService,CredentialsService) calls it and never touches an Ory SDK directly.When a DFSP is created it provisions a Hydra OAuth2 client for PM4ML machine access (
client_credentials, withclient_id == dfspId), a Kratos identity for the admin (invited via a recovery magic-link), and the Keto tuplesDfsp:<id>#parent@Hub:<hub>plusDfsp:<id>#members@<userId>for both the human identity and the machine client. A failure anywhere rolls the rest back.Authorization (gateway, not MCM)
permissions/oathkeeper-rules.ymlholds the per-route Keto checks, mirroring helm#804. MCM owns the route-to-permission contract; deployments just render the placeholders (MCM_FQDN,KETO_READ_URL,KETO_HUB_OBJECT). Keto loads the OPL frompermissions/mcm.keto.ts, andiam-bootstrapseedsHub:<hub>#admins.All the in-app role filtering is gone. List endpoints scope their rows from the
X-Rolesheader the gateway supplies: a hub-admin sees everything, adfsp:{id}member sees their own DFSPs, and a user can hold several (system integrators). The hub object id and role names are configurable rather than hardcoded.Invitation and accounts
Invitations go out as a Kratos recovery magic-link with branded HTML and plaintext courier templates ("Set up your Mojaloop Hub account"). Completion is password-only, and self-registration is disabled in Kratos.
Local stack
docker-compose gains the Traefik + Oathkeeper gateway, Ory config rendering, and the OPL mount. Keycloak, the legacy PKI CSR fixtures,
vault.hcl, and thekubernetes/manifests are removed, since deployment uses the helm charts.Verified end to end (compose
full)DFSP onboarding provisions Hydra, Kratos and Keto and rolls back on failure. An unauthenticated request gets 401; a DFSP member gets 403 on hub and other-DFSP routes; a hub-admin is allowed. All of that is decided by the gateway against Keto, not by MCM. PM4ML
client_credentialstokens issue correctly, and the branded invitation email leads through magic-link, password set, and into a role-correct portal.