diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index 47ac0868f4..1347055fd2 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -196,7 +196,10 @@ func TestAgent_Services_Sidecar(t *testing.T) { Proxy: structs.ConnectProxyConfig{ DestinationServiceName: "db", Upstreams: structs.TestUpstreams(t), - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, } a.State.AddService(srv1, "") @@ -396,7 +399,7 @@ func TestAgent_Service(t *testing.T) { Service: "web-sidecar-proxy", Port: 8000, Proxy: expectProxy.ToAPI(), - ContentHash: "fa3af167b81f6721", + ContentHash: "eb557bc310d4f8a0", Weights: api.AgentWeights{ Passing: 1, Warning: 1, @@ -410,7 +413,7 @@ func TestAgent_Service(t *testing.T) { // Copy and modify updatedResponse := *expectedResponse updatedResponse.Port = 9999 - updatedResponse.ContentHash = "c7739b50900c7483" + updatedResponse.ContentHash = "d61c11f438c7eb02" // Simple response for non-proxy service registered in TestAgent config expectWebResponse := &api.AgentService{ diff --git a/agent/config/builder.go b/agent/config/builder.go index 7e151e760a..1238670ea1 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -1691,7 +1691,8 @@ func (b *builder) serviceProxyVal(v *ServiceProxy) *structs.ConnectProxyConfig { Upstreams: b.upstreamsVal(v.Upstreams), MeshGateway: b.meshGatewayConfVal(v.MeshGateway), Expose: b.exposeConfVal(v.Expose), - TransparentProxy: boolVal(v.TransparentProxy), + Mode: b.proxyModeVal(v.Mode), + TransparentProxy: b.transparentProxyConfVal(v.TransparentProxy), } } @@ -1743,6 +1744,28 @@ func (b *builder) exposeConfVal(v *ExposeConfig) structs.ExposeConfig { return out } +func (b *builder) transparentProxyConfVal(tproxyConf *TransparentProxyConfig) structs.TransparentProxyConfig { + var out structs.TransparentProxyConfig + if tproxyConf == nil { + return out + } + + out.OutboundListenerPort = intVal(tproxyConf.OutboundListenerPort) + return out +} + +func (b *builder) proxyModeVal(v *string) structs.ProxyMode { + if v == nil { + return structs.ProxyModeDefault + } + + mode, err := structs.ValidateProxyMode(*v) + if err != nil { + b.err = multierror.Append(b.err, err) + } + return mode +} + func (b *builder) pathsVal(v []ExposePath) []structs.ExposePath { paths := make([]structs.ExposePath, len(v)) for i, p := range v { diff --git a/agent/config/config.go b/agent/config/config.go index 937d543886..b65cb52802 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -461,6 +461,12 @@ type ServiceProxy struct { // (DestinationServiceID is set) but otherwise will be ignored. LocalServicePort *int `mapstructure:"local_service_port"` + // TransparentProxy configuration. + TransparentProxy *TransparentProxyConfig `mapstructure:"transparent_proxy"` + + // Mode represents how the proxy's inbound and upstream listeners are dialed. + Mode *string `mapstructure:"mode"` + // Config is the arbitrary configuration data provided with the proxy // registration. Config map[string]interface{} `mapstructure:"config"` @@ -474,10 +480,6 @@ type ServiceProxy struct { // Expose defines whether checks or paths are exposed through the proxy Expose *ExposeConfig `mapstructure:"expose"` - - // TransparentProxy toggles whether inbound and outbound traffic is being - // redirected to the proxy. - TransparentProxy *bool `mapstructure:"transparent_proxy"` } // Upstream represents a single upstream dependency for a service or proxy. It @@ -523,6 +525,11 @@ type MeshGatewayConfig struct { Mode *string `mapstructure:"mode"` } +type TransparentProxyConfig struct { + // Mesh Gateway Mode + OutboundListenerPort *int `mapstructure:"outbound_listener_port"` +} + // ExposeConfig describes HTTP paths to expose through Envoy outside of Connect. // Users can expose individual paths and/or all HTTP/GRPC paths for checks. type ExposeConfig struct { diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 38ea470fb5..f4deb8c554 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -2582,7 +2582,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { } ] }, - "transparent_proxy": true, + "mode": "transparent", + "transparent_proxy": { + "outbound_listener_port": 10101 + }, "upstreams": [ { "destination_name": "db", @@ -2619,7 +2622,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { } ] } - transparent_proxy = true + mode = "transparent" + transparent_proxy = { + outbound_listener_port = 10101 + } upstreams = [ { destination_name = "db" @@ -2659,7 +2665,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { }, }, }, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, Upstreams: structs.Upstreams{ structs.Upstream{ DestinationType: "service", @@ -2714,7 +2723,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { } ] }, - "transparent_proxy": true, + "mode": "transparent", + "transparent_proxy": { + "outbound_listener_port": 10101 + }, "upstreams": [ { "destination_name": "db", @@ -2751,7 +2763,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { } ] } - transparent_proxy = true, + mode = "transparent" + transparent_proxy = { + outbound_listener_port = 10101 + } upstreams = [ { destination_name = "db" @@ -2791,7 +2806,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { }, }, }, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, Upstreams: structs.Upstreams{ structs.Upstream{ DestinationType: "service", @@ -3435,7 +3453,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { "mesh_gateway": { "mode": "remote" }, - "transparent_proxy": true + "mode": "transparent", + "transparent_proxy": { + "outbound_listener_port": 10101 + } } ] } @@ -3454,7 +3475,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { mesh_gateway { mode = "remote" } - transparent_proxy = true + mode = "transparent" + transparent_proxy = { + outbound_listener_port = 10101 + } } }`}, expected: func(rt *RuntimeConfig) { @@ -3473,7 +3497,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { MeshGateway: structs.MeshGatewayConfig{ Mode: structs.MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, } }, @@ -3496,7 +3523,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { "MeshGateway": { "Mode": "remote" }, - "TransparentProxy": true + "Mode": "transparent", + "TransparentProxy": { + "OutboundListenerPort": 10101 + } } ] } @@ -3515,7 +3545,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { MeshGateway { Mode = "remote" } - TransparentProxy = true + Mode = "transparent" + TransparentProxy = { + OutboundListenerPort = 10101 + } } }`}, expected: func(rt *RuntimeConfig) { @@ -3534,7 +3567,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { MeshGateway: structs.MeshGatewayConfig{ Mode: structs.MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, } }, @@ -3557,7 +3593,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { "mesh_gateway": { "mode": "remote" }, - "transparent_proxy": true + "mode": "transparent", + "transparent_proxy": { + "outbound_listener_port": 10101 + } } ] } @@ -3576,7 +3615,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { mesh_gateway { mode = "remote" } - transparent_proxy = true + mode = "transparent" + transparent_proxy = { + outbound_listener_port = 10101 + } } }`}, expected: func(rt *RuntimeConfig) { @@ -3595,7 +3637,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { MeshGateway: structs.MeshGatewayConfig{ Mode: structs.MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, } }, @@ -3618,7 +3663,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { "MeshGateway": { "Mode": "remote" }, - "TransparentProxy": true + "Mode": "transparent", + "TransparentProxy": { + "OutboundListenerPort": 10101 + } } ] } @@ -3637,7 +3685,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { MeshGateway { Mode = "remote" } - TransparentProxy = true + Mode = "transparent" + TransparentProxy = { + OutboundListenerPort = 10101 + } } }`}, expected: func(rt *RuntimeConfig) { @@ -3656,7 +3707,10 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { MeshGateway: structs.MeshGatewayConfig{ Mode: structs.MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, } }, @@ -5598,7 +5652,10 @@ func TestLoad_FullConfig(t *testing.T) { }, }, }, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, Weights: &structs.Weights{ Passing: 1, diff --git a/agent/config/testdata/full-config.hcl b/agent/config/testdata/full-config.hcl index 6b56b1bc7e..c1323ef22f 100644 --- a/agent/config/testdata/full-config.hcl +++ b/agent/config/testdata/full-config.hcl @@ -591,7 +591,10 @@ services = [ } ] } - transparent_proxy = true + mode = "transparent" + transparent_proxy = { + outbound_listener_port = 10101 + } } }, { diff --git a/agent/config/testdata/full-config.json b/agent/config/testdata/full-config.json index 4443f2879a..2c8b26df25 100644 --- a/agent/config/testdata/full-config.json +++ b/agent/config/testdata/full-config.json @@ -572,7 +572,10 @@ } ] }, - "transparent_proxy": true, + "mode": "transparent", + "transparent_proxy": { + "outbound_listener_port": 10101 + }, "upstreams": [ { "destination_name": "KPtAj2cb", diff --git a/agent/consul/config_endpoint.go b/agent/consul/config_endpoint.go index 2b3e345e54..5bf5a55963 100644 --- a/agent/consul/config_endpoint.go +++ b/agent/consul/config_endpoint.go @@ -355,9 +355,10 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r return fmt.Errorf("failed to copy global proxy-defaults: %v", err) } reply.ProxyConfig = mapCopy.(map[string]interface{}) + reply.Mode = proxyConf.Mode + reply.TransparentProxy = proxyConf.TransparentProxy reply.MeshGateway = proxyConf.MeshGateway reply.Expose = proxyConf.Expose - reply.TransparentProxy = proxyConf.TransparentProxy // Extract the global protocol from proxyConf for upstream configs. rawProtocol := proxyConf.Config["protocol"] @@ -396,8 +397,11 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r } reply.ProxyConfig["protocol"] = serviceConf.Protocol } - if serviceConf.TransparentProxy { - reply.TransparentProxy = serviceConf.TransparentProxy + if serviceConf.TransparentProxy.OutboundListenerPort != 0 { + reply.TransparentProxy.OutboundListenerPort = serviceConf.TransparentProxy.OutboundListenerPort + } + if serviceConf.Mode != structs.ProxyModeDefault { + reply.Mode = serviceConf.Mode } } @@ -413,13 +417,13 @@ func (c *ConfigEntry) ResolveServiceConfig(args *structs.ServiceConfigRequest, r var ( noUpstreamArgs = len(upstreamIDs) == 0 && len(args.Upstreams) == 0 - // Check the args and the resolved value. If it was exclusively set via a config entry, then args.TransparentProxy - // will never be true because the service config request does not use the resolved value. - tproxy = args.TransparentProxy || reply.TransparentProxy + // Check the args and the resolved value. If it was exclusively set via a config entry, then args.Mode + // will never be transparent because the service config request does not use the resolved value. + tproxy = args.Mode == structs.ProxyModeTransparent || reply.Mode == structs.ProxyModeTransparent ) // The upstreams passed as arguments to this endpoint are the upstreams explicitly defined in a proxy registration. - // If no upstreams were passed, then we should only returned the resolved config if the proxy has TransparentProxy mode enabled. + // If no upstreams were passed, then we should only returned the resolved config if the proxy in transparent mode. // Otherwise we would return a resolved upstream config to a proxy with no configured upstreams. if noUpstreamArgs && !tproxy { return nil diff --git a/agent/consul/config_endpoint_test.go b/agent/consul/config_endpoint_test.go index ea17042011..abbe952396 100644 --- a/agent/consul/config_endpoint_test.go +++ b/agent/consul/config_endpoint_test.go @@ -913,7 +913,8 @@ func TestConfigEntry_ResolveServiceConfig_TransparentProxy(t *testing.T) { &structs.ProxyConfigEntry{ Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, }, }, request: structs.ServiceConfigRequest{ @@ -921,7 +922,8 @@ func TestConfigEntry_ResolveServiceConfig_TransparentProxy(t *testing.T) { Datacenter: "dc1", }, expect: structs.ServiceConfigResponse{ - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, }, }, { @@ -930,7 +932,8 @@ func TestConfigEntry_ResolveServiceConfig_TransparentProxy(t *testing.T) { &structs.ServiceConfigEntry{ Kind: structs.ServiceDefaults, Name: "foo", - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 808}, }, }, request: structs.ServiceConfigRequest{ @@ -938,7 +941,8 @@ func TestConfigEntry_ResolveServiceConfig_TransparentProxy(t *testing.T) { Datacenter: "dc1", }, expect: structs.ServiceConfigResponse{ - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 808}, }, }, { @@ -947,12 +951,14 @@ func TestConfigEntry_ResolveServiceConfig_TransparentProxy(t *testing.T) { &structs.ProxyConfigEntry{ Kind: structs.ProxyDefaults, Name: structs.ProxyConfigGlobal, - TransparentProxy: false, + Mode: structs.ProxyModeDirect, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, }, &structs.ServiceConfigEntry{ Kind: structs.ServiceDefaults, Name: "foo", - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 808}, }, }, request: structs.ServiceConfigRequest{ @@ -960,7 +966,8 @@ func TestConfigEntry_ResolveServiceConfig_TransparentProxy(t *testing.T) { Datacenter: "dc1", }, expect: structs.ServiceConfigResponse{ - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 808}, }, }, } @@ -1245,9 +1252,9 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { }, }, request: structs.ServiceConfigRequest{ - Name: "api", - Datacenter: "dc1", - TransparentProxy: true, + Name: "api", + Datacenter: "dc1", + Mode: structs.ProxyModeTransparent, // Empty Upstreams/UpstreamIDs }, @@ -1291,7 +1298,8 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { }, // TransparentProxy on the config entry but not the config request - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, }, }, request: structs.ServiceConfigRequest{ @@ -1301,7 +1309,8 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { // Empty Upstreams/UpstreamIDs }, expect: structs.ServiceConfigResponse{ - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{ { Upstream: wildcard, @@ -1342,9 +1351,9 @@ func TestConfigEntry_ResolveServiceConfig_Upstreams(t *testing.T) { }, }, request: structs.ServiceConfigRequest{ - Name: "api", - Datacenter: "dc1", - TransparentProxy: false, + Name: "api", + Datacenter: "dc1", + Mode: structs.ProxyModeDirect, // Empty Upstreams/UpstreamIDs }, diff --git a/agent/dns_test.go b/agent/dns_test.go index 08583caeec..db03243bff 100644 --- a/agent/dns_test.go +++ b/agent/dns_test.go @@ -6688,7 +6688,7 @@ func TestDNS_trimUDPResponse_NoTrim(t *testing.T) { }, } - cfg := loadRuntimeConfig(t, `data_dir = "a" bind_addr = "127.0.0.1"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1"`) if trimmed := trimUDPResponse(req, resp, cfg.DNSUDPAnswerLimit); trimmed { t.Fatalf("Bad %#v", *resp) } @@ -6722,7 +6722,7 @@ func TestDNS_trimUDPResponse_NoTrim(t *testing.T) { func TestDNS_trimUDPResponse_TrimLimit(t *testing.T) { t.Parallel() - cfg := loadRuntimeConfig(t, `data_dir = "a" bind_addr = "127.0.0.1"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1"`) req, resp, expected := &dns.Msg{}, &dns.Msg{}, &dns.Msg{} for i := 0; i < cfg.DNSUDPAnswerLimit+1; i++ { @@ -6770,7 +6770,7 @@ func loadRuntimeConfig(t *testing.T, hcl string) *config.RuntimeConfig { func TestDNS_trimUDPResponse_TrimSize(t *testing.T) { t.Parallel() - cfg := loadRuntimeConfig(t, `data_dir = "a" bind_addr = "127.0.0.1"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1"`) req, resp := &dns.Msg{}, &dns.Msg{} for i := 0; i < 100; i++ { @@ -6823,7 +6823,7 @@ func TestDNS_trimUDPResponse_TrimSize(t *testing.T) { func TestDNS_trimUDPResponse_TrimSizeEDNS(t *testing.T) { t.Parallel() - cfg := loadRuntimeConfig(t, `data_dir = "a" bind_addr = "127.0.0.1"`) + cfg := loadRuntimeConfig(t, `node_name = "test" data_dir = "a" bind_addr = "127.0.0.1"`) req, resp := &dns.Msg{}, &dns.Msg{} diff --git a/agent/proxycfg/snapshot.go b/agent/proxycfg/snapshot.go index e79fc1507e..d0dab4deba 100644 --- a/agent/proxycfg/snapshot.go +++ b/agent/proxycfg/snapshot.go @@ -360,7 +360,7 @@ type ConfigSnapshot struct { func (s *ConfigSnapshot) Valid() bool { switch s.Kind { case structs.ServiceKindConnectProxy: - if s.Proxy.TransparentProxy && !s.ConnectProxy.ClusterConfigSet { + if s.Proxy.Mode == structs.ProxyModeTransparent && !s.ConnectProxy.ClusterConfigSet { return false } return s.Roots != nil && diff --git a/agent/proxycfg/state.go b/agent/proxycfg/state.go index 71e2182e29..5d0b886240 100644 --- a/agent/proxycfg/state.go +++ b/agent/proxycfg/state.go @@ -305,7 +305,7 @@ func (s *state) initWatchesConnectProxy(snap *ConfigSnapshot) error { // default the namespace to the namespace of this proxy service currentNamespace := s.proxyID.NamespaceOrDefault() - if s.proxyCfg.TransparentProxy { + if s.proxyCfg.Mode == structs.ProxyModeTransparent { // When in transparent proxy we will infer upstreams from intentions with this source err := s.cache.Notify(s.ctx, cachetype.IntentionUpstreamsName, &structs.ServiceSpecificRequest{ Datacenter: s.source.Datacenter, @@ -350,8 +350,8 @@ func (s *state) initWatchesConnectProxy(snap *ConfigSnapshot) error { if u.Datacenter != "" { dc = u.Datacenter } - if s.proxyCfg.TransparentProxy && (dc == "" || dc == s.source.Datacenter) { - // In TransparentProxy mode, watches for upstreams in the local DC are handled by the IntentionUpstreams watch. + if s.proxyCfg.Mode == structs.ProxyModeTransparent && (dc == "" || dc == s.source.Datacenter) { + // In transparent proxy mode, watches for upstreams in the local DC are handled by the IntentionUpstreams watch. continue } diff --git a/agent/proxycfg/state_test.go b/agent/proxycfg/state_test.go index 8fad4c6008..f4c36d5edb 100644 --- a/agent/proxycfg/state_test.go +++ b/agent/proxycfg/state_test.go @@ -1541,7 +1541,7 @@ func TestState_WatchesAndUpdates(t *testing.T) { Address: "10.0.1.1", Proxy: structs.ConnectProxyConfig{ DestinationServiceName: "api", - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, }, }, sourceDC: "dc1", @@ -1606,7 +1606,7 @@ func TestState_WatchesAndUpdates(t *testing.T) { Address: "10.0.1.1", Proxy: structs.ConnectProxyConfig{ DestinationServiceName: "api", - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, Upstreams: structs.Upstreams{ { CentrallyConfigured: true, diff --git a/agent/service_manager.go b/agent/service_manager.go index d48ba26326..e67f30ce0d 100644 --- a/agent/service_manager.go +++ b/agent/service_manager.go @@ -335,13 +335,13 @@ func makeConfigRequest(bd BaseDeps, addReq AddServiceRequest) *structs.ServiceCo } req := &structs.ServiceConfigRequest{ - Name: name, - Datacenter: bd.RuntimeConfig.Datacenter, - QueryOptions: structs.QueryOptions{Token: addReq.token}, - MeshGateway: ns.Proxy.MeshGateway, - TransparentProxy: ns.Proxy.TransparentProxy, - UpstreamIDs: upstreams, - EnterpriseMeta: ns.EnterpriseMeta, + Name: name, + Datacenter: bd.RuntimeConfig.Datacenter, + QueryOptions: structs.QueryOptions{Token: addReq.token}, + MeshGateway: ns.Proxy.MeshGateway, + Mode: ns.Proxy.Mode, + UpstreamIDs: upstreams, + EnterpriseMeta: ns.EnterpriseMeta, } if req.QueryOptions.Token == "" { req.QueryOptions.Token = bd.Tokens.AgentToken() @@ -377,8 +377,11 @@ func mergeServiceConfig(defaults *structs.ServiceConfigResponse, service *struct if ns.Proxy.MeshGateway.Mode == structs.MeshGatewayModeDefault { ns.Proxy.MeshGateway.Mode = defaults.MeshGateway.Mode } - if !ns.Proxy.TransparentProxy { - ns.Proxy.TransparentProxy = defaults.TransparentProxy + if ns.Proxy.Mode == structs.ProxyModeDefault { + ns.Proxy.Mode = defaults.Mode + } + if ns.Proxy.TransparentProxy.OutboundListenerPort == 0 { + ns.Proxy.TransparentProxy.OutboundListenerPort = defaults.TransparentProxy.OutboundListenerPort } // remoteUpstreams contains synthetic Upstreams generated from central config (service-defaults.UpstreamConfigs). @@ -406,7 +409,7 @@ func mergeServiceConfig(defaults *structs.ServiceConfigResponse, service *struct } // localUpstreams stores the upstreams seen from the local registration so that we can merge in the synthetic entries. - // In TransparentProxy mode ns.Proxy.Upstreams will likely be empty because users do not need to define upstreams explicitly. + // In transparent proxy mode ns.Proxy.Upstreams will likely be empty because users do not need to define upstreams explicitly. // So to store upstream-specific flags from central config, we add entries to ns.Proxy.Upstream with those values. localUpstreams := make(map[structs.ServiceID]struct{}) @@ -437,9 +440,9 @@ func mergeServiceConfig(defaults *structs.ServiceConfigResponse, service *struct } // Ensure upstreams present in central config are represented in the local configuration. - // This does not apply outside of TransparentProxy mode because in that situation every possible upstream already exists + // This does not apply outside of transparent mode because in that situation every possible upstream already exists // inside of ns.Proxy.Upstreams. - if ns.Proxy.TransparentProxy { + if ns.Proxy.Mode == structs.ProxyModeTransparent { for id, remote := range remoteUpstreams { if _, ok := localUpstreams[id]; ok { // Remote upstream is already present locally diff --git a/agent/service_manager_test.go b/agent/service_manager_test.go index 7a4ef3eec4..464b7087ec 100644 --- a/agent/service_manager_test.go +++ b/agent/service_manager_test.go @@ -929,7 +929,7 @@ func Test_mergeServiceConfig_UpstreamOverrides(t *testing.T) { }, }, { - name: "remote upstream config expands local upstream list in tproxy mode", + name: "remote upstream config expands local upstream list in transparent mode", args: args{ defaults: &structs.ServiceConfigResponse{ UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{ @@ -950,7 +950,10 @@ func Test_mergeServiceConfig_UpstreamOverrides(t *testing.T) { Proxy: structs.ConnectProxyConfig{ DestinationServiceName: "foo", DestinationServiceID: "foo", - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, Upstreams: structs.Upstreams{ structs.Upstream{ DestinationNamespace: "default", @@ -970,7 +973,10 @@ func Test_mergeServiceConfig_UpstreamOverrides(t *testing.T) { Proxy: structs.ConnectProxyConfig{ DestinationServiceName: "foo", DestinationServiceID: "foo", - TransparentProxy: true, + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, Upstreams: structs.Upstreams{ structs.Upstream{ DestinationNamespace: "default", @@ -993,7 +999,7 @@ func Test_mergeServiceConfig_UpstreamOverrides(t *testing.T) { }, }, { - name: "remote upstream config not added to local upstream list outside of tproxy mode", + name: "remote upstream config not added to local upstream list outside of transparent mode", args: args{ defaults: &structs.ServiceConfigResponse{ UpstreamIDConfigs: structs.OpaqueUpstreamConfigs{ @@ -1014,7 +1020,7 @@ func Test_mergeServiceConfig_UpstreamOverrides(t *testing.T) { Proxy: structs.ConnectProxyConfig{ DestinationServiceName: "foo", DestinationServiceID: "foo", - TransparentProxy: false, + Mode: structs.ProxyModeDirect, Upstreams: structs.Upstreams{ structs.Upstream{ DestinationNamespace: "default", @@ -1034,6 +1040,7 @@ func Test_mergeServiceConfig_UpstreamOverrides(t *testing.T) { Proxy: structs.ConnectProxyConfig{ DestinationServiceName: "foo", DestinationServiceID: "foo", + Mode: structs.ProxyModeDirect, Upstreams: structs.Upstreams{ structs.Upstream{ DestinationNamespace: "default", @@ -1175,3 +1182,81 @@ func Test_mergeServiceConfig_UpstreamOverrides(t *testing.T) { }) } } + +func Test_mergeServiceConfig_TransparentProxy(t *testing.T) { + type args struct { + defaults *structs.ServiceConfigResponse + service *structs.NodeService + } + tests := []struct { + name string + args args + want *structs.NodeService + }{ + { + name: "inherit transparent proxy settings", + args: args{ + defaults: &structs.ServiceConfigResponse{ + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, + }, + service: &structs.NodeService{ + ID: "foo-proxy", + Service: "foo-proxy", + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "foo", + DestinationServiceID: "foo", + Mode: structs.ProxyModeDefault, + TransparentProxy: structs.TransparentProxyConfig{}, + }, + }, + }, + want: &structs.NodeService{ + ID: "foo-proxy", + Service: "foo-proxy", + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "foo", + DestinationServiceID: "foo", + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, + }, + }, + }, + { + name: "override transparent proxy settings", + args: args{ + defaults: &structs.ServiceConfigResponse{ + Mode: structs.ProxyModeTransparent, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 10101}, + }, + service: &structs.NodeService{ + ID: "foo-proxy", + Service: "foo-proxy", + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "foo", + DestinationServiceID: "foo", + Mode: structs.ProxyModeDirect, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 808}, + }, + }, + }, + want: &structs.NodeService{ + ID: "foo-proxy", + Service: "foo-proxy", + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "foo", + DestinationServiceID: "foo", + Mode: structs.ProxyModeDirect, + TransparentProxy: structs.TransparentProxyConfig{OutboundListenerPort: 808}, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := mergeServiceConfig(tt.args.defaults, tt.args.service) + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/agent/structs/config_entry.go b/agent/structs/config_entry.go index a12e6a4077..1b01daaa12 100644 --- a/agent/structs/config_entry.go +++ b/agent/structs/config_entry.go @@ -85,9 +85,10 @@ type ServiceConfigEntry struct { Kind string Name string Protocol string - MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` - Expose ExposeConfig `json:",omitempty"` - TransparentProxy bool `json:",omitempty" alias:"transparent_proxy"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` + MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` + Expose ExposeConfig `json:",omitempty"` ExternalSNI string `json:",omitempty" alias:"external_sni"` @@ -223,9 +224,10 @@ type ProxyConfigEntry struct { Kind string Name string Config map[string]interface{} - MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` - Expose ExposeConfig `json:",omitempty"` - TransparentProxy bool `json:",omitempty" alias:"transparent_proxy"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` + MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` + Expose ExposeConfig `json:",omitempty"` Meta map[string]string `json:",omitempty"` EnterpriseMeta `hcl:",squash" mapstructure:",squash"` @@ -595,8 +597,8 @@ type ServiceConfigRequest struct { // MeshGateway contains the mesh gateway configuration from the requesting proxy's registration MeshGateway MeshGatewayConfig - // TransparentProxy indicates whether the requesting proxy is in transparent proxy mode - TransparentProxy bool + // Mode indicates how the requesting proxy's listeners are dialed + Mode ProxyMode UpstreamIDs []ServiceID @@ -859,9 +861,10 @@ type ServiceConfigResponse struct { ProxyConfig map[string]interface{} UpstreamConfigs map[string]map[string]interface{} UpstreamIDConfigs OpaqueUpstreamConfigs - MeshGateway MeshGatewayConfig `json:",omitempty"` - Expose ExposeConfig `json:",omitempty"` - TransparentProxy bool `json:",omitempty"` + MeshGateway MeshGatewayConfig `json:",omitempty"` + Expose ExposeConfig `json:",omitempty"` + TransparentProxy TransparentProxyConfig `json:",omitempty"` + Mode ProxyMode `json:",omitempty"` QueryMeta } diff --git a/agent/structs/connect_proxy_config.go b/agent/structs/connect_proxy_config.go index 2cf920a743..225c663d75 100644 --- a/agent/structs/connect_proxy_config.go +++ b/agent/structs/connect_proxy_config.go @@ -26,8 +26,8 @@ const ( // should be direct and not flow through a mesh gateway. MeshGatewayModeNone MeshGatewayMode = "none" - // MeshGatewayModeLocal represents that the Upstrea Connect connections - // should be made to a mesh gateway in the local datacenter. This is + // MeshGatewayModeLocal represents that the Upstream Connect connections + // should be made to a mesh gateway in the local datacenter. MeshGatewayModeLocal MeshGatewayMode = "local" // MeshGatewayModeRemote represents that the Upstream Connect connections @@ -75,6 +75,45 @@ func (c *MeshGatewayConfig) ToAPI() api.MeshGatewayConfig { return api.MeshGatewayConfig{Mode: api.MeshGatewayMode(c.Mode)} } +type ProxyMode string + +const ( + // ProxyModeDefault represents no specific mode and should + // be used to indicate that a different layer of the configuration + // chain should take precedence + ProxyModeDefault ProxyMode = "" + + // ProxyModeTransparent represents that inbound and outbound application + // traffic is being captured and redirected through the proxy. + ProxyModeTransparent ProxyMode = "transparent" + + // ProxyModeDirect represents that the proxy's listeners must be dialed directly + // by the local application and other proxies. + ProxyModeDirect ProxyMode = "direct" +) + +func ValidateProxyMode(mode string) (ProxyMode, error) { + switch ProxyMode(mode) { + case ProxyModeDefault: + return ProxyModeDefault, nil + case ProxyModeDirect: + return ProxyModeDirect, nil + case ProxyModeTransparent: + return ProxyModeTransparent, nil + default: + return ProxyModeDefault, fmt.Errorf("Invalid Proxy Mode: %q", mode) + } +} + +type TransparentProxyConfig struct { + // The port of the listener where outbound application traffic is being redirected to. + OutboundListenerPort int `json:",omitempty" alias:"outbound_listener_port"` +} + +func (c TransparentProxyConfig) ToAPI() api.TransparentProxyConfig { + return api.TransparentProxyConfig{OutboundListenerPort: c.OutboundListenerPort} +} + // ConnectProxyConfig describes the configuration needed for any proxy managed // or unmanaged. It describes a single logical service's listener and optionally // upstreams and sidecar-related config for a single instance. To describe a @@ -105,6 +144,9 @@ type ConnectProxyConfig struct { // (DestinationServiceID is set) but otherwise will be ignored. LocalServicePort int `json:",omitempty" alias:"local_service_port"` + // Mode represents how the proxy's inbound and upstream listeners are dialed. + Mode ProxyMode + // Config is the arbitrary configuration data provided with the proxy // registration. Config map[string]interface{} `json:",omitempty" bexpr:"-"` @@ -119,20 +161,20 @@ type ConnectProxyConfig struct { // Expose defines whether checks or paths are exposed through the proxy Expose ExposeConfig `json:",omitempty"` - // TransparentProxy toggles whether inbound and outbound traffic is being - // redirected to the proxy. - TransparentProxy bool `json:",omitempty" alias:"transparent_proxy"` + // TransparentProxy defines configuration for when the proxy is in + // transparent mode. + TransparentProxy TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` } func (t *ConnectProxyConfig) UnmarshalJSON(data []byte) (err error) { type Alias ConnectProxyConfig aux := &struct { - DestinationServiceNameSnake string `json:"destination_service_name"` - DestinationServiceIDSnake string `json:"destination_service_id"` - LocalServiceAddressSnake string `json:"local_service_address"` - LocalServicePortSnake int `json:"local_service_port"` - MeshGatewaySnake MeshGatewayConfig `json:"mesh_gateway"` - TransparentProxySnake bool `json:"transparent_proxy"` + DestinationServiceNameSnake string `json:"destination_service_name"` + DestinationServiceIDSnake string `json:"destination_service_id"` + LocalServiceAddressSnake string `json:"local_service_address"` + LocalServicePortSnake int `json:"local_service_port"` + MeshGatewaySnake MeshGatewayConfig `json:"mesh_gateway"` + TransparentProxySnake TransparentProxyConfig `json:"transparent_proxy"` *Alias }{ @@ -156,8 +198,8 @@ func (t *ConnectProxyConfig) UnmarshalJSON(data []byte) (err error) { if t.MeshGateway.Mode == "" { t.MeshGateway.Mode = aux.MeshGatewaySnake.Mode } - if !t.TransparentProxy { - t.TransparentProxy = aux.TransparentProxySnake + if t.TransparentProxy.OutboundListenerPort == 0 { + t.TransparentProxy.OutboundListenerPort = aux.TransparentProxySnake.OutboundListenerPort } return nil @@ -187,11 +229,12 @@ func (c *ConnectProxyConfig) ToAPI() *api.AgentServiceConnectProxyConfig { DestinationServiceID: c.DestinationServiceID, LocalServiceAddress: c.LocalServiceAddress, LocalServicePort: c.LocalServicePort, + Mode: api.ProxyMode(c.Mode), + TransparentProxy: c.TransparentProxy.ToAPI(), Config: c.Config, Upstreams: c.Upstreams.ToAPI(), MeshGateway: c.MeshGateway.ToAPI(), Expose: c.Expose.ToAPI(), - TransparentProxy: c.TransparentProxy, } } diff --git a/agent/structs/connect_proxy_config_test.go b/agent/structs/connect_proxy_config_test.go index 7c2c911f87..df680a0690 100644 --- a/agent/structs/connect_proxy_config_test.go +++ b/agent/structs/connect_proxy_config_test.go @@ -572,3 +572,37 @@ func TestValidateMeshGatewayMode(t *testing.T) { }) } } + +func TestValidateProxyMode(t *testing.T) { + for _, tc := range []struct { + modeConstant string + modeExplicit string + expect ProxyMode + ok bool + }{ + {string(ProxyModeDefault), "", ProxyModeDefault, true}, + {string(ProxyModeDirect), "direct", ProxyModeDirect, true}, + {string(ProxyModeTransparent), "transparent", ProxyModeTransparent, true}, + } { + tc := tc + + t.Run(tc.modeConstant+" (constant)", func(t *testing.T) { + got, err := ValidateProxyMode(tc.modeConstant) + if tc.ok { + require.NoError(t, err) + require.Equal(t, tc.expect, got) + } else { + require.Error(t, err) + } + }) + t.Run(tc.modeExplicit+" (explicit)", func(t *testing.T) { + got, err := ValidateProxyMode(tc.modeExplicit) + if tc.ok { + require.NoError(t, err) + require.Equal(t, tc.expect, got) + } else { + require.Error(t, err) + } + }) + } +} diff --git a/agent/structs/structs_filtering_test.go b/agent/structs/structs_filtering_test.go index 2fa419eeb3..eb61b5bfb2 100644 --- a/agent/structs/structs_filtering_test.go +++ b/agent/structs/structs_filtering_test.go @@ -95,6 +95,14 @@ var expectedFieldConfigMeshGatewayConfig bexpr.FieldConfigurations = bexpr.Field }, } +var expectedFieldConfigTransparentProxyConfig bexpr.FieldConfigurations = bexpr.FieldConfigurations{ + "OutboundListenerPort": &bexpr.FieldConfiguration{ + StructFieldName: "OutboundListenerPort", + CoerceFn: bexpr.CoerceInt, + SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual}, + }, +} + var expectedFieldConfigExposeConfig bexpr.FieldConfigurations = bexpr.FieldConfigurations{ "Checks": &bexpr.FieldConfiguration{ StructFieldName: "Checks", @@ -208,9 +216,13 @@ var expectedFieldConfigConnectProxyConfig bexpr.FieldConfigurations = bexpr.Fiel SubFields: expectedFieldConfigExposeConfig, }, "TransparentProxy": &bexpr.FieldConfiguration{ - StructFieldName: "TransparentProxy", - CoerceFn: bexpr.CoerceBool, - SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual}, + StructFieldName: "TransparentProxy", + SubFields: expectedFieldConfigTransparentProxyConfig, + }, + "Mode": &bexpr.FieldConfiguration{ + StructFieldName: "Mode", + CoerceFn: bexpr.CoerceString, + SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches}, }, } diff --git a/agent/xds/clusters.go b/agent/xds/clusters.go index 776b6a3244..db99104375 100644 --- a/agent/xds/clusters.go +++ b/agent/xds/clusters.go @@ -56,10 +56,11 @@ func (s *Server) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.ConfigSnapsh } clusters = append(clusters, appCluster) - // In TransparentProxy mode there needs to be a passthrough cluster for traffic going to destinations + // In transparent proxy mode there needs to be a passthrough cluster for traffic going to destinations // that aren't in Consul's catalog. - // TODO (freddy): Add cluster-wide setting that can disable this cluster and restrict traffic to catalog destinations. - if cfgSnap.Proxy.TransparentProxy { + if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent && + !cfgSnap.ConnectProxy.ClusterConfig.TransparentProxy.CatalogDestinationsOnly { + clusters = append(clusters, &envoy_cluster_v3.Cluster{ Name: OriginalDestinationClusterName, ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{ diff --git a/agent/xds/clusters_test.go b/agent/xds/clusters_test.go index e3a7e4230f..6e82ca946e 100644 --- a/agent/xds/clusters_test.go +++ b/agent/xds/clusters_test.go @@ -629,7 +629,14 @@ func TestClustersFromSnapshot(t *testing.T) { name: "transparent-proxy", create: proxycfg.TestConfigSnapshot, setup: func(snap *proxycfg.ConfigSnapshot) { - snap.Proxy.TransparentProxy = true + snap.Proxy.Mode = structs.ProxyModeTransparent + + snap.ConnectProxy.ClusterConfigSet = true + snap.ConnectProxy.ClusterConfig = &structs.ClusterConfigEntry{ + TransparentProxy: structs.TransparentProxyClusterConfig{ + CatalogDestinationsOnly: false, + }, + } }, }, } diff --git a/agent/xds/listeners.go b/agent/xds/listeners.go index a8ea5f5c8c..08cc81f84c 100644 --- a/agent/xds/listeners.go +++ b/agent/xds/listeners.go @@ -65,14 +65,19 @@ func (s *Server) listenersFromSnapshotConnectProxy(cInfo connectionInfo, cfgSnap return nil, err } - // This outboundListener is exclusively used when TransparentProxy mode is active. + // This outboundListener is exclusively used when transparent proxy mode is active. // In that situation there is a single listener where we are redirecting outbound traffic, // and each upstream gets a filter chain attached to that listener. var outboundListener *envoy_listener_v3.Listener - if cfgSnap.Proxy.TransparentProxy { + if cfgSnap.Proxy.Mode == structs.ProxyModeTransparent { + port := iptables.DefaultTProxyOutboundPort + if cfgSnap.Proxy.TransparentProxy.OutboundListenerPort != 0 { + port = cfgSnap.Proxy.TransparentProxy.OutboundListenerPort + } + // TODO (freddy) Make DefaultTProxyOutboundPort configurable - outboundListener = makeListener(OutboundListenerName, "127.0.0.1", iptables.DefaultTProxyOutboundPort, envoy_core_v3.TrafficDirection_OUTBOUND) + outboundListener = makeListener(OutboundListenerName, "127.0.0.1", port, envoy_core_v3.TrafficDirection_OUTBOUND) outboundListener.FilterChains = make([]*envoy_listener_v3.FilterChain, 0) outboundListener.ListenerFilters = []*envoy_listener_v3.ListenerFilter{ { diff --git a/agent/xds/listeners_test.go b/agent/xds/listeners_test.go index dc2cd2e9d3..1bc307c56a 100644 --- a/agent/xds/listeners_test.go +++ b/agent/xds/listeners_test.go @@ -481,11 +481,11 @@ func TestListenersFromSnapshot(t *testing.T) { name: "transparent-proxy", create: proxycfg.TestConfigSnapshot, setup: func(snap *proxycfg.ConfigSnapshot) { - snap.Proxy.TransparentProxy = true + snap.Proxy.Mode = structs.ProxyModeTransparent snap.ConnectProxy.ClusterConfigSet = true - // DiscoveryChain without an UpstreamConfig should yield a filter chain when in TransparentProxy mode + // DiscoveryChain without an UpstreamConfig should yield a filter chain when in transparent proxy mode snap.ConnectProxy.DiscoveryChain["google"] = discoverychain.TestCompileConfigEntries( t, "google", "default", "dc1", connect.TestClusterID+".consul", "dc1", nil) @@ -514,7 +514,7 @@ func TestListenersFromSnapshot(t *testing.T) { name: "transparent-proxy-catalog-destinations-only", create: proxycfg.TestConfigSnapshot, setup: func(snap *proxycfg.ConfigSnapshot) { - snap.Proxy.TransparentProxy = true + snap.Proxy.Mode = structs.ProxyModeTransparent snap.ConnectProxy.ClusterConfigSet = true snap.ConnectProxy.ClusterConfig = &structs.ClusterConfigEntry{ @@ -525,7 +525,7 @@ func TestListenersFromSnapshot(t *testing.T) { }, } - // DiscoveryChain without an UpstreamConfig should yield a filter chain when in TransparentProxy mode + // DiscoveryChain without an UpstreamConfig should yield a filter chain when in transparent proxy mode snap.ConnectProxy.DiscoveryChain["google"] = discoverychain.TestCompileConfigEntries( t, "google", "default", "dc1", connect.TestClusterID+".consul", "dc1", nil) diff --git a/agent/xds/server.go b/agent/xds/server.go index bce5d9df4a..9907747d21 100644 --- a/agent/xds/server.go +++ b/agent/xds/server.go @@ -52,7 +52,7 @@ const ( // PublicListenerName is the name we give the public listener in Envoy config. PublicListenerName = "public_listener" - // OutboundListenerName is the name we give the outbound Envoy listener when TransparentProxy mode is enabled. + // OutboundListenerName is the name we give the outbound Envoy listener when transparent proxy mode is enabled. OutboundListenerName = "outbound_listener" // LocalAppClusterName is the name we give the local application "cluster" in @@ -86,7 +86,7 @@ const ( // OriginalDestinationClusterName is the name we give to the passthrough // cluster which redirects transparently-proxied requests to their original // destination. This cluster prevents Consul from blocking connections to - // destinations outside of the catalog when in TransparentProxy mode. + // destinations outside of the catalog when in transparent proxy mode. OriginalDestinationClusterName = "original-destination" // DefaultAuthCheckFrequency is the default value for diff --git a/api/agent.go b/api/agent.go index 0ed6fc2984..acafa9cc91 100644 --- a/api/agent.go +++ b/api/agent.go @@ -118,11 +118,12 @@ type AgentServiceConnectProxyConfig struct { DestinationServiceID string `json:",omitempty"` LocalServiceAddress string `json:",omitempty"` LocalServicePort int `json:",omitempty"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy TransparentProxyConfig `json:",omitempty"` Config map[string]interface{} `json:",omitempty" bexpr:"-"` Upstreams []Upstream `json:",omitempty"` MeshGateway MeshGatewayConfig `json:",omitempty"` Expose ExposeConfig `json:",omitempty"` - TransparentProxy bool `json:",omitempty"` } const ( diff --git a/api/agent_test.go b/api/agent_test.go index 12056f2367..f0a5db2bb6 100644 --- a/api/agent_test.go +++ b/api/agent_test.go @@ -438,7 +438,7 @@ func TestAPI_AgentServices_ExternalConnectProxy(t *testing.T) { Port: 8001, Proxy: &AgentServiceConnectProxyConfig{ DestinationServiceName: "foo", - TransparentProxy: true, + Mode: ProxyModeTransparent, }, } if err := agent.ServiceRegister(reg); err != nil { @@ -455,7 +455,7 @@ func TestAPI_AgentServices_ExternalConnectProxy(t *testing.T) { if _, ok := services["foo-proxy"]; !ok { t.Fatalf("missing proxy service: %v", services) } - if !services["foo-proxy"].Proxy.TransparentProxy { + if services["foo-proxy"].Proxy.Mode != ProxyModeTransparent { t.Fatalf("expected transparent proxy mode to be enabled") } diff --git a/api/config_entry.go b/api/config_entry.go index bfb853057b..7ca8e3d78f 100644 --- a/api/config_entry.go +++ b/api/config_entry.go @@ -48,8 +48,8 @@ const ( // should be direct and not flow through a mesh gateway. MeshGatewayModeNone MeshGatewayMode = "none" - // MeshGatewayModeLocal represents that the Upstrea Connect connections - // should be made to a mesh gateway in the local datacenter. This is + // MeshGatewayModeLocal represents that the Upstream Connect connections + // should be made to a mesh gateway in the local datacenter. MeshGatewayModeLocal MeshGatewayMode = "local" // MeshGatewayModeRemote represents that the Upstream Connect connections @@ -64,6 +64,28 @@ type MeshGatewayConfig struct { Mode MeshGatewayMode `json:",omitempty"` } +type ProxyMode string + +const ( + // ProxyModeDefault represents no specific mode and should + // be used to indicate that a different layer of the configuration + // chain should take precedence + ProxyModeDefault ProxyMode = "" + + // ProxyModeTransparent represents that inbound and outbound application + // traffic is being captured and redirected through the proxy. + ProxyModeTransparent ProxyMode = "transparent" + + // ProxyModeDirect represents that the proxy's listeners must be dialed directly + // by the local application and other proxies. + ProxyModeDirect ProxyMode = "direct" +) + +type TransparentProxyConfig struct { + // The port of the listener where outbound application traffic is being redirected to. + OutboundListenerPort int `json:",omitempty" alias:"outbound_listener_port"` +} + // ExposeConfig describes HTTP paths to expose through Envoy outside of Connect. // Users can expose individual paths and/or all HTTP/GRPC paths for checks. type ExposeConfig struct { @@ -171,14 +193,15 @@ type UpstreamLimits struct { type ServiceConfigEntry struct { Kind string Name string - Namespace string `json:",omitempty"` - Protocol string `json:",omitempty"` - MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` - Connect ConnectConfiguration `json:",omitempty"` - Expose ExposeConfig `json:",omitempty"` - TransparentProxy bool `json:",omitempty" alias:"transparent_proxy"` - ExternalSNI string `json:",omitempty" alias:"external_sni"` - Meta map[string]string `json:",omitempty"` + Namespace string `json:",omitempty"` + Protocol string `json:",omitempty"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` + MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` + Connect ConnectConfiguration `json:",omitempty"` + Expose ExposeConfig `json:",omitempty"` + ExternalSNI string `json:",omitempty" alias:"external_sni"` + Meta map[string]string `json:",omitempty"` CreateIndex uint64 ModifyIndex uint64 } @@ -211,10 +234,11 @@ type ProxyConfigEntry struct { Kind string Name string Namespace string `json:",omitempty"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` Config map[string]interface{} `json:",omitempty"` MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` Expose ExposeConfig `json:",omitempty"` - TransparentProxy bool `json:",omitempty" alias:"transparent_proxy"` Meta map[string]string `json:",omitempty"` CreateIndex uint64 ModifyIndex uint64 diff --git a/api/config_entry_test.go b/api/config_entry_test.go index da4c248ee7..7492bc8722 100644 --- a/api/config_entry_test.go +++ b/api/config_entry_test.go @@ -297,7 +297,10 @@ func TestDecodeConfigEntry(t *testing.T) { "MeshGateway": { "Mode": "remote" }, - "TransparentProxy": true + "Mode": "transparent", + "TransparentProxy": { + "OutboundListenerPort": 808 + } } `, expect: &ProxyConfigEntry{ @@ -317,7 +320,8 @@ func TestDecodeConfigEntry(t *testing.T) { MeshGateway: MeshGatewayConfig{ Mode: MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: ProxyModeTransparent, + TransparentProxy: TransparentProxyConfig{OutboundListenerPort: 808}, }, }, { @@ -335,7 +339,10 @@ func TestDecodeConfigEntry(t *testing.T) { "MeshGateway": { "Mode": "remote" }, - "TransparentProxy": true, + "Mode": "transparent", + "TransparentProxy": { + "OutboundListenerPort": 808 + }, "Connect": { "UpstreamConfigs": { "redis": { @@ -380,7 +387,8 @@ func TestDecodeConfigEntry(t *testing.T) { MeshGateway: MeshGatewayConfig{ Mode: MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: ProxyModeTransparent, + TransparentProxy: TransparentProxyConfig{OutboundListenerPort: 808}, Connect: ConnectConfiguration{ UpstreamConfigs: map[string]UpstreamConfig{ "redis": { diff --git a/command/config/write/config_write_test.go b/command/config/write/config_write_test.go index 3beebbe07a..707b403750 100644 --- a/command/config/write/config_write_test.go +++ b/command/config/write/config_write_test.go @@ -182,7 +182,10 @@ func TestParseConfigEntry(t *testing.T) { mesh_gateway { mode = "remote" } - transparent_proxy = true + mode = "direct" + transparent_proxy = { + outbound_listener_port = 10101 + } `, camel: ` Kind = "proxy-defaults" @@ -201,7 +204,10 @@ func TestParseConfigEntry(t *testing.T) { MeshGateway { Mode = "remote" } - TransparentProxy = true + Mode = "direct" + TransparentProxy = { + outbound_listener_port = 10101 + } `, snakeJSON: ` { @@ -221,7 +227,10 @@ func TestParseConfigEntry(t *testing.T) { "mesh_gateway": { "mode": "remote" }, - "transparent_proxy": true + "mode": "direct", + "transparent_proxy": { + "outbound_listener_port": 10101 + } } `, camelJSON: ` @@ -242,7 +251,10 @@ func TestParseConfigEntry(t *testing.T) { "MeshGateway": { "Mode": "remote" }, - "TransparentProxy": true + "Mode": "direct", + "TransparentProxy": { + "OutboundListenerPort": 10101 + } } `, expect: &api.ProxyConfigEntry{ @@ -262,7 +274,10 @@ func TestParseConfigEntry(t *testing.T) { MeshGateway: api.MeshGatewayConfig{ Mode: api.MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: api.ProxyModeDirect, + TransparentProxy: api.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, expectJSON: &api.ProxyConfigEntry{ Kind: "proxy-defaults", @@ -281,7 +296,10 @@ func TestParseConfigEntry(t *testing.T) { MeshGateway: api.MeshGatewayConfig{ Mode: api.MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: api.ProxyModeDirect, + TransparentProxy: api.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, }, }, { @@ -443,7 +461,10 @@ func TestParseConfigEntry(t *testing.T) { mesh_gateway { mode = "remote" } - transparent_proxy = true + mode = "direct" + transparent_proxy = { + outbound_listener_port = 10101 + } connect { upstream_configs { "redis" { @@ -487,7 +508,10 @@ func TestParseConfigEntry(t *testing.T) { MeshGateway { Mode = "remote" } - TransparentProxy = true + Mode = "direct" + TransparentProxy = { + outbound_listener_port = 10101 + } connect = { upstream_configs = { "redis" = { @@ -532,7 +556,10 @@ func TestParseConfigEntry(t *testing.T) { "mesh_gateway": { "mode": "remote" }, - "transparent_proxy": true, + "mode": "direct", + "transparent_proxy": { + "outbound_listener_port": 10101 + }, "connect": { "upstream_configs": { "redis": { @@ -578,7 +605,10 @@ func TestParseConfigEntry(t *testing.T) { "MeshGateway": { "Mode": "remote" }, - "TransparentProxy": true, + "Mode": "direct", + "TransparentProxy": { + "OutboundListenerPort": 10101 + }, "Connect": { "UpstreamConfigs": { "redis": { @@ -623,7 +653,10 @@ func TestParseConfigEntry(t *testing.T) { MeshGateway: api.MeshGatewayConfig{ Mode: api.MeshGatewayModeRemote, }, - TransparentProxy: true, + Mode: api.ProxyModeDirect, + TransparentProxy: api.TransparentProxyConfig{ + OutboundListenerPort: 10101, + }, Connect: api.ConnectConfiguration{ UpstreamConfigs: map[string]api.UpstreamConfig{ "redis": { diff --git a/proto/pbservice/service.gen.go b/proto/pbservice/service.gen.go index 0b0bb3443e..eab192a4f0 100644 --- a/proto/pbservice/service.gen.go +++ b/proto/pbservice/service.gen.go @@ -14,7 +14,8 @@ func ConnectProxyConfigToStructs(s ConnectProxyConfig) structs.ConnectProxyConfi t.Upstreams = UpstreamsToStructs(s.Upstreams) t.MeshGateway = MeshGatewayConfigToStructs(s.MeshGateway) t.Expose = ExposeConfigToStructs(s.Expose) - t.TransparentProxy = s.TransparentProxy + t.TransparentProxy = TransparentProxyConfigToStructs(s.TransparentProxy) + t.Mode = s.Mode return t } func NewConnectProxyConfigFromStructs(t structs.ConnectProxyConfig) ConnectProxyConfig { @@ -27,7 +28,8 @@ func NewConnectProxyConfigFromStructs(t structs.ConnectProxyConfig) ConnectProxy s.Upstreams = NewUpstreamsFromStructs(t.Upstreams) s.MeshGateway = NewMeshGatewayConfigFromStructs(t.MeshGateway) s.Expose = NewExposeConfigFromStructs(t.Expose) - s.TransparentProxy = t.TransparentProxy + s.TransparentProxy = NewTransparentProxyConfigFromStructs(t.TransparentProxy) + s.Mode = t.Mode return s } func ExposeConfigToStructs(s ExposeConfig) structs.ExposeConfig { @@ -70,6 +72,16 @@ func NewMeshGatewayConfigFromStructs(t structs.MeshGatewayConfig) MeshGatewayCon s.Mode = t.Mode return s } +func TransparentProxyConfigToStructs(s TransparentProxyConfig) structs.TransparentProxyConfig { + var t structs.TransparentProxyConfig + t.OutboundListenerPort = int(s.OutboundListenerPort) + return t +} +func NewTransparentProxyConfigFromStructs(t structs.TransparentProxyConfig) TransparentProxyConfig { + var s TransparentProxyConfig + s.OutboundListenerPort = int32(t.OutboundListenerPort) + return s +} func ServiceConnectToStructs(s ServiceConnect) structs.ServiceConnect { var t structs.ServiceConnect t.Native = s.Native diff --git a/proto/pbservice/service.pb.binary.go b/proto/pbservice/service.pb.binary.go index 2f012d3f1a..aa449f239a 100644 --- a/proto/pbservice/service.pb.binary.go +++ b/proto/pbservice/service.pb.binary.go @@ -67,6 +67,16 @@ func (msg *MeshGatewayConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *TransparentProxyConfig) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *TransparentProxyConfig) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + // MarshalBinary implements encoding.BinaryMarshaler func (msg *ServiceDefinition) MarshalBinary() ([]byte, error) { return proto.Marshal(msg) diff --git a/proto/pbservice/service.pb.go b/proto/pbservice/service.pb.go index f42fd42e81..4de0ed625e 100644 --- a/proto/pbservice/service.pb.go +++ b/proto/pbservice/service.pb.go @@ -67,13 +67,15 @@ type ConnectProxyConfig struct { // setup. // mog: func-to=UpstreamsToStructs func-from=NewUpstreamsFromStructs Upstreams []Upstream `protobuf:"bytes,6,rep,name=Upstreams,proto3" json:"Upstreams"` - // MeshGateway defines the mesh gateway configuration for this upstream + // MeshGateway defines the mesh gateway configuration for upstreams MeshGateway MeshGatewayConfig `protobuf:"bytes,7,opt,name=MeshGateway,proto3" json:"MeshGateway"` // Expose defines whether checks or paths are exposed through the proxy Expose ExposeConfig `protobuf:"bytes,8,opt,name=Expose,proto3" json:"Expose"` - // TransparentProxy enables configuring the service mesh as if all inbound - // and outbound traffic is being redirected to this proxy - TransparentProxy bool `protobuf:"varint,9,opt,name=TransparentProxy,proto3" json:"TransparentProxy,omitempty"` + // Mode represents how the proxy's inbound and upstream listeners are dialed. + Mode github_com_hashicorp_consul_agent_structs.ProxyMode `protobuf:"bytes,9,opt,name=Mode,proto3,casttype=github.com/hashicorp/consul/agent/structs.ProxyMode" json:"Mode,omitempty"` + // TransparentProxy defines configuration for when the proxy is in + // transparent mode. + TransparentProxy TransparentProxyConfig `protobuf:"bytes,10,opt,name=TransparentProxy,proto3" json:"TransparentProxy"` } func (m *ConnectProxyConfig) Reset() { *m = ConnectProxyConfig{} } @@ -387,6 +389,48 @@ func (m *MeshGatewayConfig) XXX_DiscardUnknown() { var xxx_messageInfo_MeshGatewayConfig proto.InternalMessageInfo +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.TransparentProxyConfig +// output=service.gen.go +// name=Structs +type TransparentProxyConfig struct { + OutboundListenerPort int32 `protobuf:"varint,1,opt,name=OutboundListenerPort,proto3" json:"OutboundListenerPort,omitempty"` +} + +func (m *TransparentProxyConfig) Reset() { *m = TransparentProxyConfig{} } +func (m *TransparentProxyConfig) String() string { return proto.CompactTextString(m) } +func (*TransparentProxyConfig) ProtoMessage() {} +func (*TransparentProxyConfig) Descriptor() ([]byte, []int) { + return fileDescriptor_cbb99233b75fb80b, []int{6} +} +func (m *TransparentProxyConfig) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TransparentProxyConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TransparentProxyConfig.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TransparentProxyConfig) XXX_Merge(src proto.Message) { + xxx_messageInfo_TransparentProxyConfig.Merge(m, src) +} +func (m *TransparentProxyConfig) XXX_Size() int { + return m.Size() +} +func (m *TransparentProxyConfig) XXX_DiscardUnknown() { + xxx_messageInfo_TransparentProxyConfig.DiscardUnknown(m) +} + +var xxx_messageInfo_TransparentProxyConfig proto.InternalMessageInfo + // ServiceDefinition is used to JSON decode the Service definitions. For // documentation on specific fields see NodeService which is better documented. // @@ -435,7 +479,7 @@ func (m *ServiceDefinition) Reset() { *m = ServiceDefinition{} } func (m *ServiceDefinition) String() string { return proto.CompactTextString(m) } func (*ServiceDefinition) ProtoMessage() {} func (*ServiceDefinition) Descriptor() ([]byte, []int) { - return fileDescriptor_cbb99233b75fb80b, []int{6} + return fileDescriptor_cbb99233b75fb80b, []int{7} } func (m *ServiceDefinition) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -475,7 +519,7 @@ func (m *ServiceAddress) Reset() { *m = ServiceAddress{} } func (m *ServiceAddress) String() string { return proto.CompactTextString(m) } func (*ServiceAddress) ProtoMessage() {} func (*ServiceAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_cbb99233b75fb80b, []int{7} + return fileDescriptor_cbb99233b75fb80b, []int{8} } func (m *ServiceAddress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -516,7 +560,7 @@ func (m *Weights) Reset() { *m = Weights{} } func (m *Weights) String() string { return proto.CompactTextString(m) } func (*Weights) ProtoMessage() {} func (*Weights) Descriptor() ([]byte, []int) { - return fileDescriptor_cbb99233b75fb80b, []int{8} + return fileDescriptor_cbb99233b75fb80b, []int{9} } func (m *Weights) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -552,6 +596,7 @@ func init() { proto.RegisterType((*ExposeConfig)(nil), "pbservice.ExposeConfig") proto.RegisterType((*ExposePath)(nil), "pbservice.ExposePath") proto.RegisterType((*MeshGatewayConfig)(nil), "pbservice.MeshGatewayConfig") + proto.RegisterType((*TransparentProxyConfig)(nil), "pbservice.TransparentProxyConfig") proto.RegisterType((*ServiceDefinition)(nil), "pbservice.ServiceDefinition") proto.RegisterMapType((map[string]string)(nil), "pbservice.ServiceDefinition.MetaEntry") proto.RegisterMapType((map[string]ServiceAddress)(nil), "pbservice.ServiceDefinition.TaggedAddressesEntry") @@ -562,75 +607,78 @@ func init() { func init() { proto.RegisterFile("proto/pbservice/service.proto", fileDescriptor_cbb99233b75fb80b) } var fileDescriptor_cbb99233b75fb80b = []byte{ - // 1083 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xdd, 0x6e, 0x1b, 0x45, - 0x14, 0xf6, 0xfa, 0x27, 0xb6, 0x4f, 0x42, 0x7e, 0x26, 0x26, 0x2c, 0xa1, 0x75, 0x8c, 0x85, 0x90, - 0x05, 0x91, 0x9d, 0x26, 0x2a, 0xa5, 0x95, 0x8a, 0x44, 0xe2, 0x80, 0x2a, 0x9a, 0x62, 0x36, 0x46, - 0x15, 0x48, 0x5c, 0x4c, 0xd6, 0x93, 0xf5, 0x2a, 0xf6, 0x8c, 0x35, 0x33, 0x0e, 0xcd, 0x25, 0x6f, - 0xc0, 0x25, 0x8f, 0x81, 0xc4, 0x4b, 0xe4, 0xb2, 0x97, 0x5c, 0x45, 0x90, 0x3c, 0x04, 0x52, 0xaf, - 0xd0, 0xfc, 0xec, 0x66, 0xbd, 0x6b, 0x22, 0xe0, 0xca, 0x33, 0xe7, 0x3b, 0x3f, 0xe3, 0xf3, 0x7d, - 0xe7, 0xd8, 0x70, 0x7f, 0xc2, 0x99, 0x64, 0x9d, 0xc9, 0x89, 0x20, 0xfc, 0x3c, 0xf4, 0x49, 0xc7, - 0x7e, 0xb6, 0xb5, 0x1d, 0x55, 0x63, 0x60, 0xf3, 0x5e, 0xc0, 0x58, 0x30, 0x22, 0x1d, 0x0d, 0x9c, - 0x4c, 0x4f, 0x3b, 0x42, 0xf2, 0xa9, 0x2f, 0x8d, 0xe3, 0xe6, 0x7b, 0x51, 0x1e, 0x9f, 0x8d, 0xc7, - 0x8c, 0x76, 0xcc, 0x87, 0x05, 0xdf, 0x4f, 0x17, 0x19, 0x12, 0x3c, 0x92, 0x43, 0x7f, 0x48, 0xfc, - 0x33, 0xeb, 0x52, 0x0b, 0x58, 0xc0, 0x8c, 0x9b, 0x3a, 0x19, 0x6b, 0xf3, 0xaf, 0x02, 0xa0, 0x03, - 0x46, 0x29, 0xf1, 0x65, 0x8f, 0xb3, 0x57, 0x17, 0x07, 0x8c, 0x9e, 0x86, 0x01, 0xfa, 0x04, 0x36, - 0xba, 0x44, 0xc8, 0x90, 0x62, 0x19, 0x32, 0x7a, 0x6c, 0x92, 0xbe, 0xc0, 0x63, 0xe2, 0x3a, 0x0d, - 0xa7, 0x55, 0xf5, 0xfe, 0x01, 0x45, 0xbb, 0x50, 0xcb, 0x22, 0xcf, 0xba, 0x6e, 0x5e, 0x47, 0xcd, - 0xc5, 0xd0, 0x0e, 0xac, 0x3f, 0x67, 0x3e, 0x1e, 0x59, 0xcb, 0xe7, 0x83, 0x01, 0x27, 0x42, 0xb8, - 0x05, 0x1d, 0x32, 0x0f, 0x42, 0x1f, 0xc1, 0x6a, 0xd2, 0xdc, 0x63, 0x5c, 0xba, 0xc5, 0x86, 0xd3, - 0x2a, 0x79, 0x19, 0x3b, 0x7a, 0x08, 0x0b, 0xe6, 0x3b, 0xb9, 0xa5, 0x86, 0xd3, 0x5a, 0xdc, 0x7d, - 0xa7, 0x6d, 0xba, 0xdc, 0x8e, 0xba, 0xdc, 0x3e, 0xd6, 0x5d, 0xde, 0x2f, 0x5e, 0x5e, 0x6d, 0x39, - 0x9e, 0x75, 0x46, 0x8f, 0xa0, 0xfa, 0xed, 0x44, 0x48, 0x4e, 0xf0, 0x58, 0xb8, 0x0b, 0x8d, 0x42, - 0x6b, 0x71, 0x77, 0xbd, 0x1d, 0xb7, 0xb7, 0x1d, 0x61, 0x3a, 0x2a, 0xe7, 0xdd, 0xfa, 0xa2, 0x2e, - 0x2c, 0x1e, 0x11, 0x31, 0xfc, 0x12, 0x4b, 0xf2, 0x23, 0xbe, 0x70, 0xcb, 0xba, 0xe8, 0xbd, 0x44, - 0x68, 0x02, 0x35, 0xb5, 0x6c, 0x8e, 0x64, 0x98, 0x7a, 0xf5, 0xe1, 0xab, 0x09, 0x13, 0xc4, 0xad, - 0xd8, 0x57, 0xdf, 0x26, 0x30, 0xc0, 0x4c, 0xac, 0x75, 0x56, 0x8d, 0xe9, 0x73, 0x4c, 0xc5, 0x04, - 0x73, 0x42, 0x0d, 0xa1, 0x6e, 0xb5, 0xe1, 0xb4, 0x2a, 0x5e, 0xc6, 0xde, 0xfc, 0xad, 0x00, 0x95, - 0xe8, 0xd9, 0xa8, 0x05, 0x2b, 0x09, 0x6e, 0xfa, 0x17, 0x93, 0x88, 0xe8, 0xb4, 0x39, 0xc5, 0xb0, - 0x22, 0x5d, 0x4c, 0xb0, 0x4f, 0xe6, 0x30, 0x1c, 0x63, 0xa9, 0xec, 0x5a, 0x46, 0x85, 0x4c, 0x76, - 0xad, 0x9f, 0x3a, 0x40, 0x17, 0x4b, 0xec, 0x13, 0x2a, 0x09, 0xd7, 0x9c, 0x56, 0xbd, 0x84, 0x25, - 0x66, 0x7e, 0x3f, 0xa4, 0x83, 0x48, 0x28, 0x25, 0xed, 0x95, 0xb1, 0xa3, 0x0f, 0xe0, 0xad, 0xd8, - 0xa6, 0x25, 0xb2, 0xa0, 0x25, 0x32, 0x6b, 0x4c, 0xe8, 0xa3, 0xfc, 0x5f, 0xf4, 0x91, 0xa2, 0xb9, - 0xf2, 0xff, 0x68, 0xde, 0x81, 0xf5, 0x03, 0x42, 0x25, 0xc7, 0xa3, 0x91, 0xf5, 0x9a, 0x72, 0x32, - 0xb0, 0x94, 0xcd, 0x83, 0x9a, 0x14, 0x96, 0xad, 0xba, 0xed, 0xd4, 0xa2, 0x0d, 0x58, 0x78, 0x81, - 0x65, 0x78, 0x6e, 0x18, 0xab, 0x78, 0xf6, 0x86, 0xba, 0xb0, 0x7c, 0x1c, 0x0e, 0x88, 0x8f, 0xb9, - 0x0d, 0xd0, 0x3d, 0x9f, 0x7d, 0xa4, 0x45, 0xba, 0xe4, 0x34, 0xa4, 0xa1, 0x22, 0xc1, 0x4b, 0xc5, - 0x34, 0xbf, 0x83, 0xa5, 0xa4, 0xde, 0x54, 0xb5, 0x03, 0xb5, 0x54, 0x44, 0x54, 0xcd, 0xdc, 0xd0, - 0x03, 0x28, 0xf5, 0xb0, 0x1c, 0x0a, 0x37, 0xaf, 0x67, 0xe5, 0xed, 0x8c, 0x5e, 0x15, 0x6a, 0x5b, - 0x60, 0x3c, 0x9b, 0xbf, 0x3a, 0x00, 0xb7, 0x18, 0x6a, 0xc2, 0xd2, 0xf3, 0x50, 0x48, 0x42, 0x09, - 0xd7, 0x6c, 0x39, 0x9a, 0xad, 0x19, 0x1b, 0x42, 0x50, 0x54, 0xbe, 0x56, 0x6c, 0xfa, 0x1c, 0xd3, - 0xac, 0x2e, 0x3a, 0xb0, 0x90, 0xa0, 0x39, 0x32, 0xa2, 0x4d, 0xa8, 0xf4, 0x14, 0xa1, 0x3e, 0x1b, - 0x59, 0x59, 0xc5, 0x77, 0x25, 0xcf, 0x1e, 0xe6, 0x82, 0x0c, 0xbe, 0xe0, 0x6c, 0xac, 0xbf, 0x8f, - 0xd6, 0x54, 0xc5, 0x4b, 0x9b, 0x9b, 0xa7, 0xb0, 0x96, 0xe1, 0x15, 0x7d, 0x03, 0xc5, 0x23, 0x36, - 0xb0, 0x03, 0xb3, 0xff, 0xf4, 0xcd, 0xd5, 0xd6, 0xe3, 0x20, 0x94, 0xc3, 0xe9, 0x49, 0xdb, 0x67, - 0xe3, 0xce, 0x10, 0x8b, 0x61, 0xe8, 0x33, 0x3e, 0xe9, 0xf8, 0x8c, 0x8a, 0xe9, 0xa8, 0x83, 0x03, - 0x42, 0xa5, 0x5d, 0xed, 0x22, 0x29, 0x13, 0x95, 0xc4, 0xd3, 0xa9, 0x9a, 0x3f, 0x95, 0x61, 0x2d, - 0xc3, 0x0d, 0x3a, 0x82, 0xe2, 0x57, 0x21, 0x1d, 0xd8, 0x42, 0x8f, 0xdf, 0x5c, 0x6d, 0x3d, 0xfc, - 0xf7, 0x85, 0x6c, 0x3a, 0x95, 0xc0, 0xd3, 0x69, 0xd0, 0x32, 0xe4, 0xe3, 0xcd, 0x9c, 0x7f, 0xd6, - 0x55, 0xcd, 0x4d, 0x8c, 0xa6, 0x3e, 0x2b, 0x5b, 0x1f, 0x07, 0xc2, 0x2d, 0x36, 0x0a, 0xca, 0xa6, - 0xce, 0xc8, 0x85, 0xf2, 0xec, 0xe8, 0x45, 0x57, 0x84, 0x61, 0xa5, 0x8f, 0x83, 0x80, 0x44, 0x23, - 0x48, 0x84, 0xbb, 0xaa, 0xe5, 0xf0, 0xe0, 0x2e, 0xcd, 0xb5, 0x53, 0x31, 0x87, 0x54, 0xf2, 0x0b, - 0x2b, 0x95, 0x74, 0x3e, 0xf4, 0x04, 0x8a, 0x47, 0x44, 0x62, 0xbb, 0x92, 0x3f, 0xbc, 0x33, 0xaf, - 0x72, 0xd4, 0xc9, 0x3c, 0x1d, 0xa3, 0xd5, 0xa3, 0x04, 0x52, 0xd6, 0x02, 0xd1, 0x67, 0xb4, 0x03, - 0x25, 0xc3, 0xb8, 0x99, 0xe0, 0x5a, 0x22, 0xa1, 0xb6, 0xab, 0x9d, 0x17, 0xc9, 0x56, 0x1b, 0xd0, - 0x76, 0x3c, 0x01, 0x55, 0xfd, 0x86, 0xb9, 0x21, 0xf1, 0x5c, 0x6c, 0x43, 0xf9, 0x25, 0x09, 0x83, - 0xa1, 0x14, 0x2e, 0xe8, 0x0a, 0x28, 0xe1, 0x6e, 0x11, 0x2f, 0x72, 0x41, 0x35, 0x28, 0xf5, 0xd9, - 0x19, 0xa1, 0xee, 0xa2, 0x6e, 0xac, 0xb9, 0xa0, 0x6d, 0x58, 0x3b, 0xa4, 0xf8, 0x64, 0x44, 0xfa, - 0x38, 0xf8, 0xfa, 0x9c, 0x70, 0x1e, 0x0e, 0x88, 0xbb, 0xa4, 0x15, 0x9a, 0x05, 0xd0, 0x1e, 0x94, - 0xcc, 0xe2, 0x5f, 0xd6, 0xf5, 0xee, 0x27, 0x9f, 0x97, 0xf9, 0xa1, 0xf7, 0x8c, 0xaf, 0x5a, 0x16, - 0x87, 0x6a, 0xc1, 0x4e, 0x78, 0x28, 0x88, 0x6e, 0xf0, 0x9a, 0x8e, 0xde, 0x68, 0xdb, 0xbf, 0x19, - 0xb3, 0xa8, 0xed, 0x48, 0x2a, 0x06, 0xed, 0x41, 0xd9, 0x96, 0x70, 0x57, 0x74, 0xf8, 0xbb, 0x59, - 0x7e, 0xac, 0x83, 0x17, 0x79, 0x6e, 0xfe, 0x00, 0xb5, 0x79, 0x02, 0x40, 0xab, 0x50, 0x38, 0x23, - 0x17, 0xf6, 0x67, 0x48, 0x1d, 0x51, 0x07, 0x4a, 0xe7, 0x78, 0x34, 0x35, 0xbf, 0x35, 0x73, 0x93, - 0xdb, 0x14, 0x9e, 0xf1, 0x7b, 0x92, 0xff, 0xd4, 0xd9, 0x7c, 0x04, 0xd5, 0x58, 0x07, 0x73, 0x72, - 0xd6, 0x92, 0x39, 0xab, 0x89, 0xc0, 0xe6, 0x67, 0xf1, 0xa6, 0x8d, 0xe4, 0x9d, 0x10, 0xbe, 0x33, - 0x2b, 0xfc, 0x48, 0x59, 0xf9, 0x5b, 0x65, 0x35, 0x9f, 0xc6, 0xcc, 0xab, 0xc0, 0x1e, 0x16, 0x22, - 0xa4, 0x81, 0xdd, 0x6a, 0xd1, 0x55, 0x21, 0x2f, 0x31, 0xa7, 0x0a, 0x31, 0xb1, 0xd1, 0x75, 0xff, - 0xe8, 0xf2, 0xcf, 0x7a, 0xee, 0xf2, 0xba, 0xee, 0xbc, 0xbe, 0xae, 0x3b, 0x7f, 0x5c, 0xd7, 0x9d, - 0x9f, 0x6f, 0xea, 0xb9, 0x5f, 0x6e, 0xea, 0xb9, 0xd7, 0x37, 0xf5, 0xdc, 0xef, 0x37, 0xf5, 0xdc, - 0xf7, 0x1f, 0xdf, 0x35, 0xfc, 0xa9, 0xff, 0x83, 0x27, 0x0b, 0xda, 0xb0, 0xf7, 0x77, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x79, 0x3a, 0x36, 0x1b, 0x8e, 0x0a, 0x00, 0x00, + // 1135 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xf7, 0xfa, 0x4f, 0x6c, 0xbf, 0x94, 0x34, 0x99, 0x9a, 0xb0, 0x84, 0xd6, 0x49, 0x2d, 0x84, + 0x22, 0x88, 0xec, 0x34, 0x51, 0x09, 0xad, 0x54, 0x24, 0x12, 0x07, 0x54, 0x35, 0x69, 0xcd, 0xc6, + 0xa8, 0x02, 0x89, 0xc3, 0x78, 0x3d, 0x59, 0xaf, 0x62, 0xcf, 0x58, 0x3b, 0xe3, 0xd0, 0x1c, 0xf9, + 0x06, 0x1c, 0xf9, 0x18, 0x48, 0x7c, 0x89, 0x1c, 0x7b, 0xe4, 0x14, 0x41, 0x72, 0xe6, 0x0b, 0xe4, + 0x84, 0xe6, 0xed, 0xec, 0x66, 0xbd, 0x5e, 0xa2, 0xc2, 0xc9, 0x33, 0xef, 0xf7, 0xde, 0x6f, 0x9e, + 0xdf, 0xfb, 0xbd, 0x99, 0x85, 0x07, 0xe3, 0x40, 0x28, 0xd1, 0x1a, 0xf7, 0x24, 0x0b, 0x4e, 0x7d, + 0x97, 0xb5, 0xcc, 0x6f, 0x13, 0xed, 0xa4, 0x1a, 0x03, 0x2b, 0xf7, 0x3d, 0x21, 0xbc, 0x21, 0x6b, + 0x21, 0xd0, 0x9b, 0x1c, 0xb7, 0xa4, 0x0a, 0x26, 0xae, 0x0a, 0x1d, 0x57, 0x3e, 0x8a, 0x78, 0x5c, + 0x31, 0x1a, 0x09, 0xde, 0x0a, 0x7f, 0x0c, 0xf8, 0x30, 0x7d, 0xc8, 0x80, 0xd1, 0xa1, 0x1a, 0xb8, + 0x03, 0xe6, 0x9e, 0x18, 0x97, 0x9a, 0x27, 0x3c, 0x11, 0xba, 0xe9, 0x55, 0x68, 0x6d, 0xfc, 0x5d, + 0x04, 0xb2, 0x27, 0x38, 0x67, 0xae, 0xea, 0x04, 0xe2, 0xcd, 0xd9, 0x9e, 0xe0, 0xc7, 0xbe, 0x47, + 0x3e, 0x87, 0xe5, 0x36, 0x93, 0xca, 0xe7, 0x54, 0xf9, 0x82, 0x1f, 0x85, 0xa4, 0x2f, 0xe9, 0x88, + 0xd9, 0xd6, 0x9a, 0xb5, 0x5e, 0x75, 0xfe, 0x05, 0x25, 0x5b, 0x50, 0x9b, 0x45, 0x9e, 0xb7, 0xed, + 0x3c, 0x46, 0x65, 0x62, 0x64, 0x13, 0xee, 0x1d, 0x08, 0x97, 0x0e, 0x8d, 0xe5, 0xab, 0x7e, 0x3f, + 0x60, 0x52, 0xda, 0x05, 0x0c, 0xc9, 0x82, 0xc8, 0xa7, 0xb0, 0x98, 0x34, 0x77, 0x44, 0xa0, 0xec, + 0xe2, 0x9a, 0xb5, 0x5e, 0x72, 0x66, 0xec, 0xe4, 0x31, 0xcc, 0x85, 0xff, 0xc9, 0x2e, 0xad, 0x59, + 0xeb, 0xf3, 0x5b, 0x1f, 0x34, 0xc3, 0x2a, 0x37, 0xa3, 0x2a, 0x37, 0x8f, 0xb0, 0xca, 0xbb, 0xc5, + 0xf3, 0x8b, 0x55, 0xcb, 0x31, 0xce, 0x64, 0x07, 0xaa, 0xdf, 0x8d, 0xa5, 0x0a, 0x18, 0x1d, 0x49, + 0x7b, 0x6e, 0xad, 0xb0, 0x3e, 0xbf, 0x75, 0xaf, 0x19, 0x97, 0xb7, 0x19, 0x61, 0x18, 0x95, 0x73, + 0x6e, 0x7c, 0x49, 0x1b, 0xe6, 0x0f, 0x99, 0x1c, 0x7c, 0x43, 0x15, 0xfb, 0x89, 0x9e, 0xd9, 0x65, + 0x3c, 0xf4, 0x7e, 0x22, 0x34, 0x81, 0x86, 0x67, 0x19, 0x8e, 0x64, 0x98, 0xce, 0x7a, 0xff, 0xcd, + 0x58, 0x48, 0x66, 0x57, 0x4c, 0xd6, 0x37, 0x04, 0x21, 0x30, 0x15, 0x6b, 0x9c, 0xc9, 0x0b, 0x28, + 0x1e, 0x8a, 0x3e, 0xb3, 0xab, 0xba, 0x76, 0xbb, 0x3b, 0xd7, 0x17, 0xab, 0xdb, 0x9e, 0xaf, 0x06, + 0x93, 0x5e, 0xd3, 0x15, 0xa3, 0xd6, 0x80, 0xca, 0x81, 0xef, 0x8a, 0x60, 0xdc, 0x72, 0x05, 0x97, + 0x93, 0x61, 0x8b, 0x7a, 0x8c, 0x2b, 0xa3, 0x32, 0xd9, 0xc4, 0xfe, 0xeb, 0x70, 0x07, 0x49, 0xc8, + 0x11, 0x2c, 0x76, 0x03, 0xca, 0xe5, 0x98, 0x06, 0x8c, 0x87, 0xea, 0xb0, 0x01, 0xb3, 0x79, 0x98, + 0xc8, 0x26, 0xed, 0x32, 0x95, 0xd7, 0x0c, 0x41, 0xe3, 0xf7, 0x02, 0x54, 0xa2, 0x62, 0x91, 0x75, + 0xb8, 0x9b, 0x50, 0x44, 0xf7, 0x6c, 0x1c, 0xc9, 0x2b, 0x6d, 0x4e, 0xe9, 0x4a, 0x4b, 0x4d, 0x8e, + 0xa9, 0xcb, 0x32, 0x74, 0x15, 0x63, 0x29, 0x76, 0x14, 0x6f, 0x61, 0x86, 0x1d, 0x55, 0x5b, 0x07, + 0x68, 0x53, 0x45, 0x5d, 0xc6, 0x15, 0x0b, 0x50, 0x49, 0x55, 0x27, 0x61, 0x89, 0xf5, 0xb6, 0xeb, + 0xf3, 0x7e, 0x24, 0xcf, 0x12, 0x7a, 0xcd, 0xd8, 0xc9, 0xc7, 0xf0, 0x5e, 0x6c, 0x43, 0x61, 0xce, + 0xa1, 0x30, 0xa7, 0x8d, 0x09, 0x55, 0x96, 0xff, 0x8b, 0x2a, 0x53, 0xe2, 0xaa, 0xfc, 0x3f, 0x71, + 0x6d, 0xc2, 0xbd, 0x3d, 0xc6, 0x55, 0x40, 0x87, 0x43, 0xe3, 0x35, 0x09, 0x58, 0x1f, 0x45, 0x53, + 0x71, 0xb2, 0xa0, 0x06, 0x87, 0x05, 0x33, 0x53, 0xe6, 0xae, 0x20, 0xcb, 0x30, 0xf7, 0x92, 0x2a, + 0xff, 0x34, 0xec, 0x58, 0xc5, 0x31, 0x3b, 0xd2, 0x86, 0x85, 0x23, 0xbf, 0xcf, 0x5c, 0x1a, 0x98, + 0x00, 0xac, 0xf9, 0x74, 0x92, 0x06, 0x69, 0xb3, 0x63, 0x9f, 0xfb, 0xba, 0x09, 0x4e, 0x2a, 0xa6, + 0xf1, 0x3d, 0xdc, 0x49, 0xaa, 0x5c, 0x9f, 0xb6, 0xa7, 0xaf, 0x32, 0x19, 0x9d, 0x16, 0xee, 0xc8, + 0x23, 0x28, 0x75, 0xa8, 0x1a, 0x48, 0x3b, 0x8f, 0x13, 0xfa, 0xfe, 0xcc, 0x94, 0x68, 0xd4, 0x94, + 0x20, 0xf4, 0x6c, 0xfc, 0x66, 0x01, 0xdc, 0x60, 0xa4, 0x01, 0x77, 0x0e, 0x7c, 0xa9, 0x18, 0x67, + 0x01, 0x76, 0xcb, 0xc2, 0x6e, 0x4d, 0xd9, 0x08, 0x81, 0xa2, 0xf6, 0x35, 0x62, 0xc3, 0x75, 0xdc, + 0x66, 0xbd, 0xc1, 0xc0, 0x42, 0xa2, 0xcd, 0x91, 0x91, 0xac, 0x40, 0xa5, 0xa3, 0x1b, 0xea, 0x8a, + 0xa1, 0x91, 0x55, 0xbc, 0xd7, 0xf2, 0xec, 0xd0, 0x40, 0xb2, 0xfe, 0xd7, 0x81, 0x18, 0xe1, 0xff, + 0x41, 0x4d, 0x55, 0x9c, 0xb4, 0xb9, 0x71, 0x0c, 0x4b, 0x33, 0x7d, 0x25, 0xdf, 0x9a, 0x51, 0xc7, + 0x81, 0xd9, 0x7d, 0x76, 0x7d, 0xb1, 0xfa, 0xe4, 0xdd, 0x47, 0x3d, 0x41, 0x77, 0x33, 0xf0, 0x8d, + 0x03, 0x58, 0xce, 0x9e, 0x66, 0x3d, 0x7e, 0xaf, 0x26, 0xaa, 0x27, 0x26, 0xbc, 0x9f, 0x51, 0xad, + 0x4c, 0xac, 0xf1, 0x73, 0x19, 0x96, 0x66, 0x3a, 0x4d, 0x0e, 0xa1, 0xf8, 0xc2, 0xe7, 0x7d, 0x93, + 0xf6, 0x93, 0xeb, 0x8b, 0xd5, 0xc7, 0xef, 0x9e, 0xb6, 0xa1, 0xd3, 0x04, 0x0e, 0xd2, 0x90, 0x05, + 0xc8, 0xc7, 0xaf, 0x4b, 0xfe, 0x79, 0x5b, 0xb7, 0x2a, 0x31, 0xe8, 0xb8, 0xd6, 0xb6, 0x2e, 0xf5, + 0xa4, 0x5d, 0x5c, 0x2b, 0x68, 0x9b, 0x5e, 0x13, 0x1b, 0xca, 0xd3, 0x83, 0x1c, 0x6d, 0x09, 0x85, + 0xbb, 0x5d, 0xea, 0x79, 0x2c, 0x1a, 0x68, 0x26, 0xed, 0x45, 0x14, 0xd7, 0xa3, 0xdb, 0x14, 0xdc, + 0x4c, 0xc5, 0xec, 0x73, 0x15, 0x9c, 0x19, 0xe1, 0xa5, 0xf9, 0xc8, 0x53, 0x28, 0x1e, 0x32, 0x45, + 0xcd, 0xb3, 0xf2, 0xc9, 0xad, 0xbc, 0xda, 0x11, 0xc9, 0x1c, 0x8c, 0x41, 0x2d, 0xea, 0xca, 0x97, + 0xb1, 0xf2, 0xb8, 0x26, 0x9b, 0x50, 0x0a, 0xf5, 0x13, 0xde, 0x07, 0xb5, 0x04, 0x21, 0xda, 0xf5, + 0x0d, 0x1a, 0x0d, 0x01, 0x1a, 0xc8, 0x46, 0x3c, 0x4f, 0x55, 0xcc, 0x21, 0x33, 0x24, 0x9e, 0xb2, + 0x0d, 0x28, 0xbf, 0x66, 0xbe, 0x37, 0x50, 0xd2, 0xdc, 0xff, 0x24, 0xe1, 0x6e, 0x10, 0x27, 0x72, + 0x21, 0x35, 0x28, 0x75, 0xc5, 0x09, 0xe3, 0xf6, 0x3c, 0x16, 0x36, 0xdc, 0x90, 0x0d, 0x58, 0xda, + 0xe7, 0xb4, 0x37, 0x64, 0x5d, 0xea, 0xbd, 0x3a, 0x65, 0x41, 0xe0, 0xf7, 0x99, 0x7d, 0x07, 0xf5, + 0x3e, 0x0b, 0x90, 0x6d, 0x28, 0x85, 0xef, 0xcd, 0x02, 0x9e, 0xf7, 0x20, 0x99, 0xde, 0xcc, 0xc7, + 0x8a, 0x13, 0xfa, 0xea, 0xab, 0x67, 0x5f, 0x5f, 0xd7, 0xe3, 0xc0, 0x97, 0x0c, 0x0b, 0xbc, 0x84, + 0xd1, 0xcb, 0x4d, 0xf3, 0xa9, 0x34, 0x8d, 0x9a, 0x8a, 0xa4, 0x62, 0xc8, 0x36, 0x94, 0xcd, 0x11, + 0xf6, 0x5d, 0x0c, 0xff, 0x70, 0xb6, 0x3f, 0xc6, 0xc1, 0x89, 0x3c, 0x57, 0x7e, 0x84, 0x5a, 0x96, + 0x00, 0xc8, 0x22, 0x14, 0x4e, 0xd8, 0x99, 0x79, 0xd4, 0xf4, 0x92, 0xb4, 0xa0, 0x74, 0x4a, 0x87, + 0x93, 0xf0, 0xe5, 0xca, 0x24, 0x37, 0x14, 0x4e, 0xe8, 0xf7, 0x34, 0xff, 0x85, 0xb5, 0xb2, 0x03, + 0xd5, 0x58, 0x07, 0x19, 0x9c, 0xb5, 0x24, 0x67, 0x35, 0x11, 0xd8, 0xf8, 0x32, 0xbe, 0xb7, 0x23, + 0x79, 0x27, 0x84, 0x6f, 0x4d, 0x0b, 0x3f, 0x52, 0x56, 0xfe, 0x46, 0x59, 0x8d, 0x67, 0x71, 0xe7, + 0x75, 0x60, 0x87, 0x4a, 0xe9, 0x73, 0xcf, 0x4c, 0x7d, 0xb4, 0xd5, 0xc8, 0x6b, 0x1a, 0x70, 0x8d, + 0x84, 0xb1, 0xd1, 0x76, 0xf7, 0xf0, 0xfc, 0xaf, 0x7a, 0xee, 0xfc, 0xb2, 0x6e, 0xbd, 0xbd, 0xac, + 0x5b, 0x7f, 0x5e, 0xd6, 0xad, 0x5f, 0xae, 0xea, 0xb9, 0x5f, 0xaf, 0xea, 0xb9, 0xb7, 0x57, 0xf5, + 0xdc, 0x1f, 0x57, 0xf5, 0xdc, 0x0f, 0x9f, 0xdd, 0x36, 0xfc, 0xa9, 0x6f, 0xda, 0xde, 0x1c, 0x1a, + 0xb6, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x1f, 0xf1, 0x41, 0x33, 0x52, 0x0b, 0x00, 0x00, } func (m *ConnectProxyConfig) Marshal() (dAtA []byte, err error) { @@ -653,15 +701,22 @@ func (m *ConnectProxyConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.TransparentProxy { - i-- - if m.TransparentProxy { - dAtA[i] = 1 - } else { - dAtA[i] = 0 + { + size, err := m.TransparentProxy.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarintService(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + if len(m.Mode) > 0 { + i -= len(m.Mode) + copy(dAtA[i:], m.Mode) + i = encodeVarintService(dAtA, i, uint64(len(m.Mode))) i-- - dAtA[i] = 0x48 + dAtA[i] = 0x4a } { size, err := m.Expose.MarshalToSizedBuffer(dAtA[:i]) @@ -1012,6 +1067,34 @@ func (m *MeshGatewayConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *TransparentProxyConfig) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransparentProxyConfig) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TransparentProxyConfig) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.OutboundListenerPort != 0 { + i = encodeVarintService(dAtA, i, uint64(m.OutboundListenerPort)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *ServiceDefinition) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1325,9 +1408,12 @@ func (m *ConnectProxyConfig) Size() (n int) { n += 1 + l + sovService(uint64(l)) l = m.Expose.Size() n += 1 + l + sovService(uint64(l)) - if m.TransparentProxy { - n += 2 + l = len(m.Mode) + if l > 0 { + n += 1 + l + sovService(uint64(l)) } + l = m.TransparentProxy.Size() + n += 1 + l + sovService(uint64(l)) return n } @@ -1445,6 +1531,18 @@ func (m *MeshGatewayConfig) Size() (n int) { return n } +func (m *TransparentProxyConfig) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.OutboundListenerPort != 0 { + n += 1 + sovService(uint64(m.OutboundListenerPort)) + } + return n +} + func (m *ServiceDefinition) Size() (n int) { if m == nil { return 0 @@ -1843,10 +1941,10 @@ func (m *ConnectProxyConfig) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 9: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TransparentProxy", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) } - var v int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowService @@ -1856,12 +1954,57 @@ func (m *ConnectProxyConfig) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - m.TransparentProxy = bool(v != 0) + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthService + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthService + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Mode = github_com_hashicorp_consul_agent_structs.ProxyMode(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TransparentProxy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthService + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthService + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TransparentProxy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipService(dAtA[iNdEx:]) @@ -2683,6 +2826,78 @@ func (m *MeshGatewayConfig) Unmarshal(dAtA []byte) error { } return nil } +func (m *TransparentProxyConfig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransparentProxyConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransparentProxyConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OutboundListenerPort", wireType) + } + m.OutboundListenerPort = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.OutboundListenerPort |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipService(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthService + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthService + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ServiceDefinition) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/proto/pbservice/service.proto b/proto/pbservice/service.proto index 89e781d0d7..74398597ac 100644 --- a/proto/pbservice/service.proto +++ b/proto/pbservice/service.proto @@ -64,15 +64,18 @@ message ConnectProxyConfig { // mog: func-to=UpstreamsToStructs func-from=NewUpstreamsFromStructs repeated Upstream Upstreams = 6 [(gogoproto.nullable) = false]; - // MeshGateway defines the mesh gateway configuration for this upstream + // MeshGateway defines the mesh gateway configuration for upstreams MeshGatewayConfig MeshGateway = 7 [(gogoproto.nullable) = false]; // Expose defines whether checks or paths are exposed through the proxy ExposeConfig Expose = 8 [(gogoproto.nullable) = false]; - // TransparentProxy enables configuring the service mesh as if all inbound - // and outbound traffic is being redirected to this proxy - bool TransparentProxy = 9; + // Mode represents how the proxy's inbound and upstream listeners are dialed. + string Mode = 9 [(gogoproto.casttype) = "github.com/hashicorp/consul/agent/structs.ProxyMode"]; + + // TransparentProxy defines configuration for when the proxy is in + // transparent mode. + TransparentProxyConfig TransparentProxy = 10 [(gogoproto.nullable) = false]; } // Upstream represents a single upstream dependency for a service or proxy. It @@ -200,6 +203,15 @@ message MeshGatewayConfig { string Mode = 1 [(gogoproto.casttype) = "github.com/hashicorp/consul/agent/structs.MeshGatewayMode"]; } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.TransparentProxyConfig +// output=service.gen.go +// name=Structs +message TransparentProxyConfig { + int32 OutboundListenerPort = 1; +} + // ServiceDefinition is used to JSON decode the Service definitions. For // documentation on specific fields see NodeService which is better documented. //