github.com/kiali/kiali@v1.84.0/business/checkers/k8shttproutes/no_host_checker.go (about)

     1  package k8shttproutes
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	k8s_networking_v1 "sigs.k8s.io/gateway-api/apis/v1"
     8  	k8s_networking_v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
     9  
    10  	"github.com/kiali/kiali/kubernetes"
    11  	"github.com/kiali/kiali/models"
    12  )
    13  
    14  type NoHostChecker struct {
    15  	K8sHTTPRoute       *k8s_networking_v1.HTTPRoute
    16  	K8sReferenceGrants []*k8s_networking_v1beta1.ReferenceGrant
    17  	Namespaces         models.Namespaces
    18  	RegistryServices   []*kubernetes.RegistryService
    19  }
    20  
    21  func (n NoHostChecker) Check() ([]*models.IstioCheck, bool) {
    22  	validations := make([]*models.IstioCheck, 0)
    23  	valid := true
    24  
    25  	for k, httpRoute := range n.K8sHTTPRoute.Spec.Rules {
    26  		for i, ref := range httpRoute.BackendRefs {
    27  			if ref.Kind == nil || string(*ref.Kind) != "Service" {
    28  				continue
    29  			}
    30  			namespace := n.K8sHTTPRoute.Namespace
    31  			if ref.Namespace != nil && string(*ref.Namespace) != "" {
    32  				namespace = string(*ref.Namespace)
    33  			}
    34  			fqdn := kubernetes.GetHost(string(ref.Name), namespace, n.Namespaces.GetNames())
    35  			//service name should not be set in fqdn format
    36  			// if the http route is referencing to a service from the same namespace, then service should exist there
    37  			// if the http route is referencing to a service from other namespace, then a ReferenceGrant should exist to cross namespace reference, and the service should exist in remote namespace
    38  			if strings.Contains(string(ref.Name), ".") ||
    39  				(namespace == n.K8sHTTPRoute.Namespace && !n.checkDestination(fqdn.String(), namespace)) ||
    40  				(namespace != n.K8sHTTPRoute.Namespace && (!n.checkReferenceGrant(n.K8sHTTPRoute.Namespace, namespace) || !n.checkDestination(fqdn.String(), namespace))) {
    41  				path := fmt.Sprintf("spec/rules[%d]/backendRefs[%d]/name", k, i)
    42  				validation := models.Build("k8shttproutes.nohost.namenotfound", path)
    43  				validations = append(validations, &validation)
    44  				valid = false
    45  			}
    46  		}
    47  	}
    48  
    49  	return validations, valid
    50  }
    51  
    52  func (n NoHostChecker) checkDestination(sHost string, itemNamespace string) bool {
    53  	// Use RegistryService to check destinations that may not be covered with previous check
    54  	// i.e. Multi-cluster or Federation validations
    55  	return kubernetes.HasMatchingRegistryService(itemNamespace, sHost, n.RegistryServices)
    56  }
    57  
    58  func (n NoHostChecker) checkReferenceGrant(fromNamespace string, toNamespace string) bool {
    59  	// Use ReferenceGrant objects to check if cross namespace reference exists
    60  	return kubernetes.HasMatchingReferenceGrant(fromNamespace, toNamespace, kubernetes.K8sActualHTTPRouteType, kubernetes.ServiceType, n.K8sReferenceGrants)
    61  }