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
4 changes: 4 additions & 0 deletions api/v1alpha1/policy_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ type TargetSelector struct {
// When specified, the effective set of namespaces is always constrained to the
// namespaces watched by Envoy Gateway.
//
// Selecting targets across namespaces requires a ReferenceGrant in the target
// namespace that allows this policy kind to reference the selected target kind.
// Cross-namespace targets without a matching ReferenceGrant are ignored.
//
// +optional
Namespaces *TargetSelectorNamespaces `json:"namespaces,omitempty"`

Expand Down
4 changes: 0 additions & 4 deletions api/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ const (
// PolicyReasonDeprecatedField is used with the "Warning" condition when the policy
// uses deprecated fields that should be migrated to newer alternatives.
PolicyReasonDeprecatedField gwapiv1.PolicyConditionReason = "DeprecatedField"

// PolicyReasonRefNotPermitted is used when the policy targets a cross-namespace
// object without a matching ReferenceGrant.
PolicyReasonRefNotPermitted gwapiv1.PolicyConditionReason = "RefNotPermitted"
)
Comment thread
zhaohuabing marked this conversation as resolved.

// GroupVersionKind unambiguously identifies a Kind.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2924,6 +2924,10 @@ spec:

When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.

Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,10 @@ spec:
When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.
Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,10 @@ spec:

When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.

Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7142,6 +7142,10 @@ spec:

When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.

Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2923,6 +2923,10 @@ spec:

When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.

Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,10 @@ spec:
When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.
Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,10 @@ spec:

When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.

Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7141,6 +7141,10 @@ spec:

When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.

Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored.
properties:
from:
default: Same
Expand Down
30 changes: 4 additions & 26 deletions internal/gatewayapi/backendtrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,16 +295,14 @@ func (t *Translator) ProcessBackendTrafficPolicies(
// Process the policies targeting Routes
for i, currPolicy := range backendTrafficPolicies {
policyName := utils.NamespacedName(currPolicy)
allowed, denied := resolvePolicyTargetsFromSelectors(
currPolicy.Spec.TargetSelectors,
targetRefs := resolvePolicyTargets(
currPolicy.Spec.PolicyTargetReferences,
routes,
resources.ReferenceGrants,
egv1a1.GroupName,
egv1a1.KindBackendTrafficPolicy,
currPolicy.Namespace,
t.GetNamespace)
Comment on lines +298 to 305
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Emit status when cross-namespace selector targets are denied

This change stops tracking denied selector matches, so a policy whose cross-namespace targetSelectors lose their ReferenceGrant can drop out of the translated policy set entirely and never publish a replacement status. Because policy delete updates are ignored by the Kubernetes status subscribers (internal/provider/kubernetes/status.go skips update.Delete), the old Accepted ancestor condition can persist indefinitely even though the policy no longer applies. Fresh evidence in this commit is the removal of denied-target handling from policy processors (including this one), which makes the stale-status path reproducible during normal runtime (e.g., revoking an existing ReferenceGrant), not just during upgrade transitions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non blocking - will a ReferenceGrant, not trigger a Reconcile which will trigger a update in gateway-api layer to update status post translation ?

Copy link
Copy Markdown
Member Author

@zhaohuabing zhaohuabing May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the cross-namespace policy attachment feature does not change the pre-existing status behavior here. The same behavior already existed for selector targets before cross-namespace attachment, and this feature just makes a ReferenceGrant change another way to reach the same path.

Copy link
Copy Markdown
Member Author

@zhaohuabing zhaohuabing May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created #8926 and #8927 to track the stale status issue separately.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non blocking - will a ReferenceGrant, not trigger a Reconcile which will trigger a update in gateway-api layer to update status post translation

A ReferenceGrant will trigger a Reconcile, but stale status won't get updated for non-matching/missing ReferenceGrant due to #8927 .

plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace)
targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs)
for _, currTarget := range targetRefs {
if isRoute(currTarget) {
policy, found := handledPolicies[policyName]
Expand All @@ -318,15 +316,6 @@ func (t *Translator) ProcessBackendTrafficPolicies(
routeMap, gatewayRouteMap, gatewayPolicyMerged, gatewayPolicyMap, policy, currTarget)
}
}
if len(denied) > 0 {
policy, found := handledPolicies[policyName]
if !found {
policy = policyCopies[i]
handledPolicies[policyName] = policy
res = append(res, policy)
}
setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation)
}
}

// Process the policies targeting Listeners
Expand All @@ -351,16 +340,14 @@ func (t *Translator) ProcessBackendTrafficPolicies(
// Process the policies targeting Gateways
for i, currPolicy := range backendTrafficPolicies {
policyName := utils.NamespacedName(currPolicy)
allowed, denied := resolvePolicyTargetsFromSelectors(
currPolicy.Spec.TargetSelectors,
targetRefs := resolvePolicyTargets(
currPolicy.Spec.PolicyTargetReferences,
gateways,
resources.ReferenceGrants,
egv1a1.GroupName,
egv1a1.KindBackendTrafficPolicy,
currPolicy.Namespace,
t.GetNamespace)
plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace)
targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs)
for _, currTarget := range targetRefs {
if isGateway(currTarget) {
policy, found := handledPolicies[policyName]
Expand All @@ -373,15 +360,6 @@ func (t *Translator) ProcessBackendTrafficPolicies(
gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget)
}
}
if len(denied) > 0 {
policy, found := handledPolicies[policyName]
if !found {
policy = policyCopies[i]
handledPolicies[policyName] = policy
res = append(res, policy)
}
setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation)
}
}

for _, policy := range res {
Expand Down
15 changes: 2 additions & 13 deletions internal/gatewayapi/clienttrafficpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,15 @@ func (t *Translator) ProcessClientTrafficPolicies(
// Policy with no section set (targeting all sections)
for i, currPolicy := range clientTrafficPolicies {
policyName := utils.NamespacedName(currPolicy)
allowed, denied := resolvePolicyTargetsFromSelectors(
currPolicy.Spec.TargetSelectors,
targetRefs := resolvePolicyTargets(
currPolicy.Spec.PolicyTargetReferences,
gateways,
resources.ReferenceGrants,
egv1a1.GroupName,
egv1a1.KindClientTrafficPolicy,
currPolicy.Namespace,
t.GetNamespace,
)
plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace)
targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs)
for _, currTarget := range targetRefs {
if !hasSectionName(&currTarget) {

Expand Down Expand Up @@ -335,15 +333,6 @@ func (t *Translator) ProcessClientTrafficPolicies(
}
}
}
if len(denied) > 0 {
policy, found := handledPolicies[policyName]
if !found {
policy = policyCopies[i]
res = append(res, policy)
handledPolicies[policyName] = policy
}
setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation)
}
}

for _, policy := range res {
Expand Down
30 changes: 4 additions & 26 deletions internal/gatewayapi/envoyextensionpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,14 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(
// Process the policies targeting xRoutes
for i, currPolicy := range envoyExtensionPolicies {
policyName := utils.NamespacedName(currPolicy)
allowed, denied := resolvePolicyTargetsFromSelectors(
currPolicy.Spec.TargetSelectors,
targetRefs := resolvePolicyTargets(
currPolicy.Spec.PolicyTargetReferences,
routes,
resources.ReferenceGrants,
egv1a1.GroupName,
egv1a1.KindEnvoyExtensionPolicy,
currPolicy.Namespace,
t.GetNamespace)
plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace)
targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs)
for _, currTarget := range targetRefs {
if isRoute(currTarget) {
policy, found := handledPolicies[policyName]
Expand All @@ -159,15 +157,6 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(
routeMap, gatewayRouteMap, policy, currTarget)
}
}
if len(denied) > 0 {
policy, found := handledPolicies[policyName]
if !found {
policy = policyCopies[i]
res = append(res, policy)
handledPolicies[policyName] = policy
}
setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation)
}
}

// Process the policies targeting Listeners
Expand All @@ -193,16 +182,14 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(
// Process the policies targeting Gateways
for i, currPolicy := range envoyExtensionPolicies {
policyName := utils.NamespacedName(currPolicy)
allowed, denied := resolvePolicyTargetsFromSelectors(
currPolicy.Spec.TargetSelectors,
targetRefs := resolvePolicyTargets(
currPolicy.Spec.PolicyTargetReferences,
gateways,
resources.ReferenceGrants,
egv1a1.GroupName,
egv1a1.KindEnvoyExtensionPolicy,
currPolicy.Namespace,
t.GetNamespace)
plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace)
targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs)
for _, currTarget := range targetRefs {
if isGateway(currTarget) {
policy, found := handledPolicies[policyName]
Expand All @@ -216,15 +203,6 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(
gatewayMap, gatewayRouteMap, policy, currTarget)
}
}
if len(denied) > 0 {
policy, found := handledPolicies[policyName]
if !found {
policy = policyCopies[i]
res = append(res, policy)
handledPolicies[policyName] = policy
}
setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation)
}
}

for _, policy := range res {
Expand Down
Loading
Loading