Skip to content

Task: remove the github-tool-mcp token-exchange bridge once the production tool is SPIFFE-registered #252

Open

Description

@anatolykoyfman

Background

PR #242 moves the AuthBridge outbound leg to token-exchange-aiac, which has no routes: it derives the audience from the destination host (spiffe://<td>/ns/<ns>/sa/<service>). The production GitHub tool from cortex's github-issue demo doesn't fit that form. Its Service is github-tool-mcp, but it has no ServiceAccount of that name, and its Keycloak client is a hand-made plain github-tool. So token-exchange-aiac can't derive its client, and the demo agent's calls to it (MCP_URL=http://github-tool-mcp:9090/mcp) were not exchanged.

To keep those calls working, #242 puts one bridge entry on the outbound leg (k8s/opa-kind-enable.sh): the older token-exchange plugin, before token-exchange-aiac, with exactly one inline route:

- host: "github-tool-mcp"
  target_audience: "github-tool"
  token_scopes: "openid github-tool-aud"

default_policy: passthrough, so every other host goes on, untouched, to token-exchange-aiac. routes.file: /dev/null, so no authproxy-routes ConfigMap is read. The wiring check (k8s/authbridge-pipeline-check.py, _bridge_problem) accepts token-exchange only in exactly this form.

The real fix is on the cortex side, rossoctl/cortex#1540, which cortex closed as deferred on 2026-10-29: the Kubernetes path is not their current priority.

Task

Remove the bridge once the production tool is registered as spiffe://<td>/ns/team1/sa/github-tool-mcp. That means a ServiceAccount github-tool-mcp and an enrollment, so the operator creates that client (rossoctl/cortex#1540).

Files

  • k8s/opa-kind-enable.sh: the token-exchange entry and its comment block.
  • k8s/authbridge-pipeline-check.py: BRIDGE_ROUTE and _bridge_problem; then require token-exchange not at all.
  • test/unit/pipeline_configs.py and test/unit/test_launcher_outcome.py: the bridge cases.
  • docs/specs/PRD.md D36: the bridge bullet. k8s/opa-kind-runbook.md, demo/assets/INSTALL.md, demo/assets/agents/github_agent/README.md, docs/specs/demo/github-agent.md: the bridge notes.

Acceptance criteria

  • No token-exchange entry on the outbound leg; the wiring check rejects one again.
  • A call from github-agent to github-tool-mcp:9090/mcp is exchanged by token-exchange-aiac (aud = spiffe://<td>/ns/team1/sa/github-tool-mcp).
  • The docs no longer mention the bridge.
  • Removing the bridge needs no special order. Once …/sa/github-tool-mcp exists, token-exchange-aiac exchanges the bridge's token for it, provided github-agent holds agent-team1-github-tool-mcp-aud as a default scope (the demo's WIRE grants it as soon as the scope exists); without that link, each bridged call gets a 403 audience_not_granted. Keycloak accepts a subject token whose aud is another client when its azp is the caller (checked on Keycloak 26.5.2).

Blocked on rossoctl/cortex#1540. Related: #247.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions