Skip to content

fix(apiserver): allow queryserver egress to Linseed via guardian on managed clusters - #5240

Draft
tianfeng92 wants to merge 1 commit into
tigera:masterfrom
tianfeng92:CI-2048-apiserver-guardian-egress
Draft

fix(apiserver): allow queryserver egress to Linseed via guardian on managed clusters#5240
tianfeng92 wants to merge 1 commit into
tigera:masterfrom
tianfeng92:CI-2048-apiserver-guardian-egress

Conversation

@tianfeng92

@tianfeng92 tianfeng92 commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Description

A managed cluster runs no local Linseed, so the query server reaches it through guardian —
the URL LinseedEndpoint returns as LINSEED_URL. The calico-system.apiserver-access
policy permitted only the local Linseed pods, whose selector matches nothing on a managed
cluster, so the connection fell through to the policy's trailing Pass. The calico-system
tier's default-deny excludes calico-apiserver by design, so the traffic is then evaluated
against the customer's tiers, where any default-deny drops it.

The Manager policy board renders empty and the API call fails:

GET /api/v1/namespaces/calico-system/services/https:calico-api:8080/proxy/policies -> 500
Error: failed to get policy activity from linseed: error connecting linseed API:
Post "https://guardian.calico-system.svc/api/v1/policy_activity": context deadline exceeded

This branches the egress rule on the same condition LINSEED_URL already uses in this file:
render.GuardianEntityRule when a ManagementClusterConnection is present, local Linseed
otherwise.

The inert local-Linseed rule stays in the base policy in pkg/render/apiserver.go. It selects
no pods on a managed cluster, and APIServerConfiguration carries no cluster type to branch
on. Moving it into the extension would correct the layering at the cost of churning the base
fixture, which is better done on master alone than in a change that cherry-picks to four
release branches.

insertEgressBeforePass is extracted rather than duplicated. The OIDC path already used the
capacity-capped egress[:n-1:n-1] slice to avoid aliasing the backing array; both callers now
share it. Behaviour is unchanged.

Introduced in #4571, which added the dependency, hardcoded the guardian URL for managed
clusters, and shipped an egress rule covering only the self-hosted destination. #4786 later
refactored the URL onto the LinseedEndpoint helper and #4871 moved it into
pkg/enterprise/apiserver/; neither added the missing rule. First shipped in operator
v1.42.0, so release-v1.42 through release-v1.44 need cherry-picks.

Addresses CI-2048.

Testing

Unit tests only; not yet verified on a live managed cluster.

  • New spec asserting the guardian rule is rendered ahead of the trailing Pass when a
    ManagementClusterConnection is present, and a companion spec asserting its absence
    otherwise. Reverting the production change while keeping the tests fails the
    managed-cluster spec.
  • pkg/enterprise/apiserver 51/51, pkg/controller/apiserver 28/28, pkg/render green.
    make format-check clean, make static-checks reports 0 issues.

Release Note

Fixed the Manager policy board rendering empty on managed clusters, where the query server was not permitted egress to Linseed through guardian.

For PR author

  • Tests for change.
  • If changing pkg/apis/, run make gen-files
  • If changing versions, run make gen-versions

For PR reviewers

A note for code reviewers - all pull requests must have the following:

  • Milestone set according to targeted release.
  • Appropriate labels:
    • kind/bug if this is a bugfix.
    • kind/enhancement if this is a a new feature.
    • enterprise if this PR applies to Calico Enterprise only.

🤖 Generated with Claude Code

…anaged clusters

A managed cluster runs no local Linseed, so the queryserver reaches it
through guardian. The apiserver-access policy only permitted the local
Linseed pods, which select nothing on a managed cluster, so the request
fell through to the trailing Pass and was denied by whatever the
customer's tiers enforce.

Branch the rule the same way LINSEED_URL is already branched in this
file: guardian when a ManagementClusterConnection is present, local
Linseed otherwise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants