feat(http): Allow secrets in headers (#14743)
This commit is contained in:
parent
616ad305fe
commit
4f0ac6e155
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue