diff --git a/app/vmagent/README.md b/app/vmagent/README.md index 76233e19f8..f561102cbc 100644 --- a/app/vmagent/README.md +++ b/app/vmagent/README.md @@ -1012,6 +1012,9 @@ See the docs at https://docs.victoriametrics.com/vmagent.html . Supports an array of values separated by comma or specified via multiple flags. -remoteWrite.flushInterval duration Interval for flushing the data to remote storage. This option takes effect only when less than 10K data points per second are pushed to -remoteWrite.url (default 1s) + -remoteWrite.headers array + Optional HTTP headers to send with each request to -remoteWrite.url. For example, -remoteWrite.headers='My-Auth:foobar' would send 'My-Auth: foobar' HTTP header with every request to -remoteWrite.url. Multiple headers must be delimited by '^^': -remoteWrite.headers='header1:value1^^header2:value2' + Supports an array of values separated by comma or specified via multiple flags. -remoteWrite.label array Optional label in the form 'name=value' to add to all the metrics before sending them to -remoteWrite.url. Pass multiple -remoteWrite.label flags in order to add multiple labels to metrics before sending them to remote storage Supports an array of values separated by comma or specified via multiple flags. diff --git a/app/vmagent/remotewrite/client.go b/app/vmagent/remotewrite/client.go index d556f6cb34..4066501fdb 100644 --- a/app/vmagent/remotewrite/client.go +++ b/app/vmagent/remotewrite/client.go @@ -37,6 +37,10 @@ var ( tlsServerName = flagutil.NewArray("remoteWrite.tlsServerName", "Optional TLS server name to use for connections to -remoteWrite.url. "+ "By default the server name from -remoteWrite.url is used. If multiple args are set, then they are applied independently for the corresponding -remoteWrite.url") + headers = flagutil.NewArray("remoteWrite.headers", "Optional HTTP headers to send with each request to -remoteWrite.url. "+ + "For example, -remoteWrite.headers='My-Auth:foobar' would send 'My-Auth: foobar' HTTP header with every request to -remoteWrite.url. "+ + "Multiple headers must be delimited by '^^': -remoteWrite.headers='header1:value1^^header2:value2'") + basicAuthUsername = flagutil.NewArray("remoteWrite.basicAuth.username", "Optional basic auth username to use for -remoteWrite.url. "+ "If multiple args are set, then they are applied independently for the corresponding -remoteWrite.url") basicAuthPassword = flagutil.NewArray("remoteWrite.basicAuth.password", "Optional basic auth password to use for -remoteWrite.url. "+ @@ -183,6 +187,11 @@ func (c *client) MustStop() { } func getAuthConfig(argIdx int) (*promauth.Config, error) { + headersValue := headers.GetOptionalArg(argIdx) + var headers []string + if headersValue != "" { + headers = strings.Split(headersValue, "^^") + } username := basicAuthUsername.GetOptionalArg(argIdx) password := basicAuthPassword.GetOptionalArg(argIdx) passwordFile := basicAuthPasswordFile.GetOptionalArg(argIdx) @@ -219,7 +228,7 @@ func getAuthConfig(argIdx int) (*promauth.Config, error) { InsecureSkipVerify: tlsInsecureSkipVerify.GetOptionalArg(argIdx), } - authCfg, err := promauth.NewConfig(".", nil, basicAuthCfg, token, tokenFile, oauth2Cfg, tlsCfg, nil) + authCfg, err := promauth.NewConfig(".", nil, basicAuthCfg, token, tokenFile, oauth2Cfg, tlsCfg, headers) if err != nil { return nil, fmt.Errorf("cannot populate OAuth2 config for remoteWrite idx: %d, err: %w", argIdx, err) } @@ -301,12 +310,12 @@ again: if err != nil { logger.Panicf("BUG: unexpected error from http.NewRequest(%q): %s", c.sanitizedURL, err) } + c.authCfg.SetHeaders(req, true) h := req.Header h.Set("User-Agent", "vmagent") h.Set("Content-Type", "application/x-protobuf") h.Set("Content-Encoding", "snappy") h.Set("X-Prometheus-Remote-Write-Version", "0.1.0") - c.authCfg.SetHeaders(req, true) if c.awsCfg != nil { if err := c.awsCfg.SignRequest(req, sigv4Hash); err != nil { // there is no need in retry, request will be rejected by client.Do and retried by code below diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2b832847db..f472f1f7f2 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -20,6 +20,7 @@ If you use alerting rules or Grafana dashboards, which rely on this metric, then * FEATURE: add `-search.setLookbackToStep` command-line flag, which enables InfluxDB-like gap filling during querying. See [these docs](https://docs.victoriametrics.com/guides/migrate-from-influx.html) for details. * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add an UI for [query tracing](https://docs.victoriametrics.com/#query-tracing). It can be enabled by clicking `enable query tracing` checkbox and re-running the query. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2703). +* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): add `-remoteWrite.headers` command-line option for specifying optional HTTP headers to send to the configured `-remoteWrite.url`. For example, `-remoteWrite.headers='Foo:Bar^^Baz:x'` would send `Foo: Bar` and `Baz: x` HTTP headers with every request to `-remoteWrite.url`. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2805). * FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): add ability to specify additional HTTP headers to send to scrape targets via `headers` section in `scrape_configs`. This can be used when the scrape target requires custom authorization and authentication like in [this stackoverflow question](https://stackoverflow.com/questions/66032498/prometheus-scrape-metric-with-custom-header). For example, the following config instructs sending `My-Auth: top-secret` and `TenantID: FooBar` headers with each request to `http://host123:8080/metrics`: ```yaml diff --git a/docs/vmagent.md b/docs/vmagent.md index d6f27d2544..f816138f24 100644 --- a/docs/vmagent.md +++ b/docs/vmagent.md @@ -1016,6 +1016,9 @@ See the docs at https://docs.victoriametrics.com/vmagent.html . Supports an array of values separated by comma or specified via multiple flags. -remoteWrite.flushInterval duration Interval for flushing the data to remote storage. This option takes effect only when less than 10K data points per second are pushed to -remoteWrite.url (default 1s) + -remoteWrite.headers array + Optional HTTP headers to send with each request to -remoteWrite.url. For example, -remoteWrite.headers='My-Auth:foobar' would send 'My-Auth: foobar' HTTP header with every request to -remoteWrite.url. Multiple headers must be delimited by '^^': -remoteWrite.headers='header1:value1^^header2:value2' + Supports an array of values separated by comma or specified via multiple flags. -remoteWrite.label array Optional label in the form 'name=value' to add to all the metrics before sending them to -remoteWrite.url. Pass multiple -remoteWrite.label flags in order to add multiple labels to metrics before sending them to remote storage Supports an array of values separated by comma or specified via multiple flags. diff --git a/lib/promauth/config.go b/lib/promauth/config.go index 020f6af252..62a0efaf26 100644 --- a/lib/promauth/config.go +++ b/lib/promauth/config.go @@ -419,6 +419,8 @@ func (ba *BasicAuthConfig) NewConfig(baseDir string) (*Config, error) { } // NewConfig creates auth config from the given args. +// +// headers must be in the form 'HeaderName: header value' func NewConfig(baseDir string, az *Authorization, basicAuth *BasicAuthConfig, bearerToken, bearerTokenFile string, o *OAuth2Config, tlsConfig *TLSConfig, headers []string) (*Config, error) { var getAuthHeader func() string authDigest := ""