diff --git a/examples/go.sum b/examples/go.sum index 1bc27f276662..c6aa163b01ad 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -5,8 +5,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= diff --git a/go.mod b/go.mod index cab74e55774c..b177cfa66df5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.11 require ( github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 - github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad + github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/protobuf v1.4.2 github.com/google/go-cmp v0.5.0 diff --git a/go.sum b/go.sum index 77ee70b44354..bb25cd49156d 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= diff --git a/security/advancedtls/examples/go.sum b/security/advancedtls/examples/go.sum index 3d64689329fe..519267dbc278 100644 --- a/security/advancedtls/examples/go.sum +++ b/security/advancedtls/examples/go.sum @@ -2,7 +2,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= diff --git a/security/advancedtls/go.sum b/security/advancedtls/go.sum index 3d64689329fe..519267dbc278 100644 --- a/security/advancedtls/go.sum +++ b/security/advancedtls/go.sum @@ -2,7 +2,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= diff --git a/xds/internal/client/lds_test.go b/xds/internal/client/lds_test.go index bdce958f30ca..c75ed7667d5c 100644 --- a/xds/internal/client/lds_test.go +++ b/xds/internal/client/lds_test.go @@ -41,6 +41,7 @@ import ( v2httppb "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2" v2listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v2" v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" + v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" v3httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" v3tlspb "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" anypb "github.com/golang/protobuf/ptypes/any" @@ -92,6 +93,11 @@ func (s) TestUnmarshalListener_ClientSide(t *testing.T) { Name: "customFilter", ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: wrappedCustomFilterTypedStructConfig}, } + customOptionalFilter = &v3httppb.HttpFilter{ + Name: "customFilter", + ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: customFilterConfig}, + IsOptional: true, + } customFilter2 = &v3httppb.HttpFilter{ Name: "customFilter2", ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: customFilterConfig}, @@ -100,6 +106,11 @@ func (s) TestUnmarshalListener_ClientSide(t *testing.T) { Name: "errFilter", ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: errFilterConfig}, } + errOptionalFilter = &v3httppb.HttpFilter{ + Name: "errFilter", + ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: errFilterConfig}, + IsOptional: true, + } clientOnlyCustomFilter = &v3httppb.HttpFilter{ Name: "clientOnlyCustomFilter", ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: clientOnlyCustomFilterConfig}, @@ -108,6 +119,15 @@ func (s) TestUnmarshalListener_ClientSide(t *testing.T) { Name: "serverOnlyCustomFilter", ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: serverOnlyCustomFilterConfig}, } + unknownFilter = &v3httppb.HttpFilter{ + Name: "unknownFilter", + ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: unknownFilterConfig}, + } + unknownOptionalFilter = &v3httppb.HttpFilter{ + Name: "unknownFilter", + ConfigType: &v3httppb.HttpFilter_TypedConfig{TypedConfig: unknownFilterConfig}, + IsOptional: true, + } v3LisWithFilters = func(fs ...*v3httppb.HttpFilter) *anypb.Any { hcm := &v3httppb.HttpConnectionManager{ RouteSpecifier: &v3httppb.HttpConnectionManager_Rds{ @@ -342,6 +362,20 @@ func (s) TestUnmarshalListener_ClientSide(t *testing.T) { }, }, }, + { + name: "v3 with optional custom filter", + resources: []*anypb.Any{v3LisWithFilters(customOptionalFilter)}, + wantUpdate: map[string]ListenerUpdate{ + v3LDSTarget: { + RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second, + HTTPFilters: []HTTPFilter{{ + Name: "customFilter", + Filter: httpFilter{}, + Config: filterConfig{Cfg: customFilterConfig}, + }}, + }, + }, + }, { name: "v3 with custom filter, fault injection disabled", resources: []*anypb.Any{v3LisWithFilters(customFilter)}, @@ -397,6 +431,23 @@ func (s) TestUnmarshalListener_ClientSide(t *testing.T) { resources: []*anypb.Any{v3LisWithFilters(errFilter)}, wantErr: true, }, + { + name: "v3 with optional err filter", + resources: []*anypb.Any{v3LisWithFilters(errOptionalFilter)}, + wantErr: true, + }, + { + name: "v3 with unknown filter", + resources: []*anypb.Any{v3LisWithFilters(unknownFilter)}, + wantErr: true, + }, + { + name: "v3 with unknown filter (optional)", + resources: []*anypb.Any{v3LisWithFilters(unknownOptionalFilter)}, + wantUpdate: map[string]ListenerUpdate{ + v3LDSTarget: {RouteConfigName: v3RouteConfigName, MaxStreamDuration: time.Second}, + }, + }, { name: "v3 with error filter, fault injection disabled", resources: []*anypb.Any{v3LisWithFilters(errFilter)}, @@ -1190,3 +1241,23 @@ func init() { panic(err.Error()) } } + +var unknownFilterConfig = &anypb.Any{ + TypeUrl: "unknown.custom.filter", + Value: []byte{1, 2, 3}, +} + +func wrappedOptionalFilter(name string) *anypb.Any { + filter := &v3routepb.FilterConfig{ + IsOptional: true, + Config: &anypb.Any{ + TypeUrl: name, + Value: []byte{1, 2, 3}, + }, + } + w, err := ptypes.MarshalAny(filter) + if err != nil { + panic("error marshalling any: " + err.Error()) + } + return w +} diff --git a/xds/internal/client/rds_test.go b/xds/internal/client/rds_test.go index 1a33c90a7dbc..9bc068fd9d96 100644 --- a/xds/internal/client/rds_test.go +++ b/xds/internal/client/rds_test.go @@ -445,11 +445,31 @@ func (s) TestRDSGenerateRDSUpdateFromRouteConfiguration(t *testing.T) { rc: goodRouteConfigWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedCustomFilterTypedStructConfig}), wantUpdate: goodUpdateWithFilterConfigs(map[string]httpfilter.FilterConfig{"foo": filterConfig{Override: customFilterTypedStructConfig}}), }, + { + name: "good-route-config-with-optional-http-filter-config", + rc: goodRouteConfigWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedOptionalFilter("custom.filter")}), + wantUpdate: goodUpdateWithFilterConfigs(map[string]httpfilter.FilterConfig{"foo": filterConfig{Override: customFilterConfig}}), + }, { name: "good-route-config-with-http-err-filter-config", rc: goodRouteConfigWithFilterConfigs(map[string]*anypb.Any{"foo": errFilterConfig}), wantError: true, }, + { + name: "good-route-config-with-http-optional-err-filter-config", + rc: goodRouteConfigWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedOptionalFilter("err.custom.filter")}), + wantError: true, + }, + { + name: "good-route-config-with-http-unknown-filter-config", + rc: goodRouteConfigWithFilterConfigs(map[string]*anypb.Any{"foo": unknownFilterConfig}), + wantError: true, + }, + { + name: "good-route-config-with-http-optional-unknown-filter-config", + rc: goodRouteConfigWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedOptionalFilter("unknown.custom.filter")}), + wantUpdate: goodUpdateWithFilterConfigs(nil), + }, { name: "good-route-config-with-http-err-filter-config-fi-disabled", disableFI: true, @@ -897,6 +917,11 @@ func (s) TestRoutesProtoToSlice(t *testing.T) { routes: goodRouteWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedCustomFilterTypedStructConfig}), wantRoutes: goodUpdateWithFilterConfigs(map[string]httpfilter.FilterConfig{"foo": filterConfig{Override: customFilterTypedStructConfig}}), }, + { + name: "with optional custom HTTP filter config", + routes: goodRouteWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedOptionalFilter("custom.filter")}), + wantRoutes: goodUpdateWithFilterConfigs(map[string]httpfilter.FilterConfig{"foo": filterConfig{Override: customFilterConfig}}), + }, { name: "with custom HTTP filter config, FI disabled", disableFI: true, @@ -908,12 +933,27 @@ func (s) TestRoutesProtoToSlice(t *testing.T) { routes: goodRouteWithFilterConfigs(map[string]*anypb.Any{"foo": errFilterConfig}), wantErr: true, }, + { + name: "with optional erroring custom HTTP filter config", + routes: goodRouteWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedOptionalFilter("err.custom.filter")}), + wantErr: true, + }, { name: "with erroring custom HTTP filter config, FI disabled", disableFI: true, routes: goodRouteWithFilterConfigs(map[string]*anypb.Any{"foo": errFilterConfig}), wantRoutes: goodUpdateWithFilterConfigs(nil), }, + { + name: "with unknown custom HTTP filter config", + routes: goodRouteWithFilterConfigs(map[string]*anypb.Any{"foo": unknownFilterConfig}), + wantErr: true, + }, + { + name: "with optional unknown custom HTTP filter config", + routes: goodRouteWithFilterConfigs(map[string]*anypb.Any{"foo": wrappedOptionalFilter("unknown.custom.filter")}), + wantRoutes: goodUpdateWithFilterConfigs(nil), + }, } cmpOpts := []cmp.Option{ diff --git a/xds/internal/client/xds.go b/xds/internal/client/xds.go index 055a782d468b..aba8a605e590 100644 --- a/xds/internal/client/xds.go +++ b/xds/internal/client/xds.go @@ -144,14 +144,31 @@ func unwrapHTTPFilterConfig(config *anypb.Any) (proto.Message, string, error) { return s, s.GetTypeUrl(), nil } -func validateHTTPFilterConfig(cfg *anypb.Any, lds bool) (httpfilter.Filter, httpfilter.FilterConfig, error) { +func validateHTTPFilterConfig(cfg *anypb.Any, lds, optional, validateServer, validateClient bool) (httpfilter.Filter, httpfilter.FilterConfig, error) { config, typeURL, err := unwrapHTTPFilterConfig(cfg) if err != nil { return nil, nil, err } filterBuilder := httpfilter.Get(typeURL) if filterBuilder == nil { - return nil, nil, fmt.Errorf("no filter implementation found for %q", typeURL) + err = fmt.Errorf("no filter implementation found for %q", typeURL) + } else { + if validateServer { + if _, ok := filterBuilder.(httpfilter.ServerInterceptorBuilder); !ok { + err = fmt.Errorf("not supported server-side") + } + } + if validateClient { + if _, ok := filterBuilder.(httpfilter.ClientInterceptorBuilder); !ok { + err = fmt.Errorf("not supported client-side") + } + } + } + if err != nil { + if optional { + return nil, nil, nil + } + return nil, nil, err } parseFunc := filterBuilder.ParseFilterConfig if !lds { @@ -170,9 +187,23 @@ func processHTTPFilterOverrides(cfgs map[string]*anypb.Any) (map[string]httpfilt } m := make(map[string]httpfilter.FilterConfig) for name, cfg := range cfgs { - _, config, err := validateHTTPFilterConfig(cfg, false) + optional := false + if typeURL := cfg.GetTypeUrl(); typeURL == "type.googleapis.com/envoy.config.route.v3.FilterConfig" { + s := new(v3routepb.FilterConfig) + if err := ptypes.UnmarshalAny(cfg, s); err != nil { + return nil, fmt.Errorf("filter override %q: error unmarshalling FilterConfig: %v", name, err) + } + cfg = s.GetConfig() + optional = s.GetIsOptional() + } + + httpFilter, config, err := validateHTTPFilterConfig(cfg, false, optional, false, false) if err != nil { - return nil, err + return nil, fmt.Errorf("filter override %q: %v", name, err) + } + if httpFilter == nil { + // Optional configs are ignored. + continue } m[name] = config } @@ -196,18 +227,13 @@ func processHTTPFilters(filters []*v3httppb.HttpFilter, server bool) ([]HTTPFilt } seenNames[name] = true - httpFilter, config, err := validateHTTPFilterConfig(filter.GetTypedConfig(), true) + httpFilter, config, err := validateHTTPFilterConfig(filter.GetTypedConfig(), true, filter.GetIsOptional(), server, !server) if err != nil { return nil, err } - if server { - if _, ok := httpFilter.(httpfilter.ServerInterceptorBuilder); !ok { - return nil, fmt.Errorf("httpFilter %q not supported server-side", name) - } - } else { - if _, ok := httpFilter.(httpfilter.ClientInterceptorBuilder); !ok { - return nil, fmt.Errorf("httpFilter %q not supported client-side", name) - } + if httpFilter == nil { + // Optional configs are ignored. + continue } // Save name/config