1
18
19 package xds_test
20
21 import (
22 "context"
23 "fmt"
24 "testing"
25
26 "google.golang.org/grpc"
27 "google.golang.org/grpc/credentials/insecure"
28 xdscreds "google.golang.org/grpc/credentials/xds"
29 "google.golang.org/grpc/internal/stubserver"
30 "google.golang.org/grpc/internal/testutils"
31 "google.golang.org/grpc/internal/testutils/xds/e2e"
32
33 v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
34 v3tlspb "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
35 testgrpc "google.golang.org/grpc/interop/grpc_testing"
36 testpb "google.golang.org/grpc/interop/grpc_testing"
37 )
38
39 func (s) TestUnmarshalListener_WithUpdateValidatorFunc(t *testing.T) {
40 const (
41 serviceName = "my-service-client-side-xds"
42 missingIdentityProviderInstance = "missing-identity-provider-instance"
43 missingRootProviderInstance = "missing-root-provider-instance"
44 )
45
46 tests := []struct {
47 name string
48 securityConfig *v3corepb.TransportSocket
49 wantErr bool
50 }{
51 {
52 name: "both identity and root providers are not present in bootstrap",
53 securityConfig: &v3corepb.TransportSocket{
54 Name: "envoy.transport_sockets.tls",
55 ConfigType: &v3corepb.TransportSocket_TypedConfig{
56 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
57 CommonTlsContext: &v3tlspb.CommonTlsContext{
58 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
59 InstanceName: missingIdentityProviderInstance,
60 },
61 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
62 ValidationContext: &v3tlspb.CertificateValidationContext{
63 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
64 InstanceName: missingRootProviderInstance,
65 },
66 },
67 },
68 },
69 }),
70 },
71 },
72 wantErr: true,
73 },
74 {
75 name: "only identity provider is not present in bootstrap",
76 securityConfig: &v3corepb.TransportSocket{
77 Name: "envoy.transport_sockets.tls",
78 ConfigType: &v3corepb.TransportSocket_TypedConfig{
79 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
80 CommonTlsContext: &v3tlspb.CommonTlsContext{
81 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
82 InstanceName: missingIdentityProviderInstance,
83 },
84 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
85 ValidationContext: &v3tlspb.CertificateValidationContext{
86 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
87 InstanceName: e2e.ServerSideCertProviderInstance,
88 },
89 },
90 },
91 },
92 }),
93 },
94 },
95 wantErr: true,
96 },
97 {
98 name: "only root provider is not present in bootstrap",
99 securityConfig: &v3corepb.TransportSocket{
100 Name: "envoy.transport_sockets.tls",
101 ConfigType: &v3corepb.TransportSocket_TypedConfig{
102 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
103 CommonTlsContext: &v3tlspb.CommonTlsContext{
104 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
105 InstanceName: e2e.ServerSideCertProviderInstance,
106 },
107 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
108 ValidationContext: &v3tlspb.CertificateValidationContext{
109 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
110 InstanceName: missingRootProviderInstance,
111 },
112 },
113 },
114 },
115 }),
116 },
117 },
118 wantErr: true,
119 },
120 {
121 name: "both identity and root providers are present in bootstrap",
122 securityConfig: &v3corepb.TransportSocket{
123 Name: "envoy.transport_sockets.tls",
124 ConfigType: &v3corepb.TransportSocket_TypedConfig{
125 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
126 CommonTlsContext: &v3tlspb.CommonTlsContext{
127 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
128 InstanceName: e2e.ServerSideCertProviderInstance,
129 },
130 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
131 ValidationContext: &v3tlspb.CertificateValidationContext{
132 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
133 InstanceName: e2e.ServerSideCertProviderInstance,
134 },
135 },
136 },
137 },
138 }),
139 },
140 },
141 wantErr: false,
142 },
143 }
144
145 for _, test := range tests {
146 t.Run(test.name, func(t *testing.T) {
147 managementServer, nodeID, bootstrapContents, resolver, cleanup1 := e2e.SetupManagementServer(t, e2e.ManagementServerOptions{})
148 defer cleanup1()
149
150 lis, cleanup2 := setupGRPCServer(t, bootstrapContents)
151 defer cleanup2()
152
153
154
155 host, port, err := hostPortFromListener(lis)
156 if err != nil {
157 t.Fatalf("failed to retrieve host and port of server: %v", err)
158 }
159
160
161
162
163 resources := e2e.DefaultClientResources(e2e.ResourceParams{
164 DialTarget: serviceName,
165 NodeID: nodeID,
166 Host: host,
167 Port: port,
168 SecLevel: e2e.SecurityLevelMTLS,
169 })
170
171
172 inboundLis := e2e.DefaultServerListener(host, port, e2e.SecurityLevelMTLS, "routeName")
173 for _, fc := range inboundLis.GetFilterChains() {
174 fc.TransportSocket = test.securityConfig
175 }
176 resources.Listeners = append(resources.Listeners, inboundLis)
177
178 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
179 defer cancel()
180 if err := managementServer.Update(ctx, resources); err != nil {
181 t.Fatal(err)
182 }
183
184
185 creds, err := xdscreds.NewClientCredentials(xdscreds.ClientOptions{FallbackCreds: insecure.NewCredentials()})
186 if err != nil {
187 t.Fatal(err)
188 }
189
190
191 cc, err := grpc.DialContext(ctx, fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(creds), grpc.WithResolvers(resolver))
192 if err != nil {
193 t.Fatalf("failed to dial local test server: %v", err)
194 }
195 defer cc.Close()
196
197
198
199 timeout := defaultTestTimeout
200 if test.wantErr {
201 timeout = defaultTestShortTimeout
202 }
203 ctx, cancel = context.WithTimeout(ctx, timeout)
204 defer cancel()
205 client := testgrpc.NewTestServiceClient(cc)
206 if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); (err != nil) != test.wantErr {
207 t.Fatalf("EmptyCall() returned err: %v, wantErr %v", err, test.wantErr)
208 }
209 })
210 }
211 }
212
213 func (s) TestUnmarshalCluster_WithUpdateValidatorFunc(t *testing.T) {
214 const (
215 serviceName = "my-service-client-side-xds"
216 missingIdentityProviderInstance = "missing-identity-provider-instance"
217 missingRootProviderInstance = "missing-root-provider-instance"
218 )
219
220 tests := []struct {
221 name string
222 securityConfig *v3corepb.TransportSocket
223 wantErr bool
224 }{
225 {
226 name: "both identity and root providers are not present in bootstrap",
227 securityConfig: &v3corepb.TransportSocket{
228 Name: "envoy.transport_sockets.tls",
229 ConfigType: &v3corepb.TransportSocket_TypedConfig{
230 TypedConfig: testutils.MarshalAny(t, &v3tlspb.UpstreamTlsContext{
231 CommonTlsContext: &v3tlspb.CommonTlsContext{
232 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
233 InstanceName: missingIdentityProviderInstance,
234 },
235 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
236 ValidationContext: &v3tlspb.CertificateValidationContext{
237 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
238 InstanceName: missingRootProviderInstance,
239 },
240 },
241 },
242 },
243 }),
244 },
245 },
246 wantErr: true,
247 },
248 {
249 name: "only identity provider is not present in bootstrap",
250 securityConfig: &v3corepb.TransportSocket{
251 Name: "envoy.transport_sockets.tls",
252 ConfigType: &v3corepb.TransportSocket_TypedConfig{
253 TypedConfig: testutils.MarshalAny(t, &v3tlspb.UpstreamTlsContext{
254 CommonTlsContext: &v3tlspb.CommonTlsContext{
255 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
256 InstanceName: missingIdentityProviderInstance,
257 },
258 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
259 ValidationContext: &v3tlspb.CertificateValidationContext{
260 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
261 InstanceName: e2e.ClientSideCertProviderInstance,
262 },
263 },
264 },
265 },
266 }),
267 },
268 },
269 wantErr: true,
270 },
271 {
272 name: "only root provider is not present in bootstrap",
273 securityConfig: &v3corepb.TransportSocket{
274 Name: "envoy.transport_sockets.tls",
275 ConfigType: &v3corepb.TransportSocket_TypedConfig{
276 TypedConfig: testutils.MarshalAny(t, &v3tlspb.UpstreamTlsContext{
277 CommonTlsContext: &v3tlspb.CommonTlsContext{
278 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
279 InstanceName: e2e.ClientSideCertProviderInstance,
280 },
281 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
282 ValidationContext: &v3tlspb.CertificateValidationContext{
283 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
284 InstanceName: missingRootProviderInstance,
285 },
286 },
287 },
288 },
289 }),
290 },
291 },
292 wantErr: true,
293 },
294 {
295 name: "both identity and root providers are present in bootstrap",
296 securityConfig: &v3corepb.TransportSocket{
297 Name: "envoy.transport_sockets.tls",
298 ConfigType: &v3corepb.TransportSocket_TypedConfig{
299 TypedConfig: testutils.MarshalAny(t, &v3tlspb.UpstreamTlsContext{
300 CommonTlsContext: &v3tlspb.CommonTlsContext{
301 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
302 InstanceName: e2e.ClientSideCertProviderInstance,
303 },
304 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
305 ValidationContext: &v3tlspb.CertificateValidationContext{
306 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
307 InstanceName: e2e.ClientSideCertProviderInstance,
308 },
309 },
310 },
311 },
312 }),
313 },
314 },
315 wantErr: false,
316 },
317 }
318
319 for _, test := range tests {
320 t.Run(test.name, func(t *testing.T) {
321
322
323
324 managementServer, nodeID, _, resolver, cleanup1 := e2e.SetupManagementServer(t, e2e.ManagementServerOptions{})
325 defer cleanup1()
326
327 server := stubserver.StartTestService(t, nil)
328 defer server.Stop()
329
330
331
332
333 resources := e2e.DefaultClientResources(e2e.ResourceParams{
334 DialTarget: serviceName,
335 NodeID: nodeID,
336 Host: "localhost",
337 Port: testutils.ParsePort(t, server.Address),
338 SecLevel: e2e.SecurityLevelMTLS,
339 })
340 resources.Clusters[0].TransportSocket = test.securityConfig
341 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
342 defer cancel()
343 if err := managementServer.Update(ctx, resources); err != nil {
344 t.Fatal(err)
345 }
346
347 cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolver))
348 if err != nil {
349 t.Fatalf("failed to dial local test server: %v", err)
350 }
351 defer cc.Close()
352
353
354
355 timeout := defaultTestTimeout
356 if test.wantErr {
357 timeout = defaultTestShortTimeout
358 }
359 ctx2, cancel2 := context.WithTimeout(ctx, timeout)
360 defer cancel2()
361 client := testgrpc.NewTestServiceClient(cc)
362 if _, err := client.EmptyCall(ctx2, &testpb.Empty{}, grpc.WaitForReady(true)); (err != nil) != test.wantErr {
363 t.Fatalf("EmptyCall() returned err: %v, wantErr %v", err, test.wantErr)
364 }
365 })
366 }
367 }
368
View as plain text