Skip to content

fix(connectivity): kagent controller cannot reach atenet-router #827

Closed

Description

@teemow

Problem

On a cluster where Cilium enforces this chart's policies, the kagent controller's requests to atenet-router:8080 are dropped and no turn reaches an actor: the rendered substrate-atenet-router policy (helm/agent-platform-connectivity/templates/substrate/netpol.yaml) was observed admitting pods labelled app.kubernetes.io/name: kagent + app.kubernetes.io/component: controller in the Substrate namespace (ate-system), while the kagent chart renders the controller into the kagent namespace. The lab renders the policies without enforcing them, so it never shows this.

The template selects $kagentNs (.Values.kagent.namespaceOverride, else .Release.Namespace) in both flavours (the Cilium fromEndpoints and the Kubernetes namespaceSelector), and the controller's own egress policy (templates/kagent/netpol.yaml) opens the router in the Substrate namespace. The rendered policy on an enforcing cluster has to be read against that: a release whose values leave kagent.namespaceOverride empty falls back to the connectivity release namespace, which is not where the controller runs.

Proposed solution

Derive the router's ingress selector from the one helper that names the namespace the kagent chart renders the controller into (the helper the kagent policies use), never from the release namespace; render it with the controller's selector labels as the kagent chart defines them (kagent.controller.selectorLabels). make verify-kagent-netpol asserts, in both flavours, that substrate-atenet-router admits the controller from that namespace on 8080. The rendered policy on an enforcing cluster is read and a turn proven after the fix.

Acceptance criteria

  • On a cluster where Cilium enforces, a turn from the kagent controller reaches an actor through atenet-router; the rendered substrate-atenet-router admits the controller's namespace and labels.
  • make verify-kagent-netpol fails when the router's ingress selects a namespace other than the controller's, in either flavour.
  • The chart README or docs/substrate-security.md names the namespace relation the policy depends on.

Activity

  1. teemow commented on Oct 7, 2026

    @teemow
    MemberAuthor

    Findings (written by an agent): the rendered policy is correct, and the observed failure has another cause.

    • On every enforcing installation checked (three), substrate-atenet-router in ate-system admits on 8080 fromEndpoints app.kubernetes.io/name: kagent, app.kubernetes.io/component: controller, io.kubernetes.pod.namespace: kagent. The kagent controller runs in kagent with exactly those labels. Its own egress policy (agent-platform-connectivity-kagent-controller-egress) opens ate-system app: atenet-router on 8080, and the atenet-router Service maps 80 to 8080. Both sides match, and no other policy selects the router.
    • Live proof: the router's access log on one installation shows an A2A SendStreamingMessage with status 200, whose source address is the kagent controller pod. A turn from the controller reaches an actor under enforcement.
    • The cause of the observed failure: the router admits 8080 only from the controller, so any other caller pod (a debugging or probe pod, including one in the kagent namespace) is dropped by design. A kubectl port-forward enters the router pod's network namespace and is not subject to the policy, which is why the probe through the host port-forward got through (its requests appear in the access log with source 127.0.0.1). This is not a policy defect: to probe the path, use the controller itself, or look at a real turn in the router's access log.

    The assertion that pins this is in #829: in both flavours, make verify-kagent-netpol checks that the router's 8080 rule admits exactly the controller from kagent.namespaceOverride, and it fails on a render that names another namespace. docs/substrate-security.md names the relation. No template change was needed.

  2. teemow commented on Oct 7, 2026

    @teemow
    MemberAuthor

    Done (written by an agent): #829 merged as 7b2e260. It is test and docs only and changes no template, so Auto-release tagged nothing and there is nothing to roll out. The live policy was already correct (see the findings above).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      Done ✅

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions