github.com/kiali/kiali@v1.84.0/business/references/virtual_service_references.go (about)

     1  package references
     2  
     3  import (
     4  	networking_v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
     5  	security_v1beta "istio.io/client-go/pkg/apis/security/v1beta1"
     6  
     7  	"github.com/kiali/kiali/kubernetes"
     8  	"github.com/kiali/kiali/models"
     9  )
    10  
    11  type VirtualServiceReferences struct {
    12  	Namespace             string
    13  	Namespaces            models.Namespaces
    14  	VirtualServices       []*networking_v1beta1.VirtualService
    15  	DestinationRules      []*networking_v1beta1.DestinationRule
    16  	AuthorizationPolicies []*security_v1beta.AuthorizationPolicy
    17  }
    18  
    19  func (n VirtualServiceReferences) References() models.IstioReferencesMap {
    20  	result := models.IstioReferencesMap{}
    21  
    22  	for _, vs := range n.VirtualServices {
    23  		key := models.IstioReferenceKey{Namespace: vs.Namespace, Name: vs.Name, ObjectType: models.ObjectTypeSingular[kubernetes.VirtualServices]}
    24  		references := &models.IstioReferences{}
    25  		references.ServiceReferences = n.getServiceReferences(vs)
    26  		references.ObjectReferences = n.getConfigReferences(vs)
    27  		result.MergeReferencesMap(models.IstioReferencesMap{key: references})
    28  	}
    29  
    30  	return result
    31  }
    32  
    33  func (n VirtualServiceReferences) getServiceReferences(vs *networking_v1beta1.VirtualService) []models.ServiceReference {
    34  	keys := make(map[string]bool)
    35  	allServices := make([]models.ServiceReference, 0)
    36  	result := make([]models.ServiceReference, 0)
    37  	namespace := vs.Namespace
    38  
    39  	for _, httpRoute := range vs.Spec.Http {
    40  		if httpRoute != nil {
    41  			for _, dest := range httpRoute.Route {
    42  				if dest != nil {
    43  					host := dest.Destination.Host
    44  					if host == "" {
    45  						continue
    46  					}
    47  					fqdn := kubernetes.GetHost(host, namespace, n.Namespaces.GetNames())
    48  					if !fqdn.IsWildcard() {
    49  						allServices = append(allServices, models.ServiceReference{Name: fqdn.Service, Namespace: fqdn.Namespace})
    50  					}
    51  				}
    52  			}
    53  		}
    54  	}
    55  
    56  	for _, tcpRoute := range vs.Spec.Tcp {
    57  		if tcpRoute != nil {
    58  			for _, dest := range tcpRoute.Route {
    59  				if dest != nil {
    60  					host := dest.Destination.Host
    61  					if host == "" {
    62  						continue
    63  					}
    64  					fqdn := kubernetes.GetHost(host, namespace, n.Namespaces.GetNames())
    65  					if !fqdn.IsWildcard() {
    66  						allServices = append(allServices, models.ServiceReference{Name: fqdn.Service, Namespace: fqdn.Namespace})
    67  					}
    68  				}
    69  			}
    70  		}
    71  	}
    72  
    73  	for _, tlsRoute := range vs.Spec.Tls {
    74  		if tlsRoute != nil {
    75  			for _, dest := range tlsRoute.Route {
    76  				if dest != nil {
    77  					host := dest.Destination.Host
    78  					if host == "" {
    79  						continue
    80  					}
    81  					fqdn := kubernetes.GetHost(host, namespace, n.Namespaces.GetNames())
    82  					if !fqdn.IsWildcard() {
    83  						allServices = append(allServices, models.ServiceReference{Name: fqdn.Service, Namespace: fqdn.Namespace})
    84  					}
    85  				}
    86  			}
    87  		}
    88  	}
    89  	// filter unique references
    90  	for _, sv := range allServices {
    91  		if !keys[sv.Name+"."+sv.Namespace] {
    92  			result = append(result, sv)
    93  			keys[sv.Name+"."+sv.Namespace] = true
    94  		}
    95  	}
    96  	return result
    97  }
    98  
    99  func (n VirtualServiceReferences) getConfigReferences(vs *networking_v1beta1.VirtualService) []models.IstioReference {
   100  	keys := make(map[string]bool)
   101  	result := make([]models.IstioReference, 0)
   102  	allGateways := getAllGateways(vs)
   103  	// filter unique references
   104  	for _, gw := range allGateways {
   105  		if !keys[gw.Name+"."+gw.Namespace+"/"+gw.ObjectType] {
   106  			result = append(result, gw)
   107  			keys[gw.Name+"."+gw.Namespace+"/"+gw.ObjectType] = true
   108  		}
   109  	}
   110  	allDRs := n.getAllDestinationRules(vs)
   111  	// filter unique references
   112  	for _, dr := range allDRs {
   113  		if !keys[dr.Name+"."+dr.Namespace+"/"+dr.ObjectType] {
   114  			result = append(result, dr)
   115  			keys[dr.Name+"."+dr.Namespace+"/"+dr.ObjectType] = true
   116  		}
   117  	}
   118  	allAuthPolicies := n.getAuthPolicies(vs)
   119  	// filter unique references
   120  	for _, ap := range allAuthPolicies {
   121  		if !keys[ap.Name+"."+ap.Namespace+"/"+ap.ObjectType] {
   122  			result = append(result, ap)
   123  			keys[ap.Name+"."+ap.Namespace+"/"+ap.ObjectType] = true
   124  		}
   125  	}
   126  	return result
   127  }
   128  
   129  func (n VirtualServiceReferences) getAllDestinationRules(virtualService *networking_v1beta1.VirtualService) []models.IstioReference {
   130  	allDRs := make([]models.IstioReference, 0)
   131  	for _, dr := range n.DestinationRules {
   132  		if len(virtualService.Spec.Http) > 0 {
   133  			for _, httpRoute := range virtualService.Spec.Http {
   134  				if httpRoute == nil {
   135  					continue
   136  				}
   137  				if len(httpRoute.Route) > 0 {
   138  					for _, dest := range httpRoute.Route {
   139  						if dest == nil || dest.Destination == nil {
   140  							continue
   141  						}
   142  						host := dest.Destination.Host
   143  						drHost := kubernetes.GetHost(host, dr.Namespace, n.Namespaces.GetNames())
   144  						vsHost := kubernetes.GetHost(dr.Spec.Host, virtualService.Namespace, n.Namespaces.GetNames())
   145  						if kubernetes.FilterByHost(vsHost.String(), vsHost.Namespace, drHost.Service, drHost.Namespace) {
   146  							allDRs = append(allDRs, models.IstioReference{Name: dr.Name, Namespace: dr.Namespace, ObjectType: models.ObjectTypeSingular[kubernetes.DestinationRules]})
   147  						}
   148  					}
   149  				}
   150  			}
   151  		}
   152  
   153  		if len(virtualService.Spec.Tcp) > 0 {
   154  			for _, tcpRoute := range virtualService.Spec.Tcp {
   155  				if tcpRoute == nil {
   156  					continue
   157  				}
   158  				if len(tcpRoute.Route) > 0 {
   159  					for _, dest := range tcpRoute.Route {
   160  						if dest == nil || dest.Destination == nil {
   161  							continue
   162  						}
   163  						host := dest.Destination.Host
   164  						drHost := kubernetes.GetHost(host, dr.Namespace, n.Namespaces.GetNames())
   165  						vsHost := kubernetes.GetHost(dr.Spec.Host, virtualService.Namespace, n.Namespaces.GetNames())
   166  						if kubernetes.FilterByHost(vsHost.String(), vsHost.Namespace, drHost.Service, drHost.Namespace) {
   167  							allDRs = append(allDRs, models.IstioReference{Name: dr.Name, Namespace: dr.Namespace, ObjectType: models.ObjectTypeSingular[kubernetes.DestinationRules]})
   168  						}
   169  					}
   170  				}
   171  			}
   172  		}
   173  
   174  		if len(virtualService.Spec.Tls) > 0 {
   175  			for _, tlsRoute := range virtualService.Spec.Tls {
   176  				if tlsRoute == nil {
   177  					continue
   178  				}
   179  				if len(tlsRoute.Route) > 0 {
   180  					for _, dest := range tlsRoute.Route {
   181  						if dest == nil || dest.Destination == nil {
   182  							continue
   183  						}
   184  						host := dest.Destination.Host
   185  						drHost := kubernetes.GetHost(host, dr.Namespace, n.Namespaces.GetNames())
   186  						vsHost := kubernetes.GetHost(dr.Spec.Host, virtualService.Namespace, n.Namespaces.GetNames())
   187  						if kubernetes.FilterByHost(vsHost.String(), vsHost.Namespace, drHost.Service, drHost.Namespace) {
   188  							allDRs = append(allDRs, models.IstioReference{Name: dr.Name, Namespace: dr.Namespace, ObjectType: models.ObjectTypeSingular[kubernetes.DestinationRules]})
   189  						}
   190  					}
   191  				}
   192  			}
   193  		}
   194  	}
   195  	return allDRs
   196  }
   197  
   198  func getAllGateways(vs *networking_v1beta1.VirtualService) []models.IstioReference {
   199  	allGateways := make([]models.IstioReference, 0)
   200  	namespace := vs.Namespace
   201  	if len(vs.Spec.Gateways) > 0 {
   202  		allGateways = append(allGateways, getGatewayReferences(vs.Spec.Gateways, namespace)...)
   203  	}
   204  	if len(vs.Spec.Http) > 0 {
   205  		for _, httpRoute := range vs.Spec.Http {
   206  			if httpRoute != nil {
   207  				for _, match := range httpRoute.Match {
   208  					if match != nil && match.Gateways != nil {
   209  						allGateways = append(allGateways, getGatewayReferences(match.Gateways, namespace)...)
   210  					}
   211  				}
   212  			}
   213  		}
   214  	}
   215  	// TODO TCPMatch is not completely supported in Istio yet
   216  	if len(vs.Spec.Tls) > 0 {
   217  		for _, tlsRoute := range vs.Spec.Tls {
   218  			if tlsRoute != nil {
   219  				for _, match := range tlsRoute.Match {
   220  					if match != nil {
   221  						allGateways = append(allGateways, getGatewayReferences(match.Gateways, namespace)...)
   222  					}
   223  				}
   224  			}
   225  		}
   226  	}
   227  	return allGateways
   228  }
   229  
   230  func getGatewayReferences(gateways []string, namespace string) []models.IstioReference {
   231  	result := make([]models.IstioReference, 0)
   232  	for _, gate := range gateways {
   233  		gw := kubernetes.ParseGatewayAsHost(gate, namespace)
   234  		if !gw.IsWildcard() {
   235  			if gate == "mesh" {
   236  				result = append(result, models.IstioReference{Name: gw.Service, ObjectType: models.ObjectTypeSingular[kubernetes.Gateways]})
   237  			} else {
   238  				result = append(result, models.IstioReference{Name: gw.Service, Namespace: gw.Namespace, ObjectType: models.ObjectTypeSingular[kubernetes.Gateways]})
   239  			}
   240  		}
   241  	}
   242  	return result
   243  }
   244  
   245  func (n VirtualServiceReferences) getAuthPolicies(vs *networking_v1beta1.VirtualService) []models.IstioReference {
   246  	result := make([]models.IstioReference, 0)
   247  	for _, ap := range n.AuthorizationPolicies {
   248  		namespace := ap.Namespace
   249  		for _, rule := range ap.Spec.Rules {
   250  			if rule == nil {
   251  				continue
   252  			}
   253  			if len(rule.To) > 0 {
   254  				for _, t := range rule.To {
   255  					if t == nil || t.Operation == nil || len(t.Operation.Hosts) == 0 {
   256  						continue
   257  					}
   258  					for _, h := range t.Operation.Hosts {
   259  						fqdn := kubernetes.GetHost(h, namespace, n.Namespaces.GetNames())
   260  						if !fqdn.IsWildcard() {
   261  							for hostIdx := 0; hostIdx < len(vs.Spec.Hosts); hostIdx++ {
   262  								vHost := vs.Spec.Hosts[hostIdx]
   263  
   264  								hostS := kubernetes.ParseHost(vHost, vs.Namespace)
   265  								if hostS.String() == fqdn.String() {
   266  									result = append(result, models.IstioReference{Name: ap.Name, Namespace: ap.Namespace, ObjectType: models.ObjectTypeSingular[kubernetes.AuthorizationPolicies]})
   267  									continue
   268  								}
   269  							}
   270  						}
   271  					}
   272  				}
   273  			}
   274  		}
   275  	}
   276  	return result
   277  }