github.com/kiali/kiali@v1.84.0/business/checkers/destinationrules/traffic_policy_checker.go (about) 1 package destinationrules 2 3 import ( 4 "fmt" 5 6 networking_v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" 7 8 "github.com/kiali/kiali/kubernetes" 9 "github.com/kiali/kiali/models" 10 ) 11 12 type TrafficPolicyChecker struct { 13 DestinationRules []*networking_v1beta1.DestinationRule 14 MTLSDetails kubernetes.MTLSDetails 15 } 16 17 func (t TrafficPolicyChecker) Check() models.IstioValidations { 18 validations := models.IstioValidations{} 19 20 refdMtls := t.drsWithNonLocalmTLSEnabled() 21 22 // Check whether DRs override mTLS. 23 for _, dr := range t.DestinationRules { 24 drSameHosts := sameHostDestinationRules(dr, refdMtls, t.DestinationRules) 25 26 // Continue if there aren't DestinationRules enabling mTLS non-locally 27 // and pointing to same host as dr. 28 if len(drSameHosts) == 0 { 29 continue 30 } 31 32 // Invalid if there isn't trafficPolicy specified or trafficPolicy doesn't specify TLSSettings 33 if !hasTrafficPolicy(dr) || !hasTLSSettings(dr) { 34 check := models.Build("destinationrules.trafficpolicy.notlssettings", "spec/trafficPolicy") 35 key := models.BuildKey(DestinationRulesCheckerType, dr.Name, dr.Namespace) 36 37 refKeys := make([]models.IstioValidationKey, 0, len(refdMtls)) 38 for _, dr := range drSameHosts { 39 refKeys = append(refKeys, models.BuildKey(DestinationRulesCheckerType, dr.Name, dr.Namespace)) 40 } 41 42 validation := buildDestinationRuleValidation(dr, check, true, refKeys) 43 44 if _, exists := validations[key]; !exists { 45 validations.MergeValidations(models.IstioValidations{key: validation}) 46 } 47 } 48 } 49 50 return validations 51 } 52 53 func (t TrafficPolicyChecker) drsWithNonLocalmTLSEnabled() []*networking_v1beta1.DestinationRule { 54 mtlsDrs := make([]*networking_v1beta1.DestinationRule, 0) 55 for _, dr := range t.MTLSDetails.DestinationRules { 56 fqdn := kubernetes.ParseHost(dr.Spec.Host, dr.Namespace) 57 if isNonLocalmTLSForServiceEnabled(dr, fqdn.String()) { 58 mtlsDrs = append(mtlsDrs, dr) 59 } 60 } 61 return mtlsDrs 62 } 63 64 func sameHostDestinationRules(dr *networking_v1beta1.DestinationRule, mdrs []*networking_v1beta1.DestinationRule, edrs []*networking_v1beta1.DestinationRule) []*networking_v1beta1.DestinationRule { 65 shdrs := make([]*networking_v1beta1.DestinationRule, 0, len(mdrs)+len(edrs)) 66 drHost := kubernetes.ParseHost(dr.Spec.Host, dr.Namespace) 67 68 for _, mdr := range mdrs { 69 mdrHost := kubernetes.ParseHost(mdr.Spec.Host, dr.Namespace) 70 if mdrHost.Service == "*.local" || 71 (mdrHost.Cluster == drHost.Cluster && mdrHost.Namespace == drHost.Namespace) { 72 shdrs = append(shdrs, mdr) 73 } 74 } 75 76 for _, edr := range edrs { 77 // skip the current DR 78 if edr.Name == dr.Name && edr.Namespace == dr.Namespace { 79 continue 80 } 81 dHost := edr.Spec.Host 82 if ismTLSEnabled(edr) && 83 (dHost == fmt.Sprintf("*.%s.%s", drHost.Namespace, drHost.Cluster) || dHost == drHost.String()) { 84 shdrs = append(shdrs, edr) 85 } 86 } 87 88 return shdrs 89 } 90 91 func hasTrafficPolicy(dr *networking_v1beta1.DestinationRule) bool { 92 return dr.Spec.TrafficPolicy != nil 93 } 94 95 func hasTLSSettings(dr *networking_v1beta1.DestinationRule) bool { 96 return hasTrafficPolicyTLS(dr) || hasPortTLS(dr) 97 } 98 99 // hasPortTLS returns true when there is one port that specifies any TLS settings 100 func hasPortTLS(dr *networking_v1beta1.DestinationRule) bool { 101 if dr.Spec.TrafficPolicy != nil { 102 for _, portLevel := range dr.Spec.TrafficPolicy.PortLevelSettings { 103 if portLevel.Tls != nil { 104 return true 105 } 106 } 107 } 108 return false 109 } 110 111 // hasTrafficPolicyTLS returns true when there is a trafficPolicy specifying any tls mode 112 func hasTrafficPolicyTLS(dr *networking_v1beta1.DestinationRule) bool { 113 if dr.Spec.TrafficPolicy != nil && dr.Spec.TrafficPolicy.Tls != nil { 114 return true 115 } 116 return false 117 } 118 119 func buildDestinationRuleValidation(dr *networking_v1beta1.DestinationRule, checks models.IstioCheck, valid bool, refKeys []models.IstioValidationKey) *models.IstioValidation { 120 validation := &models.IstioValidation{ 121 Name: dr.Name, 122 ObjectType: DestinationRulesCheckerType, 123 Valid: valid, 124 Checks: []*models.IstioCheck{ 125 &checks, 126 }, 127 References: refKeys, 128 } 129 130 return validation 131 }