From b5aab27c219bccd652737683bd2d960799a08264 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Fri, 5 Jul 2019 08:06:47 -0700 Subject: [PATCH] connect: allow overriding envoy listener bind_address (#6033) * connect: allow overriding envoy listener bind_address * Update agent/xds/config.go Co-Authored-By: Kyle Havlovitz * connect: allow overriding envoy listener bind_port * envoy: support unix sockets for grpc in bootstrap Add AgentSocket BootstrapTplArgs which if set overrides the AgentAddress and AgentPort to generate a bootstrap which points Envoy to a unix socket file instead of an ip:port. * Add a test for passing the consul addr as a unix socket * Fix config formatting for envoy bootstrap tests * Fix listeners test cases for bind addr/port * Update website/source/docs/connect/proxies/envoy.md --- agent/xds/config.go | 16 ++- agent/xds/config_test.go | 33 +++++ agent/xds/listeners.go | 17 ++- agent/xds/listeners_test.go | 22 ++++ .../listener-bind-address-port.golden | 116 ++++++++++++++++++ .../listeners/listener-bind-address.golden | 116 ++++++++++++++++++ .../listeners/listener-bind-port.golden | 116 ++++++++++++++++++ command/connect/envoy/bootstrap_tpl.go | 13 ++ command/connect/envoy/envoy.go | 48 +++++--- command/connect/envoy/envoy_test.go | 15 +++ .../envoy/testdata/access-log-path.golden | 6 +- .../connect/envoy/testdata/defaults.golden | 6 +- .../envoy/testdata/extra_-multiple.golden | 6 +- .../envoy/testdata/extra_-single.golden | 6 +- .../envoy/testdata/grpc-addr-env.golden | 6 +- .../envoy/testdata/grpc-addr-flag.golden | 6 +- .../envoy/testdata/grpc-addr-unix.golden | 57 +++++++++ .../testdata/stats-config-override.golden | 6 +- .../connect/envoy/testdata/token-arg.golden | 6 +- .../connect/envoy/testdata/token-env.golden | 6 +- .../envoy/testdata/token-file-arg.golden | 6 +- .../envoy/testdata/token-file-env.golden | 6 +- .../testdata/zipkin-tracing-config.golden | 6 +- website/source/docs/connect/proxies/envoy.md | 4 + 24 files changed, 573 insertions(+), 72 deletions(-) create mode 100644 agent/xds/testdata/listeners/listener-bind-address-port.golden create mode 100644 agent/xds/testdata/listeners/listener-bind-address.golden create mode 100644 agent/xds/testdata/listeners/listener-bind-port.golden create mode 100644 command/connect/envoy/testdata/grpc-addr-unix.golden diff --git a/agent/xds/config.go b/agent/xds/config.go index 84d8d0bc40..83a67b944b 100644 --- a/agent/xds/config.go +++ b/agent/xds/config.go @@ -29,10 +29,20 @@ type ProxyConfig struct { LocalConnectTimeoutMs int `mapstructure:"local_connect_timeout_ms"` // Protocol describes the service's protocol. Valid values are "tcp", - // "http" and "grpc". Anything else is treated as tcp. The enables protocol - // aware features like per-request metrics and connection pooling, tracing, - // routing etc. + // "http" and "grpc". Anything else is treated as tcp. This enables + // protocol aware features like per-request metrics and connection + // pooling, tracing, routing etc. Protocol string `mapstructure:"protocol"` + + // BindAddress overrides the address the proxy's listener binds to. This + // enables proxies in network namespaces to bind to a different address + // than the host address. + BindAddress string `mapstructure:"bind_address"` + + // BindPort overrides the port the proxy's listener binds to. This + // enable proxies in network namespaces to bind to a different port + // than the host port being advertised. + BindPort int `mapstructure:"bind_port"` } // ParseProxyConfig returns the ProxyConfig parsed from the an opaque map. If an diff --git a/agent/xds/config_test.go b/agent/xds/config_test.go index 1b46105e24..9df5202b9d 100644 --- a/agent/xds/config_test.go +++ b/agent/xds/config_test.go @@ -59,6 +59,39 @@ func TestParseProxyConfig(t *testing.T) { LocalConnectTimeoutMs: 5000, }, }, + { + name: "bind address override, string", + input: map[string]interface{}{ + "bind_address": "127.0.0.2", + }, + want: ProxyConfig{ + LocalConnectTimeoutMs: 5000, + Protocol: "tcp", + BindAddress: "127.0.0.2", + }, + }, + { + name: "bind port override, string", + input: map[string]interface{}{ + "bind_port": "8888", + }, + want: ProxyConfig{ + LocalConnectTimeoutMs: 5000, + Protocol: "tcp", + BindPort: 8888, + }, + }, + { + name: "bind port override, int", + input: map[string]interface{}{ + "bind_port": 8889, + }, + want: ProxyConfig{ + LocalConnectTimeoutMs: 5000, + Protocol: "tcp", + BindPort: 8889, + }, + }, { name: "local connect timeout override, string", input: map[string]interface{}{ diff --git a/agent/xds/listeners.go b/agent/xds/listeners.go index 4abeb88a52..9c90cdd939 100644 --- a/agent/xds/listeners.go +++ b/agent/xds/listeners.go @@ -234,10 +234,23 @@ func (s *Server) makePublicListener(cfgSnap *proxycfg.ConfigSnapshot, token stri if l == nil { // No user config, use default listener addr := cfgSnap.Address - if addr == "" { + + // Override with bind address if one is set, otherwise default + // to 0.0.0.0 + if cfg.BindAddress != "" { + addr = cfg.BindAddress + } else if addr == "" { addr = "0.0.0.0" } - l = makeListener(PublicListenerName, addr, cfgSnap.Port) + + // Override with bind port if one is set, otherwise default to + // proxy service's address + port := cfgSnap.Port + if cfg.BindPort != 0 { + port = cfg.BindPort + } + + l = makeListener(PublicListenerName, addr, port) filter, err := makeListenerFilter(false, cfg.Protocol, "public_listener", LocalAppClusterName, "", true) if err != nil { diff --git a/agent/xds/listeners_test.go b/agent/xds/listeners_test.go index c7fac60d0b..223fadc21d 100644 --- a/agent/xds/listeners_test.go +++ b/agent/xds/listeners_test.go @@ -33,6 +33,28 @@ func TestListenersFromSnapshot(t *testing.T) { create: proxycfg.TestConfigSnapshot, setup: nil, // Default snapshot }, + { + name: "listener-bind-address", + create: proxycfg.TestConfigSnapshot, + setup: func(snap *proxycfg.ConfigSnapshot) { + snap.Proxy.Config["bind_address"] = "127.0.0.2" + }, + }, + { + name: "listener-bind-port", + create: proxycfg.TestConfigSnapshot, + setup: func(snap *proxycfg.ConfigSnapshot) { + snap.Proxy.Config["bind_port"] = 8888 + }, + }, + { + name: "listener-bind-address-port", + create: proxycfg.TestConfigSnapshot, + setup: func(snap *proxycfg.ConfigSnapshot) { + snap.Proxy.Config["bind_address"] = "127.0.0.2" + snap.Proxy.Config["bind_port"] = 8888 + }, + }, { name: "http-public-listener", create: proxycfg.TestConfigSnapshot, diff --git a/agent/xds/testdata/listeners/listener-bind-address-port.golden b/agent/xds/testdata/listeners/listener-bind-address-port.golden new file mode 100644 index 0000000000..1d7a8114fe --- /dev/null +++ b/agent/xds/testdata/listeners/listener-bind-address-port.golden @@ -0,0 +1,116 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "db", + "stat_prefix": "upstream_db_tcp" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "prepared_query:geo-cache", + "stat_prefix": "upstream_prepared_query_geo-cache_tcp" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "public_listener:127.0.0.2:8888", + "address": { + "socketAddress": { + "address": "127.0.0.2", + "portValue": 8888 + } + }, + "filterChains": [ + { + "tlsContext": { + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + }, + "filters": [ + { + "name": "envoy.ext_authz", + "config": { + "grpc_service": { + "envoy_grpc": { + "cluster_name": "local_agent" + }, + "initial_metadata": [ + { + "key": "x-consul-token", + "value": "my-token" + } + ] + }, + "stat_prefix": "connect_authz" + } + }, + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "local_app", + "stat_prefix": "public_listener_tcp" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.api.v2.Listener", + "nonce": "00000001" +} diff --git a/agent/xds/testdata/listeners/listener-bind-address.golden b/agent/xds/testdata/listeners/listener-bind-address.golden new file mode 100644 index 0000000000..59f9b159c5 --- /dev/null +++ b/agent/xds/testdata/listeners/listener-bind-address.golden @@ -0,0 +1,116 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "db", + "stat_prefix": "upstream_db_tcp" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "prepared_query:geo-cache", + "stat_prefix": "upstream_prepared_query_geo-cache_tcp" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "public_listener:127.0.0.2:9999", + "address": { + "socketAddress": { + "address": "127.0.0.2", + "portValue": 9999 + } + }, + "filterChains": [ + { + "tlsContext": { + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + }, + "filters": [ + { + "name": "envoy.ext_authz", + "config": { + "grpc_service": { + "envoy_grpc": { + "cluster_name": "local_agent" + }, + "initial_metadata": [ + { + "key": "x-consul-token", + "value": "my-token" + } + ] + }, + "stat_prefix": "connect_authz" + } + }, + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "local_app", + "stat_prefix": "public_listener_tcp" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.api.v2.Listener", + "nonce": "00000001" +} diff --git a/agent/xds/testdata/listeners/listener-bind-port.golden b/agent/xds/testdata/listeners/listener-bind-port.golden new file mode 100644 index 0000000000..4a4173b3f8 --- /dev/null +++ b/agent/xds/testdata/listeners/listener-bind-port.golden @@ -0,0 +1,116 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "db", + "stat_prefix": "upstream_db_tcp" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "prepared_query:geo-cache", + "stat_prefix": "upstream_prepared_query_geo-cache_tcp" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.api.v2.Listener", + "name": "public_listener:0.0.0.0:8888", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 8888 + } + }, + "filterChains": [ + { + "tlsContext": { + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + }, + "filters": [ + { + "name": "envoy.ext_authz", + "config": { + "grpc_service": { + "envoy_grpc": { + "cluster_name": "local_agent" + }, + "initial_metadata": [ + { + "key": "x-consul-token", + "value": "my-token" + } + ] + }, + "stat_prefix": "connect_authz" + } + }, + { + "name": "envoy.tcp_proxy", + "config": { + "cluster": "local_app", + "stat_prefix": "public_listener_tcp" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.api.v2.Listener", + "nonce": "00000001" +} diff --git a/command/connect/envoy/bootstrap_tpl.go b/command/connect/envoy/bootstrap_tpl.go index 5e43706012..b1c9d2c79c 100644 --- a/command/connect/envoy/bootstrap_tpl.go +++ b/command/connect/envoy/bootstrap_tpl.go @@ -27,6 +27,11 @@ type BootstrapTplArgs struct { // TLS is enabled. AgentCAFile string + // AgentSocket is the path to a Unix Socket for communicating with the + // local agent's gRPC endpoint. Disabled if the empty (the default), + // but overrides AgentAddress and AgentPort if set. + AgentSocket string + // AdminAccessLogPath The path to write the access log for the // administration server. If no access log is desired specify // "/dev/null". By default it will use "/dev/null". @@ -122,12 +127,20 @@ const bootstrapTemplate = `{ {{- end }} "http2_protocol_options": {}, "hosts": [ + {{- if .AgentSocket -}} + { + "pipe": { + "path": "{{ .AgentSocket }}" + } + } + {{- else -}} { "socket_address": { "address": "{{ .AgentAddress }}", "port_value": {{ .AgentPort }} } } + {{- end -}} ] } {{- if .StaticClustersJSON -}} diff --git a/command/connect/envoy/envoy.go b/command/connect/envoy/envoy.go index 67a71c0fa3..7021eee468 100644 --- a/command/connect/envoy/envoy.go +++ b/command/connect/envoy/envoy.go @@ -360,26 +360,35 @@ func (c *cmd) templateArgs() (*BootstrapTplArgs, error) { // is an IP this will fail to parse as a URL with "parse 127.0.0.1:8500: first // path segment in URL cannot contain colon". On the other hand we also // support both http(s)://host:port and unix:///path/to/file. - addrPort := strings.TrimPrefix(c.grpcAddr, "http://") - addrPort = strings.TrimPrefix(c.grpcAddr, "https://") + var agentAddr, agentPort, agentSock string + if grpcAddr := strings.TrimPrefix(c.grpcAddr, "unix://"); grpcAddr != c.grpcAddr { + // Path to unix socket + agentSock = grpcAddr + } else { + // Parse as host:port with option http prefix + grpcAddr = strings.TrimPrefix(c.grpcAddr, "http://") + grpcAddr = strings.TrimPrefix(c.grpcAddr, "https://") - agentAddr, agentPort, err := net.SplitHostPort(addrPort) - if err != nil { - return nil, fmt.Errorf("Invalid Consul HTTP address: %s", err) - } - if agentAddr == "" { - agentAddr = "127.0.0.1" - } + var err error + agentAddr, agentPort, err = net.SplitHostPort(grpcAddr) + if err != nil { + return nil, fmt.Errorf("Invalid Consul HTTP address: %s", err) + } + if agentAddr == "" { + agentAddr = "127.0.0.1" + } - // We use STATIC for agent which means we need to resolve DNS names like - // `localhost` ourselves. We could use STRICT_DNS or LOGICAL_DNS with envoy - // but Envoy resolves `localhost` differently to go on macOS at least which - // causes paper cuts like default dev agent (which binds specifically to - // 127.0.0.1) isn't reachable since Envoy resolves localhost to `[::]` and - // can't connect. - agentIP, err := net.ResolveIPAddr("ip", agentAddr) - if err != nil { - return nil, fmt.Errorf("Failed to resolve agent address: %s", err) + // We use STATIC for agent which means we need to resolve DNS names like + // `localhost` ourselves. We could use STRICT_DNS or LOGICAL_DNS with envoy + // but Envoy resolves `localhost` differently to go on macOS at least which + // causes paper cuts like default dev agent (which binds specifically to + // 127.0.0.1) isn't reachable since Envoy resolves localhost to `[::]` and + // can't connect. + agentIP, err := net.ResolveIPAddr("ip", agentAddr) + if err != nil { + return nil, fmt.Errorf("Failed to resolve agent address: %s", err) + } + agentAddr = agentIP.String() } adminAddr, adminPort, err := net.SplitHostPort(c.adminBind) @@ -414,8 +423,9 @@ func (c *cmd) templateArgs() (*BootstrapTplArgs, error) { return &BootstrapTplArgs{ ProxyCluster: cluster, ProxyID: c.proxyID, - AgentAddress: agentIP.String(), + AgentAddress: agentAddr, AgentPort: agentPort, + AgentSocket: agentSock, AgentTLS: useTLS, AgentCAFile: httpCfg.TLSConfig.CAFile, AdminAccessLogPath: adminAccessLogPath, diff --git a/command/connect/envoy/envoy_test.go b/command/connect/envoy/envoy_test.go index 2f15ac59a8..73ec77aff7 100644 --- a/command/connect/envoy/envoy_test.go +++ b/command/connect/envoy/envoy_test.go @@ -206,6 +206,21 @@ func TestGenerateConfig(t *testing.T) { LocalAgentClusterName: xds.LocalAgentClusterName, }, }, + { + Name: "grpc-addr-unix", + Flags: []string{"-proxy-id", "test-proxy", + "-grpc-addr", "unix:///var/run/consul.sock"}, + Env: []string{}, + WantArgs: BootstrapTplArgs{ + ProxyCluster: "test-proxy", + ProxyID: "test-proxy", + AgentSocket: "/var/run/consul.sock", + AdminAccessLogPath: "/dev/null", + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + LocalAgentClusterName: xds.LocalAgentClusterName, + }, + }, { Name: "access-log-path", Flags: []string{"-proxy-id", "test-proxy", "-admin-access-log-path", "/some/path/access.log"}, diff --git a/command/connect/envoy/testdata/access-log-path.golden b/command/connect/envoy/testdata/access-log-path.golden index ff389654ad..4ce76d3529 100644 --- a/command/connect/envoy/testdata/access-log-path.golden +++ b/command/connect/envoy/testdata/access-log-path.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/defaults.golden b/command/connect/envoy/testdata/defaults.golden index 292de71e51..32c0240c28 100644 --- a/command/connect/envoy/testdata/defaults.golden +++ b/command/connect/envoy/testdata/defaults.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/extra_-multiple.golden b/command/connect/envoy/testdata/extra_-multiple.golden index d3dcabe9e7..9f9ca8cea5 100644 --- a/command/connect/envoy/testdata/extra_-multiple.golden +++ b/command/connect/envoy/testdata/extra_-multiple.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] }, { diff --git a/command/connect/envoy/testdata/extra_-single.golden b/command/connect/envoy/testdata/extra_-single.golden index 29192ecb7c..bb20d2ddd9 100644 --- a/command/connect/envoy/testdata/extra_-single.golden +++ b/command/connect/envoy/testdata/extra_-single.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] }, { diff --git a/command/connect/envoy/testdata/grpc-addr-env.golden b/command/connect/envoy/testdata/grpc-addr-env.golden index e9c823b905..3a686b03b1 100644 --- a/command/connect/envoy/testdata/grpc-addr-env.golden +++ b/command/connect/envoy/testdata/grpc-addr-env.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 9999 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/grpc-addr-flag.golden b/command/connect/envoy/testdata/grpc-addr-flag.golden index e9c823b905..3a686b03b1 100644 --- a/command/connect/envoy/testdata/grpc-addr-flag.golden +++ b/command/connect/envoy/testdata/grpc-addr-flag.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 9999 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/grpc-addr-unix.golden b/command/connect/envoy/testdata/grpc-addr-unix.golden new file mode 100644 index 0000000000..260fae8fda --- /dev/null +++ b/command/connect/envoy/testdata/grpc-addr-unix.golden @@ -0,0 +1,57 @@ +{ + "admin": { + "access_log_path": "/dev/null", + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 19000 + } + } + }, + "node": { + "cluster": "test-proxy", + "id": "test-proxy" + }, + "static_resources": { + "clusters": [ + { + "name": "local_agent", + "connect_timeout": "1s", + "type": "STATIC", + "http2_protocol_options": {}, + "hosts": [{ + "pipe": { + "path": "/var/run/consul.sock" + } + }] + } + ] + }, + "stats_config": { + "stats_tags": [ + { + "tag_name": "local_cluster", + "fixed_value": "test-proxy" + } + ], + "use_all_default_tags": true + }, + "dynamic_resources": { + "lds_config": { "ads": {} }, + "cds_config": { "ads": {} }, + "ads_config": { + "api_type": "GRPC", + "grpc_services": { + "initial_metadata": [ + { + "key": "x-consul-token", + "value": "" + } + ], + "envoy_grpc": { + "cluster_name": "local_agent" + } + } + } + } +} diff --git a/command/connect/envoy/testdata/stats-config-override.golden b/command/connect/envoy/testdata/stats-config-override.golden index 2fb2eec75f..2375727748 100644 --- a/command/connect/envoy/testdata/stats-config-override.golden +++ b/command/connect/envoy/testdata/stats-config-override.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/token-arg.golden b/command/connect/envoy/testdata/token-arg.golden index 07b7f6cac4..75014d50b5 100644 --- a/command/connect/envoy/testdata/token-arg.golden +++ b/command/connect/envoy/testdata/token-arg.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/token-env.golden b/command/connect/envoy/testdata/token-env.golden index 07b7f6cac4..75014d50b5 100644 --- a/command/connect/envoy/testdata/token-env.golden +++ b/command/connect/envoy/testdata/token-env.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/token-file-arg.golden b/command/connect/envoy/testdata/token-file-arg.golden index 07b7f6cac4..75014d50b5 100644 --- a/command/connect/envoy/testdata/token-file-arg.golden +++ b/command/connect/envoy/testdata/token-file-arg.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/token-file-env.golden b/command/connect/envoy/testdata/token-file-env.golden index 07b7f6cac4..75014d50b5 100644 --- a/command/connect/envoy/testdata/token-file-env.golden +++ b/command/connect/envoy/testdata/token-file-env.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] } ] }, diff --git a/command/connect/envoy/testdata/zipkin-tracing-config.golden b/command/connect/envoy/testdata/zipkin-tracing-config.golden index 5cfcc0e4ad..71cdf2ec7d 100644 --- a/command/connect/envoy/testdata/zipkin-tracing-config.golden +++ b/command/connect/envoy/testdata/zipkin-tracing-config.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 8502 } - } - ] + }] }, { "name": "zipkin", diff --git a/website/source/docs/connect/proxies/envoy.md b/website/source/docs/connect/proxies/envoy.md index 44ff6682df..9d600474bf 100644 --- a/website/source/docs/connect/proxies/envoy.md +++ b/website/source/docs/connect/proxies/envoy.md @@ -196,6 +196,10 @@ defaults that are inherited by all services. filter](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/http_filters/grpc_http1_bridge_filter#config-http-filters-grpc-bridge) that translates HTTP/1.1 calls into gRPC, and instruments metrics with `gRPC-status` trailer codes. +- `bind_address` - Override the address Envoy's public listener binds to. By + default Envoy will bind to the service address or 0.0.0.0 if there is not explicit address on the service registration. +- `bind_port` - Override the port Envoy's public listener binds to. By default + Envoy will bind to the service port. - `local_connect_timeout_ms` - The number of milliseconds allowed to make connections to the local application instance before timing out. Defaults to 5000 (5 seconds).