Skip to content

Commit 479741a

Browse files
committed
implmentation
Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com>
1 parent 7dbee3d commit 479741a

26 files changed

Lines changed: 3040 additions & 242 deletions

api/v1alpha1/shared_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ const (
6767
// PolicyReasonDeprecatedField is used with the "Warning" condition when the policy
6868
// uses deprecated fields that should be migrated to newer alternatives.
6969
PolicyReasonDeprecatedField gwapiv1.PolicyConditionReason = "DeprecatedField"
70+
71+
// PolicyReasonRefNotPermitted is used with the "Accepted" condition when the policy
72+
// targets a cross-namespace object without a matching ReferenceGrant.
73+
PolicyReasonRefNotPermitted gwapiv1.PolicyConditionReason = "RefNotPermitted"
7074
)
7175

7276
// GroupVersionKind unambiguously identifies a Kind.

internal/gatewayapi/backendtrafficpolicy.go

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ import (
1414
"time"
1515

1616
perr "github.com/pkg/errors"
17+
corev1 "k8s.io/api/core/v1"
1718
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1819
"k8s.io/apimachinery/pkg/types"
1920
"k8s.io/apimachinery/pkg/util/sets"
2021
"k8s.io/utils/ptr"
2122
"sigs.k8s.io/controller-runtime/pkg/client"
2223
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
24+
gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"
2325

2426
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
2527
egv1a1validation "github.com/envoyproxy/gateway/api/v1alpha1/validation"
@@ -68,6 +70,8 @@ func BuildBTPRoutingTypeIndex(
6870
btps []*egv1a1.BackendTrafficPolicy,
6971
routes []client.Object,
7072
gateways []*GatewayContext,
73+
referenceGrants []*gwapiv1b1.ReferenceGrant,
74+
namespaceLookup func(string) *corev1.Namespace,
7175
) *BTPRoutingTypeIndex {
7276
idx := &BTPRoutingTypeIndex{
7377
routeRuleLevel: make(map[btpRoutingKey]*egv1a1.RoutingType),
@@ -88,7 +92,18 @@ func BuildBTPRoutingTypeIndex(
8892
continue
8993
}
9094

91-
refs := getPolicyTargetRefs(btp.Spec.PolicyTargetReferences, allTargets, btp.Namespace)
95+
refs := getPolicyTargetRefs(
96+
btp.Spec.PolicyTargetReferences,
97+
allTargets,
98+
crossNamespaceFrom{
99+
group: egv1a1.GroupVersion.Group,
100+
kind: "BackendTrafficPolicy",
101+
namespace: btp.Namespace,
102+
},
103+
referenceGrants,
104+
btp.Namespace,
105+
namespaceLookup,
106+
)
92107
for _, ref := range refs {
93108
kind := string(ref.Kind)
94109
key := btpRoutingKey{
@@ -257,12 +272,22 @@ func (t *Translator) ProcessBackendTrafficPolicies(
257272
// 4. Finally, the policies targeting Gateways
258273

259274
// Build gateway policy maps, which are needed when processing the policies targeting xRoutes.
260-
t.buildGatewayPolicyMap(backendTrafficPolicies, gateways, gatewayMap, gatewayPolicyMap)
275+
t.buildGatewayPolicyMap(backendTrafficPolicies, gateways, gatewayMap, gatewayPolicyMap, resources.ReferenceGrants)
261276

262277
// Process the policies targeting RouteRules
263278
for _, currPolicy := range backendTrafficPolicies {
264279
policyName := utils.NamespacedName(currPolicy)
265-
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, routes, currPolicy.Namespace)
280+
routeMatches := getPolicySelectorTargetMatches(currPolicy.Spec.PolicyTargetReferences, routes, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, resources.ReferenceGrants, currPolicy.Namespace, t.GetNamespace)
281+
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, routes, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, resources.ReferenceGrants, currPolicy.Namespace, t.GetNamespace)
282+
if len(routeMatches.Denied) > 0 {
283+
policy, found := handledPolicies[policyName]
284+
if !found {
285+
policy = currPolicy
286+
handledPolicies[policyName] = policy
287+
res = append(res, policy)
288+
}
289+
setPolicyTargetRefNotPermittedStatus(&policy.Status, routeMatches.Denied, t.GatewayControllerName, policy.Generation)
290+
}
266291
for _, currTarget := range targetRefs {
267292
// If the target is not a gateway, then it's an xRoute. If the section name is defined, then it's a route rule.
268293
if currTarget.Kind != resource.KindGateway && currTarget.SectionName != nil {
@@ -282,7 +307,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(
282307
// Process the policies targeting Routes
283308
for _, currPolicy := range backendTrafficPolicies {
284309
policyName := utils.NamespacedName(currPolicy)
285-
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, routes, currPolicy.Namespace)
310+
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, routes, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, resources.ReferenceGrants, currPolicy.Namespace, t.GetNamespace)
286311
for _, currTarget := range targetRefs {
287312
// If the target is not a gateway, then it's an xRoute. If the section name is not defined, then it's a route.
288313
if currTarget.Kind != resource.KindGateway && currTarget.SectionName == nil {
@@ -302,7 +327,17 @@ func (t *Translator) ProcessBackendTrafficPolicies(
302327
// Process the policies targeting Listeners
303328
for _, currPolicy := range backendTrafficPolicies {
304329
policyName := utils.NamespacedName(currPolicy)
305-
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways, currPolicy.Namespace)
330+
gatewayMatches := getPolicySelectorTargetMatches(currPolicy.Spec.PolicyTargetReferences, gateways, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, resources.ReferenceGrants, currPolicy.Namespace, t.GetNamespace)
331+
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, resources.ReferenceGrants, currPolicy.Namespace, t.GetNamespace)
332+
if len(gatewayMatches.Denied) > 0 {
333+
policy, found := handledPolicies[policyName]
334+
if !found {
335+
policy = currPolicy
336+
handledPolicies[policyName] = policy
337+
res = append(res, policy)
338+
}
339+
setPolicyTargetRefNotPermittedStatus(&policy.Status, gatewayMatches.Denied, t.GatewayControllerName, policy.Generation)
340+
}
306341
for _, currTarget := range targetRefs {
307342
// If the target is a gateway and the section name is defined, then it's a listener.
308343
if currTarget.Kind == resource.KindGateway && currTarget.SectionName != nil {
@@ -312,16 +347,18 @@ func (t *Translator) ProcessBackendTrafficPolicies(
312347
handledPolicies[policyName] = policy
313348
res = append(res, policy)
314349
}
350+
targetNamespace := namespaceForPolicyTargetRef(currTarget, currPolicy.Namespace, gatewayMatches.Allowed)
315351
t.processBackendTrafficPolicyForGateway(xdsIR,
316-
gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget)
352+
gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget, targetNamespace)
317353
}
318354
}
319355
}
320356

321357
// Process the policies targeting Gateways
322358
for _, currPolicy := range backendTrafficPolicies {
323359
policyName := utils.NamespacedName(currPolicy)
324-
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways, currPolicy.Namespace)
360+
gatewayMatches := getPolicySelectorTargetMatches(currPolicy.Spec.PolicyTargetReferences, gateways, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, resources.ReferenceGrants, currPolicy.Namespace, t.GetNamespace)
361+
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, resources.ReferenceGrants, currPolicy.Namespace, t.GetNamespace)
325362
for _, currTarget := range targetRefs {
326363
// If the target is a gateway and the section name is not defined, then it's a gateway.
327364
if currTarget.Kind == resource.KindGateway && currTarget.SectionName == nil {
@@ -331,8 +368,9 @@ func (t *Translator) ProcessBackendTrafficPolicies(
331368
handledPolicies[policyName] = policy
332369
res = append(res, policy)
333370
}
371+
targetNamespace := namespaceForPolicyTargetRef(currTarget, currPolicy.Namespace, gatewayMatches.Allowed)
334372
t.processBackendTrafficPolicyForGateway(xdsIR,
335-
gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget)
373+
gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget, targetNamespace)
336374
}
337375
}
338376
}
@@ -351,15 +389,17 @@ func (t *Translator) buildGatewayPolicyMap(
351389
gateways []*GatewayContext,
352390
gatewayMap map[types.NamespacedName]*policyGatewayTargetContext,
353391
gatewayPolicyMap map[NamespacedNameWithSection]*egv1a1.BackendTrafficPolicy,
392+
referenceGrants []*gwapiv1b1.ReferenceGrant,
354393
) {
355394
for _, currPolicy := range backendTrafficPolicies {
356-
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways, currPolicy.Namespace)
395+
gatewayMatches := getPolicySelectorTargetMatches(currPolicy.Spec.PolicyTargetReferences, gateways, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, referenceGrants, currPolicy.Namespace, t.GetNamespace)
396+
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways, crossNamespaceFrom{group: egv1a1.GroupVersion.Group, kind: "BackendTrafficPolicy", namespace: currPolicy.Namespace}, referenceGrants, currPolicy.Namespace, t.GetNamespace)
357397
for _, currTarget := range targetRefs {
358398
if currTarget.Kind == resource.KindGateway {
359399
// Check if the gateway exists
360400
key := types.NamespacedName{
361401
Name: string(currTarget.Name),
362-
Namespace: currPolicy.Namespace,
402+
Namespace: namespaceForPolicyTargetRef(currTarget, currPolicy.Namespace, gatewayMatches.Allowed),
363403
}
364404
gateway, ok := gatewayMap[key]
365405
if !ok {
@@ -397,7 +437,7 @@ func (t *Translator) processBackendTrafficPolicyForRoute(
397437
gatewayPolicyMergedMap *GatewayPolicyRouteMap,
398438
gatewayPolicyMap map[NamespacedNameWithSection]*egv1a1.BackendTrafficPolicy,
399439
policy *egv1a1.BackendTrafficPolicy,
400-
currTarget gwapiv1.LocalPolicyTargetReferenceWithSectionName,
440+
currTarget PolicyTargetReferenceWithSectionName,
401441
) {
402442
var (
403443
targetedRoute RouteContext
@@ -568,7 +608,7 @@ func (t *Translator) processBackendTrafficPolicyForRoute(
568608
key := policyTargetRouteKey{
569609
Kind: string(currTarget.Kind),
570610
Name: string(currTarget.Name),
571-
Namespace: policy.Namespace,
611+
Namespace: string(currTarget.Namespace),
572612
}
573613
overriddenTargetsMessage := getOverriddenTargetsMessageForRoute(routeMap[key], currTarget.SectionName)
574614
if overriddenTargetsMessage != "" {
@@ -590,15 +630,16 @@ func (t *Translator) processBackendTrafficPolicyForGateway(
590630
gatewayRouteMap *GatewayPolicyRouteMap,
591631
gatewayPolicyMergedMap *GatewayPolicyRouteMap,
592632
policy *egv1a1.BackendTrafficPolicy,
593-
currTarget gwapiv1.LocalPolicyTargetReferenceWithSectionName,
633+
currTarget PolicyTargetReferenceWithSectionName,
634+
targetNamespace string,
594635
) {
595636
var (
596637
targetedGateway *GatewayContext
597638
resolveErr *status.PolicyResolveError
598639
)
599640

600641
// Negative statuses have already been assigned so it's safe to skip
601-
targetedGateway, resolveErr = resolveBackendTrafficPolicyGatewayTargetRef(policy, currTarget, gatewayMap)
642+
targetedGateway, resolveErr = resolveBackendTrafficPolicyGatewayTargetRef(currTarget, targetNamespace, gatewayMap)
602643
if targetedGateway == nil {
603644
return
604645
}
@@ -664,14 +705,14 @@ func (t *Translator) processBackendTrafficPolicyForGateway(
664705
}
665706

666707
func resolveBackendTrafficPolicyGatewayTargetRef(
667-
policy *egv1a1.BackendTrafficPolicy,
668-
target gwapiv1.LocalPolicyTargetReferenceWithSectionName,
708+
target PolicyTargetReferenceWithSectionName,
709+
targetNamespace string,
669710
gateways map[types.NamespacedName]*policyGatewayTargetContext,
670711
) (*GatewayContext, *status.PolicyResolveError) {
671712
// Check if the gateway exists
672713
key := types.NamespacedName{
673714
Name: string(target.Name),
674-
Namespace: policy.Namespace,
715+
Namespace: targetNamespace,
675716
}
676717
gateway, ok := gateways[key]
677718

@@ -729,14 +770,14 @@ func resolveBackendTrafficPolicyGatewayTargetRef(
729770

730771
func resolveBackendTrafficPolicyRouteTargetRef(
731772
policy *egv1a1.BackendTrafficPolicy,
732-
target gwapiv1.LocalPolicyTargetReferenceWithSectionName,
773+
target PolicyTargetReferenceWithSectionName,
733774
routes map[policyTargetRouteKey]*policyRouteTargetContext,
734775
) (RouteContext, *status.PolicyResolveError) {
735776
// Check if the route exists
736777
key := policyTargetRouteKey{
737778
Kind: string(target.Kind),
738779
Name: string(target.Name),
739-
Namespace: policy.Namespace,
780+
Namespace: string(target.Namespace),
740781
}
741782

742783
route, ok := routes[key]
@@ -789,7 +830,7 @@ func resolveBackendTrafficPolicyRouteTargetRef(
789830
func (t *Translator) translateBackendTrafficPolicyForRoute(
790831
policy *egv1a1.BackendTrafficPolicy,
791832
route RouteContext,
792-
target gwapiv1.LocalPolicyTargetReferenceWithSectionName,
833+
target PolicyTargetReferenceWithSectionName,
793834
xdsIR resource.XdsIRMap,
794835
policyTargetGatewayNN *types.NamespacedName,
795836
policyTargetListener *gwapiv1.SectionName,
@@ -815,7 +856,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(
815856

816857
func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge(
817858
policy, parentPolicy *egv1a1.BackendTrafficPolicy,
818-
target gwapiv1.LocalPolicyTargetReferenceWithSectionName,
859+
target PolicyTargetReferenceWithSectionName,
819860
policyTargetGatewayNN types.NamespacedName, policyTargetListener *gwapiv1.SectionName, route RouteContext,
820861
xdsIR resource.XdsIRMap,
821862
) error {
@@ -876,7 +917,7 @@ func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge(
876917
func (t *Translator) applyTrafficFeatureToRoute(route RouteContext,
877918
tf *ir.TrafficFeatures, errs error,
878919
policy *egv1a1.BackendTrafficPolicy,
879-
target gwapiv1.LocalPolicyTargetReferenceWithSectionName,
920+
target PolicyTargetReferenceWithSectionName,
880921
x *ir.Xds,
881922
policyTargetListener *gwapiv1.SectionName,
882923
) {
@@ -1169,7 +1210,7 @@ func buildBackendMetrics(metrics *egv1a1.BackendMetrics) *ir.BackendMetrics {
11691210
}
11701211

11711212
func (t *Translator) translateBackendTrafficPolicyForGateway(
1172-
policy *egv1a1.BackendTrafficPolicy, target gwapiv1.LocalPolicyTargetReferenceWithSectionName,
1213+
policy *egv1a1.BackendTrafficPolicy, target PolicyTargetReferenceWithSectionName,
11731214
gateway *GatewayContext, xdsIR resource.XdsIRMap,
11741215
) error {
11751216
tf, errs := t.buildTrafficFeatures(policy)

internal/gatewayapi/backendtrafficpolicy_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,7 @@ func TestBTPRoutingTypeIndex(t *testing.T) {
17441744

17451745
for _, tt := range tests {
17461746
t.Run(tt.name, func(t *testing.T) {
1747-
idx := BuildBTPRoutingTypeIndex(tt.btps, tt.routes, tt.gateways)
1747+
idx := BuildBTPRoutingTypeIndex(tt.btps, tt.routes, tt.gateways, nil, nil)
17481748
got := idx.LookupBTPRoutingType(tt.routeKind, tt.routeNN, tt.gatewayNN, tt.listenerName, tt.routeRuleName)
17491749
require.Equal(t, tt.expected, got)
17501750
})

internal/gatewayapi/clienttrafficpolicy.go

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const (
3232
AllSections = "/"
3333
)
3434

35-
func hasSectionName(target *gwapiv1.LocalPolicyTargetReferenceWithSectionName) bool {
35+
func hasSectionName(target *PolicyTargetReferenceWithSectionName) bool {
3636
return target.SectionName != nil
3737
}
3838

@@ -90,15 +90,22 @@ func (t *Translator) ProcessClientTrafficPolicies(
9090
// so there's no need to try to match targets with selectors
9191
targetRefs := currPolicy.Spec.GetTargetRefs()
9292
for _, currTarget := range targetRefs {
93-
if hasSectionName(&currTarget) {
93+
targetRef := PolicyTargetReferenceWithSectionName{
94+
Group: currTarget.Group,
95+
Kind: currTarget.Kind,
96+
Name: currTarget.Name,
97+
Namespace: gwapiv1.Namespace(currPolicy.Namespace),
98+
SectionName: currTarget.SectionName,
99+
}
100+
if hasSectionName(&targetRef) {
94101
policy, found := handledPolicies[policyName]
95102
if !found {
96103
policy = currPolicy
97104
handledPolicies[policyName] = policy
98105
res = append(res, policy)
99106
}
100107

101-
gateway, resolveErr := resolveClientTrafficPolicyTargetRef(policy, &currTarget, gatewayMap)
108+
gateway, resolveErr := resolveClientTrafficPolicyTargetRef(policy, &targetRef, gatewayMap)
102109

103110
// Negative statuses have already been assigned so its safe to skip
104111
if gateway == nil {
@@ -182,7 +189,39 @@ func (t *Translator) ProcessClientTrafficPolicies(
182189
// Policy with no section set (targeting all sections)
183190
for _, currPolicy := range clientTrafficPolicies {
184191
policyName := utils.NamespacedName(currPolicy)
185-
targetRefs := getPolicyTargetRefs(currPolicy.Spec.PolicyTargetReferences, gateways, currPolicy.Namespace)
192+
matches := getPolicySelectorTargetMatches(
193+
currPolicy.Spec.PolicyTargetReferences,
194+
gateways,
195+
crossNamespaceFrom{
196+
group: egv1a1.GroupVersion.Group,
197+
kind: "ClientTrafficPolicy",
198+
namespace: currPolicy.Namespace,
199+
},
200+
resources.ReferenceGrants,
201+
currPolicy.Namespace,
202+
t.GetNamespace,
203+
)
204+
targetRefs := getPolicyTargetRefs(
205+
currPolicy.Spec.PolicyTargetReferences,
206+
gateways,
207+
crossNamespaceFrom{
208+
group: egv1a1.GroupVersion.Group,
209+
kind: "ClientTrafficPolicy",
210+
namespace: currPolicy.Namespace,
211+
},
212+
resources.ReferenceGrants,
213+
currPolicy.Namespace,
214+
t.GetNamespace,
215+
)
216+
if len(matches.Denied) > 0 {
217+
policy, found := handledPolicies[policyName]
218+
if !found {
219+
policy = currPolicy
220+
res = append(res, policy)
221+
handledPolicies[policyName] = policy
222+
}
223+
setPolicyTargetRefNotPermittedStatus(&policy.Status, matches.Denied, t.GatewayControllerName, policy.Generation)
224+
}
186225
for _, currTarget := range targetRefs {
187226
if !hasSectionName(&currTarget) {
188227

@@ -311,13 +350,13 @@ func (t *Translator) ProcessClientTrafficPolicies(
311350

312351
func resolveClientTrafficPolicyTargetRef(
313352
policy *egv1a1.ClientTrafficPolicy,
314-
targetRef *gwapiv1.LocalPolicyTargetReferenceWithSectionName,
353+
targetRef *PolicyTargetReferenceWithSectionName,
315354
gateways map[types.NamespacedName]*policyGatewayTargetContext,
316355
) (*GatewayContext, *status.PolicyResolveError) {
317356
// Check if the gateway exists
318357
key := types.NamespacedName{
319358
Name: string(targetRef.Name),
320-
Namespace: policy.Namespace,
359+
Namespace: string(targetRef.Namespace),
321360
}
322361
gateway, ok := gateways[key]
323362

0 commit comments

Comments
 (0)