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  }