diff --git a/agent/xds/config.go b/agent/xds/config.go index 89e92106d9..cfbd23e070 100644 --- a/agent/xds/config.go +++ b/agent/xds/config.go @@ -27,11 +27,11 @@ type ProxyConfig struct { // Note: This escape hatch is compatible with the discovery chain. PublicListenerJSON string `mapstructure:"envoy_public_listener_json"` - // LstenerTracingJSON is a complete override ("escape hatch") for the + // ListenerTracingJSON is a complete override ("escape hatch") for the // listeners tracing configuration. // // Note: This escape hatch is compatible with the discovery chain. - LstenerTracingJSON string `mapstructure:"envoy_listener_tracing_json"` + ListenerTracingJSON string `mapstructure:"envoy_listener_tracing_json"` // LocalClusterJSON is a complete override ("escape hatch") for the // local application cluster. diff --git a/agent/xds/listeners.go b/agent/xds/listeners.go index b3c9577e13..488cc6eb85 100644 --- a/agent/xds/listeners.go +++ b/agent/xds/listeners.go @@ -115,9 +115,9 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) } var tracing *envoy_http_v3.HttpConnectionManager_Tracing - if proxyCfg.LstenerTracingJSON != "" { - if tracing, err = makeTracingFromUserConfig(proxyCfg.LstenerTracingJSON); err != nil { - s.Logger.Warn("failed to parse LstenerTracingJSON config", "error", err) + if proxyCfg.ListenerTracingJSON != "" { + if tracing, err = makeTracingFromUserConfig(proxyCfg.ListenerTracingJSON); err != nil { + s.Logger.Warn("failed to parse ListenerTracingJSON config", "error", err) } } @@ -1209,9 +1209,9 @@ func (s *ResourceGenerator) makeInboundListener(cfgSnap *proxycfg.ConfigSnapshot l = makePortListener(name, addr, port, envoy_core_v3.TrafficDirection_INBOUND) var tracing *envoy_http_v3.HttpConnectionManager_Tracing - if cfg.LstenerTracingJSON != "" { - if tracing, err = makeTracingFromUserConfig(cfg.LstenerTracingJSON); err != nil { - s.Logger.Warn("failed to parse LstenerTracingJSON config", "error", err) + if cfg.ListenerTracingJSON != "" { + if tracing, err = makeTracingFromUserConfig(cfg.ListenerTracingJSON); err != nil { + s.Logger.Warn("failed to parse ListenerTracingJSON config", "error", err) } } @@ -1338,7 +1338,7 @@ func (s *ResourceGenerator) makeExposedCheckListener(cfgSnap *proxycfg.ConfigSna statPrefix: "", routePath: path.Path, httpAuthzFilter: nil, - // in the exposed check listener de don't set the tracing configuration + // in the exposed check listener we don't set the tracing configuration } f, err := makeListenerFilter(opts) if err != nil { @@ -1578,9 +1578,9 @@ func (s *ResourceGenerator) makeFilterChainTerminatingGateway(cfgSnap *proxycfg. s.Logger.Warn("failed to parse Connect.Proxy.Config", "error", err) } var tracing *envoy_http_v3.HttpConnectionManager_Tracing - if proxyCfg.LstenerTracingJSON != "" { - if tracing, err = makeTracingFromUserConfig(proxyCfg.LstenerTracingJSON); err != nil { - s.Logger.Warn("failed to parse LstenerTracingJSON config", "error", err) + if proxyCfg.ListenerTracingJSON != "" { + if tracing, err = makeTracingFromUserConfig(proxyCfg.ListenerTracingJSON); err != nil { + s.Logger.Warn("failed to parse ListenerTracingJSON config", "error", err) } } diff --git a/agent/xds/listeners_test.go b/agent/xds/listeners_test.go index c51730074c..1112222f3f 100644 --- a/agent/xds/listeners_test.go +++ b/agent/xds/listeners_test.go @@ -772,6 +772,15 @@ func TestListenersFromSnapshot(t *testing.T) { name: "transparent-proxy-terminating-gateway", create: proxycfg.TestConfigSnapshotTransparentProxyTerminatingGatewayCatalogDestinationsOnly, }, + { + name: "custom-trace-listener", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "http" + ns.Proxy.Config["envoy_listener_tracing_json"] = customTraceJSON(t) + }, nil) + }, + }, } latestEnvoyVersion := proxysupport.EnvoyVersions[0] @@ -947,6 +956,40 @@ func customHTTPListenerJSON(t testinf.T, opts customHTTPListenerJSONOptions) str return buf.String() } +func customTraceJSON(t testinf.T) string { + t.Helper() + return ` + { + "@type" : "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.Tracing", + "provider" : { + "name" : "envoy.tracers.zipkin", + "typed_config" : { + "@type" : "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig", + "collector_cluster" : "otelcolector", + "collector_endpoint" : "/api/v2/spans", + "collector_endpoint_version" : "HTTP_JSON", + "shared_span_context" : false + } + }, + "custom_tags" : [ + { + "tag" : "custom_header", + "request_header" : { + "name" : "x-custom-traceid", + "default_value" : "" + } + }, + { + "tag" : "alloc_id", + "environment" : { + "name" : "NOMAD_ALLOC_ID" + } + } + ] + } + ` +} + type configFetcherFunc func() string var _ ConfigFetcher = (configFetcherFunc)(nil) diff --git a/agent/xds/testdata/listeners/custom-trace-listener.latest.golden b/agent/xds/testdata/listeners/custom-trace-listener.latest.golden new file mode 100644 index 0000000000..5fce12bb73 --- /dev/null +++ b/agent/xds/testdata/listeners/custom-trace-listener.latest.golden @@ -0,0 +1,180 @@ +{ + "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 + } + }, + "filterChains": [ + { + "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" + } + } + ] + } + ], + "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 + } + }, + "filterChains": [ + { + "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" + } + } + ] + } + ], + "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 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "public_listener", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "name": "public_listener", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + + } + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "customTags": [ + { + "tag": "custom_header", + "requestHeader": { + "name": "x-custom-traceid" + } + }, + { + "tag": "alloc_id", + "environment": { + "name": "NOMAD_ALLOC_ID" + } + } + ], + "provider": { + "name": "envoy.tracers.zipkin", + "typedConfig": { + "@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig", + "collectorCluster": "otelcolector", + "collectorEndpoint": "/api/v2/spans", + "sharedSpanContext": false, + "collectorEndpointVersion": "HTTP_JSON" + } + } + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "setCurrentClientCertDetails": { + "subject": true, + "cert": true, + "chain": true, + "dns": true, + "uri": true + } + } + } + ], + "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" + }, + "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 + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/website/content/docs/connect/proxies/envoy.mdx b/website/content/docs/connect/proxies/envoy.mdx index 7ada5b6fd0..020a0510f0 100644 --- a/website/content/docs/connect/proxies/envoy.mdx +++ b/website/content/docs/connect/proxies/envoy.mdx @@ -759,6 +759,45 @@ definition](/docs/connect/registration/service-registration) or +- `envoy_listener_tracing_json` - Specifies a [tracing + configuration](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto#envoy-v3-api-msg-extensions-filters-network-http-connection-manager-v3-httpconnectionmanager-tracing) + to be inserter in the public and upstreams listeners of the proxy. + + + + ```json + { + "@type" : "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.Tracing", + "provider" : { + "name" : "envoy.tracers.zipkin", + "typed_config" : { + "@type" : "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig", + "collector_cluster" : "otelcolector", + "collector_endpoint" : "/api/v2/spans", + "collector_endpoint_version" : "HTTP_JSON", + "shared_span_context" : false + } + }, + "custom_tags" : [ + { + "tag" : "custom_header", + "request_header" : { + "name" : "x-custom-traceid", + "default_value" : "" + } + }, + { + "tag" : "alloc_id", + "environment" : { + "name" : "NOMAD_ALLOC_ID" + } + } + ] + } + ``` + + + - `envoy_local_cluster_json` - Specifies a complete [Envoy cluster][pb-cluster] to be delivered in place of the local application cluster. This allows customization of timeouts, rate limits, load balancing strategy etc.