diff --git a/plugins/inputs/http/README.md b/plugins/inputs/http/README.md index c76043237..54153232f 100644 --- a/plugins/inputs/http/README.md +++ b/plugins/inputs/http/README.md @@ -17,8 +17,8 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. ## Secret-store support -This plugin supports secrets from secret-stores for the `username`, `password` -and `token` option. +This plugin supports secrets from secret-stores for the `username`, `password`, +`token` and `headers` option. See the [secret-store documentation][SECRETSTORE] for more details on how to use them. diff --git a/plugins/inputs/http/http.go b/plugins/inputs/http/http.go index 58cc93881..2c2024977 100644 --- a/plugins/inputs/http/http.go +++ b/plugins/inputs/http/http.go @@ -38,9 +38,9 @@ type HTTP struct { Token config.Secret `toml:"token"` TokenFile string `toml:"token_file"` - Headers map[string]string `toml:"headers"` - SuccessStatusCodes []int `toml:"success_status_codes"` - Log telegraf.Logger `toml:"-"` + Headers map[string]*config.Secret `toml:"headers"` + SuccessStatusCodes []int `toml:"success_status_codes"` + Log telegraf.Logger `toml:"-"` httpconfig.HTTPClientConfig @@ -142,11 +142,19 @@ func (h *HTTP) gatherURL(acc telegraf.Accumulator, url string) error { } for k, v := range h.Headers { - if strings.EqualFold(k, "host") { - request.Host = v - } else { - request.Header.Add(k, v) + secret, err := v.Get() + if err != nil { + return err } + + headerVal := secret.String() + if strings.EqualFold(k, "host") { + request.Host = headerVal + } else { + request.Header.Add(k, headerVal) + } + + secret.Destroy() } if err := h.setRequestAuth(request); err != nil { diff --git a/plugins/inputs/http/http_test.go b/plugins/inputs/http/http_test.go index c688c5c13..881aba9a1 100644 --- a/plugins/inputs/http/http_test.go +++ b/plugins/inputs/http/http_test.go @@ -3,6 +3,7 @@ package http_test import ( "compress/gzip" "fmt" + "github.com/influxdata/telegraf/config" "io" "math/rand" "net" @@ -82,9 +83,10 @@ func TestHTTPHeaders(t *testing.T) { defer fakeServer.Close() address := fakeServer.URL + "/endpoint" + headerSecret := config.NewSecret([]byte(headerValue)) plugin := &httpplugin.HTTP{ URLs: []string{address}, - Headers: map[string]string{header: headerValue}, + Headers: map[string]*config.Secret{header: &headerSecret}, Log: testutil.Logger{}, } @@ -116,7 +118,7 @@ func TestHTTPContentLengthHeader(t *testing.T) { address := fakeServer.URL + "/endpoint" plugin := &httpplugin.HTTP{ URLs: []string{address}, - Headers: map[string]string{}, + Headers: map[string]*config.Secret{}, Body: "{}", Log: testutil.Logger{}, } diff --git a/plugins/outputs/http/README.md b/plugins/outputs/http/README.md index ce1262b72..51812563e 100644 --- a/plugins/outputs/http/README.md +++ b/plugins/outputs/http/README.md @@ -15,8 +15,8 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. ## Secret-store support -This plugin supports secrets from secret-stores for the `username` and -`password` option. +This plugin supports secrets from secret-stores for the `username`, `password` +and `headers` option. See the [secret-store documentation][SECRETSTORE] for more details on how to use them. diff --git a/plugins/outputs/http/http.go b/plugins/outputs/http/http.go index 63c707103..a6cdb1a8a 100644 --- a/plugins/outputs/http/http.go +++ b/plugins/outputs/http/http.go @@ -43,15 +43,15 @@ const ( ) type HTTP struct { - URL string `toml:"url"` - Method string `toml:"method"` - Username config.Secret `toml:"username"` - Password config.Secret `toml:"password"` - Headers map[string]string `toml:"headers"` - ContentEncoding string `toml:"content_encoding"` - UseBatchFormat bool `toml:"use_batch_format"` - AwsService string `toml:"aws_service"` - NonRetryableStatusCodes []int `toml:"non_retryable_statuscodes"` + URL string `toml:"url"` + Method string `toml:"method"` + Username config.Secret `toml:"username"` + Password config.Secret `toml:"password"` + Headers map[string]*config.Secret `toml:"headers"` + ContentEncoding string `toml:"content_encoding"` + UseBatchFormat bool `toml:"use_batch_format"` + AwsService string `toml:"aws_service"` + NonRetryableStatusCodes []int `toml:"non_retryable_statuscodes"` httpconfig.HTTPClientConfig Log telegraf.Logger `toml:"-"` @@ -204,11 +204,20 @@ func (h *HTTP) writeMetric(reqBody []byte) error { if h.ContentEncoding == "gzip" { req.Header.Set("Content-Encoding", "gzip") } + for k, v := range h.Headers { - if strings.EqualFold(k, "host") { - req.Host = v + secret, err := v.Get() + if err != nil { + return err } - req.Header.Set(k, v) + + headerVal := secret.String() + if strings.EqualFold(k, "host") { + req.Host = headerVal + } + req.Header.Set(k, headerVal) + + secret.Destroy() } resp, err := h.client.Do(req) diff --git a/plugins/outputs/http/http_test.go b/plugins/outputs/http/http_test.go index 2a9e5903a..d903765e4 100644 --- a/plugins/outputs/http/http_test.go +++ b/plugins/outputs/http/http_test.go @@ -290,6 +290,7 @@ func TestContentType(t *testing.T) { u, err := url.Parse("http://" + ts.Listener.Addr().String()) require.NoError(t, err) + headerSecret := config.NewSecret([]byte("application/json")) tests := []struct { name string plugin *HTTP @@ -306,7 +307,7 @@ func TestContentType(t *testing.T) { name: "overwrite content_type", plugin: &HTTP{ URL: u.String(), - Headers: map[string]string{"Content-Type": "application/json"}, + Headers: map[string]*config.Secret{"Content-Type": &headerSecret}, }, expected: "application/json", },