From dde0fb71526c7fd7971c1748cc54e08c13043ecd Mon Sep 17 00:00:00 2001 From: itielo Date: Thu, 11 Jul 2024 08:16:14 +0300 Subject: [PATCH 1/3] Configuring httpSD http client from TAs clienthttp --- .../prometheusreceiver/metrics_receiver.go | 84 ++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/receiver/prometheusreceiver/metrics_receiver.go b/receiver/prometheusreceiver/metrics_receiver.go index 65dbd580ea11..2314fe50275c 100644 --- a/receiver/prometheusreceiver/metrics_receiver.go +++ b/receiver/prometheusreceiver/metrics_receiver.go @@ -6,6 +6,7 @@ package prometheusreceiver // import "github.com/open-telemetry/opentelemetry-co import ( "bytes" "context" + "encoding/base64" "errors" "fmt" "io" @@ -14,6 +15,7 @@ import ( "os" "reflect" "regexp" + "strings" "sync" "time" "unsafe" @@ -145,6 +147,80 @@ func (r *pReceiver) startTargetAllocator(allocConf *TargetAllocator, baseCfg *Pr return nil } +// ConvertTLSVersion converts a string TLS version to the corresponding config.TLSVersion value in prometheus common. +func convertTLSVersion(version string) (commonconfig.TLSVersion, error) { + normalizedVersion := "TLS" + strings.TrimPrefix(version, ".") + + if tlsVersion, exists := commonconfig.TLSVersions[normalizedVersion]; exists { + return tlsVersion, nil + } + return 0, fmt.Errorf("unsupported TLS version: %s", version) +} + +// configureSDHTTPClientConfig configures the http client for the service discovery manager +// based on the provided TargetAllocator configuration. +func configureSDHTTPClientConfigFromTA(httpSD *promHTTP.SDConfig, allocConf *TargetAllocator) error { + httpSD.HTTPClientConfig.FollowRedirects = false + + httpSD.HTTPClientConfig.TLSConfig = commonconfig.TLSConfig{ + InsecureSkipVerify: allocConf.TLSSetting.InsecureSkipVerify, + ServerName: allocConf.TLSSetting.ServerName, + CAFile: allocConf.TLSSetting.CAFile, + CertFile: allocConf.TLSSetting.CertFile, + KeyFile: allocConf.TLSSetting.KeyFile, + } + + if allocConf.TLSSetting.CAPem != "" { + decodedCA, err := base64.StdEncoding.DecodeString(string(allocConf.TLSSetting.CAPem)) + if err != nil { + return fmt.Errorf("failed to decode CA: %w", err) + } + httpSD.HTTPClientConfig.TLSConfig.CA = string(decodedCA) + } + + if allocConf.TLSSetting.CertPem != "" { + decodedCert, err := base64.StdEncoding.DecodeString(string(allocConf.TLSSetting.CertPem)) + if err != nil { + return fmt.Errorf("failed to decode Cert: %w", err) + } + httpSD.HTTPClientConfig.TLSConfig.Cert = string(decodedCert) + } + + if allocConf.TLSSetting.KeyPem != "" { + decodedKey, err := base64.StdEncoding.DecodeString(string(allocConf.TLSSetting.KeyPem)) + if err != nil { + return fmt.Errorf("failed to decode Key: %w", err) + } + httpSD.HTTPClientConfig.TLSConfig.Key = commonconfig.Secret(decodedKey) + } + + if allocConf.TLSSetting.MinVersion != "" { + minVersion, err := convertTLSVersion(allocConf.TLSSetting.MinVersion) + if err != nil { + return err + } + httpSD.HTTPClientConfig.TLSConfig.MinVersion = minVersion + } + + if allocConf.TLSSetting.MaxVersion != "" { + maxVersion, err := convertTLSVersion(allocConf.TLSSetting.MaxVersion) + if err != nil { + return err + } + httpSD.HTTPClientConfig.TLSConfig.MaxVersion = maxVersion + } + + if allocConf.ProxyURL != "" { + proxyURL, err := url.Parse(allocConf.ProxyURL) + if err != nil { + return err + } + httpSD.HTTPClientConfig.ProxyURL = commonconfig.URL{URL: proxyURL} + } + + return nil +} + // syncTargetAllocator request jobs from targetAllocator and update underlying receiver, if the response does not match the provided compareHash. // baseDiscoveryCfg can be used to provide additional ScrapeConfigs which will be added to the retrieved jobs. func (r *pReceiver) syncTargetAllocator(compareHash uint64, allocConf *TargetAllocator, baseCfg *PromConfig) (uint64, error) { @@ -179,7 +255,13 @@ func (r *pReceiver) syncTargetAllocator(compareHash uint64, allocConf *TargetAll } escapedJob := url.QueryEscape(jobName) httpSD.URL = fmt.Sprintf("%s/jobs/%s/targets?collector_id=%s", allocConf.Endpoint, escapedJob, allocConf.CollectorID) - httpSD.HTTPClientConfig.FollowRedirects = false + + err = configureSDHTTPClientConfigFromTA(&httpSD, allocConf) + if err != nil { + r.settings.Logger.Error("Failed to configure http client config", zap.Error(err)) + return 0, err + } + scrapeConfig.ServiceDiscoveryConfigs = discovery.Configs{ &httpSD, } From 7d46a801d452d72a9c0b085d051843d6af71e860 Mon Sep 17 00:00:00 2001 From: itielo Date: Thu, 11 Jul 2024 08:48:21 +0300 Subject: [PATCH 2/3] Fixed tls version convertion. Added tests --- .../prometheusreceiver/metrics_receiver.go | 2 +- .../metrics_receiver_test.go | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/receiver/prometheusreceiver/metrics_receiver.go b/receiver/prometheusreceiver/metrics_receiver.go index 2314fe50275c..a8205bef5519 100644 --- a/receiver/prometheusreceiver/metrics_receiver.go +++ b/receiver/prometheusreceiver/metrics_receiver.go @@ -149,7 +149,7 @@ func (r *pReceiver) startTargetAllocator(allocConf *TargetAllocator, baseCfg *Pr // ConvertTLSVersion converts a string TLS version to the corresponding config.TLSVersion value in prometheus common. func convertTLSVersion(version string) (commonconfig.TLSVersion, error) { - normalizedVersion := "TLS" + strings.TrimPrefix(version, ".") + normalizedVersion := "TLS" + strings.ReplaceAll(version, ".", "") if tlsVersion, exists := commonconfig.TLSVersions[normalizedVersion]; exists { return tlsVersion, nil diff --git a/receiver/prometheusreceiver/metrics_receiver_test.go b/receiver/prometheusreceiver/metrics_receiver_test.go index b0c1ed784ce1..fb9da9816cf7 100644 --- a/receiver/prometheusreceiver/metrics_receiver_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_test.go @@ -5,19 +5,25 @@ package prometheusreceiver import ( "context" + "encoding/base64" "fmt" "net/http" "net/http/httptest" + "net/url" "strings" "testing" "time" gokitlog "github.com/go-kit/log" + commonconfig "github.com/prometheus/common/config" "github.com/prometheus/common/model" promConfig "github.com/prometheus/prometheus/config" + promHTTP "github.com/prometheus/prometheus/discovery/http" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configopaque" + "go.opentelemetry.io/collector/config/configtls" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/receiver/receivertest" @@ -1640,3 +1646,51 @@ scrape_configs: require.Contains(t, gotUA, set.BuildInfo.Command) require.Contains(t, gotUA, set.BuildInfo.Version) } + +func TestConfigureSDHTTPClientConfigFromTA(t *testing.T) { + ta := &TargetAllocator{} + ta.TLSSetting = configtls.ClientConfig{ + InsecureSkipVerify: true, + ServerName: "test.server", + Config: configtls.Config{ + CAFile: "/path/to/ca", + CertFile: "/path/to/cert", + KeyFile: "/path/to/key", + CAPem: configopaque.String(base64.StdEncoding.EncodeToString([]byte("test-ca"))), + CertPem: configopaque.String(base64.StdEncoding.EncodeToString([]byte("test-cert"))), + KeyPem: configopaque.String(base64.StdEncoding.EncodeToString([]byte("test-key"))), + MinVersion: "1.2", + MaxVersion: "1.3", + }, + } + ta.ProxyURL = "http://proxy.test" + + httpSD := &promHTTP.SDConfig{RefreshInterval: model.Duration(30 * time.Second)} + + err := configureSDHTTPClientConfigFromTA(httpSD, ta) + + assert.NoError(t, err) + + assert.Equal(t, false, httpSD.HTTPClientConfig.FollowRedirects) + assert.Equal(t, true, httpSD.HTTPClientConfig.TLSConfig.InsecureSkipVerify) + assert.Equal(t, "test.server", httpSD.HTTPClientConfig.TLSConfig.ServerName) + assert.Equal(t, "/path/to/ca", httpSD.HTTPClientConfig.TLSConfig.CAFile) + assert.Equal(t, "/path/to/cert", httpSD.HTTPClientConfig.TLSConfig.CertFile) + assert.Equal(t, "/path/to/key", httpSD.HTTPClientConfig.TLSConfig.KeyFile) + assert.Equal(t, "test-ca", httpSD.HTTPClientConfig.TLSConfig.CA) + assert.Equal(t, "test-cert", httpSD.HTTPClientConfig.TLSConfig.Cert) + assert.Equal(t, commonconfig.Secret("test-key"), httpSD.HTTPClientConfig.TLSConfig.Key) + assert.Equal(t, commonconfig.TLSVersions["TLS12"], httpSD.HTTPClientConfig.TLSConfig.MinVersion) + assert.Equal(t, commonconfig.TLSVersions["TLS13"], httpSD.HTTPClientConfig.TLSConfig.MaxVersion) + + parsedProxyURL, _ := url.Parse("http://proxy.test") + assert.Equal(t, commonconfig.URL{URL: parsedProxyURL}, httpSD.HTTPClientConfig.ProxyURL) + + // Test case with empty TargetAllocator + emptyTA := &TargetAllocator{} + emptyHTTPSD := &promHTTP.SDConfig{RefreshInterval: model.Duration(30 * time.Second)} + + err = configureSDHTTPClientConfigFromTA(emptyHTTPSD, emptyTA) + + assert.NoError(t, err) +} From 9d8963842706b06e3119d23c838ca3b84a92c6cd Mon Sep 17 00:00:00 2001 From: itielo Date: Thu, 11 Jul 2024 09:10:25 +0300 Subject: [PATCH 3/3] Added changelog --- ...tpSD-client-config-from-TA-confighttp.yaml | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .chloggen/httpSD-client-config-from-TA-confighttp.yaml diff --git a/.chloggen/httpSD-client-config-from-TA-confighttp.yaml b/.chloggen/httpSD-client-config-from-TA-confighttp.yaml new file mode 100644 index 000000000000..dd247004c8c0 --- /dev/null +++ b/.chloggen/httpSD-client-config-from-TA-confighttp.yaml @@ -0,0 +1,28 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: prometheusreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Use confighttp for httpSD client config + + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [33370] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: []