[release-v1.44] fix(apiserver): allow queryserver egress to Linseed via guardian on managed clusters - #5263
Conversation
…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>
75949d7 to
9a3542b
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes managed-cluster Manager policy board failures by ensuring the API server’s network policy allows the query server to reach Linseed via Guardian when ManagementClusterConnection is present, and includes a separate CRD regeneration commit (from make gen-versions) that updates several Calico/Enterprise CRD schemas.
Changes:
- Add a managed-cluster-specific egress allow rule to Guardian in the API server enterprise policy modifier (inserted before the trailing
Passrule). - Add unit tests covering presence/absence of the Guardian egress rule depending on whether the cluster is managed.
- Regenerate imported CRD YAMLs (FelixConfiguration/BGPConfiguration docs/enums, plus additional IPPool CEL validations and description updates).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/enterprise/apiserver/extension.go | Adds helper to insert egress rules before Pass and adds Guardian egress allow on managed clusters. |
| pkg/enterprise/apiserver/extension_test.go | Adds tests asserting Guardian egress rule is inserted before trailing Pass only on managed clusters. |
| pkg/imports/crds/enterprise/v3.projectcalico.org/projectcalico.org_felixconfigurations.yaml | CRD regen: updates bpfAttachType docs/enums and expands programClusterRoutes docs/enums/default text. |
| pkg/imports/crds/enterprise/v3.projectcalico.org/projectcalico.org_bgpconfigurations.yaml | CRD regen: expands programClusterRoutes docs/enums/default text. |
| pkg/imports/crds/enterprise/v1.crd.projectcalico.org/crd.projectcalico.org_felixconfigurations.yaml | CRD regen: same FelixConfiguration schema/doc updates as v3. |
| pkg/imports/crds/enterprise/v1.crd.projectcalico.org/crd.projectcalico.org_bgpconfigurations.yaml | CRD regen: same BGPConfiguration schema/doc updates as v1. |
| pkg/imports/crds/calico/v3.projectcalico.org/projectcalico.org_ippools.yaml | CRD regen: updates IPPool blockSize description and adds additional CEL validations. |
| pkg/imports/crds/calico/v3.projectcalico.org/projectcalico.org_felixconfigurations.yaml | CRD regen: updates bpfAttachType docs/enums/default text to include Netkit. |
| pkg/imports/crds/calico/v1.crd.projectcalico.org/crd.projectcalico.org_ippools.yaml | CRD regen: same IPPool blockSize description and CEL validation updates as v3. |
| pkg/imports/crds/calico/v1.crd.projectcalico.org/crd.projectcalico.org_felixconfigurations.yaml | CRD regen: same bpfAttachType docs/enums/default text to include Netkit. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| blockSize: | ||
| description: |- | ||
| The block size to use for IP address assignments from this pool. Defaults to 26 for IPv4 and 122 for IPv6. | ||
| The block size must be between 0 and 32 for IPv4 and between 0 and 128 for IPv6. It must also be smaller than | ||
| or equal to the size of the pool CIDR. | ||
| The block size must be between 20 and 32 for IPv4 and between 116 and 128 for IPv6. It must also be smaller | ||
| than or equal to the size of the pool CIDR. |
| blockSize: | ||
| description: |- | ||
| The block size to use for IP address assignments from this pool. Defaults to 26 for IPv4 and 122 for IPv6. | ||
| The block size must be between 0 and 32 for IPv4 and between 0 and 128 for IPv6. It must also be smaller than | ||
| or equal to the size of the pool CIDR. | ||
| The block size must be between 20 and 32 for IPv4 and between 116 and 128 for IPv6. It must also be smaller | ||
| than or equal to the size of the pool CIDR. |
make gen-versions produces changes against the committed CRDs on this branch, so validate-gen-versions fails dirty-check for every PR opened against it. Commit the regenerated output. The drift is upstream CRD movement, not a change of ours, across FelixConfiguration, IPPool and BGPConfiguration for both calico and enterprise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
9a3542b to
2d2b32e
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
pkg/imports/crds/calico/v3.projectcalico.org/projectcalico.org_ippools.yaml:97
- The updated blockSize description says it must be between 20–32 (IPv4) / 116–128 (IPv6), but the schema still allows 0 and the CEL validation explicitly allows blockSize==0. The description should mention that 0 is permitted (and what it means) to avoid confusing users.
blockSize:
description: |-
The block size to use for IP address assignments from this pool. Defaults to 26 for IPv4 and 122 for IPv6.
The block size must be between 20 and 32 for IPv4 and between 116 and 128 for IPv6. It must also be smaller
than or equal to the size of the pool CIDR.
pkg/imports/crds/calico/v1.crd.projectcalico.org/crd.projectcalico.org_ippools.yaml:72
- The updated blockSize description says it must be between 20–32 (IPv4) / 116–128 (IPv6), but the schema still allows 0 and the CEL validation explicitly allows blockSize==0. The description should mention that 0 is permitted (and what it means) to avoid confusing users.
blockSize:
description: |-
The block size to use for IP address assignments from this pool. Defaults to 26 for IPv4 and 122 for IPv6.
The block size must be between 20 and 32 for IPv4 and between 116 and 128 for IPv6. It must also be smaller
than or equal to the size of the pool CIDR.
| // insertEgressBeforePass inserts rule ahead of the policy's trailing Pass rule, so that it is | ||
| // evaluated before the tier hands the traffic to subsequent tiers. |
Description
Clean cherry-pick of #5240, no adaptation needed — this branch carries the
pkg/enterprise/apiserverextension mechanism (#4871), so the commit applies as-is.A managed cluster runs no local Linseed, so the query server reaches it through guardian —
the URL
LinseedEndpointreturns asLINSEED_URL. Thecalico-system.apiserver-accesspolicy 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. Thecalico-systemtier's default-deny excludes
calico-apiserverby design, so the traffic is then evaluatedagainst the customer's tiers, where any default-deny drops it. The Manager policy board
renders empty and policy activity requests return 500.
The rule is branched in
modifyAPIServerPolicyonmanagementClusterConnection, which is thesame condition the
LINSEED_URLenv var already uses in that file.Addresses CI-2048.
Testing
Verified on a live managed cluster on the master change (#5240): with the customer's
default-deny in a tier after
calico-system, the original operator returned the reported 500on
GET /policiesafter a 19.5s guardian timeout, and the fixed operator returned 200 in0.58s with the
calico-systemtier present. The deny stayed applied across both runs and onlythe operator image changed.
On this branch:
pkg/enterprise/apiserversuite green, including the specs covering the rulebeing rendered ahead of the trailing
Passon a managed cluster and absent otherwise.Release Note
For PR author
make gen-filesmake gen-versionsFor PR reviewers
A note for code reviewers - all pull requests must have the following:
kind/bugif this is a bugfix.kind/enhancementif this is a a new feature.enterpriseif this PR applies to Calico Enterprise only.🤖 Generated with Claude Code
Second commit — CRD regeneration.
make gen-versionsproduces changes against thecommitted CRDs on this branch, so
dirty-checkfails. A separatechore(crds)commit carriesthe regenerated output; it is isolated so it can be reviewed or dropped on its own.
FV is red on this branch regardless of this change — #5211 and #5229 both fail FV with no
CRD change at all. Note that the regenerated IPPool CRD is rejected by the API server on CEL
cost (
x-kubernetes-validations[9].rule: estimated rule cost exceeds budget by factor of more than 100x), so FV now fails atdeploy-crdsrather than on individual specs. That rule needsbounding with
maxItems/maxLengthwhere the CRD is generated upstream; fixing it there iswhat turns FV green for this branch and for #5211 and #5229.