Stéphane Tailland ca0a11fd94 feat(mcp): authorise tool-call parameters, not just the tool name
The ACL answers 'may this identity call create-product'. Nothing answered 'may
it call it with these arguments' — write authorises writing, not this
particular record. And the read cap counts calls, so one call asking for a
hundred thousand rows cost the same as one asking for ten.

The OPA plugin sends the decoded JSON-RPC body, so the decision point sees the
tool name and its arguments. The policy lives once in k8s-platform/opa and every
domain asks the same server.

Enforced at the gateway rather than in an agent, because an agent that has been
talked into something is the case this exists for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 18:08:00 +02:00
2026-08-20 13:24:10 +02:00
2026-08-20 17:27:09 +02:00

catalog-api

Kong routing/policy layer for the catalog slice of classic-models-api (see /Users/stephanetailland/git/classic-models-api), split out per the DDD decomposition in ../kong-konnect-deployment-strategy.md. The backend itself stays a single monolith — only Kong does the domain split.

Two exposure surfaces of the same API, both proxying to the real classic-models-api backend:

  • REST (kong/rest/) — 14 routes covering products/productlines.
  • MCP (kong/mcp/) — the same catalog exposed as MCP tools (list-products, get-product, create-product so far; extending to the rest is mechanical), via ai-mcp-proxy.

Auth

openid-connect on both surfaces, with a distinct audience each (catalog-api for REST, mcp-catalog for MCP) and a real RFC 8693 token exchange chain: MCP → catalog-api → classic-models-api (REST's own exchange target), narrowing the token before it ever reaches the backend — the backend never sees a token minted for a different audience. consumer_claims/consumer_by map the JWT sub to a Kong Consumer for per-consumer rate limiting; consumer_groups_claim maps realm roles to Kong Consumer Groups for MCP's per-tool ACLs.

Other policies

Per-consumer + API-level rate limiting, response caching (GET/HEAD), audit log (http-log, endpoint still a placeholder — no real log collector in this lab).

Structure

  • dev/gitrepository.yaml + dev/flux-kustomization.yaml — this repo, self-referential; deploys ./kong into the catalog domain's dev environment (dependsOn the domain's Gateway infra in dataplane-catalog).
  • dev/externalsecret.yaml — git deploy key (ESO/Vault).
  • dev/token-exchange-broker-externalsecret.yaml — the shared client secret Kong uses to authenticate its own token-exchange calls to Keycloak.
  • kong/rest/, kong/mcp/ — see above.
  • openapi.yaml — extracted from the live backend, filtered to this domain's paths/schemas.
S
Description
No description provided
Readme 116 KiB