github.com/kiali/kiali@v1.84.0/business/checkers/authorization/no_host_checker.go (about) 1 package authorization 2 3 import ( 4 "fmt" 5 6 api_security_v1beta "istio.io/api/security/v1beta1" 7 networking_v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" 8 security_v1beta "istio.io/client-go/pkg/apis/security/v1beta1" 9 10 "github.com/kiali/kiali/kubernetes" 11 "github.com/kiali/kiali/models" 12 ) 13 14 type NoHostChecker struct { 15 AuthorizationPolicy *security_v1beta.AuthorizationPolicy 16 Namespaces models.Namespaces 17 ServiceEntries map[string][]string 18 VirtualServices []*networking_v1beta1.VirtualService 19 RegistryServices []*kubernetes.RegistryService 20 PolicyAllowAny bool 21 } 22 23 func (n NoHostChecker) Check() ([]*models.IstioCheck, bool) { 24 checks, valid := make([]*models.IstioCheck, 0), true 25 26 // Getting rules array. If not present, quitting validation. 27 if len(n.AuthorizationPolicy.Spec.Rules) == 0 { 28 return checks, valid 29 } 30 31 // Getting slice of Rules. Quitting if not an slice. 32 for ruleIdx, rule := range n.AuthorizationPolicy.Spec.Rules { 33 if rule == nil { 34 continue 35 } 36 37 if len(rule.To) > 0 { 38 fromChecks, fromValid := n.validateHost(ruleIdx, rule.To) 39 checks = append(checks, fromChecks...) 40 valid = valid && fromValid 41 } 42 43 } 44 return checks, valid 45 } 46 47 func (n NoHostChecker) validateHost(ruleIdx int, to []*api_security_v1beta.Rule_To) ([]*models.IstioCheck, bool) { 48 if len(to) == 0 { 49 return nil, true 50 } 51 namespace := n.AuthorizationPolicy.Namespace 52 checks, valid := make([]*models.IstioCheck, 0, len(to)), true 53 for toIdx, t := range to { 54 if t == nil { 55 continue 56 } 57 58 if t.Operation == nil { 59 continue 60 } 61 62 if len(t.Operation.Hosts) == 0 { 63 continue 64 } 65 66 for hostIdx, h := range t.Operation.Hosts { 67 fqdn := kubernetes.GetHost(h, namespace, n.Namespaces.GetNames()) 68 if !n.hasMatchingService(fqdn, namespace) { 69 path := fmt.Sprintf("spec/rules[%d]/to[%d]/operation/hosts[%d]", ruleIdx, toIdx, hostIdx) 70 validation := models.Build("authorizationpolicy.nodest.matchingregistry", path) 71 if n.PolicyAllowAny { 72 validation.Severity = models.WarningSeverity 73 } 74 valid = false 75 checks = append(checks, &validation) 76 } 77 } 78 } 79 80 return checks, valid 81 } 82 83 func (n NoHostChecker) hasMatchingService(host kubernetes.Host, itemNamespace string) bool { 84 // Covering 'servicename.namespace' host format scenario 85 _, localNs := kubernetes.ParseTwoPartHost(host) 86 87 // Check wildcard hosts - needs to match "*" and "*.suffix" also.. 88 if host.IsWildcard() && localNs == itemNamespace { 89 return true 90 } 91 92 // Check ServiceEntries 93 if kubernetes.HasMatchingServiceEntries(host.String(), n.ServiceEntries) { 94 return true 95 } 96 97 // Check VirtualServices 98 if kubernetes.HasMatchingVirtualServices(host, n.VirtualServices) { 99 return true 100 } 101 102 // Use RegistryService to check destinations that may not be covered with previous check 103 // i.e. Multi-cluster or Federation validations 104 if kubernetes.HasMatchingRegistryService(itemNamespace, host.String(), n.RegistryServices) { 105 return true 106 } 107 108 return false 109 }