1
17
18 package xdsresource
19
20 import (
21 "fmt"
22 "strings"
23 "testing"
24 "time"
25
26 v2xdspb "github.com/envoyproxy/go-control-plane/envoy/api/v2"
27 "github.com/google/go-cmp/cmp"
28 "google.golang.org/grpc/internal/pretty"
29 "google.golang.org/grpc/internal/testutils"
30 "google.golang.org/grpc/internal/testutils/xds/e2e"
31 "google.golang.org/grpc/xds/internal/httpfilter"
32 "google.golang.org/grpc/xds/internal/xdsclient/xdsresource/version"
33 "google.golang.org/protobuf/proto"
34 "google.golang.org/protobuf/types/known/anypb"
35 "google.golang.org/protobuf/types/known/durationpb"
36 "google.golang.org/protobuf/types/known/structpb"
37 "google.golang.org/protobuf/types/known/wrapperspb"
38
39 v1xdsudpatypepb "github.com/cncf/xds/go/udpa/type/v1"
40 v3xdsxdstypepb "github.com/cncf/xds/go/xds/type/v3"
41 v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
42 v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
43 rpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3"
44 v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
45 v3rbacpb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/rbac/v3"
46 v3httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
47 v3tlspb "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
48 v3discoverypb "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
49 v3matcherpb "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
50
51 _ "google.golang.org/grpc/xds/internal/httpfilter/rbac"
52 _ "google.golang.org/grpc/xds/internal/httpfilter/router"
53 )
54
55 func (s) TestUnmarshalListener_ClientSide(t *testing.T) {
56 const (
57 v3LDSTarget = "lds.target.good:3333"
58 v3RouteConfigName = "v3RouteConfig"
59 routeName = "routeName"
60 )
61
62 var (
63 customFilter = &v3httppb.HttpFilter{
64 Name: "customFilter",
65 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: customFilterConfig},
66 }
67 oldTypedStructFilter = &v3httppb.HttpFilter{
68 Name: "customFilter",
69 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: testutils.MarshalAny(t, customFilterOldTypedStructConfig)},
70 }
71 newTypedStructFilter = &v3httppb.HttpFilter{
72 Name: "customFilter",
73 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: testutils.MarshalAny(t, customFilterNewTypedStructConfig)},
74 }
75 customOptionalFilter = &v3httppb.HttpFilter{
76 Name: "customFilter",
77 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: customFilterConfig},
78 IsOptional: true,
79 }
80 customFilter2 = &v3httppb.HttpFilter{
81 Name: "customFilter2",
82 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: customFilterConfig},
83 }
84 errFilter = &v3httppb.HttpFilter{
85 Name: "errFilter",
86 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: errFilterConfig},
87 }
88 errOptionalFilter = &v3httppb.HttpFilter{
89 Name: "errFilter",
90 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: errFilterConfig},
91 IsOptional: true,
92 }
93 clientOnlyCustomFilter = &v3httppb.HttpFilter{
94 Name: "clientOnlyCustomFilter",
95 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: clientOnlyCustomFilterConfig},
96 }
97 serverOnlyCustomFilter = &v3httppb.HttpFilter{
98 Name: "serverOnlyCustomFilter",
99 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: serverOnlyCustomFilterConfig},
100 }
101 serverOnlyOptionalCustomFilter = &v3httppb.HttpFilter{
102 Name: "serverOnlyOptionalCustomFilter",
103 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: serverOnlyCustomFilterConfig},
104 IsOptional: true,
105 }
106 unknownFilter = &v3httppb.HttpFilter{
107 Name: "unknownFilter",
108 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: unknownFilterConfig},
109 }
110 unknownOptionalFilter = &v3httppb.HttpFilter{
111 Name: "unknownFilter",
112 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: unknownFilterConfig},
113 IsOptional: true,
114 }
115 v3LisWithInlineRoute = testutils.MarshalAny(t, &v3listenerpb.Listener{
116 Name: v3LDSTarget,
117 ApiListener: &v3listenerpb.ApiListener{
118 ApiListener: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
119 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
120 RouteConfig: &v3routepb.RouteConfiguration{
121 Name: routeName,
122 VirtualHosts: []*v3routepb.VirtualHost{{
123 Domains: []string{v3LDSTarget},
124 Routes: []*v3routepb.Route{{
125 Match: &v3routepb.RouteMatch{
126 PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"},
127 },
128 Action: &v3routepb.Route_Route{
129 Route: &v3routepb.RouteAction{
130 ClusterSpecifier: &v3routepb.RouteAction_Cluster{Cluster: clusterName},
131 }}}}}}},
132 },
133 HttpFilters: []*v3httppb.HttpFilter{emptyRouterFilter},
134 CommonHttpProtocolOptions: &v3corepb.HttpProtocolOptions{
135 MaxStreamDuration: durationpb.New(time.Second),
136 },
137 }),
138 },
139 })
140 v3LisWithFilters = func(fs ...*v3httppb.HttpFilter) *anypb.Any {
141 fs = append(fs, emptyRouterFilter)
142 return testutils.MarshalAny(t, &v3listenerpb.Listener{
143 Name: v3LDSTarget,
144 ApiListener: &v3listenerpb.ApiListener{
145 ApiListener: testutils.MarshalAny(t,
146 &v3httppb.HttpConnectionManager{
147 RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{
148 Rds: &v3httppb.Rds{
149 ConfigSource: &v3corepb.ConfigSource{
150 ConfigSourceSpecifier: &v3corepb.ConfigSource_Ads{Ads: &v3corepb.AggregatedConfigSource{}},
151 },
152 RouteConfigName: v3RouteConfigName,
153 },
154 },
155 CommonHttpProtocolOptions: &v3corepb.HttpProtocolOptions{
156 MaxStreamDuration: durationpb.New(time.Second),
157 },
158 HttpFilters: fs,
159 }),
160 },
161 })
162 }
163 v3LisToTestRBAC = func(xffNumTrustedHops uint32, originalIpDetectionExtensions []*v3corepb.TypedExtensionConfig) *anypb.Any {
164 return testutils.MarshalAny(t, &v3listenerpb.Listener{
165 Name: v3LDSTarget,
166 ApiListener: &v3listenerpb.ApiListener{
167 ApiListener: testutils.MarshalAny(t,
168 &v3httppb.HttpConnectionManager{
169 RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{
170 Rds: &v3httppb.Rds{
171 ConfigSource: &v3corepb.ConfigSource{
172 ConfigSourceSpecifier: &v3corepb.ConfigSource_Ads{Ads: &v3corepb.AggregatedConfigSource{}},
173 },
174 RouteConfigName: v3RouteConfigName,
175 },
176 },
177 CommonHttpProtocolOptions: &v3corepb.HttpProtocolOptions{
178 MaxStreamDuration: durationpb.New(time.Second),
179 },
180 HttpFilters: []*v3httppb.HttpFilter{emptyRouterFilter},
181 XffNumTrustedHops: xffNumTrustedHops,
182 OriginalIpDetectionExtensions: originalIpDetectionExtensions,
183 }),
184 },
185 })
186 }
187
188 v3ListenerWithCDSConfigSourceSelf = testutils.MarshalAny(t, &v3listenerpb.Listener{
189 Name: v3LDSTarget,
190 ApiListener: &v3listenerpb.ApiListener{
191 ApiListener: testutils.MarshalAny(t,
192 &v3httppb.HttpConnectionManager{
193 RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{
194 Rds: &v3httppb.Rds{
195 ConfigSource: &v3corepb.ConfigSource{
196 ConfigSourceSpecifier: &v3corepb.ConfigSource_Self{},
197 },
198 RouteConfigName: v3RouteConfigName,
199 },
200 },
201 HttpFilters: []*v3httppb.HttpFilter{emptyRouterFilter},
202 }),
203 },
204 })
205 )
206
207 tests := []struct {
208 name string
209 resource *anypb.Any
210 wantName string
211 wantUpdate ListenerUpdate
212 wantErr bool
213 }{
214 {
215 name: "non-listener resource",
216 resource: &anypb.Any{TypeUrl: version.V3HTTPConnManagerURL},
217 wantErr: true,
218 },
219 {
220 name: "badly marshaled listener resource",
221 resource: &anypb.Any{
222 TypeUrl: version.V3ListenerURL,
223 Value: func() []byte {
224 lis := &v3listenerpb.Listener{
225 Name: v3LDSTarget,
226 ApiListener: &v3listenerpb.ApiListener{
227 ApiListener: &anypb.Any{
228 TypeUrl: version.V3HTTPConnManagerURL,
229 Value: []byte{1, 2, 3, 4},
230 },
231 },
232 }
233 mLis, _ := proto.Marshal(lis)
234 return mLis
235 }(),
236 },
237 wantName: v3LDSTarget,
238 wantErr: true,
239 },
240 {
241 name: "wrong type in apiListener",
242 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
243 Name: v3LDSTarget,
244 ApiListener: &v3listenerpb.ApiListener{
245 ApiListener: testutils.MarshalAny(t, &v2xdspb.Listener{}),
246 },
247 }),
248 wantName: v3LDSTarget,
249 wantErr: true,
250 },
251 {
252 name: "empty httpConnMgr in apiListener",
253 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
254 Name: v3LDSTarget,
255 ApiListener: &v3listenerpb.ApiListener{
256 ApiListener: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
257 RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{
258 Rds: &v3httppb.Rds{},
259 },
260 }),
261 },
262 }),
263 wantName: v3LDSTarget,
264 wantErr: true,
265 },
266 {
267 name: "scopedRoutes routeConfig in apiListener",
268 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
269 Name: v3LDSTarget,
270 ApiListener: &v3listenerpb.ApiListener{
271 ApiListener: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
272 RouteSpecifier: &v3httppb.HttpConnectionManager_ScopedRoutes{},
273 }),
274 },
275 }),
276 wantName: v3LDSTarget,
277 wantErr: true,
278 },
279 {
280 name: "rds.ConfigSource in apiListener is Self",
281 resource: v3ListenerWithCDSConfigSourceSelf,
282 wantName: v3LDSTarget,
283 wantUpdate: ListenerUpdate{
284 RouteConfigName: v3RouteConfigName,
285 HTTPFilters: []HTTPFilter{makeRouterFilter(t)},
286 Raw: v3ListenerWithCDSConfigSourceSelf,
287 },
288 },
289 {
290 name: "rds.ConfigSource in apiListener is not ADS or Self",
291 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
292 Name: v3LDSTarget,
293 ApiListener: &v3listenerpb.ApiListener{
294 ApiListener: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
295 RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{
296 Rds: &v3httppb.Rds{
297 ConfigSource: &v3corepb.ConfigSource{
298 ConfigSourceSpecifier: &v3corepb.ConfigSource_Path{
299 Path: "/some/path",
300 },
301 },
302 RouteConfigName: v3RouteConfigName,
303 },
304 },
305 }),
306 },
307 }),
308 wantName: v3LDSTarget,
309 wantErr: true,
310 },
311 {
312 name: "v3 with no filters",
313 resource: v3LisWithFilters(),
314 wantName: v3LDSTarget,
315 wantUpdate: ListenerUpdate{
316 RouteConfigName: v3RouteConfigName,
317 MaxStreamDuration: time.Second,
318 HTTPFilters: makeRouterFilterList(t),
319 Raw: v3LisWithFilters(),
320 },
321 },
322 {
323 name: "v3 no terminal filter",
324 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
325 Name: v3LDSTarget,
326 ApiListener: &v3listenerpb.ApiListener{
327 ApiListener: testutils.MarshalAny(t,
328 &v3httppb.HttpConnectionManager{
329 RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{
330 Rds: &v3httppb.Rds{
331 ConfigSource: &v3corepb.ConfigSource{
332 ConfigSourceSpecifier: &v3corepb.ConfigSource_Ads{Ads: &v3corepb.AggregatedConfigSource{}},
333 },
334 RouteConfigName: v3RouteConfigName,
335 },
336 },
337 CommonHttpProtocolOptions: &v3corepb.HttpProtocolOptions{
338 MaxStreamDuration: durationpb.New(time.Second),
339 },
340 }),
341 },
342 }),
343 wantName: v3LDSTarget,
344 wantErr: true,
345 },
346 {
347 name: "v3 with custom filter",
348 resource: v3LisWithFilters(customFilter),
349 wantName: v3LDSTarget,
350 wantUpdate: ListenerUpdate{
351 RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second,
352 HTTPFilters: []HTTPFilter{
353 {
354 Name: "customFilter",
355 Filter: httpFilter{},
356 Config: filterConfig{Cfg: customFilterConfig},
357 },
358 makeRouterFilter(t),
359 },
360 Raw: v3LisWithFilters(customFilter),
361 },
362 },
363 {
364 name: "v3 with custom filter in old typed struct",
365 resource: v3LisWithFilters(oldTypedStructFilter),
366 wantName: v3LDSTarget,
367 wantUpdate: ListenerUpdate{
368 RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second,
369 HTTPFilters: []HTTPFilter{
370 {
371 Name: "customFilter",
372 Filter: httpFilter{},
373 Config: filterConfig{Cfg: customFilterOldTypedStructConfig},
374 },
375 makeRouterFilter(t),
376 },
377 Raw: v3LisWithFilters(oldTypedStructFilter),
378 },
379 },
380 {
381 name: "v3 with custom filter in new typed struct",
382 resource: v3LisWithFilters(newTypedStructFilter),
383 wantName: v3LDSTarget,
384 wantUpdate: ListenerUpdate{
385 RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second,
386 HTTPFilters: []HTTPFilter{
387 {
388 Name: "customFilter",
389 Filter: httpFilter{},
390 Config: filterConfig{Cfg: customFilterNewTypedStructConfig},
391 },
392 makeRouterFilter(t),
393 },
394 Raw: v3LisWithFilters(newTypedStructFilter),
395 },
396 },
397 {
398 name: "v3 with optional custom filter",
399 resource: v3LisWithFilters(customOptionalFilter),
400 wantName: v3LDSTarget,
401 wantUpdate: ListenerUpdate{
402 RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second,
403 HTTPFilters: []HTTPFilter{
404 {
405 Name: "customFilter",
406 Filter: httpFilter{},
407 Config: filterConfig{Cfg: customFilterConfig},
408 },
409 makeRouterFilter(t),
410 },
411 Raw: v3LisWithFilters(customOptionalFilter),
412 },
413 },
414 {
415 name: "v3 with two filters with same name",
416 resource: v3LisWithFilters(customFilter, customFilter),
417 wantName: v3LDSTarget,
418 wantErr: true,
419 },
420 {
421 name: "v3 with two filters - same type different name",
422 resource: v3LisWithFilters(customFilter, customFilter2),
423 wantName: v3LDSTarget,
424 wantUpdate: ListenerUpdate{
425 RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second,
426 HTTPFilters: []HTTPFilter{{
427 Name: "customFilter",
428 Filter: httpFilter{},
429 Config: filterConfig{Cfg: customFilterConfig},
430 }, {
431 Name: "customFilter2",
432 Filter: httpFilter{},
433 Config: filterConfig{Cfg: customFilterConfig},
434 },
435 makeRouterFilter(t),
436 },
437 Raw: v3LisWithFilters(customFilter, customFilter2),
438 },
439 },
440 {
441 name: "v3 with server-only filter",
442 resource: v3LisWithFilters(serverOnlyCustomFilter),
443 wantName: v3LDSTarget,
444 wantErr: true,
445 },
446 {
447 name: "v3 with optional server-only filter",
448 resource: v3LisWithFilters(serverOnlyOptionalCustomFilter),
449 wantName: v3LDSTarget,
450 wantUpdate: ListenerUpdate{
451 RouteConfigName: v3RouteConfigName,
452 MaxStreamDuration: time.Second,
453 Raw: v3LisWithFilters(serverOnlyOptionalCustomFilter),
454 HTTPFilters: makeRouterFilterList(t),
455 },
456 },
457 {
458 name: "v3 with client-only filter",
459 resource: v3LisWithFilters(clientOnlyCustomFilter),
460 wantName: v3LDSTarget,
461 wantUpdate: ListenerUpdate{
462 RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second,
463 HTTPFilters: []HTTPFilter{
464 {
465 Name: "clientOnlyCustomFilter",
466 Filter: clientOnlyHTTPFilter{},
467 Config: filterConfig{Cfg: clientOnlyCustomFilterConfig},
468 },
469 makeRouterFilter(t)},
470 Raw: v3LisWithFilters(clientOnlyCustomFilter),
471 },
472 },
473 {
474 name: "v3 with err filter",
475 resource: v3LisWithFilters(errFilter),
476 wantName: v3LDSTarget,
477 wantErr: true,
478 },
479 {
480 name: "v3 with optional err filter",
481 resource: v3LisWithFilters(errOptionalFilter),
482 wantName: v3LDSTarget,
483 wantErr: true,
484 },
485 {
486 name: "v3 with unknown filter",
487 resource: v3LisWithFilters(unknownFilter),
488 wantName: v3LDSTarget,
489 wantErr: true,
490 },
491 {
492 name: "v3 with unknown filter (optional)",
493 resource: v3LisWithFilters(unknownOptionalFilter),
494 wantName: v3LDSTarget,
495 wantUpdate: ListenerUpdate{
496 RouteConfigName: v3RouteConfigName,
497 MaxStreamDuration: time.Second,
498 HTTPFilters: makeRouterFilterList(t),
499 Raw: v3LisWithFilters(unknownOptionalFilter),
500 },
501 },
502 {
503 name: "v3 listener resource",
504 resource: v3LisWithFilters(),
505 wantName: v3LDSTarget,
506 wantUpdate: ListenerUpdate{
507 RouteConfigName: v3RouteConfigName,
508 MaxStreamDuration: time.Second,
509 HTTPFilters: makeRouterFilterList(t),
510 Raw: v3LisWithFilters(),
511 },
512 },
513 {
514 name: "v3 listener resource wrapped",
515 resource: testutils.MarshalAny(t, &v3discoverypb.Resource{Resource: v3LisWithFilters()}),
516 wantName: v3LDSTarget,
517 wantUpdate: ListenerUpdate{
518 RouteConfigName: v3RouteConfigName,
519 MaxStreamDuration: time.Second,
520 HTTPFilters: makeRouterFilterList(t),
521 Raw: v3LisWithFilters(),
522 },
523 },
524
525
526
527
528 {
529 name: "rbac-allow-equating-direct-remote-ip-and-remote-ip-valid",
530 resource: v3LisToTestRBAC(0, nil),
531 wantName: v3LDSTarget,
532 wantUpdate: ListenerUpdate{
533 RouteConfigName: v3RouteConfigName,
534 MaxStreamDuration: time.Second,
535 HTTPFilters: []HTTPFilter{makeRouterFilter(t)},
536 Raw: v3LisToTestRBAC(0, nil),
537 },
538 },
539
540
541
542
543
544 {
545 name: "rbac-allow-equating-direct-remote-ip-and-remote-ip-invalid-num-untrusted-hops",
546 resource: v3LisToTestRBAC(1, nil),
547 wantName: v3LDSTarget,
548 wantErr: true,
549 },
550
551
552
553
554 {
555 name: "rbac-allow-equating-direct-remote-ip-and-remote-ip-invalid-original-ip-detection-extension",
556 resource: v3LisToTestRBAC(0, []*v3corepb.TypedExtensionConfig{{Name: "something"}}),
557 wantName: v3LDSTarget,
558 wantErr: true,
559 },
560 {
561 name: "v3 listener with inline route configuration",
562 resource: v3LisWithInlineRoute,
563 wantName: v3LDSTarget,
564 wantUpdate: ListenerUpdate{
565 InlineRouteConfig: &RouteConfigUpdate{
566 VirtualHosts: []*VirtualHost{{
567 Domains: []string{v3LDSTarget},
568 Routes: []*Route{{Prefix: newStringP("/"), WeightedClusters: map[string]WeightedCluster{clusterName: {Weight: 1}}, ActionType: RouteActionRoute}},
569 }}},
570 MaxStreamDuration: time.Second,
571 Raw: v3LisWithInlineRoute,
572 HTTPFilters: makeRouterFilterList(t),
573 },
574 },
575 }
576
577 for _, test := range tests {
578 t.Run(test.name, func(t *testing.T) {
579 name, update, err := unmarshalListenerResource(test.resource)
580 if (err != nil) != test.wantErr {
581 t.Errorf("unmarshalListenerResource(%s), got err: %v, wantErr: %v", pretty.ToJSON(test.resource), err, test.wantErr)
582 }
583 if name != test.wantName {
584 t.Errorf("unmarshalListenerResource(%s), got name: %s, want: %s", pretty.ToJSON(test.resource), name, test.wantName)
585 }
586 if diff := cmp.Diff(update, test.wantUpdate, cmpOpts); diff != "" {
587 t.Errorf("unmarshalListenerResource(%s), got unexpected update, diff (-got +want): %v", pretty.ToJSON(test.resource), diff)
588 }
589 })
590 }
591 }
592
593 func (s) TestUnmarshalListener_ServerSide(t *testing.T) {
594 const (
595 v3LDSTarget = "grpc/server?xds.resource.listening_address=0.0.0.0:9999"
596 testVersion = "test-version-lds-server"
597 )
598
599 var (
600 serverOnlyCustomFilter = &v3httppb.HttpFilter{
601 Name: "serverOnlyCustomFilter",
602 ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: serverOnlyCustomFilterConfig},
603 }
604 routeConfig = &v3routepb.RouteConfiguration{
605 Name: "routeName",
606 VirtualHosts: []*v3routepb.VirtualHost{{
607 Domains: []string{"lds.target.good:3333"},
608 Routes: []*v3routepb.Route{{
609 Match: &v3routepb.RouteMatch{
610 PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"},
611 },
612 Action: &v3routepb.Route_NonForwardingAction{},
613 }}}}}
614 inlineRouteConfig = &RouteConfigUpdate{
615 VirtualHosts: []*VirtualHost{{
616 Domains: []string{"lds.target.good:3333"},
617 Routes: []*Route{{Prefix: newStringP("/"), ActionType: RouteActionNonForwardingAction}},
618 }}}
619 emptyValidNetworkFilters = []*v3listenerpb.Filter{
620 {
621 Name: "filter-1",
622 ConfigType: &v3listenerpb.Filter_TypedConfig{
623 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
624 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
625 RouteConfig: routeConfig,
626 },
627 HttpFilters: []*v3httppb.HttpFilter{e2e.RouterHTTPFilter},
628 }),
629 },
630 },
631 }
632 localSocketAddress = &v3corepb.Address{
633 Address: &v3corepb.Address_SocketAddress{
634 SocketAddress: &v3corepb.SocketAddress{
635 Address: "0.0.0.0",
636 PortSpecifier: &v3corepb.SocketAddress_PortValue{
637 PortValue: 9999,
638 },
639 },
640 },
641 }
642 listenerEmptyTransportSocket = testutils.MarshalAny(t, &v3listenerpb.Listener{
643 Name: v3LDSTarget,
644 Address: localSocketAddress,
645 FilterChains: []*v3listenerpb.FilterChain{
646 {
647 Name: "filter-chain-1",
648 Filters: emptyValidNetworkFilters,
649 },
650 },
651 })
652 listenerNoValidationContextDeprecatedFields = testutils.MarshalAny(t, &v3listenerpb.Listener{
653 Name: v3LDSTarget,
654 Address: localSocketAddress,
655 FilterChains: []*v3listenerpb.FilterChain{
656 {
657 Name: "filter-chain-1",
658 Filters: emptyValidNetworkFilters,
659 TransportSocket: &v3corepb.TransportSocket{
660 Name: "envoy.transport_sockets.tls",
661 ConfigType: &v3corepb.TransportSocket_TypedConfig{
662 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
663 CommonTlsContext: &v3tlspb.CommonTlsContext{
664 TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
665 InstanceName: "identityPluginInstance",
666 CertificateName: "identityCertName",
667 },
668 },
669 }),
670 },
671 },
672 },
673 },
674 DefaultFilterChain: &v3listenerpb.FilterChain{
675 Name: "default-filter-chain-1",
676 Filters: emptyValidNetworkFilters,
677 TransportSocket: &v3corepb.TransportSocket{
678 Name: "envoy.transport_sockets.tls",
679 ConfigType: &v3corepb.TransportSocket_TypedConfig{
680 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
681 CommonTlsContext: &v3tlspb.CommonTlsContext{
682 TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
683 InstanceName: "defaultIdentityPluginInstance",
684 CertificateName: "defaultIdentityCertName",
685 },
686 },
687 }),
688 },
689 },
690 },
691 })
692 listenerNoValidationContextNewFields = testutils.MarshalAny(t, &v3listenerpb.Listener{
693 Name: v3LDSTarget,
694 Address: localSocketAddress,
695 FilterChains: []*v3listenerpb.FilterChain{
696 {
697 Name: "filter-chain-1",
698 Filters: emptyValidNetworkFilters,
699 TransportSocket: &v3corepb.TransportSocket{
700 Name: "envoy.transport_sockets.tls",
701 ConfigType: &v3corepb.TransportSocket_TypedConfig{
702 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
703 CommonTlsContext: &v3tlspb.CommonTlsContext{
704 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
705 InstanceName: "identityPluginInstance",
706 CertificateName: "identityCertName",
707 },
708 },
709 }),
710 },
711 },
712 },
713 },
714 DefaultFilterChain: &v3listenerpb.FilterChain{
715 Name: "default-filter-chain-1",
716 Filters: emptyValidNetworkFilters,
717 TransportSocket: &v3corepb.TransportSocket{
718 Name: "envoy.transport_sockets.tls",
719 ConfigType: &v3corepb.TransportSocket_TypedConfig{
720 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
721 CommonTlsContext: &v3tlspb.CommonTlsContext{
722 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
723 InstanceName: "defaultIdentityPluginInstance",
724 CertificateName: "defaultIdentityCertName",
725 },
726 },
727 }),
728 },
729 },
730 },
731 })
732 listenerWithValidationContextDeprecatedFields = testutils.MarshalAny(t, &v3listenerpb.Listener{
733 Name: v3LDSTarget,
734 Address: localSocketAddress,
735 FilterChains: []*v3listenerpb.FilterChain{
736 {
737 Name: "filter-chain-1",
738 Filters: emptyValidNetworkFilters,
739 TransportSocket: &v3corepb.TransportSocket{
740 Name: "envoy.transport_sockets.tls",
741 ConfigType: &v3corepb.TransportSocket_TypedConfig{
742 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
743 RequireClientCertificate: &wrapperspb.BoolValue{Value: true},
744 CommonTlsContext: &v3tlspb.CommonTlsContext{
745 TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
746 InstanceName: "identityPluginInstance",
747 CertificateName: "identityCertName",
748 },
749 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContextCertificateProviderInstance{
750 ValidationContextCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
751 InstanceName: "rootPluginInstance",
752 CertificateName: "rootCertName",
753 },
754 },
755 },
756 }),
757 },
758 },
759 },
760 },
761 DefaultFilterChain: &v3listenerpb.FilterChain{
762 Name: "default-filter-chain-1",
763 Filters: emptyValidNetworkFilters,
764 TransportSocket: &v3corepb.TransportSocket{
765 Name: "envoy.transport_sockets.tls",
766 ConfigType: &v3corepb.TransportSocket_TypedConfig{
767 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
768 RequireClientCertificate: &wrapperspb.BoolValue{Value: true},
769 CommonTlsContext: &v3tlspb.CommonTlsContext{
770 TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
771 InstanceName: "defaultIdentityPluginInstance",
772 CertificateName: "defaultIdentityCertName",
773 },
774 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContextCertificateProviderInstance{
775 ValidationContextCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
776 InstanceName: "defaultRootPluginInstance",
777 CertificateName: "defaultRootCertName",
778 },
779 },
780 },
781 }),
782 },
783 },
784 },
785 })
786 listenerWithValidationContextNewFields = testutils.MarshalAny(t, &v3listenerpb.Listener{
787 Name: v3LDSTarget,
788 Address: localSocketAddress,
789 FilterChains: []*v3listenerpb.FilterChain{
790 {
791 Name: "filter-chain-1",
792 Filters: emptyValidNetworkFilters,
793 TransportSocket: &v3corepb.TransportSocket{
794 Name: "envoy.transport_sockets.tls",
795 ConfigType: &v3corepb.TransportSocket_TypedConfig{
796 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
797 RequireClientCertificate: &wrapperspb.BoolValue{Value: true},
798 CommonTlsContext: &v3tlspb.CommonTlsContext{
799 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
800 InstanceName: "identityPluginInstance",
801 CertificateName: "identityCertName",
802 },
803 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContext{
804 ValidationContext: &v3tlspb.CertificateValidationContext{
805 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
806 InstanceName: "rootPluginInstance",
807 CertificateName: "rootCertName",
808 },
809 },
810 },
811 },
812 }),
813 },
814 },
815 },
816 },
817 DefaultFilterChain: &v3listenerpb.FilterChain{
818 Name: "default-filter-chain-1",
819 Filters: emptyValidNetworkFilters,
820 TransportSocket: &v3corepb.TransportSocket{
821 Name: "envoy.transport_sockets.tls",
822 ConfigType: &v3corepb.TransportSocket_TypedConfig{
823 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
824 RequireClientCertificate: &wrapperspb.BoolValue{Value: true},
825 CommonTlsContext: &v3tlspb.CommonTlsContext{
826 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
827 InstanceName: "defaultIdentityPluginInstance",
828 CertificateName: "defaultIdentityCertName",
829 },
830 ValidationContextType: &v3tlspb.CommonTlsContext_CombinedValidationContext{
831 CombinedValidationContext: &v3tlspb.CommonTlsContext_CombinedCertificateValidationContext{
832 DefaultValidationContext: &v3tlspb.CertificateValidationContext{
833 CaCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
834 InstanceName: "defaultRootPluginInstance",
835 CertificateName: "defaultRootCertName",
836 },
837 },
838 },
839 },
840 },
841 }),
842 },
843 },
844 },
845 })
846 )
847 v3LisToTestRBAC := func(xffNumTrustedHops uint32, originalIpDetectionExtensions []*v3corepb.TypedExtensionConfig) *anypb.Any {
848 return testutils.MarshalAny(t, &v3listenerpb.Listener{
849 Name: v3LDSTarget,
850 Address: localSocketAddress,
851 FilterChains: []*v3listenerpb.FilterChain{
852 {
853 Name: "filter-chain-1",
854 Filters: []*v3listenerpb.Filter{
855 {
856 Name: "filter-1",
857 ConfigType: &v3listenerpb.Filter_TypedConfig{
858 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
859 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
860 RouteConfig: routeConfig,
861 },
862 HttpFilters: []*v3httppb.HttpFilter{e2e.RouterHTTPFilter},
863 XffNumTrustedHops: xffNumTrustedHops,
864 OriginalIpDetectionExtensions: originalIpDetectionExtensions,
865 }),
866 },
867 },
868 },
869 },
870 },
871 })
872 }
873 v3LisWithBadRBACConfiguration := func(rbacCfg *v3rbacpb.RBAC) *anypb.Any {
874 return testutils.MarshalAny(t, &v3listenerpb.Listener{
875 Name: v3LDSTarget,
876 Address: localSocketAddress,
877 FilterChains: []*v3listenerpb.FilterChain{
878 {
879 Name: "filter-chain-1",
880 Filters: []*v3listenerpb.Filter{
881 {
882 Name: "filter-1",
883 ConfigType: &v3listenerpb.Filter_TypedConfig{
884 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
885 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
886 RouteConfig: routeConfig,
887 },
888 HttpFilters: []*v3httppb.HttpFilter{e2e.HTTPFilter("rbac", rbacCfg), e2e.RouterHTTPFilter},
889 }),
890 },
891 },
892 },
893 },
894 },
895 })
896 }
897 badRBACCfgRegex := &v3rbacpb.RBAC{
898 Rules: &rpb.RBAC{
899 Action: rpb.RBAC_ALLOW,
900 Policies: map[string]*rpb.Policy{
901 "bad-regex-value": {
902 Permissions: []*rpb.Permission{
903 {Rule: &rpb.Permission_Any{Any: true}},
904 },
905 Principals: []*rpb.Principal{
906 {Identifier: &rpb.Principal_Header{Header: &v3routepb.HeaderMatcher{Name: ":method", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_SafeRegexMatch{SafeRegexMatch: &v3matcherpb.RegexMatcher{Regex: "["}}}}},
907 },
908 },
909 },
910 },
911 }
912 badRBACCfgDestIP := &v3rbacpb.RBAC{
913 Rules: &rpb.RBAC{
914 Action: rpb.RBAC_ALLOW,
915 Policies: map[string]*rpb.Policy{
916 "certain-destination-ip": {
917 Permissions: []*rpb.Permission{
918 {Rule: &rpb.Permission_DestinationIp{DestinationIp: &v3corepb.CidrRange{AddressPrefix: "not a correct address", PrefixLen: &wrapperspb.UInt32Value{Value: uint32(10)}}}},
919 },
920 Principals: []*rpb.Principal{
921 {Identifier: &rpb.Principal_Any{Any: true}},
922 },
923 },
924 },
925 },
926 }
927
928 tests := []struct {
929 name string
930 resource *anypb.Any
931 wantName string
932 wantUpdate ListenerUpdate
933 wantErr string
934 }{
935 {
936 name: "non-empty listener filters",
937 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
938 Name: v3LDSTarget,
939 ListenerFilters: []*v3listenerpb.ListenerFilter{
940 {Name: "listener-filter-1"},
941 },
942 }),
943 wantName: v3LDSTarget,
944 wantErr: "unsupported field 'listener_filters'",
945 },
946 {
947 name: "use_original_dst is set",
948 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
949 Name: v3LDSTarget,
950 UseOriginalDst: &wrapperspb.BoolValue{Value: true},
951 }),
952 wantName: v3LDSTarget,
953 wantErr: "unsupported field 'use_original_dst'",
954 },
955 {
956 name: "no address field",
957 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{Name: v3LDSTarget}),
958 wantName: v3LDSTarget,
959 wantErr: "no address field in LDS response",
960 },
961 {
962 name: "no socket address field",
963 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
964 Name: v3LDSTarget,
965 Address: &v3corepb.Address{},
966 }),
967 wantName: v3LDSTarget,
968 wantErr: "no socket_address field in LDS response",
969 },
970 {
971 name: "no filter chains and no default filter chain",
972 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
973 Name: v3LDSTarget,
974 Address: localSocketAddress,
975 FilterChains: []*v3listenerpb.FilterChain{
976 {
977 FilterChainMatch: &v3listenerpb.FilterChainMatch{DestinationPort: &wrapperspb.UInt32Value{Value: 666}},
978 Filters: emptyValidNetworkFilters,
979 },
980 },
981 }),
982 wantName: v3LDSTarget,
983 wantErr: "no supported filter chains and no default filter chain",
984 },
985 {
986 name: "missing http connection manager network filter",
987 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
988 Name: v3LDSTarget,
989 Address: localSocketAddress,
990 FilterChains: []*v3listenerpb.FilterChain{
991 {
992 Name: "filter-chain-1",
993 },
994 },
995 }),
996 wantName: v3LDSTarget,
997 wantErr: "missing HttpConnectionManager filter",
998 },
999 {
1000 name: "missing filter name in http filter",
1001 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1002 Name: v3LDSTarget,
1003 Address: localSocketAddress,
1004 FilterChains: []*v3listenerpb.FilterChain{
1005 {
1006 Name: "filter-chain-1",
1007 Filters: []*v3listenerpb.Filter{
1008 {
1009 ConfigType: &v3listenerpb.Filter_TypedConfig{
1010 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{}),
1011 },
1012 },
1013 },
1014 },
1015 },
1016 }),
1017 wantName: v3LDSTarget,
1018 wantErr: "missing name field in filter",
1019 },
1020 {
1021 name: "duplicate filter names in http filter",
1022 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1023 Name: v3LDSTarget,
1024 Address: localSocketAddress,
1025 FilterChains: []*v3listenerpb.FilterChain{
1026 {
1027 Name: "filter-chain-1",
1028 Filters: []*v3listenerpb.Filter{
1029 {
1030 Name: "name",
1031 ConfigType: &v3listenerpb.Filter_TypedConfig{
1032 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
1033 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
1034 RouteConfig: routeConfig,
1035 },
1036 HttpFilters: []*v3httppb.HttpFilter{emptyRouterFilter},
1037 }),
1038 },
1039 },
1040 {
1041 Name: "name",
1042 ConfigType: &v3listenerpb.Filter_TypedConfig{
1043 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
1044 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
1045 RouteConfig: routeConfig,
1046 },
1047 HttpFilters: []*v3httppb.HttpFilter{emptyRouterFilter},
1048 }),
1049 },
1050 },
1051 },
1052 },
1053 },
1054 }),
1055 wantName: v3LDSTarget,
1056 wantErr: "duplicate filter name",
1057 },
1058 {
1059 name: "no terminal filter",
1060 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1061 Name: v3LDSTarget,
1062 Address: localSocketAddress,
1063 FilterChains: []*v3listenerpb.FilterChain{
1064 {
1065 Name: "filter-chain-1",
1066 Filters: []*v3listenerpb.Filter{
1067 {
1068 Name: "name",
1069 ConfigType: &v3listenerpb.Filter_TypedConfig{
1070 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
1071 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
1072 RouteConfig: routeConfig,
1073 },
1074 }),
1075 },
1076 },
1077 },
1078 },
1079 },
1080 }),
1081 wantName: v3LDSTarget,
1082 wantErr: "http filters list is empty",
1083 },
1084 {
1085 name: "terminal filter not last",
1086 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1087 Name: v3LDSTarget,
1088 Address: localSocketAddress,
1089 FilterChains: []*v3listenerpb.FilterChain{
1090 {
1091 Name: "filter-chain-1",
1092 Filters: []*v3listenerpb.Filter{
1093 {
1094 Name: "name",
1095 ConfigType: &v3listenerpb.Filter_TypedConfig{
1096 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
1097 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
1098 RouteConfig: routeConfig,
1099 },
1100 HttpFilters: []*v3httppb.HttpFilter{emptyRouterFilter, serverOnlyCustomFilter},
1101 }),
1102 },
1103 },
1104 },
1105 },
1106 },
1107 }),
1108 wantName: v3LDSTarget,
1109 wantErr: "is a terminal filter but it is not last in the filter chain",
1110 },
1111 {
1112 name: "last not terminal filter",
1113 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1114 Name: v3LDSTarget,
1115 Address: localSocketAddress,
1116 FilterChains: []*v3listenerpb.FilterChain{
1117 {
1118 Name: "filter-chain-1",
1119 Filters: []*v3listenerpb.Filter{
1120 {
1121 Name: "name",
1122 ConfigType: &v3listenerpb.Filter_TypedConfig{
1123 TypedConfig: testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
1124 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
1125 RouteConfig: routeConfig,
1126 },
1127 HttpFilters: []*v3httppb.HttpFilter{serverOnlyCustomFilter},
1128 }),
1129 },
1130 },
1131 },
1132 },
1133 },
1134 }),
1135 wantName: v3LDSTarget,
1136 wantErr: "is not a terminal filter",
1137 },
1138 {
1139 name: "unsupported oneof in typed config of http filter",
1140 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1141 Name: v3LDSTarget,
1142 Address: localSocketAddress,
1143 FilterChains: []*v3listenerpb.FilterChain{
1144 {
1145 Name: "filter-chain-1",
1146 Filters: []*v3listenerpb.Filter{
1147 {
1148 Name: "name",
1149 ConfigType: &v3listenerpb.Filter_ConfigDiscovery{},
1150 },
1151 },
1152 },
1153 },
1154 }),
1155 wantName: v3LDSTarget,
1156 wantErr: "unsupported config_type",
1157 },
1158 {
1159 name: "overlapping filter chain match criteria",
1160 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1161 Name: v3LDSTarget,
1162 Address: localSocketAddress,
1163 FilterChains: []*v3listenerpb.FilterChain{
1164 {
1165 FilterChainMatch: &v3listenerpb.FilterChainMatch{SourcePorts: []uint32{1, 2, 3, 4, 5}},
1166 Filters: emptyValidNetworkFilters,
1167 },
1168 {
1169 FilterChainMatch: &v3listenerpb.FilterChainMatch{},
1170 Filters: emptyValidNetworkFilters,
1171 },
1172 {
1173 FilterChainMatch: &v3listenerpb.FilterChainMatch{SourcePorts: []uint32{5, 6, 7}},
1174 Filters: emptyValidNetworkFilters,
1175 },
1176 },
1177 }),
1178 wantName: v3LDSTarget,
1179 wantErr: "multiple filter chains with overlapping matching rules are defined",
1180 },
1181 {
1182 name: "unsupported network filter",
1183 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1184 Name: v3LDSTarget,
1185 Address: localSocketAddress,
1186 FilterChains: []*v3listenerpb.FilterChain{
1187 {
1188 Name: "filter-chain-1",
1189 Filters: []*v3listenerpb.Filter{
1190 {
1191 Name: "name",
1192 ConfigType: &v3listenerpb.Filter_TypedConfig{
1193 TypedConfig: testutils.MarshalAny(t, &v3httppb.LocalReplyConfig{}),
1194 },
1195 },
1196 },
1197 },
1198 },
1199 }),
1200 wantName: v3LDSTarget,
1201 wantErr: "unsupported network filter",
1202 },
1203 {
1204 name: "badly marshaled network filter",
1205 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1206 Name: v3LDSTarget,
1207 Address: localSocketAddress,
1208 FilterChains: []*v3listenerpb.FilterChain{
1209 {
1210 Name: "filter-chain-1",
1211 Filters: []*v3listenerpb.Filter{
1212 {
1213 Name: "name",
1214 ConfigType: &v3listenerpb.Filter_TypedConfig{
1215 TypedConfig: &anypb.Any{
1216 TypeUrl: version.V3HTTPConnManagerURL,
1217 Value: []byte{1, 2, 3, 4},
1218 },
1219 },
1220 },
1221 },
1222 },
1223 },
1224 }),
1225 wantName: v3LDSTarget,
1226 wantErr: "failed unmarshalling of network filter",
1227 },
1228 {
1229 name: "unexpected transport socket name",
1230 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1231 Name: v3LDSTarget,
1232 Address: localSocketAddress,
1233 FilterChains: []*v3listenerpb.FilterChain{
1234 {
1235 Name: "filter-chain-1",
1236 Filters: emptyValidNetworkFilters,
1237 TransportSocket: &v3corepb.TransportSocket{
1238 Name: "unsupported-transport-socket-name",
1239 },
1240 },
1241 },
1242 }),
1243 wantName: v3LDSTarget,
1244 wantErr: "transport_socket field has unexpected name",
1245 },
1246 {
1247 name: "unexpected transport socket typedConfig URL",
1248 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1249 Name: v3LDSTarget,
1250 Address: localSocketAddress,
1251 FilterChains: []*v3listenerpb.FilterChain{
1252 {
1253 Name: "filter-chain-1",
1254 Filters: emptyValidNetworkFilters,
1255 TransportSocket: &v3corepb.TransportSocket{
1256 Name: "envoy.transport_sockets.tls",
1257 ConfigType: &v3corepb.TransportSocket_TypedConfig{
1258 TypedConfig: testutils.MarshalAny(t, &v3tlspb.UpstreamTlsContext{}),
1259 },
1260 },
1261 },
1262 },
1263 }),
1264 wantName: v3LDSTarget,
1265 wantErr: "transport_socket field has unexpected typeURL",
1266 },
1267 {
1268 name: "badly marshaled transport socket",
1269 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1270 Name: v3LDSTarget,
1271 Address: localSocketAddress,
1272 FilterChains: []*v3listenerpb.FilterChain{
1273 {
1274 Name: "filter-chain-1",
1275 Filters: emptyValidNetworkFilters,
1276 TransportSocket: &v3corepb.TransportSocket{
1277 Name: "envoy.transport_sockets.tls",
1278 ConfigType: &v3corepb.TransportSocket_TypedConfig{
1279 TypedConfig: &anypb.Any{
1280 TypeUrl: version.V3DownstreamTLSContextURL,
1281 Value: []byte{1, 2, 3, 4},
1282 },
1283 },
1284 },
1285 },
1286 },
1287 }),
1288 wantName: v3LDSTarget,
1289 wantErr: "failed to unmarshal DownstreamTlsContext in LDS response",
1290 },
1291 {
1292 name: "missing CommonTlsContext",
1293 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1294 Name: v3LDSTarget,
1295 Address: localSocketAddress,
1296 FilterChains: []*v3listenerpb.FilterChain{
1297 {
1298 Name: "filter-chain-1",
1299 Filters: emptyValidNetworkFilters,
1300 TransportSocket: &v3corepb.TransportSocket{
1301 Name: "envoy.transport_sockets.tls",
1302 ConfigType: &v3corepb.TransportSocket_TypedConfig{
1303 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{}),
1304 },
1305 },
1306 },
1307 },
1308 }),
1309 wantName: v3LDSTarget,
1310 wantErr: "DownstreamTlsContext in LDS response does not contain a CommonTlsContext",
1311 },
1312 {
1313 name: "rbac-allow-equating-direct-remote-ip-and-remote-ip-valid",
1314 resource: v3LisToTestRBAC(0, nil),
1315 wantName: v3LDSTarget,
1316 wantUpdate: ListenerUpdate{
1317 InboundListenerCfg: &InboundListenerConfig{
1318 Address: "0.0.0.0",
1319 Port: "9999",
1320 FilterChains: &FilterChainManager{
1321 dstPrefixMap: map[string]*destPrefixEntry{
1322 unspecifiedPrefixMapKey: {
1323 srcTypeArr: [3]*sourcePrefixes{
1324 {
1325 srcPrefixMap: map[string]*sourcePrefixEntry{
1326 unspecifiedPrefixMapKey: {
1327 srcPortMap: map[int]*FilterChain{
1328 0: {
1329 InlineRouteConfig: inlineRouteConfig,
1330 HTTPFilters: makeRouterFilterList(t),
1331 },
1332 },
1333 },
1334 },
1335 },
1336 },
1337 },
1338 },
1339 },
1340 },
1341 Raw: listenerEmptyTransportSocket,
1342 },
1343 },
1344 {
1345 name: "rbac-allow-equating-direct-remote-ip-and-remote-ip-invalid-num-untrusted-hops",
1346 resource: v3LisToTestRBAC(1, nil),
1347 wantName: v3LDSTarget,
1348 wantErr: "xff_num_trusted_hops must be unset or zero",
1349 },
1350 {
1351 name: "rbac-allow-equating-direct-remote-ip-and-remote-ip-invalid-original-ip-detection-extension",
1352 resource: v3LisToTestRBAC(0, []*v3corepb.TypedExtensionConfig{{Name: "something"}}),
1353 wantName: v3LDSTarget,
1354 wantErr: "original_ip_detection_extensions must be empty",
1355 },
1356 {
1357 name: "rbac-with-invalid-regex",
1358 resource: v3LisWithBadRBACConfiguration(badRBACCfgRegex),
1359 wantName: v3LDSTarget,
1360 wantErr: "error parsing config for filter",
1361 },
1362 {
1363 name: "rbac-with-invalid-destination-ip-matcher",
1364 resource: v3LisWithBadRBACConfiguration(badRBACCfgDestIP),
1365 wantName: v3LDSTarget,
1366 wantErr: "error parsing config for filter",
1367 },
1368 {
1369 name: "unsupported validation context in transport socket",
1370 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1371 Name: v3LDSTarget,
1372 Address: localSocketAddress,
1373 FilterChains: []*v3listenerpb.FilterChain{
1374 {
1375 Name: "filter-chain-1",
1376 Filters: emptyValidNetworkFilters,
1377 TransportSocket: &v3corepb.TransportSocket{
1378 Name: "envoy.transport_sockets.tls",
1379 ConfigType: &v3corepb.TransportSocket_TypedConfig{
1380 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
1381 CommonTlsContext: &v3tlspb.CommonTlsContext{
1382 ValidationContextType: &v3tlspb.CommonTlsContext_ValidationContextSdsSecretConfig{
1383 ValidationContextSdsSecretConfig: &v3tlspb.SdsSecretConfig{
1384 Name: "foo-sds-secret",
1385 },
1386 },
1387 },
1388 }),
1389 },
1390 },
1391 },
1392 },
1393 }),
1394 wantName: v3LDSTarget,
1395 wantErr: "validation context contains unexpected type",
1396 },
1397 {
1398 name: "empty transport socket",
1399 resource: listenerEmptyTransportSocket,
1400 wantName: v3LDSTarget,
1401 wantUpdate: ListenerUpdate{
1402 InboundListenerCfg: &InboundListenerConfig{
1403 Address: "0.0.0.0",
1404 Port: "9999",
1405 FilterChains: &FilterChainManager{
1406 dstPrefixMap: map[string]*destPrefixEntry{
1407 unspecifiedPrefixMapKey: {
1408 srcTypeArr: [3]*sourcePrefixes{
1409 {
1410 srcPrefixMap: map[string]*sourcePrefixEntry{
1411 unspecifiedPrefixMapKey: {
1412 srcPortMap: map[int]*FilterChain{
1413 0: {
1414 InlineRouteConfig: inlineRouteConfig,
1415 HTTPFilters: makeRouterFilterList(t),
1416 },
1417 },
1418 },
1419 },
1420 },
1421 },
1422 },
1423 },
1424 },
1425 },
1426 Raw: listenerEmptyTransportSocket,
1427 },
1428 },
1429 {
1430 name: "no identity and root certificate providers using deprecated fields",
1431 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1432 Name: v3LDSTarget,
1433 Address: localSocketAddress,
1434 FilterChains: []*v3listenerpb.FilterChain{
1435 {
1436 Name: "filter-chain-1",
1437 Filters: emptyValidNetworkFilters,
1438 TransportSocket: &v3corepb.TransportSocket{
1439 Name: "envoy.transport_sockets.tls",
1440 ConfigType: &v3corepb.TransportSocket_TypedConfig{
1441 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
1442 RequireClientCertificate: &wrapperspb.BoolValue{Value: true},
1443 CommonTlsContext: &v3tlspb.CommonTlsContext{
1444 TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{
1445 InstanceName: "identityPluginInstance",
1446 CertificateName: "identityCertName",
1447 },
1448 },
1449 }),
1450 },
1451 },
1452 },
1453 },
1454 }),
1455 wantName: v3LDSTarget,
1456 wantErr: "security configuration on the server-side does not contain root certificate provider instance name, but require_client_cert field is set",
1457 },
1458 {
1459 name: "no identity and root certificate providers using new fields",
1460 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1461 Name: v3LDSTarget,
1462 Address: localSocketAddress,
1463 FilterChains: []*v3listenerpb.FilterChain{
1464 {
1465 Name: "filter-chain-1",
1466 Filters: emptyValidNetworkFilters,
1467 TransportSocket: &v3corepb.TransportSocket{
1468 Name: "envoy.transport_sockets.tls",
1469 ConfigType: &v3corepb.TransportSocket_TypedConfig{
1470 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
1471 RequireClientCertificate: &wrapperspb.BoolValue{Value: true},
1472 CommonTlsContext: &v3tlspb.CommonTlsContext{
1473 TlsCertificateProviderInstance: &v3tlspb.CertificateProviderPluginInstance{
1474 InstanceName: "identityPluginInstance",
1475 CertificateName: "identityCertName",
1476 },
1477 },
1478 }),
1479 },
1480 },
1481 },
1482 },
1483 }),
1484 wantName: v3LDSTarget,
1485 wantErr: "security configuration on the server-side does not contain root certificate provider instance name, but require_client_cert field is set",
1486 },
1487 {
1488 name: "no identity certificate provider with require_client_cert",
1489 resource: testutils.MarshalAny(t, &v3listenerpb.Listener{
1490 Name: v3LDSTarget,
1491 Address: localSocketAddress,
1492 FilterChains: []*v3listenerpb.FilterChain{
1493 {
1494 Name: "filter-chain-1",
1495 Filters: emptyValidNetworkFilters,
1496 TransportSocket: &v3corepb.TransportSocket{
1497 Name: "envoy.transport_sockets.tls",
1498 ConfigType: &v3corepb.TransportSocket_TypedConfig{
1499 TypedConfig: testutils.MarshalAny(t, &v3tlspb.DownstreamTlsContext{
1500 CommonTlsContext: &v3tlspb.CommonTlsContext{},
1501 }),
1502 },
1503 },
1504 },
1505 },
1506 }),
1507 wantName: v3LDSTarget,
1508 wantErr: "security configuration on the server-side does not contain identity certificate provider instance name",
1509 },
1510 {
1511 name: "happy case with no validation context using deprecated fields",
1512 resource: listenerNoValidationContextDeprecatedFields,
1513 wantName: v3LDSTarget,
1514 wantUpdate: ListenerUpdate{
1515 InboundListenerCfg: &InboundListenerConfig{
1516 Address: "0.0.0.0",
1517 Port: "9999",
1518 FilterChains: &FilterChainManager{
1519 dstPrefixMap: map[string]*destPrefixEntry{
1520 unspecifiedPrefixMapKey: {
1521 srcTypeArr: [3]*sourcePrefixes{
1522 {
1523 srcPrefixMap: map[string]*sourcePrefixEntry{
1524 unspecifiedPrefixMapKey: {
1525 srcPortMap: map[int]*FilterChain{
1526 0: {
1527 SecurityCfg: &SecurityConfig{
1528 IdentityInstanceName: "identityPluginInstance",
1529 IdentityCertName: "identityCertName",
1530 },
1531 InlineRouteConfig: inlineRouteConfig,
1532 HTTPFilters: makeRouterFilterList(t),
1533 },
1534 },
1535 },
1536 },
1537 },
1538 },
1539 },
1540 },
1541 def: &FilterChain{
1542 SecurityCfg: &SecurityConfig{
1543 IdentityInstanceName: "defaultIdentityPluginInstance",
1544 IdentityCertName: "defaultIdentityCertName",
1545 },
1546 InlineRouteConfig: inlineRouteConfig,
1547 HTTPFilters: makeRouterFilterList(t),
1548 },
1549 },
1550 },
1551 Raw: listenerNoValidationContextDeprecatedFields,
1552 },
1553 },
1554 {
1555 name: "happy case with no validation context using new fields",
1556 resource: listenerNoValidationContextNewFields,
1557 wantName: v3LDSTarget,
1558 wantUpdate: ListenerUpdate{
1559 InboundListenerCfg: &InboundListenerConfig{
1560 Address: "0.0.0.0",
1561 Port: "9999",
1562 FilterChains: &FilterChainManager{
1563 dstPrefixMap: map[string]*destPrefixEntry{
1564 unspecifiedPrefixMapKey: {
1565 srcTypeArr: [3]*sourcePrefixes{
1566 {
1567 srcPrefixMap: map[string]*sourcePrefixEntry{
1568 unspecifiedPrefixMapKey: {
1569 srcPortMap: map[int]*FilterChain{
1570 0: {
1571 SecurityCfg: &SecurityConfig{
1572 IdentityInstanceName: "identityPluginInstance",
1573 IdentityCertName: "identityCertName",
1574 },
1575 InlineRouteConfig: inlineRouteConfig,
1576 HTTPFilters: makeRouterFilterList(t),
1577 },
1578 },
1579 },
1580 },
1581 },
1582 },
1583 },
1584 },
1585 def: &FilterChain{
1586 SecurityCfg: &SecurityConfig{
1587 IdentityInstanceName: "defaultIdentityPluginInstance",
1588 IdentityCertName: "defaultIdentityCertName",
1589 },
1590 InlineRouteConfig: inlineRouteConfig,
1591 HTTPFilters: makeRouterFilterList(t),
1592 },
1593 },
1594 },
1595 Raw: listenerNoValidationContextNewFields,
1596 },
1597 },
1598 {
1599 name: "happy case with validation context provider instance with deprecated fields",
1600 resource: listenerWithValidationContextDeprecatedFields,
1601 wantName: v3LDSTarget,
1602 wantUpdate: ListenerUpdate{
1603 InboundListenerCfg: &InboundListenerConfig{
1604 Address: "0.0.0.0",
1605 Port: "9999",
1606 FilterChains: &FilterChainManager{
1607 dstPrefixMap: map[string]*destPrefixEntry{
1608 unspecifiedPrefixMapKey: {
1609 srcTypeArr: [3]*sourcePrefixes{
1610 {
1611 srcPrefixMap: map[string]*sourcePrefixEntry{
1612 unspecifiedPrefixMapKey: {
1613 srcPortMap: map[int]*FilterChain{
1614 0: {
1615 SecurityCfg: &SecurityConfig{
1616 RootInstanceName: "rootPluginInstance",
1617 RootCertName: "rootCertName",
1618 IdentityInstanceName: "identityPluginInstance",
1619 IdentityCertName: "identityCertName",
1620 RequireClientCert: true,
1621 },
1622 InlineRouteConfig: inlineRouteConfig,
1623 HTTPFilters: makeRouterFilterList(t),
1624 },
1625 },
1626 },
1627 },
1628 },
1629 },
1630 },
1631 },
1632 def: &FilterChain{
1633 SecurityCfg: &SecurityConfig{
1634 RootInstanceName: "defaultRootPluginInstance",
1635 RootCertName: "defaultRootCertName",
1636 IdentityInstanceName: "defaultIdentityPluginInstance",
1637 IdentityCertName: "defaultIdentityCertName",
1638 RequireClientCert: true,
1639 },
1640 InlineRouteConfig: inlineRouteConfig,
1641 HTTPFilters: makeRouterFilterList(t),
1642 },
1643 },
1644 },
1645 Raw: listenerWithValidationContextDeprecatedFields,
1646 },
1647 },
1648 {
1649 name: "happy case with validation context provider instance with new fields",
1650 resource: listenerWithValidationContextNewFields,
1651 wantName: v3LDSTarget,
1652 wantUpdate: ListenerUpdate{
1653 InboundListenerCfg: &InboundListenerConfig{
1654 Address: "0.0.0.0",
1655 Port: "9999",
1656 FilterChains: &FilterChainManager{
1657 dstPrefixMap: map[string]*destPrefixEntry{
1658 unspecifiedPrefixMapKey: {
1659 srcTypeArr: [3]*sourcePrefixes{
1660 {
1661 srcPrefixMap: map[string]*sourcePrefixEntry{
1662 unspecifiedPrefixMapKey: {
1663 srcPortMap: map[int]*FilterChain{
1664 0: {
1665 SecurityCfg: &SecurityConfig{
1666 RootInstanceName: "rootPluginInstance",
1667 RootCertName: "rootCertName",
1668 IdentityInstanceName: "identityPluginInstance",
1669 IdentityCertName: "identityCertName",
1670 RequireClientCert: true,
1671 },
1672 InlineRouteConfig: inlineRouteConfig,
1673 HTTPFilters: makeRouterFilterList(t),
1674 },
1675 },
1676 },
1677 },
1678 },
1679 },
1680 },
1681 },
1682 def: &FilterChain{
1683 SecurityCfg: &SecurityConfig{
1684 RootInstanceName: "defaultRootPluginInstance",
1685 RootCertName: "defaultRootCertName",
1686 IdentityInstanceName: "defaultIdentityPluginInstance",
1687 IdentityCertName: "defaultIdentityCertName",
1688 RequireClientCert: true,
1689 },
1690 InlineRouteConfig: inlineRouteConfig,
1691 HTTPFilters: makeRouterFilterList(t),
1692 },
1693 },
1694 },
1695 Raw: listenerWithValidationContextNewFields,
1696 },
1697 },
1698 }
1699
1700 for _, test := range tests {
1701 t.Run(test.name, func(t *testing.T) {
1702 name, update, err := unmarshalListenerResource(test.resource)
1703 if err != nil && !strings.Contains(err.Error(), test.wantErr) {
1704 t.Errorf("unmarshalListenerResource(%s) = %v wantErr: %q", pretty.ToJSON(test.resource), err, test.wantErr)
1705 }
1706 if name != test.wantName {
1707 t.Errorf("unmarshalListenerResource(%s), got name: %s, want: %s", pretty.ToJSON(test.resource), name, test.wantName)
1708 }
1709 if diff := cmp.Diff(update, test.wantUpdate, cmpOpts); diff != "" {
1710 t.Errorf("unmarshalListenerResource(%s), got unexpected update, diff (-got +want): %v", pretty.ToJSON(test.resource), diff)
1711 }
1712 })
1713 }
1714 }
1715
1716 type filterConfig struct {
1717 httpfilter.FilterConfig
1718 Cfg proto.Message
1719 Override proto.Message
1720 }
1721
1722
1723 type httpFilter struct {
1724 httpfilter.ClientInterceptorBuilder
1725 httpfilter.ServerInterceptorBuilder
1726 }
1727
1728 func (httpFilter) TypeURLs() []string { return []string{"custom.filter"} }
1729
1730 func (httpFilter) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {
1731 return filterConfig{Cfg: cfg}, nil
1732 }
1733
1734 func (httpFilter) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {
1735 return filterConfig{Override: override}, nil
1736 }
1737
1738 func (httpFilter) IsTerminal() bool {
1739 return false
1740 }
1741
1742
1743 type errHTTPFilter struct {
1744 httpfilter.ClientInterceptorBuilder
1745 }
1746
1747 func (errHTTPFilter) TypeURLs() []string { return []string{"err.custom.filter"} }
1748
1749 func (errHTTPFilter) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {
1750 return nil, fmt.Errorf("error from ParseFilterConfig")
1751 }
1752
1753 func (errHTTPFilter) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {
1754 return nil, fmt.Errorf("error from ParseFilterConfigOverride")
1755 }
1756
1757 func (errHTTPFilter) IsTerminal() bool {
1758 return false
1759 }
1760
1761 func init() {
1762 httpfilter.Register(httpFilter{})
1763 httpfilter.Register(errHTTPFilter{})
1764 httpfilter.Register(serverOnlyHTTPFilter{})
1765 httpfilter.Register(clientOnlyHTTPFilter{})
1766 }
1767
1768
1769 type serverOnlyHTTPFilter struct {
1770 httpfilter.ServerInterceptorBuilder
1771 }
1772
1773 func (serverOnlyHTTPFilter) TypeURLs() []string { return []string{"serverOnly.custom.filter"} }
1774
1775 func (serverOnlyHTTPFilter) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {
1776 return filterConfig{Cfg: cfg}, nil
1777 }
1778
1779 func (serverOnlyHTTPFilter) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {
1780 return filterConfig{Override: override}, nil
1781 }
1782
1783 func (serverOnlyHTTPFilter) IsTerminal() bool {
1784 return false
1785 }
1786
1787
1788 type clientOnlyHTTPFilter struct {
1789 httpfilter.ClientInterceptorBuilder
1790 }
1791
1792 func (clientOnlyHTTPFilter) TypeURLs() []string { return []string{"clientOnly.custom.filter"} }
1793
1794 func (clientOnlyHTTPFilter) ParseFilterConfig(cfg proto.Message) (httpfilter.FilterConfig, error) {
1795 return filterConfig{Cfg: cfg}, nil
1796 }
1797
1798 func (clientOnlyHTTPFilter) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {
1799 return filterConfig{Override: override}, nil
1800 }
1801
1802 func (clientOnlyHTTPFilter) IsTerminal() bool {
1803 return false
1804 }
1805
1806 var customFilterConfig = &anypb.Any{
1807 TypeUrl: "custom.filter",
1808 Value: []byte{1, 2, 3},
1809 }
1810
1811 var errFilterConfig = &anypb.Any{
1812 TypeUrl: "err.custom.filter",
1813 Value: []byte{1, 2, 3},
1814 }
1815
1816 var serverOnlyCustomFilterConfig = &anypb.Any{
1817 TypeUrl: "serverOnly.custom.filter",
1818 Value: []byte{1, 2, 3},
1819 }
1820
1821 var clientOnlyCustomFilterConfig = &anypb.Any{
1822 TypeUrl: "clientOnly.custom.filter",
1823 Value: []byte{1, 2, 3},
1824 }
1825
1826
1827 var customFilterOldTypedStructConfig = &v1xdsudpatypepb.TypedStruct{
1828 TypeUrl: "custom.filter",
1829 Value: &structpb.Struct{
1830 Fields: map[string]*structpb.Value{
1831 "foo": {Kind: &structpb.Value_StringValue{StringValue: "bar"}},
1832 },
1833 },
1834 }
1835
1836
1837 var customFilterNewTypedStructConfig = &v3xdsxdstypepb.TypedStruct{
1838 TypeUrl: "custom.filter",
1839 Value: &structpb.Struct{
1840 Fields: map[string]*structpb.Value{
1841 "foo": {Kind: &structpb.Value_StringValue{StringValue: "bar"}},
1842 },
1843 },
1844 }
1845
1846 var unknownFilterConfig = &anypb.Any{
1847 TypeUrl: "unknown.custom.filter",
1848 Value: []byte{1, 2, 3},
1849 }
1850
1851 func wrappedOptionalFilter(t *testing.T, name string) *anypb.Any {
1852 return testutils.MarshalAny(t, &v3routepb.FilterConfig{
1853 IsOptional: true,
1854 Config: &anypb.Any{
1855 TypeUrl: name,
1856 Value: []byte{1, 2, 3},
1857 },
1858 })
1859 }
1860
View as plain text