1313package controller
1414
1515import (
16+ "cmp"
1617 "context"
1718 "encoding/pem"
1819 "errors"
@@ -31,6 +32,8 @@ import (
3132 "k8s.io/apimachinery/pkg/labels"
3233 "k8s.io/apimachinery/pkg/types"
3334 "sigs.k8s.io/controller-runtime/pkg/client"
35+ "sigs.k8s.io/controller-runtime/pkg/event"
36+ "sigs.k8s.io/controller-runtime/pkg/predicate"
3437 "sigs.k8s.io/controller-runtime/pkg/reconcile"
3538 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
3639 "sigs.k8s.io/gateway-api/apis/v1beta1"
@@ -736,19 +739,32 @@ func getListenerStatus(
736739 conditionProgrammed .Reason = string (gatewayv1 .ListenerReasonInvalid )
737740 break
738741 }
739- if ok := checkReferenceGrantBetweenGatewayAndSecret (gateway .Namespace , ref , grants ); ! ok {
740- conditionResolvedRefs .Status = metav1 .ConditionFalse
741- conditionResolvedRefs .Reason = string (gatewayv1 .ListenerReasonRefNotPermitted )
742- conditionResolvedRefs .Message = "certificateRefs cross namespaces is not permitted"
743- conditionProgrammed .Status = metav1 .ConditionFalse
744- conditionProgrammed .Reason = string (gatewayv1 .ListenerReasonInvalid )
745- break
746- }
747- ns := gateway .Namespace
748- if ref .Namespace != nil {
749- ns = string (* ref .Namespace )
742+ // if cross namespaces, check if the Gateway has the permission to access the Secret
743+ if ref .Namespace != nil && string (* ref .Namespace ) != gateway .Namespace {
744+ if ok := checkReferenceGrant (
745+ v1beta1.ReferenceGrantFrom {
746+ Group : gatewayv1 .GroupName ,
747+ Kind : KindGateway ,
748+ Namespace : v1beta1 .Namespace (gateway .Namespace ),
749+ },
750+ v1beta1.ReferenceGrantTo {
751+ Group : corev1 .GroupName ,
752+ Kind : KindSecret ,
753+ Name : & ref .Name ,
754+ },
755+ grants ,
756+ ); ! ok {
757+ conditionResolvedRefs .Status = metav1 .ConditionFalse
758+ conditionResolvedRefs .Reason = string (gatewayv1 .ListenerReasonRefNotPermitted )
759+ conditionResolvedRefs .Message = "certificateRefs cross namespaces is not permitted"
760+ conditionProgrammed .Status = metav1 .ConditionFalse
761+ conditionProgrammed .Reason = string (gatewayv1 .ListenerReasonInvalid )
762+ break
763+ }
750764 }
751- if err := mrgc .Get (ctx , client.ObjectKey {Namespace : ns , Name : string (ref .Name )}, & secret ); err != nil {
765+
766+ ns := cmp .Or (ref .Namespace , (* gatewayv1 .Namespace )(& gateway .Namespace ))
767+ if err := mrgc .Get (ctx , client.ObjectKey {Namespace : string (* ns ), Name : string (ref .Name )}, & secret ); err != nil {
752768 conditionResolvedRefs .Status = metav1 .ConditionFalse
753769 conditionResolvedRefs .Reason = string (gatewayv1 .ListenerReasonInvalidCertificateRef )
754770 conditionResolvedRefs .Message = err .Error ()
@@ -1070,28 +1086,36 @@ func isTLSSecretValid(secret *corev1.Secret) (string, bool) {
10701086 return "" , true
10711087}
10721088
1073- func checkReferenceGrantBetweenGatewayAndSecret (gwNamespace string , certRef gatewayv1.SecretObjectReference , grants []v1beta1.ReferenceGrant ) bool {
1074- // if not cross namespaces
1075- if certRef .Namespace == nil || string (* certRef .Namespace ) == gwNamespace {
1076- return true
1089+ func referenceGrantPredicates (kind gatewayv1.Kind ) predicate.Funcs {
1090+ var filter = func (obj client.Object ) bool {
1091+ grant , ok := obj .(* v1beta1.ReferenceGrant )
1092+ if ! ok {
1093+ return false
1094+ }
1095+ for _ , from := range grant .Spec .From {
1096+ if from .Kind == kind && string (from .Group ) == gatewayv1 .GroupName {
1097+ return true
1098+ }
1099+ }
1100+ return false
1101+ }
1102+ predicates := predicate .NewPredicateFuncs (filter )
1103+ predicates .UpdateFunc = func (e event.UpdateEvent ) bool {
1104+ return filter (e .ObjectOld ) || filter (e .ObjectNew )
10771105 }
1106+ return predicates
1107+ }
10781108
1109+ func checkReferenceGrant (from v1beta1.ReferenceGrantFrom , to v1beta1.ReferenceGrantTo , grants []v1beta1.ReferenceGrant ) bool {
10791110 for _ , grant := range grants {
1080- if grant .Namespace == string (* certRef .Namespace ) {
1081- for _ , from := range grant .Spec .From {
1082- gw := v1beta1.ReferenceGrantFrom {
1083- Group : gatewayv1 .GroupName ,
1084- Kind : KindGateway ,
1085- Namespace : v1beta1 .Namespace (gwNamespace ),
1086- }
1087- if from == gw {
1088- for _ , to := range grant .Spec .To {
1089- if to .Group == corev1 .GroupName && to .Kind == KindSecret && (to .Name == nil || * to .Name == certRef .Name ) {
1090- return true
1091- }
1092- }
1093- }
1094- }
1111+ grantFrom := slices .ContainsFunc (grant .Spec .From , func (item v1beta1.ReferenceGrantFrom ) bool {
1112+ return item == from
1113+ })
1114+ grantTo := slices .ContainsFunc (grant .Spec .To , func (item v1beta1.ReferenceGrantTo ) bool {
1115+ return item .Group == to .Group && item .Kind == to .Kind && to .Name != nil && (item .Name == nil || * item .Name == * to .Name )
1116+ })
1117+ if grantFrom && grantTo {
1118+ return true
10951119 }
10961120 }
10971121 return false
0 commit comments