istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/networking/plugin/authn/authentication.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 authn 16 17 import ( 18 hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" 19 20 "istio.io/istio/pilot/pkg/model" 21 "istio.io/istio/pilot/pkg/networking" 22 "istio.io/istio/pilot/pkg/security/authn" 23 "istio.io/istio/pkg/log" 24 ) 25 26 var authnLog = log.RegisterScope("authn", "authn debugging") 27 28 type Builder struct { 29 applier authn.PolicyApplier 30 trustDomains []string 31 proxy *model.Proxy 32 } 33 34 func NewBuilder(push *model.PushContext, proxy *model.Proxy) *Builder { 35 return NewBuilderForService(push, proxy, nil) 36 } 37 38 func NewBuilderForService(push *model.PushContext, proxy *model.Proxy, svc *model.Service) *Builder { 39 applier := authn.NewPolicyApplier(push, proxy, svc) 40 trustDomains := TrustDomainsForValidation(push.Mesh) 41 return &Builder{ 42 applier: applier, 43 proxy: proxy, 44 trustDomains: trustDomains, 45 } 46 } 47 48 func (b *Builder) ForPort(port uint32) authn.MTLSSettings { 49 if b == nil { 50 return authn.MTLSSettings{ 51 Port: port, 52 Mode: model.MTLSDisable, 53 } 54 } 55 return b.applier.InboundMTLSSettings(port, b.proxy, b.trustDomains, authn.NoOverride) 56 } 57 58 func (b *Builder) ForHBONE() authn.MTLSSettings { 59 if b == nil { 60 return authn.MTLSSettings{ 61 Port: model.HBoneInboundListenPort, 62 Mode: model.MTLSDisable, 63 } 64 } 65 // HBONE is always strict 66 return b.applier.InboundMTLSSettings(model.HBoneInboundListenPort, b.proxy, b.trustDomains, model.MTLSStrict) 67 } 68 69 func (b *Builder) ForPassthrough() []authn.MTLSSettings { 70 if b == nil { 71 return []authn.MTLSSettings{{ 72 Port: 0, 73 Mode: model.MTLSDisable, 74 }} 75 } 76 // We need to create configuration for the passthrough, 77 // but also any ports that are not explicitly declared in the Service but are in the mTLS port level settings. 78 79 resp := []authn.MTLSSettings{ 80 // Full passthrough - no port match 81 b.applier.InboundMTLSSettings(0, b.proxy, b.trustDomains, authn.NoOverride), 82 } 83 84 // Then generate the per-port passthrough filter chains. 85 for port := range b.applier.PortLevelSetting() { 86 // Skip the per-port passthrough filterchain if the port is already handled by InboundMTLSConfiguration(). 87 if !needPerPortPassthroughFilterChain(port, b.proxy) { 88 continue 89 } 90 91 authnLog.Debugf("InboundMTLSConfiguration: build extra pass through filter chain for %v:%d", b.proxy.ID, port) 92 resp = append(resp, b.applier.InboundMTLSSettings(port, b.proxy, b.trustDomains, authn.NoOverride)) 93 } 94 return resp 95 } 96 97 func (b *Builder) BuildHTTP(class networking.ListenerClass) []*hcm.HttpFilter { 98 if b == nil { 99 return nil 100 } 101 if class == networking.ListenerClassSidecarOutbound { 102 // Only applies to inbound and gateways 103 return nil 104 } 105 if b.proxy.SupportsEnvoyExtendedJwt() { 106 filter := b.applier.JwtFilter(true, b.proxy.Type != model.SidecarProxy) 107 if filter != nil { 108 return []*hcm.HttpFilter{filter} 109 } 110 return nil 111 } 112 res := []*hcm.HttpFilter{} 113 if filter := b.applier.JwtFilter(false, false); filter != nil { 114 res = append(res, filter) 115 } 116 forSidecar := b.proxy.Type == model.SidecarProxy 117 if filter := b.applier.AuthNFilter(forSidecar); filter != nil { 118 res = append(res, filter) 119 } 120 121 return res 122 } 123 124 func needPerPortPassthroughFilterChain(port uint32, node *model.Proxy) bool { 125 // If there is any Sidecar defined, check if the port is explicitly defined there. 126 // This means the Sidecar resource takes precedence over the service. A port defined in service but not in Sidecar 127 // means the port is going to be handled by the pass through filter chain. 128 if node.SidecarScope.HasIngressListener() { 129 for _, ingressListener := range node.SidecarScope.Sidecar.Ingress { 130 if port == ingressListener.Port.Number { 131 return false 132 } 133 } 134 return true 135 } 136 137 // If there is no Sidecar, check if the port is appearing in any service. 138 for _, si := range node.ServiceTargets { 139 if port == si.Port.TargetPort { 140 return false 141 } 142 } 143 return true 144 }