istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/config/analysis/analyzers/k8sgateway/workloadselector.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package k8sgateway
    16  
    17  import (
    18  	typev1beta1 "istio.io/api/type/v1beta1"
    19  	"istio.io/istio/pkg/config"
    20  	"istio.io/istio/pkg/config/analysis"
    21  	"istio.io/istio/pkg/config/analysis/msg"
    22  	"istio.io/istio/pkg/config/constants"
    23  	"istio.io/istio/pkg/config/resource"
    24  	"istio.io/istio/pkg/config/schema/gvk"
    25  	"istio.io/istio/pkg/maps"
    26  )
    27  
    28  var _ analysis.Analyzer = &SelectorAnalyzer{}
    29  
    30  type SelectorAnalyzer struct{}
    31  
    32  var policyGVKs = []config.GroupVersionKind{
    33  	gvk.AuthorizationPolicy,
    34  	gvk.RequestAuthentication,
    35  	gvk.Telemetry,
    36  	gvk.WasmPlugin,
    37  }
    38  
    39  type policy interface {
    40  	GetSelector() *typev1beta1.WorkloadSelector
    41  	GetTargetRef() *typev1beta1.PolicyTargetReference
    42  }
    43  
    44  func (w *SelectorAnalyzer) Metadata() analysis.Metadata {
    45  	return analysis.Metadata{
    46  		Name:        "k8sgateway.SelectorAnalyzer",
    47  		Description: "Check that selectors are effective for Kubernetes gateway",
    48  		Inputs: []config.GroupVersionKind{
    49  			gvk.AuthorizationPolicy,
    50  			gvk.RequestAuthentication,
    51  			gvk.Telemetry,
    52  			gvk.WasmPlugin,
    53  			gvk.Pod,
    54  		},
    55  	}
    56  }
    57  
    58  // Analyze implements analysis.Analyzer
    59  func (w *SelectorAnalyzer) Analyze(context analysis.Context) {
    60  	pods := gatewayPodsLabelMap(context)
    61  
    62  	handleResource := func(r *resource.Instance, gvkType config.GroupVersionKind) {
    63  		spec, ok := r.Message.(policy)
    64  		if spec.GetTargetRef() != nil {
    65  			return
    66  		}
    67  		if !ok || spec.GetSelector() == nil {
    68  			return
    69  		}
    70  		selector := spec.GetSelector()
    71  		for _, pod := range pods[r.Metadata.FullName.Namespace.String()] {
    72  			if maps.Contains(pod, selector.MatchLabels) {
    73  				context.Report(gvkType, msg.NewIneffectiveSelector(r, pod[constants.GatewayNameLabel]))
    74  			}
    75  		}
    76  	}
    77  
    78  	for _, gvkType := range policyGVKs {
    79  		context.ForEach(gvkType, func(r *resource.Instance) bool {
    80  			handleResource(r, gvkType)
    81  			return true
    82  		})
    83  	}
    84  }
    85  
    86  // gatewayPodsLabelMap returns a map of pod namespaces to labels for all pods with a gateway label
    87  func gatewayPodsLabelMap(context analysis.Context) map[string][]map[string]string {
    88  	pods := make(map[string][]map[string]string)
    89  	context.ForEach(gvk.Pod, func(resource *resource.Instance) bool {
    90  		if _, ok := resource.Metadata.Labels[constants.GatewayNameLabel]; !ok {
    91  			return true
    92  		}
    93  		ns := resource.Metadata.FullName.Namespace.String()
    94  		pods[ns] = append(pods[ns], resource.Metadata.Labels)
    95  		return true
    96  	})
    97  	return pods
    98  }