diff --git a/agent/proxycfg/connect_proxy.go b/agent/proxycfg/connect_proxy.go index f9c46103a094..873f942ba407 100644 --- a/agent/proxycfg/connect_proxy.go +++ b/agent/proxycfg/connect_proxy.go @@ -5,6 +5,8 @@ package proxycfg import ( "context" + "crypto/sha1" + "encoding/base64" "fmt" "path" "strings" @@ -660,8 +662,14 @@ func (s *handlerConnectProxy) maybeInitializeHCPMetricsWatches(ctx context.Conte // The path includes the proxy ID so that when multiple proxies are on the same host // they each have a distinct path to send their metrics. - sock := fmt.Sprintf("%s_%s.sock", s.proxyID.NamespaceOrDefault(), s.proxyID.ID) - path := path.Join(hcpCfg.HCPMetricsBindSocketDir, sock) + id := s.proxyID.NamespaceOrDefault() + "_" + s.proxyID.ID + + // UNIX domain sockets paths have a max length of 108, so we take a hash of the compound ID + // to limit the length of the socket path. + h := sha1.New() + h.Write([]byte(id)) + hash := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) + path := path.Join(hcpCfg.HCPMetricsBindSocketDir, hash+".sock") upstream := structs.Upstream{ DestinationNamespace: acl.DefaultNamespaceName, diff --git a/agent/proxycfg/state_test.go b/agent/proxycfg/state_test.go index aa11dc43f542..32be1fb94ec2 100644 --- a/agent/proxycfg/state_test.go +++ b/agent/proxycfg/state_test.go @@ -3722,7 +3722,7 @@ func TestState_WatchesAndUpdates(t *testing.T) { DestinationNamespace: "default", DestinationPartition: "default", DestinationName: apimod.HCPMetricsCollectorName, - LocalBindSocketPath: "/tmp/consul/hcp-metrics/default_web-sidecar-proxy.sock", + LocalBindSocketPath: "/tmp/consul/hcp-metrics/gqmuzdHCUPAEY5mbF8vgkZCNI14.sock", Config: map[string]interface{}{ "protocol": "grpc", }, diff --git a/agent/structs/config_entry.go b/agent/structs/config_entry.go index dd6671268e0d..c18a8013b6d4 100644 --- a/agent/structs/config_entry.go +++ b/agent/structs/config_entry.go @@ -468,6 +468,10 @@ func (e *ProxyConfigEntry) Validate() error { return err } + if err := validateOpaqueProxyConfig(e.Config); err != nil { + return fmt.Errorf("Config: %w", err) + } + if err := envoyextensions.ValidateExtensions(e.EnvoyExtensions.ToAPI()); err != nil { return err } @@ -1329,6 +1333,17 @@ func (c *ConfigEntryResponse) UnmarshalBinary(data []byte) error { return nil } +func validateOpaqueProxyConfig(config map[string]interface{}) error { + // This max is chosen to stay under the 104 character limit on OpenBSD, FreeBSD, MacOS. + // It assumes the socket's filename is fixed at 32 characters. + const maxSocketDirLen = 70 + + if path, _ := config["envoy_hcp_metrics_bind_socket_dir"].(string); len(path) > maxSocketDirLen { + return fmt.Errorf("envoy_hcp_metrics_bind_socket_dir length %d exceeds max %d", len(path), maxSocketDirLen) + } + return nil +} + func validateConfigEntryMeta(meta map[string]string) error { var err error if len(meta) > metaMaxKeyPairs { diff --git a/agent/structs/config_entry_test.go b/agent/structs/config_entry_test.go index b7fad39a37a5..9143dc05d993 100644 --- a/agent/structs/config_entry_test.go +++ b/agent/structs/config_entry_test.go @@ -3261,6 +3261,15 @@ func TestProxyConfigEntry(t *testing.T) { EnterpriseMeta: *acl.DefaultEnterpriseMeta(), }, }, + "proxy config entry has invalid opaque config": { + entry: &ProxyConfigEntry{ + Name: "global", + Config: map[string]interface{}{ + "envoy_hcp_metrics_bind_socket_dir": "/Consul/is/a/networking/platform/that/enables/securing/your/networking/", + }, + }, + validateErr: "Config: envoy_hcp_metrics_bind_socket_dir length 71 exceeds max", + }, "proxy config has invalid failover policy": { entry: &ProxyConfigEntry{ Name: "global", @@ -3445,3 +3454,33 @@ func uintPointer(v uint32) *uint32 { func durationPointer(d time.Duration) *time.Duration { return &d } + +func TestValidateOpaqueConfigMap(t *testing.T) { + tt := map[string]struct { + input map[string]interface{} + expectErr string + }{ + "hcp metrics socket dir is valid": { + input: map[string]interface{}{ + "envoy_hcp_metrics_bind_socket_dir": "/etc/consul.d/hcp"}, + expectErr: "", + }, + "hcp metrics socket dir is too long": { + input: map[string]interface{}{ + "envoy_hcp_metrics_bind_socket_dir": "/Consul/is/a/networking/platform/that/enables/securing/your/networking/", + }, + expectErr: "envoy_hcp_metrics_bind_socket_dir length 71 exceeds max 70", + }, + } + + for name, tc := range tt { + t.Run(name, func(t *testing.T) { + err := validateOpaqueProxyConfig(tc.input) + if tc.expectErr != "" { + require.ErrorContains(t, err, tc.expectErr) + return + } + require.NoError(t, err) + }) + } +} diff --git a/agent/structs/structs.go b/agent/structs/structs.go index 3e12999e7baf..1771b18be03b 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -1508,6 +1508,10 @@ func (s *NodeService) ValidateForAgent() error { "A Proxy cannot also be Connect Native, only typical services")) } + if err := validateOpaqueProxyConfig(s.Proxy.Config); err != nil { + result = multierror.Append(result, fmt.Errorf("Proxy.Config: %w", err)) + } + // ensure we don't have multiple upstreams for the same service var ( upstreamKeys = make(map[UpstreamKey]struct{}) diff --git a/agent/structs/structs_test.go b/agent/structs/structs_test.go index 49861f86c29c..6d887da9ac77 100644 --- a/agent/structs/structs_test.go +++ b/agent/structs/structs_test.go @@ -826,6 +826,16 @@ func TestStructs_NodeService_ValidateConnectProxy(t *testing.T) { "", }, + { + "connect-proxy: invalid opaque config", + func(x *NodeService) { + x.Proxy.Config = map[string]interface{}{ + "envoy_hcp_metrics_bind_socket_dir": "/Consul/is/a/networking/platform/that/enables/securing/your/networking/", + } + }, + "Proxy.Config: envoy_hcp_metrics_bind_socket_dir length 71 exceeds max", + }, + { "connect-proxy: no Proxy.DestinationServiceName", func(x *NodeService) { x.Proxy.DestinationServiceName = "" }, diff --git a/agent/xds/testdata/listeners/hcp-metrics.latest.golden b/agent/xds/testdata/listeners/hcp-metrics.latest.golden index d89036a935cb..c1e0d04734a3 100644 --- a/agent/xds/testdata/listeners/hcp-metrics.latest.golden +++ b/agent/xds/testdata/listeners/hcp-metrics.latest.golden @@ -1,184 +1,184 @@ { - "versionInfo": "00000001", - "resources": [ + "versionInfo": "00000001", + "resources": [ { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "db:127.0.0.1:9191", - "address": { - "socketAddress": { - "address": "127.0.0.1", - "portValue": 9191 + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 } }, - "filterChains": [ + "filterChains": [ { - "filters": [ + "filters": [ { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.db.default.default.dc1", - "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } ] } ], - "trafficDirection": "OUTBOUND" + "trafficDirection": "OUTBOUND" }, { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "hcp-metrics-collector:/tmp/consul/hcp-metrics/default_web-sidecar-proxy.sock", - "address": { - "pipe": { - "path": "/tmp/consul/hcp-metrics/default_web-sidecar-proxy.sock" + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "hcp-metrics-collector:/tmp/consul/hcp-metrics/gqmuzdHCUPAEY5mbF8vgkZCNI14.sock", + "address": { + "pipe": { + "path": "/tmp/consul/hcp-metrics/gqmuzdHCUPAEY5mbF8vgkZCNI14.sock" } }, - "filterChains": [ + "filterChains": [ { - "filters": [ + "filters": [ { - "name": "envoy.filters.network.http_connection_manager", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "statPrefix": "upstream.hcp-metrics-collector.default.default.dc1", - "routeConfig": { - "name": "hcp-metrics-collector", - "virtualHosts": [ + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "upstream.hcp-metrics-collector.default.default.dc1", + "routeConfig": { + "name": "hcp-metrics-collector", + "virtualHosts": [ { - "name": "hcp-metrics-collector.default.default.dc1", - "domains": [ + "name": "hcp-metrics-collector.default.default.dc1", + "domains": [ "*" ], - "routes": [ + "routes": [ { - "match": { - "prefix": "/" + "match": { + "prefix": "/" }, - "route": { - "cluster": "hcp-metrics-collector.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + "route": { + "cluster": "hcp-metrics-collector.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } ] } ] }, - "httpFilters": [ + "httpFilters": [ { - "name": "envoy.filters.http.grpc_stats", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", - "statsForAllMethods": true + "name": "envoy.filters.http.grpc_stats", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig", + "statsForAllMethods": true } }, { - "name": "envoy.filters.http.grpc_http1_bridge", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" + "name": "envoy.filters.http.grpc_http1_bridge", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config" } }, { - "name": "envoy.filters.http.router", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" } } ], - "tracing": { - "randomSampling": {} + "tracing": { + "randomSampling": {} }, - "http2ProtocolOptions": {} + "http2ProtocolOptions": {} } } ] } ], - "trafficDirection": "OUTBOUND" + "trafficDirection": "OUTBOUND" }, { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "prepared_query:geo-cache:127.10.10.10:8181", - "address": { - "socketAddress": { - "address": "127.10.10.10", - "portValue": 8181 + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 } }, - "filterChains": [ + "filterChains": [ { - "filters": [ + "filters": [ { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "upstream.prepared_query_geo-cache", - "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" } } ] } ], - "trafficDirection": "OUTBOUND" + "trafficDirection": "OUTBOUND" }, { - "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", - "name": "public_listener:0.0.0.0:9999", - "address": { - "socketAddress": { - "address": "0.0.0.0", - "portValue": 9999 + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 } }, - "filterChains": [ + "filterChains": [ { - "filters": [ + "filters": [ { - "name": "envoy.filters.network.rbac", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", - "rules": {}, - "statPrefix": "connect_authz" + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" } }, { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "public_listener", - "cluster": "local_app" + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "public_listener", + "cluster": "local_app" } } ], - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", - "commonTlsContext": { - "tlsParams": {}, - "tlsCertificates": [ + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "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" + "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" + "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" + "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 + "requireClientCertificate": true } } } ], - "trafficDirection": "INBOUND" + "trafficDirection": "INBOUND" } ], - "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", - "nonce": "00000001" + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" } \ No newline at end of file diff --git a/command/connect/envoy/bootstrap_config.go b/command/connect/envoy/bootstrap_config.go index 337e1cf5db66..8ace2c37aa87 100644 --- a/command/connect/envoy/bootstrap_config.go +++ b/command/connect/envoy/bootstrap_config.go @@ -5,6 +5,8 @@ package envoy import ( "bytes" + "crypto/sha1" + "encoding/base64" "encoding/json" "fmt" "net" @@ -14,7 +16,6 @@ import ( "strings" "text/template" - "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/api" ) @@ -811,13 +812,28 @@ func (c *BootstrapConfig) generateListenerConfig(args *BootstrapTplArgs, bindAdd return nil } -// appendHCPMetricsConfig generates config to enable a socket at path: /_.sock -// or /.sock, if namespace is empty. +// appendHCPMetricsConfig generates config to enable a socket at path: /.sock +// We take the hash of the compound proxy ID for a few reasons: +// +// - The proxy ID is included because this socket path must be unique per proxy. Each Envoy proxy will ship +// its metrics to HCP using its own loopback listener at this path. +// +// - The hash is needed because UNIX domain socket paths must be less than 104 characters. By using a b64 encoded +// SHA1 hash we end up with 27 chars for the name, 5 chars for the extension, and the remainder is saved for +// the configurable socket dir. The length of the directory's path is validated on writes to avoid going over. func appendHCPMetricsConfig(args *BootstrapTplArgs, hcpMetricsBindSocketDir string) { // Normalize namespace to "default". This ensures we match the namespace behaviour in proxycfg package, // where a dynamic listener will be created at the same socket path via xDS. - sock := fmt.Sprintf("%s_%s.sock", acl.NamespaceOrDefault(args.Namespace), args.ProxyID) - path := path.Join(hcpMetricsBindSocketDir, sock) + ns := args.Namespace + if ns == "" { + ns = "default" + } + id := ns + "_" + args.ProxyID + + h := sha1.New() + h.Write([]byte(id)) + hash := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) + path := path.Join(hcpMetricsBindSocketDir, hash+".sock") if args.StatsSinksJSON != "" { args.StatsSinksJSON += ",\n" diff --git a/command/connect/envoy/bootstrap_config_test.go b/command/connect/envoy/bootstrap_config_test.go index d9d10803c1d6..a43814c729a8 100644 --- a/command/connect/envoy/bootstrap_config_test.go +++ b/command/connect/envoy/bootstrap_config_test.go @@ -556,7 +556,7 @@ const ( "endpoint": { "address": { "pipe": { - "path": "/tmp/consul/hcp-metrics/default_web-sidecar-proxy.sock" + "path": "/tmp/consul/hcp-metrics/gqmuzdHCUPAEY5mbF8vgkZCNI14.sock" } } } @@ -654,7 +654,7 @@ func TestBootstrapConfig_ConfigureArgs(t *testing.T) { "endpoint": { "address": { "pipe": { - "path": "/tmp/consul/hcp-metrics/default_web-sidecar-proxy.sock" + "path": "/tmp/consul/hcp-metrics/gqmuzdHCUPAEY5mbF8vgkZCNI14.sock" } } } diff --git a/command/connect/envoy/testdata/hcp-metrics.golden b/command/connect/envoy/testdata/hcp-metrics.golden index dbae64eecf67..e1f5112c02e8 100644 --- a/command/connect/envoy/testdata/hcp-metrics.golden +++ b/command/connect/envoy/testdata/hcp-metrics.golden @@ -68,7 +68,7 @@ "endpoint": { "address": { "pipe": { - "path": "/tmp/consul/hcp-metrics/default_test-proxy.sock" + "path": "/tmp/consul/hcp-metrics/k3bWnyJyKvjUYXrBdOX2nXzSSCQ.sock" } } }