istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/xds/endpoints/mtls_checker.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 endpoints
    16  
    17  import (
    18  	endpoint "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
    19  
    20  	networkingapi "istio.io/api/networking/v1alpha3"
    21  	"istio.io/istio/pilot/pkg/model"
    22  	"istio.io/istio/pilot/pkg/networking/util"
    23  	"istio.io/istio/pilot/pkg/security/authn"
    24  	"istio.io/istio/pkg/config"
    25  )
    26  
    27  // TODO this logic is probably done elsewhere in XDS, possible code-reuse + perf improvements
    28  type mtlsChecker struct {
    29  	push            *model.PushContext
    30  	svcPort         int
    31  	destinationRule *networkingapi.ClientTLSSettings_TLSmode
    32  }
    33  
    34  func newMtlsChecker(push *model.PushContext, svcPort int, dr *config.Config, subset string) *mtlsChecker {
    35  	return &mtlsChecker{
    36  		push:            push,
    37  		svcPort:         svcPort,
    38  		destinationRule: tlsModeForDestinationRule(dr, subset, svcPort),
    39  	}
    40  }
    41  
    42  // isMtlsEnabled returns true if the given lbEp has mTLS enabled.
    43  func isMtlsEnabled(lbEp *endpoint.LbEndpoint) bool {
    44  	return lbEp.Metadata.FilterMetadata[util.EnvoyTransportSocketMetadataKey].
    45  		GetFields()[model.TLSModeLabelShortname].
    46  		GetStringValue() == model.IstioMutualTLSModeLabel
    47  }
    48  
    49  // checkMtlsEnabled computes whether mTLS should be enabled or not. This is determined based
    50  // on the DR, original endpoint TLSMode (based on injection of sidecar), and PeerAuthentication settings.
    51  func (c *mtlsChecker) checkMtlsEnabled(ep *model.IstioEndpoint, isWaypoint bool) bool {
    52  	if drMode := c.destinationRule; drMode != nil {
    53  		return *drMode == networkingapi.ClientTLSSettings_ISTIO_MUTUAL
    54  	}
    55  
    56  	// if endpoint has no sidecar or explicitly tls disabled by "security.istio.io/tlsMode" label.
    57  	if ep.TLSMode != model.IstioMutualTLSModeLabel {
    58  		return false
    59  	}
    60  
    61  	return authn.
    62  		NewMtlsPolicy(c.push, ep.Namespace, ep.Labels, isWaypoint).
    63  		GetMutualTLSModeForPort(ep.EndpointPort) != model.MTLSDisable
    64  }
    65  
    66  func tlsModeForDestinationRule(drc *config.Config, subset string, port int) *networkingapi.ClientTLSSettings_TLSmode {
    67  	if drc == nil {
    68  		return nil
    69  	}
    70  	dr, ok := drc.Spec.(*networkingapi.DestinationRule)
    71  	if !ok || dr == nil {
    72  		return nil
    73  	}
    74  
    75  	if subset == "" {
    76  		return trafficPolicyTLSModeForPort(dr.GetTrafficPolicy(), port)
    77  	}
    78  
    79  	for _, ss := range dr.Subsets {
    80  		if ss.Name != subset {
    81  			continue
    82  		}
    83  		return trafficPolicyTLSModeForPort(ss.GetTrafficPolicy(), port)
    84  	}
    85  	return nil
    86  }
    87  
    88  func trafficPolicyTLSModeForPort(tp *networkingapi.TrafficPolicy, port int) *networkingapi.ClientTLSSettings_TLSmode {
    89  	if tp == nil {
    90  		return nil
    91  	}
    92  	var mode *networkingapi.ClientTLSSettings_TLSmode
    93  	if tp.Tls != nil {
    94  		mode = &tp.Tls.Mode
    95  	}
    96  	// if there is a port-level setting matching this cluster
    97  	for _, portSettings := range tp.GetPortLevelSettings() {
    98  		if int(portSettings.GetPort().GetNumber()) == port && portSettings.Tls != nil {
    99  			mode = &portSettings.Tls.Mode
   100  			break
   101  		}
   102  	}
   103  	return mode
   104  }