From 7c5ef2aa3fd114853de16d9794da3b71816592a8 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Thu, 16 Jun 2022 17:18:37 -0700 Subject: [PATCH] command: Add TLS support for envoy prometheus endpoint --- command/connect/envoy/bootstrap_config.go | 65 +++- .../connect/envoy/bootstrap_config_test.go | 182 ++++++++++ command/connect/envoy/bootstrap_tpl.go | 15 + command/connect/envoy/envoy.go | 30 ++ command/connect/envoy/envoy_test.go | 66 ++++ .../prometheus-metrics-tls-ca-file.golden | 320 ++++++++++++++++++ .../prometheus-metrics-tls-ca-path.golden | 320 ++++++++++++++++++ 7 files changed, 997 insertions(+), 1 deletion(-) create mode 100644 command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden create mode 100644 command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden diff --git a/command/connect/envoy/bootstrap_config.go b/command/connect/envoy/bootstrap_config.go index 9c94eaac7..f2ea33b7f 100644 --- a/command/connect/envoy/bootstrap_config.go +++ b/command/connect/envoy/bootstrap_config.go @@ -637,6 +637,31 @@ func (c *BootstrapConfig) generateListenerConfig(args *BootstrapTplArgs, bindAdd ] } }` + + // Enable TLS on the prometheus listener if cert/private key are provided. + var tlsConfig string + if args.PrometheusCertFile != "" { + tlsConfig = `, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificateSdsSecretConfigs": [ + { + "name": "prometheus_cert" + } + ], + "validationContextSdsSecretConfig": { + "trustedCa": { + "name": "prometheus_validation_context" + } + } + } + } + }` + } + listenerJSON := `{ "name": "` + name + `_listener", "address": { @@ -694,11 +719,43 @@ func (c *BootstrapConfig) generateListenerConfig(args *BootstrapTplArgs, bindAdd ] } } - ] + ]` + tlsConfig + ` } ] }` + secretsTemplate := `{ + "name": "prometheus_cert", + "tlsCertificate": { + "certificateChain": { + "filename": "%s" + }, + "privateKey": { + "filename": "%s" + } + } + }, + { + "name": "prometheus_validation_context", + "validationContext": { + %s + } + }` + var validationContext string + if args.PrometheusCAPath != "" { + validationContext = fmt.Sprintf(`"watchedDirectory": { + "path": "%s" + }`, args.PrometheusCAPath) + } else { + validationContext = fmt.Sprintf(`"trustedCa": { + "filename": "%s" + }`, args.PrometheusCAFile) + } + var secretsJSON string + if args.PrometheusCertFile != "" { + secretsJSON = fmt.Sprintf(secretsTemplate, args.PrometheusCertFile, args.PrometheusKeyFile, validationContext) + } + // Make sure we do not append the same cluster multiple times, as that will // cause envoy startup to fail. selfAdminClusterExists, err := containsSelfAdminCluster(args.StaticClustersJSON) @@ -716,6 +773,12 @@ func (c *BootstrapConfig) generateListenerConfig(args *BootstrapTplArgs, bindAdd listenerJSON = ",\n" + listenerJSON } args.StaticListenersJSON += listenerJSON + + if args.StaticSecretsJSON != "" { + secretsJSON = ",\n" + secretsJSON + } + args.StaticSecretsJSON += secretsJSON + return nil } diff --git a/command/connect/envoy/bootstrap_config_test.go b/command/connect/envoy/bootstrap_config_test.go index f02ae04c5..bb471566c 100644 --- a/command/connect/envoy/bootstrap_config_test.go +++ b/command/connect/envoy/bootstrap_config_test.go @@ -273,6 +273,126 @@ const ( } ] }` + expectedPromListenerWithBackendAndTLS = `{ + "name": "envoy_prometheus_metrics_listener", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 9000 + } + }, + "filter_chains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "envoy_prometheus_metrics", + "codec_type": "HTTP1", + "route_config": { + "name": "self_admin_route", + "virtual_hosts": [ + { + "name": "self_admin", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "path": "/metrics" + }, + "route": { + "cluster": "prometheus_backend", + "prefix_rewrite": "/stats/prometheus" + } + }, + { + "match": { + "prefix": "/" + }, + "direct_response": { + "status": 404 + } + } + ] + } + ] + }, + "http_filters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificateSdsSecretConfigs": [ + { + "name": "prometheus_cert" + } + ], + "validationContextSdsSecretConfig": { + "trustedCa": { + "name": "prometheus_validation_context" + } + } + } + } + } + } + ] + }` + + expectedPromSecretsWithBackendAndTLS = `{ + "name": "prometheus_cert", + "tlsCertificate": { + "certificateChain": { + "filename": "test-cert-file" + }, + "privateKey": { + "filename": "test-key-file" + } + } + }, + { + "name": "prometheus_validation_context", + "validationContext": { + "trustedCa": { + "filename": "test-ca-file" + } + } + }` + + expectedPromSecretsWithBackendAndTLSCAPath = `{ + "name": "prometheus_cert", + "tlsCertificate": { + "certificateChain": { + "filename": "test-cert-file" + }, + "privateKey": { + "filename": "test-key-file" + } + } + }, + { + "name": "prometheus_validation_context", + "validationContext": { + "watchedDirectory": { + "path": "test-ca-directory" + } + } + }` + expectedStatsListener = `{ "name": "envoy_metrics_listener", "address": { @@ -760,6 +880,68 @@ func TestBootstrapConfig_ConfigureArgs(t *testing.T) { }, wantErr: false, }, + { + name: "prometheus-bind-addr-with-backend-and-tls", + input: BootstrapConfig{ + PrometheusBindAddr: "0.0.0.0:9000", + }, + baseArgs: BootstrapTplArgs{ + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + PrometheusBackendPort: "20100", + PrometheusScrapePath: "/metrics", + PrometheusCAFile: "test-ca-file", + PrometheusCertFile: "test-cert-file", + PrometheusKeyFile: "test-key-file", + }, + wantArgs: BootstrapTplArgs{ + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + // Should use the "prometheus_backend" cluster instead, which + // uses the PrometheusBackendPort rather than Envoy admin port + StaticClustersJSON: expectedPrometheusBackendCluster, + StaticListenersJSON: expectedPromListenerWithBackendAndTLS, + StaticSecretsJSON: expectedPromSecretsWithBackendAndTLS, + StatsConfigJSON: defaultStatsConfigJSON, + PrometheusBackendPort: "20100", + PrometheusScrapePath: "/metrics", + PrometheusCAFile: "test-ca-file", + PrometheusCertFile: "test-cert-file", + PrometheusKeyFile: "test-key-file", + }, + wantErr: false, + }, + { + name: "prometheus-bind-addr-with-backend-and-tls-ca-path", + input: BootstrapConfig{ + PrometheusBindAddr: "0.0.0.0:9000", + }, + baseArgs: BootstrapTplArgs{ + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + PrometheusBackendPort: "20100", + PrometheusScrapePath: "/metrics", + PrometheusCAPath: "test-ca-directory", + PrometheusCertFile: "test-cert-file", + PrometheusKeyFile: "test-key-file", + }, + wantArgs: BootstrapTplArgs{ + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + // Should use the "prometheus_backend" cluster instead, which + // uses the PrometheusBackendPort rather than Envoy admin port + StaticClustersJSON: expectedPrometheusBackendCluster, + StaticListenersJSON: expectedPromListenerWithBackendAndTLS, + StaticSecretsJSON: expectedPromSecretsWithBackendAndTLSCAPath, + StatsConfigJSON: defaultStatsConfigJSON, + PrometheusBackendPort: "20100", + PrometheusScrapePath: "/metrics", + PrometheusCAPath: "test-ca-directory", + PrometheusCertFile: "test-cert-file", + PrometheusKeyFile: "test-key-file", + }, + wantErr: false, + }, { name: "stats-bind-addr", input: BootstrapConfig{ diff --git a/command/connect/envoy/bootstrap_tpl.go b/command/connect/envoy/bootstrap_tpl.go index 6cb238d49..e6b71f548 100644 --- a/command/connect/envoy/bootstrap_tpl.go +++ b/command/connect/envoy/bootstrap_tpl.go @@ -76,6 +76,10 @@ type BootstrapTplArgs struct { // https://www.envoyproxy.io/docs/envoy/v1.9.0/api-v2/config/metrics/v2/stats.proto#envoy-api-msg-config-metrics-v2-statsconfig. StatsConfigJSON string + // StaticSecretsJSON is a JSON string containing zero or more Secret definitions. + // See https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/secret.proto#envoy-v3-api-msg-extensions-transport-sockets-tls-v3-secret + StaticSecretsJSON string + // StatsFlushInterval is the time duration between Envoy stats flushes. It is // in proto3 "duration" string format for example "1.12s" See // https://developers.google.com/protocol-buffers/docs/proto3#json and @@ -106,6 +110,11 @@ type BootstrapTplArgs struct { // PrometheusScrapePath will configure the path where metrics are exposed on // the envoy_prometheus_bind_addr listener. PrometheusScrapePath string + + PrometheusCAFile string + PrometheusCAPath string + PrometheusCertFile string + PrometheusKeyFile string } // GRPC settings used in the bootstrap template. @@ -209,6 +218,12 @@ const bootstrapTemplate = `{ {{ .StaticListenersJSON }} ] {{- end }} + {{- if .StaticSecretsJSON -}} + , + "secrets": [ + {{ .StaticSecretsJSON }} + ] + {{- end }} }, {{- if .StatsSinksJSON }} "stats_sinks": {{ .StatsSinksJSON }}, diff --git a/command/connect/envoy/envoy.go b/command/connect/envoy/envoy.go index a78ae54d5..342357dfa 100644 --- a/command/connect/envoy/envoy.go +++ b/command/connect/envoy/envoy.go @@ -52,6 +52,10 @@ type cmd struct { envoyVersion string prometheusBackendPort string prometheusScrapePath string + prometheusCAFile string + prometheusCAPath string + prometheusCertFile string + prometheusKeyFile string // mesh gateway registration information register bool @@ -174,6 +178,19 @@ func (c *cmd) init() { "0.0.0.0:20200/scrape-metrics. "+ "Only applicable when envoy_prometheus_bind_addr is set in proxy config.") + c.flags.StringVar(&c.prometheusCAFile, "prometheus-ca-file", "", + "Path to a CA file for Envoy to use when serving TLS on the Prometheus metrics endpoint. "+ + "Only applicable when envoy_prometheus_bind_addr is set in proxy config.") + c.flags.StringVar(&c.prometheusCAPath, "prometheus-ca-path", "", + "Path to a directory of CA certificates for Envoy to use when serving the Prometheus metrics endpoint. "+ + "Only applicable when envoy_prometheus_bind_addr is set in proxy config.") + c.flags.StringVar(&c.prometheusCertFile, "prometheus-cert-file", "", + "Path to a certificate file for Envoy to use when serving TLS on the Prometheus metrics endpoint. "+ + "Only applicable when envoy_prometheus_bind_addr is set in proxy config.") + c.flags.StringVar(&c.prometheusKeyFile, "prometheus-key-file", "", + "Path to a private key file for Envoy to use when serving TLS on the Prometheus metrics endpoint. "+ + "Only applicable when envoy_prometheus_bind_addr is set in proxy config.") + c.http = &flags.HTTPFlags{} flags.Merge(c.flags, c.http.ClientFlags()) flags.Merge(c.flags, c.http.MultiTenancyFlags()) @@ -306,6 +323,15 @@ func (c *cmd) run(args []string) int { return 1 } + // If any of CA/Cert/Key are specified, make sure they are all present. + if c.prometheusKeyFile != "" || c.prometheusCertFile != "" || (c.prometheusCAFile != "" || c.prometheusCAPath != "") { + if c.prometheusKeyFile == "" || c.prometheusCertFile == "" || (c.prometheusCAFile == "" && c.prometheusCAPath == "") { + c.UI.Error("Must provide a CA (-prometheus-ca-file or -prometheus-ca-path) as well as " + + "-prometheus-cert-file and -prometheus-key-file to enable TLS for prometheus metrics") + return 1 + } + } + if c.register { if c.nodeName != "" { c.UI.Error("'-register' cannot be used with '-node-name'") @@ -505,6 +531,10 @@ func (c *cmd) templateArgs() (*BootstrapTplArgs, error) { Datacenter: httpCfg.Datacenter, PrometheusBackendPort: c.prometheusBackendPort, PrometheusScrapePath: c.prometheusScrapePath, + PrometheusCAFile: c.prometheusCAFile, + PrometheusCAPath: c.prometheusCAPath, + PrometheusCertFile: c.prometheusCertFile, + PrometheusKeyFile: c.prometheusKeyFile, }, nil } diff --git a/command/connect/envoy/envoy_test.go b/command/connect/envoy/envoy_test.go index 0e29a6934..4eedd16d4 100644 --- a/command/connect/envoy/envoy_test.go +++ b/command/connect/envoy/envoy_test.go @@ -211,6 +211,72 @@ func TestGenerateConfig(t *testing.T) { PrometheusScrapePath: "/scrape-path", }, }, + { + Name: "prometheus-metrics-tls-ca-file", + Flags: []string{"-proxy-id", "test-proxy", + "-prometheus-backend-port", "20100", "-prometheus-scrape-path", "/scrape-path", + "-prometheus-ca-file", "../../../test/key/ourdomain.cer", "-prometheus-cert-file", "../../../test/key/ourdomain_server.cer", + "-prometheus-key-file", "../../../test/key/ourdomain_server.key"}, + ProxyConfig: map[string]interface{}{ + // When envoy_prometheus_bind_addr is set, if + // PrometheusBackendPort is set, there will be a + // "prometheus_backend" cluster in the Envoy configuration. + "envoy_prometheus_bind_addr": "0.0.0.0:9000", + }, + WantArgs: BootstrapTplArgs{ + ProxyCluster: "test-proxy", + ProxyID: "test-proxy", + // We don't know this til after the lookup so it will be empty in the + // initial args call we are testing here. + ProxySourceService: "", + GRPC: GRPC{ + AgentAddress: "127.0.0.1", + AgentPort: "8502", // Note this is the gRPC port + }, + AdminAccessLogPath: "/dev/null", + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + LocalAgentClusterName: xds.LocalAgentClusterName, + PrometheusBackendPort: "20100", + PrometheusScrapePath: "/scrape-path", + PrometheusCAFile: "../../../test/key/ourdomain.cer", + PrometheusCertFile: "../../../test/key/ourdomain_server.cer", + PrometheusKeyFile: "../../../test/key/ourdomain_server.key", + }, + }, + { + Name: "prometheus-metrics-tls-ca-path", + Flags: []string{"-proxy-id", "test-proxy", + "-prometheus-backend-port", "20100", "-prometheus-scrape-path", "/scrape-path", + "-prometheus-ca-path", "../../../test/ca_path", "-prometheus-cert-file", "../../../test/key/ourdomain_server.cer", + "-prometheus-key-file", "../../../test/key/ourdomain_server.key"}, + ProxyConfig: map[string]interface{}{ + // When envoy_prometheus_bind_addr is set, if + // PrometheusBackendPort is set, there will be a + // "prometheus_backend" cluster in the Envoy configuration. + "envoy_prometheus_bind_addr": "0.0.0.0:9000", + }, + WantArgs: BootstrapTplArgs{ + ProxyCluster: "test-proxy", + ProxyID: "test-proxy", + // We don't know this til after the lookup so it will be empty in the + // initial args call we are testing here. + ProxySourceService: "", + GRPC: GRPC{ + AgentAddress: "127.0.0.1", + AgentPort: "8502", // Note this is the gRPC port + }, + AdminAccessLogPath: "/dev/null", + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + LocalAgentClusterName: xds.LocalAgentClusterName, + PrometheusBackendPort: "20100", + PrometheusScrapePath: "/scrape-path", + PrometheusCAPath: "../../../test/ca_path", + PrometheusCertFile: "../../../test/key/ourdomain_server.cer", + PrometheusKeyFile: "../../../test/key/ourdomain_server.key", + }, + }, { Name: "token-arg", Flags: []string{"-proxy-id", "test-proxy", diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden new file mode 100644 index 000000000..239250c72 --- /dev/null +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden @@ -0,0 +1,320 @@ +{ + "admin": { + "access_log_path": "/dev/null", + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 19000 + } + } + }, + "node": { + "cluster": "test", + "id": "test-proxy", + "metadata": { + "namespace": "default", + "partition": "default" + } + }, + "static_resources": { + "clusters": [ + { + "name": "local_agent", + "ignore_health_on_host_removal": false, + "connect_timeout": "1s", + "type": "STATIC", + "http2_protocol_options": {}, + "loadAssignment": { + "clusterName": "local_agent", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 8502 + } + } + } + } + ] + } + ] + } + }, + { + "name": "prometheus_backend", + "ignore_health_on_host_removal": false, + "connect_timeout": "5s", + "type": "STATIC", + "http_protocol_options": {}, + "loadAssignment": { + "clusterName": "prometheus_backend", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 20100 + } + } + } + } + ] + } + ] + } + } + ], + "listeners": [ + { + "name": "envoy_prometheus_metrics_listener", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 9000 + } + }, + "filter_chains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "envoy_prometheus_metrics", + "codec_type": "HTTP1", + "route_config": { + "name": "self_admin_route", + "virtual_hosts": [ + { + "name": "self_admin", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "path": "/scrape-path" + }, + "route": { + "cluster": "prometheus_backend", + "prefix_rewrite": "/stats/prometheus" + } + }, + { + "match": { + "prefix": "/" + }, + "direct_response": { + "status": 404 + } + } + ] + } + ] + }, + "http_filters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificateSdsSecretConfigs": [ + { + "name": "prometheus_cert" + } + ], + "validationContextSdsSecretConfig": { + "trustedCa": { + "name": "prometheus_validation_context" + } + } + } + } + } + } + ] + } + ], + "secrets": [ + { + "name": "prometheus_cert", + "tlsCertificate": { + "certificateChain": { + "filename": "../../../test/key/ourdomain_server.cer" + }, + "privateKey": { + "filename": "../../../test/key/ourdomain_server.key" + } + } + }, + { + "name": "prometheus_validation_context", + "validationContext": { + "trustedCa": { + "filename": "../../../test/key/ourdomain.cer" + } + } + } + ] + }, + "stats_config": { + "stats_tags": [ + { + "regex": "^cluster\\.(?:passthrough~)?((?:([^.]+)~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.custom_hash" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.service_subset" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.service" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.namespace" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.partition" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.datacenter" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.routing_type" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.([^.]+)\\.consul\\.)", + "tag_name": "consul.destination.trust_domain" + }, + { + "regex": "^cluster\\.(?:passthrough~)?(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.target" + }, + { + "regex": "^cluster\\.(?:passthrough~)?(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+)\\.consul\\.)", + "tag_name": "consul.destination.full_target" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.(([^.]+)(?:\\.[^.]+)?(?:\\.[^.]+)?\\.[^.]+\\.)", + "tag_name": "consul.upstream.service" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.[^.]+)?(?:\\.[^.]+)?\\.([^.]+)\\.)", + "tag_name": "consul.upstream.datacenter" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.([^.]+))?(?:\\.[^.]+)?\\.[^.]+\\.)", + "tag_name": "consul.upstream.namespace" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.[^.]+)?(?:\\.([^.]+))?\\.[^.]+\\.)", + "tag_name": "consul.upstream.partition" + }, + { + "regex": "^cluster\\.((?:([^.]+)~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.custom_hash" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.service_subset" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.service" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.namespace" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.datacenter" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.[^.]+\\.consul\\.)", + "tag_name": "consul.routing_type" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.([^.]+)\\.consul\\.)", + "tag_name": "consul.trust_domain" + }, + { + "regex": "^cluster\\.(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.target" + }, + { + "regex": "^cluster\\.(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+)\\.consul\\.)", + "tag_name": "consul.full_target" + }, + { + "tag_name": "local_cluster", + "fixed_value": "test" + }, + { + "tag_name": "consul.source.service", + "fixed_value": "test" + }, + { + "tag_name": "consul.source.namespace", + "fixed_value": "default" + }, + { + "tag_name": "consul.source.partition", + "fixed_value": "default" + }, + { + "tag_name": "consul.source.datacenter", + "fixed_value": "dc1" + } + ], + "use_all_default_tags": true + }, + "dynamic_resources": { + "lds_config": { + "ads": {}, + "resource_api_version": "V3" + }, + "cds_config": { + "ads": {}, + "resource_api_version": "V3" + }, + "ads_config": { + "api_type": "DELTA_GRPC", + "transport_api_version": "V3", + "grpc_services": { + "initial_metadata": [ + { + "key": "x-consul-token", + "value": "" + } + ], + "envoy_grpc": { + "cluster_name": "local_agent" + } + } + } + } +} + diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden new file mode 100644 index 000000000..c00fa54ed --- /dev/null +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden @@ -0,0 +1,320 @@ +{ + "admin": { + "access_log_path": "/dev/null", + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 19000 + } + } + }, + "node": { + "cluster": "test", + "id": "test-proxy", + "metadata": { + "namespace": "default", + "partition": "default" + } + }, + "static_resources": { + "clusters": [ + { + "name": "local_agent", + "ignore_health_on_host_removal": false, + "connect_timeout": "1s", + "type": "STATIC", + "http2_protocol_options": {}, + "loadAssignment": { + "clusterName": "local_agent", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 8502 + } + } + } + } + ] + } + ] + } + }, + { + "name": "prometheus_backend", + "ignore_health_on_host_removal": false, + "connect_timeout": "5s", + "type": "STATIC", + "http_protocol_options": {}, + "loadAssignment": { + "clusterName": "prometheus_backend", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 20100 + } + } + } + } + ] + } + ] + } + } + ], + "listeners": [ + { + "name": "envoy_prometheus_metrics_listener", + "address": { + "socket_address": { + "address": "0.0.0.0", + "port_value": 9000 + } + }, + "filter_chains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "envoy_prometheus_metrics", + "codec_type": "HTTP1", + "route_config": { + "name": "self_admin_route", + "virtual_hosts": [ + { + "name": "self_admin", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "path": "/scrape-path" + }, + "route": { + "cluster": "prometheus_backend", + "prefix_rewrite": "/stats/prometheus" + } + }, + { + "match": { + "prefix": "/" + }, + "direct_response": { + "status": 404 + } + } + ] + } + ] + }, + "http_filters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ] + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsCertificateSdsSecretConfigs": [ + { + "name": "prometheus_cert" + } + ], + "validationContextSdsSecretConfig": { + "trustedCa": { + "name": "prometheus_validation_context" + } + } + } + } + } + } + ] + } + ], + "secrets": [ + { + "name": "prometheus_cert", + "tlsCertificate": { + "certificateChain": { + "filename": "../../../test/key/ourdomain_server.cer" + }, + "privateKey": { + "filename": "../../../test/key/ourdomain_server.key" + } + } + }, + { + "name": "prometheus_validation_context", + "validationContext": { + "watchedDirectory": { + "path": "../../../test/ca_path" + } + } + } + ] + }, + "stats_config": { + "stats_tags": [ + { + "regex": "^cluster\\.(?:passthrough~)?((?:([^.]+)~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.custom_hash" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.service_subset" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.service" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.namespace" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.partition" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.datacenter" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.routing_type" + }, + { + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.([^.]+)\\.consul\\.)", + "tag_name": "consul.destination.trust_domain" + }, + { + "regex": "^cluster\\.(?:passthrough~)?(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.destination.target" + }, + { + "regex": "^cluster\\.(?:passthrough~)?(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+)\\.consul\\.)", + "tag_name": "consul.destination.full_target" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.(([^.]+)(?:\\.[^.]+)?(?:\\.[^.]+)?\\.[^.]+\\.)", + "tag_name": "consul.upstream.service" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.[^.]+)?(?:\\.[^.]+)?\\.([^.]+)\\.)", + "tag_name": "consul.upstream.datacenter" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.([^.]+))?(?:\\.[^.]+)?\\.[^.]+\\.)", + "tag_name": "consul.upstream.namespace" + }, + { + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.[^.]+)?(?:\\.([^.]+))?\\.[^.]+\\.)", + "tag_name": "consul.upstream.partition" + }, + { + "regex": "^cluster\\.((?:([^.]+)~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.custom_hash" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.service_subset" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.service" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.namespace" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.datacenter" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.[^.]+\\.consul\\.)", + "tag_name": "consul.routing_type" + }, + { + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.([^.]+)\\.consul\\.)", + "tag_name": "consul.trust_domain" + }, + { + "regex": "^cluster\\.(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)", + "tag_name": "consul.target" + }, + { + "regex": "^cluster\\.(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+)\\.consul\\.)", + "tag_name": "consul.full_target" + }, + { + "tag_name": "local_cluster", + "fixed_value": "test" + }, + { + "tag_name": "consul.source.service", + "fixed_value": "test" + }, + { + "tag_name": "consul.source.namespace", + "fixed_value": "default" + }, + { + "tag_name": "consul.source.partition", + "fixed_value": "default" + }, + { + "tag_name": "consul.source.datacenter", + "fixed_value": "dc1" + } + ], + "use_all_default_tags": true + }, + "dynamic_resources": { + "lds_config": { + "ads": {}, + "resource_api_version": "V3" + }, + "cds_config": { + "ads": {}, + "resource_api_version": "V3" + }, + "ads_config": { + "api_type": "DELTA_GRPC", + "transport_api_version": "V3", + "grpc_services": { + "initial_metadata": [ + { + "key": "x-consul-token", + "value": "" + } + ], + "envoy_grpc": { + "cluster_name": "local_agent" + } + } + } + } +} +