istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/networking/core/cluster_traffic_policy_test.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 core 16 17 import ( 18 "fmt" 19 "reflect" 20 "testing" 21 22 cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" 23 core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 24 proxyprotocol "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/proxy_protocol/v3" 25 tls "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" 26 27 networking "istio.io/api/networking/v1alpha3" 28 "istio.io/istio/pilot/pkg/model" 29 "istio.io/istio/pilot/pkg/networking/util" 30 ) 31 32 func TestApplyUpstreamProxyProtocol(t *testing.T) { 33 istioMutualTLSSettings := &networking.ClientTLSSettings{ 34 Mode: networking.ClientTLSSettings_ISTIO_MUTUAL, 35 SubjectAltNames: []string{"custom.foo.com"}, 36 Sni: "custom.foo.com", 37 } 38 mutualTLSSettingsWithCerts := &networking.ClientTLSSettings{ 39 Mode: networking.ClientTLSSettings_MUTUAL, 40 CaCertificates: "root-cert.pem", 41 ClientCertificate: "cert-chain.pem", 42 PrivateKey: "key.pem", 43 SubjectAltNames: []string{"custom.foo.com"}, 44 Sni: "custom.foo.com", 45 } 46 simpleTLSSettingsWithCerts := &networking.ClientTLSSettings{ 47 Mode: networking.ClientTLSSettings_SIMPLE, 48 CaCertificates: "root-cert.pem", 49 SubjectAltNames: []string{"custom.foo.com"}, 50 Sni: "custom.foo.com", 51 } 52 53 tests := []struct { 54 name string 55 mtlsCtx mtlsContextType 56 discoveryType cluster.Cluster_DiscoveryType 57 tls *networking.ClientTLSSettings 58 proxyProtocolSettings *networking.TrafficPolicy_ProxyProtocol 59 expectTransportSocket bool 60 expectTransportSocketMatch bool 61 62 validateTLSContext func(t *testing.T, ctx *tls.UpstreamTlsContext) 63 }{ 64 { 65 name: "user specified without tls", 66 mtlsCtx: userSupplied, 67 discoveryType: cluster.Cluster_EDS, 68 tls: nil, 69 proxyProtocolSettings: &networking.TrafficPolicy_ProxyProtocol{ 70 Version: networking.TrafficPolicy_ProxyProtocol_V2, 71 }, 72 expectTransportSocket: false, 73 expectTransportSocketMatch: false, 74 }, 75 { 76 name: "user specified with istio_mutual tls", 77 mtlsCtx: userSupplied, 78 discoveryType: cluster.Cluster_EDS, 79 tls: istioMutualTLSSettings, 80 proxyProtocolSettings: &networking.TrafficPolicy_ProxyProtocol{ 81 Version: networking.TrafficPolicy_ProxyProtocol_V2, 82 }, 83 expectTransportSocket: true, 84 expectTransportSocketMatch: false, 85 validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) { 86 if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNInMeshWithMxc) { 87 t.Fatalf("expected alpn list %v; got %v", util.ALPNInMeshWithMxc, got) 88 } 89 }, 90 }, 91 { 92 name: "user specified simple tls", 93 mtlsCtx: userSupplied, 94 discoveryType: cluster.Cluster_EDS, 95 tls: simpleTLSSettingsWithCerts, 96 proxyProtocolSettings: &networking.TrafficPolicy_ProxyProtocol{ 97 Version: networking.TrafficPolicy_ProxyProtocol_V2, 98 }, 99 expectTransportSocket: true, 100 expectTransportSocketMatch: false, 101 validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) { 102 rootName := "file-root:" + mutualTLSSettingsWithCerts.CaCertificates 103 if got := ctx.CommonTlsContext.GetCombinedValidationContext().GetValidationContextSdsSecretConfig().GetName(); rootName != got { 104 t.Fatalf("expected root name %v got %v", rootName, got) 105 } 106 if got := ctx.CommonTlsContext.GetAlpnProtocols(); got != nil { 107 t.Fatalf("expected alpn list nil as not h2 or Istio_Mutual TLS Setting; got %v", got) 108 } 109 if got := ctx.GetSni(); got != simpleTLSSettingsWithCerts.Sni { 110 t.Fatalf("expected TLSContext SNI %v; got %v", simpleTLSSettingsWithCerts.Sni, got) 111 } 112 }, 113 }, 114 { 115 name: "user specified mutual tls", 116 mtlsCtx: userSupplied, 117 discoveryType: cluster.Cluster_EDS, 118 tls: mutualTLSSettingsWithCerts, 119 proxyProtocolSettings: &networking.TrafficPolicy_ProxyProtocol{ 120 Version: networking.TrafficPolicy_ProxyProtocol_V2, 121 }, 122 expectTransportSocket: true, 123 expectTransportSocketMatch: false, 124 validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) { 125 rootName := "file-root:" + mutualTLSSettingsWithCerts.CaCertificates 126 certName := fmt.Sprintf("file-cert:%s~%s", mutualTLSSettingsWithCerts.ClientCertificate, mutualTLSSettingsWithCerts.PrivateKey) 127 if got := ctx.CommonTlsContext.GetCombinedValidationContext().GetValidationContextSdsSecretConfig().GetName(); rootName != got { 128 t.Fatalf("expected root name %v got %v", rootName, got) 129 } 130 if got := ctx.CommonTlsContext.GetTlsCertificateSdsSecretConfigs()[0].GetName(); certName != got { 131 t.Fatalf("expected cert name %v got %v", certName, got) 132 } 133 if got := ctx.CommonTlsContext.GetAlpnProtocols(); got != nil { 134 t.Fatalf("expected alpn list nil as not h2 or Istio_Mutual TLS Setting; got %v", got) 135 } 136 if got := ctx.GetSni(); got != mutualTLSSettingsWithCerts.Sni { 137 t.Fatalf("expected TLSContext SNI %v; got %v", mutualTLSSettingsWithCerts.Sni, got) 138 } 139 }, 140 }, 141 { 142 name: "auto detect with tls", 143 mtlsCtx: autoDetected, 144 discoveryType: cluster.Cluster_EDS, 145 tls: istioMutualTLSSettings, 146 proxyProtocolSettings: &networking.TrafficPolicy_ProxyProtocol{ 147 Version: networking.TrafficPolicy_ProxyProtocol_V2, 148 }, 149 expectTransportSocket: false, 150 expectTransportSocketMatch: true, 151 validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) { 152 if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNInMeshWithMxc) { 153 t.Fatalf("expected alpn list %v; got %v", util.ALPNInMeshWithMxc, got) 154 } 155 }, 156 }, 157 } 158 159 proxy := &model.Proxy{ 160 Type: model.SidecarProxy, 161 Metadata: &model.NodeMetadata{}, 162 IstioVersion: &model.IstioVersion{Major: 1, Minor: 5}, 163 } 164 push := model.NewPushContext() 165 for _, test := range tests { 166 t.Run(test.name, func(t *testing.T) { 167 cb := NewClusterBuilder(proxy, &model.PushRequest{Push: push}, model.DisabledCache{}) 168 opts := &buildClusterOpts{ 169 mutable: newClusterWrapper(&cluster.Cluster{ 170 ClusterDiscoveryType: &cluster.Cluster_Type{Type: test.discoveryType}, 171 }), 172 mesh: push.Mesh, 173 } 174 cb.applyUpstreamTLSSettings(opts, test.tls, test.mtlsCtx) 175 // apply proxy protocol settings 176 cb.applyUpstreamProxyProtocol(opts, test.proxyProtocolSettings) 177 cluster := opts.mutable.cluster 178 if test.expectTransportSocket && cluster.TransportSocket == nil || 179 !test.expectTransportSocket && cluster.TransportSocket != nil { 180 t.Errorf("Expected TransportSocket %v", test.expectTransportSocket) 181 } 182 if test.expectTransportSocketMatch && cluster.TransportSocketMatches == nil || 183 !test.expectTransportSocketMatch && cluster.TransportSocketMatches != nil { 184 t.Errorf("Expected TransportSocketMatch %v", test.expectTransportSocketMatch) 185 } 186 upstreamProxyProtocol := &proxyprotocol.ProxyProtocolUpstreamTransport{} 187 if cluster.TransportSocket != nil { 188 if got := cluster.TransportSocket.Name; got != "envoy.transport_sockets.upstream_proxy_protocol" { 189 t.Errorf("Expected TransportSocket name %v, got %v", "envoy.transport_sockets.upstream_proxy_protocol", got) 190 } 191 if err := cluster.TransportSocket.GetTypedConfig().UnmarshalTo(upstreamProxyProtocol); err != nil { 192 t.Fatal(err) 193 } 194 if upstreamProxyProtocol.Config.Version != core.ProxyProtocolConfig_Version(test.proxyProtocolSettings.Version) { 195 t.Errorf("Expected proxy protocol version %v, got %v", test.proxyProtocolSettings.Version, upstreamProxyProtocol.Config.Version) 196 } 197 if test.validateTLSContext != nil { 198 ctx := &tls.UpstreamTlsContext{} 199 if err := upstreamProxyProtocol.TransportSocket.GetTypedConfig().UnmarshalTo(ctx); err != nil { 200 t.Fatal(err) 201 } 202 } 203 } 204 205 for i, match := range cluster.TransportSocketMatches { 206 if err := match.TransportSocket.GetTypedConfig().UnmarshalTo(upstreamProxyProtocol); err != nil { 207 t.Fatal(err) 208 } 209 if upstreamProxyProtocol.Config.Version != core.ProxyProtocolConfig_Version(test.proxyProtocolSettings.Version) { 210 t.Errorf("Expected proxy protocol version %v, got %v", test.proxyProtocolSettings.Version, upstreamProxyProtocol.Config.Version) 211 } 212 if test.validateTLSContext != nil && i == 0 { 213 ctx := &tls.UpstreamTlsContext{} 214 if err := upstreamProxyProtocol.TransportSocket.GetTypedConfig().UnmarshalTo(ctx); err != nil { 215 t.Fatal(err) 216 } 217 } 218 } 219 }) 220 } 221 }