-
Notifications
You must be signed in to change notification settings - Fork 565
Expand file tree
/
Copy pathno_k8sgateway_checker.go
More file actions
99 lines (86 loc) · 3.6 KB
/
Copy pathno_k8sgateway_checker.go
File metadata and controls
99 lines (86 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package k8shttproutes
import (
"fmt"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
k8s_networking_v1 "sigs.k8s.io/gateway-api/apis/v1"
"github.com/kiali/kiali/config"
"github.com/kiali/kiali/kubernetes"
"github.com/kiali/kiali/log"
"github.com/kiali/kiali/models"
)
type NoK8sGatewayChecker struct {
Cluster string
Conf *config.Config
GatewayNames map[string]k8s_networking_v1.Gateway
IdentityDomain string
K8sHTTPRoute *k8s_networking_v1.HTTPRoute
Namespaces models.Namespaces
}
// Check validates that the HTTPRoute is pointing to an existing Gateway
func (s NoK8sGatewayChecker) Check() ([]*models.IstioCheck, bool) {
validations := make([]*models.IstioCheck, 0)
valid := s.ValidateHTTPRouteGateways(&validations)
return validations, valid
}
// ValidateHTTPRouteGateways checks all HTTPRoute gateways and checks that they're found from the given list of gatewayNames. Also return index of missing gatways to show clearer error path in editor
func (s NoK8sGatewayChecker) ValidateHTTPRouteGateways(validations *[]*models.IstioCheck) bool {
valid := true
gvk := kubernetes.K8sGateways
if len(s.K8sHTTPRoute.Spec.ParentRefs) > 0 {
for index, parentRef := range s.K8sHTTPRoute.Spec.ParentRefs {
if string(parentRef.Name) != "" && string(*parentRef.Kind) == gvk.Kind && string(*parentRef.Group) == gvk.Group {
gwNs := s.K8sHTTPRoute.Namespace
if parentRef.Namespace != nil && string(*parentRef.Namespace) != "" {
gwNs = string(*parentRef.Namespace)
}
valid = CheckGateway(string(parentRef.Name), gwNs, s.K8sHTTPRoute.Namespace, s.Cluster, s.GatewayNames, s.Namespaces, validations, fmt.Sprintf("spec/parentRefs[%d]/name/%s", index, string(parentRef.Name)), s.IdentityDomain) && valid
}
}
}
return valid
}
func CheckGateway(gwName, gwNs, routeNs, cluster string, gatewayNames map[string]k8s_networking_v1.Gateway, nss models.Namespaces, validations *[]*models.IstioCheck, location string, identityDomain string) bool {
hostname := kubernetes.ParseGatewayAsHost(gwName, gwNs, identityDomain)
for gw := range gatewayNames {
gwHostname := kubernetes.ParseHost(gw, gwNs, identityDomain)
if found := kubernetes.FilterByHost(hostname.String(), hostname.Namespace, gw, gwHostname.Namespace, identityDomain); found {
if gwHostname.Namespace == routeNs {
return true
} else if IsGatewaySharedWithNS(routeNs, cluster, gatewayNames[gw], nss) {
return true
}
}
}
validation := models.Build("k8sroutes.nok8sgateway", location)
*validations = append(*validations, &validation)
return false
}
// IsGatewaySharedWithNS returns true if any listener on the Gateway allows
// routes from the given namespace via allowedRoutes.namespaces. It supports
// the full Kubernetes LabelSelector (both matchLabels and matchExpressions).
func IsGatewaySharedWithNS(namespace string, cluster string, gw k8s_networking_v1.Gateway, nss models.Namespaces) bool {
ns := nss.GetNamespace(namespace, cluster)
if ns == nil {
return false
}
for _, l := range gw.Spec.Listeners {
if l.AllowedRoutes == nil || l.AllowedRoutes.Namespaces == nil || l.AllowedRoutes.Namespaces.From == nil {
continue
}
if *l.AllowedRoutes.Namespaces.From == "All" {
return true
}
if *l.AllowedRoutes.Namespaces.From == "Selector" && l.AllowedRoutes.Namespaces.Selector != nil {
selector, err := meta_v1.LabelSelectorAsSelector(l.AllowedRoutes.Namespaces.Selector)
if err != nil {
log.Errorf("skipping invalid gateway allowedRoutes selector: %v", err)
continue
}
if selector.Matches(labels.Set(ns.Labels)) {
return true
}
}
}
return false
}