github.com/cilium/cilium@v1.16.2/operator/pkg/gateway-api/routechecks/route_checks.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package routechecks 5 6 import ( 7 corev1 "k8s.io/api/core/v1" 8 k8serrors "k8s.io/apimachinery/pkg/api/errors" 9 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 "sigs.k8s.io/controller-runtime/pkg/client" 11 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" 12 gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" 13 14 "github.com/cilium/cilium/operator/pkg/gateway-api/helpers" 15 ) 16 17 func CheckAgainstCrossNamespaceBackendReferences(input Input) (bool, error) { 18 continueChecks := true 19 20 for _, rule := range input.GetRules() { 21 for _, be := range rule.GetBackendRefs() { 22 ns := helpers.NamespaceDerefOr(be.Namespace, input.GetNamespace()) 23 24 if ns != input.GetNamespace() && !helpers.IsBackendReferenceAllowed(input.GetNamespace(), be, input.GetGVK(), input.GetGrants()) { 25 // no reference grants, update the status for all the parents 26 input.SetAllParentCondition(metav1.Condition{ 27 Type: string(gatewayv1.RouteConditionResolvedRefs), 28 Status: metav1.ConditionFalse, 29 Reason: string(gatewayv1.RouteReasonRefNotPermitted), 30 Message: "Cross namespace references are not allowed", 31 }) 32 33 continueChecks = false 34 } 35 } 36 } 37 return continueChecks, nil 38 } 39 40 func CheckBackend(input Input) (bool, error) { 41 continueChecks := true 42 43 for _, rule := range input.GetRules() { 44 for _, be := range rule.GetBackendRefs() { 45 if !helpers.IsService(be.BackendObjectReference) && !helpers.IsServiceImport(be.BackendObjectReference) { 46 input.SetAllParentCondition(metav1.Condition{ 47 Type: string(gatewayv1alpha2.RouteConditionResolvedRefs), 48 Status: metav1.ConditionFalse, 49 Reason: string(gatewayv1.RouteReasonInvalidKind), 50 Message: "Unsupported backend kind " + string(*be.Kind), 51 }) 52 53 continueChecks = false 54 continue 55 } 56 if be.BackendObjectReference.Port == nil { 57 input.SetAllParentCondition(metav1.Condition{ 58 Type: string(gatewayv1alpha2.RouteConditionResolvedRefs), 59 Status: metav1.ConditionFalse, 60 Reason: string(gatewayv1.RouteReasonInvalidKind), 61 Message: "Must have port for backend object reference", 62 }) 63 64 continueChecks = false 65 continue 66 } 67 } 68 } 69 70 return continueChecks, nil 71 } 72 73 func CheckHasServiceImportSupport(input Input) (bool, error) { 74 for _, rule := range input.GetRules() { 75 for _, be := range rule.GetBackendRefs() { 76 if !helpers.IsServiceImport(be.BackendObjectReference) { 77 continue 78 } 79 80 if !helpers.HasServiceImportSupport(input.GetClient().Scheme()) { 81 input.SetAllParentCondition(metav1.Condition{ 82 Type: string(gatewayv1.RouteConditionResolvedRefs), 83 Status: metav1.ConditionFalse, 84 Reason: string(gatewayv1.RouteReasonBackendNotFound), 85 Message: "Attempt to reference a ServiceImport backend while " + 86 "the corresponding CRD is not installed, " + 87 "please restart the cilium-operator if the CRD is already installed", 88 }) 89 return false, nil 90 } 91 return true, nil 92 } 93 } 94 95 return true, nil 96 } 97 98 func CheckBackendIsExistingService(input Input) (bool, error) { 99 for _, rule := range input.GetRules() { 100 for _, be := range rule.GetBackendRefs() { 101 ns := helpers.NamespaceDerefOr(be.Namespace, input.GetNamespace()) 102 svcName, err := helpers.GetBackendServiceName(input.GetClient(), ns, be.BackendObjectReference) 103 if err != nil { 104 // Service Import does not exist, update the status for all the parents 105 // The `Accepted` condition on a route only describes whether 106 // the route attached successfully to its parent, so no error 107 // is returned here, so that the next validation can be run. 108 input.SetAllParentCondition(metav1.Condition{ 109 Type: string(gatewayv1.RouteConditionResolvedRefs), 110 Status: metav1.ConditionFalse, 111 Reason: string(gatewayv1.RouteReasonBackendNotFound), 112 Message: err.Error(), 113 }) 114 continue 115 } 116 svc := &corev1.Service{} 117 if err := input.GetClient().Get(input.GetContext(), client.ObjectKey{Name: svcName, Namespace: ns}, svc); err != nil { 118 if !k8serrors.IsNotFound(err) { 119 input.Log().WithError(err).Error("Failed to get Service") 120 return false, err 121 } 122 // Service does not exist, update the status for all the parents 123 // The `Accepted` condition on a route only describes whether 124 // the route attached successfully to its parent, so no error 125 // is returned here, so that the next validation can be run. 126 input.SetAllParentCondition(metav1.Condition{ 127 Type: string(gatewayv1.RouteConditionResolvedRefs), 128 Status: metav1.ConditionFalse, 129 Reason: string(gatewayv1.RouteReasonBackendNotFound), 130 Message: err.Error(), 131 }) 132 } 133 } 134 } 135 136 return true, nil 137 }