github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/xds/internal/xdsclient/xdsresource/unmarshal_lds_test.go (about)

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