Commit Graph

10 Commits

Author SHA1 Message Date
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
Stéphane Tailland 2143c5f0bb feat(mcp): cap read volume per caller identity
A scope authorises a read and says nothing about volume. An agent reads a
thousand records in seconds where a person clicks ten, and until now nothing
noticed: the token is valid, the tool is permitted, the ACL passes.

identifier: credential keys the counter on the sub claim — the end user, whoever
is asking on their behalf — so an agent looping under one person's identity
spends that person's budget and cannot spend everyone's. Per-route namespace, so
a busy catalog cannot exhaust another domain's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 18:04:14 +02:00
Stéphane Tailland 95f9b611b3 Capture request/response bodies for audit-log via pre/post-function
Body capture lives in dedicated audit-log-body-capture(-bindings).yaml
files, separate from audit-log.yaml itself, so they can be dropped
without touching the base logging plugin (degrades gracefully to
metadata-only via nil custom_fields). Response body captured in
body_filter (chunk-accumulated) rather than the log phase, which
cannot call kong.response.get_raw_body() directly.
2026-08-21 14:53:52 +02:00
Stéphane Tailland 6fa122207e Capture request/response bodies in audit-log, extend it to MCP
custom_fields_by_lua adds request_body/response_body to the http-log
payload. Bodies and the raw Authorization header are now both logged
in clear text — dev only, flagged in the plugin file itself.
2026-08-21 14:40:20 +02:00
Stéphane Tailland fa7abfe5bd Drop the manual KongCertificate/KongSNI workaround
Turned out unnecessary: the real blocker was the missing
konghq.com/secret=true label on the Vault-sourced Secret, not a gap
in the Gateway API TLS translation itself. Once that label was added
(k8s-platform), the operator's own auto-generated KongCertificate/SNI
started working and this manual one just collided with it.
2026-08-21 09:51:23 +02:00
Stéphane Tailland 01f873b773 Bind the Gateway TLS secret to Konnect via KongCertificate/KongSNI
Gateway API's listeners[].tls.certificateRefs never gets synced to
Konnect by the gateway operator in this setup — same working pattern
as every other resource here (KongService, KongRoute, ...): a
Kong-native CRD, not the Gateway API's own translation.
2026-08-21 09:47:29 +02:00
Stéphane Tailland 4a1c772b80 Expose catalog-api under /catalog/v1, decoupled from the backend path
Public routes no longer leak classic-models-api's own /api/v1 prefix.
request-transformer-advanced rewrites to the real backend path per route.
2026-08-21 09:22:33 +02:00
Stéphane Tailland f929a0f7e4 MCP server 2026-08-20 16:26:48 +02:00
Stéphane Tailland 8b7ab3b846 Additional plugins 2026-08-20 15:03:25 +02:00
Stéphane Tailland 9546953b97 Flux refactoring 2026-08-20 14:37:08 +02:00