Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Removed

- **M2M agent impersonation RBAC.** The `agents.<name>.m2m` block (and the `impersonation.yaml` / `_agent-impersonation.tpl` templates it rendered) is removed from `agentic-platform-connectivity`. Agents no longer get a deputy `Role`/`ClusterRole` letting mcp-kubernetes impersonate the agent's own identity or bind its groups to ClusterRoles. The only supported flow is on-behalf-of: muster mints a token with the human as `sub` and the agent SA in the RFC 8693 `act` claim, and the mcp-kubernetes chart's `*-obo-impersonate` ClusterRole authorizes impersonating the human. Requires mcp-kubernetes with M2M removed and muster with the matching broker config.
- **Retired the `agentic-platform-crds` bundle chart** — every component now owns its CRDs (app-owned CRDs). The standalone chart (`helm/agentic-platform-crds/`), its CircleCI build/test/push jobs, and the now-dead Renovate `helmv3` lockstep `packageRules` are deleted. There is no longer a `components.agentic-platform-crds` entry in the meta-package.

### Changed
Expand Down
42 changes: 16 additions & 26 deletions docs/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,32 +173,22 @@ agentic-platform-mcps:
clientSecretKey: client-secret
```

### Machine-to-machine (M2M): local mint + impersonation

A kagent agent reaching a downstream server is a machine, not a human with a Dex
token. muster validates the agent's inbound ServiceAccount token, then
**local-mints** (`auth.mode: localMint`, `enableJWTMode: true`) a token carrying a
configured subject and groups for the downstream audience. The downstream server
(e.g. mcp-kubernetes) cannot present that token to the kube-apiserver as a bearer
(wrong issuer/audience), so it authenticates with its own SA token and sets
`Impersonate-User`/`Impersonate-Group` headers to act *as* the agent. Kubernetes RBAC
and the audit log then reflect the agent, not the proxy.

The same identity is configured in three places, which must agree:

- **muster** — the `tokenExchangeBroker.workloadGroupGrants` entry (which inbound
subject to mint for, and the groups to inject), set in giantswarm-config next to
the rest of the muster broker config;
- **mcp-kubernetes** — its `trustedIssuers` (`impersonateUser`/`impersonateGroups`),
set in its own app values;
- **the RBAC** — rendered by agentic-platform-connectivity from `agents.<name>.m2m`:
the impersonation `Role`/`ClusterRole` letting each `m2m.impersonators` SA
impersonate `m2m.granted`, plus a `ClusterRoleBinding` per `m2m.granted.clusterRoles`
for the agent's actual access.

A `system:serviceaccount:…` granted user yields a namespaced `serviceaccounts` Role
plus a groups `ClusterRole`; a plain username (e.g. `agent:sre`) yields a single
cluster-scoped `users`+`groups` ClusterRole.
### On-behalf-of (OBO): local mint + human impersonation

A kagent agent reaching a downstream server forwards the human's muster token as
`Authorization` and its own ServiceAccount token as `X-Actor-Token`. muster
validates both and **local-mints** (`auth.mode: localMint`, `enableJWTMode: true`) a
token for the downstream audience carrying the human as `sub` and the agent SA in
the RFC 8693 `act` claim. The downstream server (e.g. mcp-kubernetes) cannot present
that token to the kube-apiserver as a bearer (wrong issuer/audience), so it
authenticates with its own SA token and sets `Impersonate-User` to the human plus
`Impersonate-Extra-actor` to the agent SA. Kubernetes RBAC and the audit log then
reflect the human, with the acting agent recorded.

A trusted-issuer token with no `act` claim is rejected: only on-behalf-of is
accepted, and any cryptographically validated actor is allowed (the impersonated
human's downstream RBAC governs access). The impersonation `ClusterRole` is rendered
by the mcp-kubernetes chart (`*-obo-impersonate`), not by agentic-platform.

---

Expand Down

This file was deleted.

This file was deleted.

40 changes: 7 additions & 33 deletions helm/agentic-platform-connectivity/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -733,22 +733,20 @@ agents:

# kagent agents, keyed by agent name. Each enabled entry renders: the Agent CR
# (prompt, model, tools); a per-agent muster RemoteMCPServer named "muster-<name>"
# whose headersFrom Secret carries the agent's OWN SA Bearer token (so muster
# authenticates tool calls as system:serviceaccount:<kagent-ns>:<serviceAccount>,
# the M2M subject); the mint Job + refresh CronJob + Secret RBAC that run as that
# SA; and, when m2m.enabled, the impersonation RBAC. Add an agent = add a key.
# whose headersFrom Secret carries the agent's OWN SA Bearer token (the
# on-behalf-of actor presented to muster as X-Actor-Token); the mint Job +
# refresh CronJob + Secret RBAC that run as that SA. Add an agent = add a key.
# Keyed by name (not a list) so per-cluster values deep-merge field-by-field — a
# cluster can flip enabled or tweak the prompt without restating the whole entry.
# The kagent controller auto-creates the SA named after the agent, which is both
# the M2M subject and the on-behalf-of actor. Agents run the Python ADK.
# The kagent controller auto-creates the SA named after the agent, which is the
# on-behalf-of actor. Agents run the Python ADK.
#
# Disabled by default; enable per cluster in giantswarm-config.
definitions:
sre-agent:
enabled: false
# SA whose token is minted and presented to muster. Defaults to the agent
# name (the SA the kagent controller creates for it). Must match the muster
# workloadGroupGrant subject and mcp-kubernetes impersonateUser.
# SA whose token is minted and presented to muster as the on-behalf-of actor.
# Defaults to the agent name (the SA the kagent controller creates for it).
serviceAccount: sre-agent
# ModelConfig CR the agent uses. Defaults to the one kagent's sub-chart
# creates from kagent.providers.anthropic.
Expand Down Expand Up @@ -831,30 +829,6 @@ agents:
resources: {}
# Optional extra env for the agent Deployment.
env: []
# Impersonation RBAC for this agent's M2M identity: lets the deputy SAs
# (mcp-kubernetes) impersonate the agent at the apiserver, and binds the
# agent's groups to ClusterRoles for its actual access. The matching muster
# workloadGroupGrant is configured in giantswarm-config; it and
# mcp-kubernetes' impersonateUser/impersonateGroups must agree with `granted`.
m2m:
enabled: false
# Identity the deputy impersonates; must equal mcp-kubernetes' impersonateUser.
# An SA-prefixed user renders a namespaced serviceaccounts Role; a plain
# username (e.g. "agent:sre") renders a cluster-scoped users rule instead.
granted:
user: "system:serviceaccount:kagent:sre-agent"
# Groups the deputy impersonates (muster injects them; the deputy also
# appends system:authenticated, which the ClusterRole therefore allows).
groups:
- agent:sre
# ClusterRoles to bind the granted groups to (the agent's actual K8s authz);
# one ClusterRoleBinding per role. Empty = no binding (granting cluster-wide
# read is left an explicit per-cluster opt-in). Set e.g. [read-all].
clusterRoles: []
# ServiceAccounts permitted to impersonate `granted` at the apiserver.
impersonators:
- name: mcp-kubernetes
namespace: mcp-kubernetes
# Agentgateway route — exposes this agent's A2A endpoint at /agents/<name>
# on the agentgateway inner Gateway (agentgateway-* ingress modes only).
# Rendered automatically when the agent is enabled. Only in-cluster callers
Expand Down
40 changes: 7 additions & 33 deletions helm/agentic-platform/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -910,25 +910,23 @@ agents:

# kagent agents, keyed by agent name. Each enabled entry renders: the Agent CR
# (prompt, model, tools); a per-agent muster RemoteMCPServer named "muster-<name>"
# whose headersFrom Secret carries the agent's OWN SA Bearer token (so muster
# authenticates tool calls as system:serviceaccount:<kagent-ns>:<serviceAccount>,
# the M2M subject); the mint Job + refresh CronJob + Secret RBAC that run as that
# SA; and, when m2m.enabled, the impersonation RBAC. Add an agent = add a key.
# whose headersFrom Secret carries the agent's OWN SA Bearer token (the
# on-behalf-of actor presented to muster as X-Actor-Token); the mint Job +
# refresh CronJob + Secret RBAC that run as that SA. Add an agent = add a key.
# An agent that forwards the human token (allowedHeaders includes "authorization",
# OBO mode) drops the headersFrom injection AND the mint Job/CronJob/RBAC — it
# presents the propagated user muster token, not an SA token.
# Keyed by name (not a list) so per-cluster values deep-merge field-by-field — a
# cluster can flip enabled or tweak the prompt without restating the whole entry.
# The kagent controller auto-creates the SA named after the agent, which is both
# the M2M subject and the on-behalf-of actor. Agents run the Python ADK.
# The kagent controller auto-creates the SA named after the agent, which is the
# on-behalf-of actor. Agents run the Python ADK.
#
# Disabled by default; enable per cluster in giantswarm-config.
definitions:
sre-agent:
enabled: false
# SA whose token is minted and presented to muster. Defaults to the agent
# name (the SA the kagent controller creates for it). Must match the muster
# workloadGroupGrant subject and mcp-kubernetes impersonateUser.
# SA whose token is minted and presented to muster as the on-behalf-of actor.
# Defaults to the agent name (the SA the kagent controller creates for it).
serviceAccount: sre-agent
# ModelConfig CR the agent uses. Defaults to the one kagent's sub-chart
# creates from kagent.providers.anthropic.
Expand Down Expand Up @@ -1010,30 +1008,6 @@ agents:
resources: {}
# Optional extra env for the agent Deployment.
env: []
# Impersonation RBAC for this agent's M2M identity: lets the deputy SAs
# (mcp-kubernetes) impersonate the agent at the apiserver, and binds the
# agent's groups to ClusterRoles for its actual access. The matching muster
# workloadGroupGrant is configured in giantswarm-config; it and
# mcp-kubernetes' impersonateUser/impersonateGroups must agree with `granted`.
m2m:
enabled: false
# Identity the deputy impersonates; must equal mcp-kubernetes' impersonateUser.
# An SA-prefixed user renders a namespaced serviceaccounts Role; a plain
# username (e.g. "agent:sre") renders a cluster-scoped users rule instead.
granted:
user: "system:serviceaccount:kagent:sre-agent"
# Groups the deputy impersonates (muster injects them; the deputy also
# appends system:authenticated, which the ClusterRole therefore allows).
groups:
- agent:sre
# ClusterRoles to bind the granted groups to (the agent's actual K8s authz);
# one ClusterRoleBinding per role. Empty = no binding (granting cluster-wide
# read is left an explicit per-cluster opt-in). Set e.g. [read-all].
clusterRoles: []
# ServiceAccounts permitted to impersonate `granted` at the apiserver.
impersonators:
- name: mcp-kubernetes
namespace: mcp-kubernetes

# List of additional RemoteMCPServer CRs to create in the kagent namespace.
# Use for MCP servers other than the built-in muster. Each entry creates one
Expand Down