diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index e877dca9a052..4106abbbde72 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -1215,6 +1215,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index 4af4077896fb..b1c162387a74 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -1941,6 +1941,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index ea0580e28548..8950cbe8ada8 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -1368,6 +1368,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/journalbeat/journalbeat.reference.yml b/journalbeat/journalbeat.reference.yml index a823b45a3ea6..28e9ae522611 100644 --- a/journalbeat/journalbeat.reference.yml +++ b/journalbeat/journalbeat.reference.yml @@ -1157,6 +1157,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/libbeat/_meta/config/setup.kibana.reference.yml.tmpl b/libbeat/_meta/config/setup.kibana.reference.yml.tmpl index dd023ebd7e7d..6489909caaf1 100644 --- a/libbeat/_meta/config/setup.kibana.reference.yml.tmpl +++ b/libbeat/_meta/config/setup.kibana.reference.yml.tmpl @@ -21,4 +21,8 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + {{include "ssl.reference.yml.tmpl" . | indent 2 }} diff --git a/libbeat/docs/shared-kibana-config.asciidoc b/libbeat/docs/shared-kibana-config.asciidoc index e39fec570135..6cb3a1e9e29f 100644 --- a/libbeat/docs/shared-kibana-config.asciidoc +++ b/libbeat/docs/shared-kibana-config.asciidoc @@ -97,6 +97,18 @@ The {kibana-ref}/xpack-spaces.html[Kibana space] ID to use. If specified, {beatname_uc} loads Kibana assets into this Kibana space. Omit this option to use the default space. +[float] +===== `setup.kibana.headers` + +Custom HTTP headers to add to each request sent to Kibana. +Example: + +[source,yaml] +------------------------------------------------------------------------------ +setup.kibana.headers: + X-My-Header: Header contents +------------------------------------------------------------------------------ + [float] ==== `setup.kibana.ssl.enabled` diff --git a/libbeat/kibana/client.go b/libbeat/kibana/client.go index d2e30ed5f2ab..3b951ee5e345 100644 --- a/libbeat/kibana/client.go +++ b/libbeat/kibana/client.go @@ -41,6 +41,7 @@ type Connection struct { URL string Username string Password string + Headers http.Header HTTP *http.Client Version common.Version @@ -132,11 +133,17 @@ func NewClientWithConfig(config *ClientConfig) (*Client, error) { return nil, err } + headers := make(http.Header) + for k, v := range config.Headers { + headers.Set(k, v) + } + client := &Client{ Connection: Connection{ URL: kibanaURL, Username: username, Password: password, + Headers: headers, HTTP: &http.Client{ Transport: &http.Transport{ Dial: dialer.Dial, @@ -203,17 +210,21 @@ func (conn *Connection) SendWithContext(ctx context.Context, method, extraPath s req.SetBasicAuth(conn.Username, conn.Password) } + addHeaders(req.Header, conn.Headers) + addHeaders(req.Header, headers) req.Header.Set("Content-Type", "application/json") - req.Header.Add("Accept", "application/json") + req.Header.Set("Accept", "application/json") req.Header.Set("kbn-xsrf", "1") - for header, values := range headers { - for _, value := range values { - req.Header.Add(header, value) + return conn.RoundTrip(req) +} + +func addHeaders(out, in http.Header) { + for k, vs := range in { + for _, v := range vs { + out.Add(k, v) } } - - return conn.RoundTrip(req) } // Implements RoundTrip interface diff --git a/libbeat/kibana/client_config.go b/libbeat/kibana/client_config.go index 07897b9fad9a..09709e3d81d1 100644 --- a/libbeat/kibana/client_config.go +++ b/libbeat/kibana/client_config.go @@ -25,14 +25,18 @@ import ( // ClientConfig to connect to Kibana type ClientConfig struct { - Protocol string `config:"protocol" yaml:"protocol,omitempty"` - Host string `config:"host" yaml:"host,omitempty"` - Path string `config:"path" yaml:"path,omitempty"` - SpaceID string `config:"space.id" yaml:"space.id,omitempty"` - Username string `config:"username" yaml:"username,omitempty"` - Password string `config:"password" yaml:"password,omitempty"` - TLS *tlscommon.Config `config:"ssl" yaml:"ssl"` - Timeout time.Duration `config:"timeout" yaml:"timeout"` + Protocol string `config:"protocol" yaml:"protocol,omitempty"` + Host string `config:"host" yaml:"host,omitempty"` + Path string `config:"path" yaml:"path,omitempty"` + SpaceID string `config:"space.id" yaml:"space.id,omitempty"` + Username string `config:"username" yaml:"username,omitempty"` + Password string `config:"password" yaml:"password,omitempty"` + TLS *tlscommon.Config `config:"ssl" yaml:"ssl"` + Timeout time.Duration `config:"timeout" yaml:"timeout"` + + // Headers holds headers to include in every request sent to Kibana. + Headers map[string]string `config:"headers" yaml:"headers,omitempty"` + IgnoreVersion bool } diff --git a/libbeat/kibana/client_test.go b/libbeat/kibana/client_test.go index 00d736e60d66..ac5b9cff7e26 100644 --- a/libbeat/kibana/client_test.go +++ b/libbeat/kibana/client_test.go @@ -18,12 +18,16 @@ package kibana import ( + "fmt" "net/http" "net/http/httptest" "net/url" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/elastic/beats/v7/libbeat/common" ) func TestErrorJson(t *testing.T) { @@ -74,3 +78,44 @@ func TestSuccess(t *testing.T) { assert.Equal(t, http.StatusOK, code) assert.NoError(t, err) } + +func TestNewKibanaClient(t *testing.T) { + var requests []*http.Request + kibanaTs := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requests = append(requests, r) + if r.URL.Path == "/api/status" { + w.Write([]byte(`{"version":{"number":"1.2.3-beta","build_snapshot":true}}`)) + } + })) + defer kibanaTs.Close() + + client, err := NewKibanaClient(common.MustNewConfigFrom(fmt.Sprintf(` +protocol: http +host: %s +headers: + key: value + content-type: text/plain + accept: text/plain + kbn-xsrf: 0 +`, kibanaTs.Listener.Addr().String()))) + require.NoError(t, err) + require.NotNil(t, client) + + client.Request(http.MethodPost, "/foo", url.Values{}, http.Header{"key": []string{"another_value"}}, nil) + + // NewKibanaClient issues a request to /api/status to fetch the version. + require.Len(t, requests, 2) + assert.Equal(t, "/api/status", requests[0].URL.Path) + assert.Equal(t, []string{"value"}, requests[0].Header.Values("key")) + assert.Equal(t, "1.2.3-beta-SNAPSHOT", client.Version.String()) + + // Headers specified in cient.Request are added to those defined in config. + // + // Content-Type, Accept, and kbn-xsrf cannot be overridden. + assert.Equal(t, "/foo", requests[1].URL.Path) + assert.Equal(t, []string{"value", "another_value"}, requests[1].Header.Values("key")) + assert.Equal(t, []string{"application/json"}, requests[1].Header.Values("Content-Type")) + assert.Equal(t, []string{"application/json"}, requests[1].Header.Values("Accept")) + assert.Equal(t, []string{"1"}, requests[1].Header.Values("kbn-xsrf")) + +} diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index a4dd0c97f55b..d8a64676957d 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -1980,6 +1980,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 371770c13d2e..c2c9ae159995 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -1641,6 +1641,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index a16a600e3059..0a3ee7802036 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -1137,6 +1137,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/x-pack/auditbeat/auditbeat.reference.yml b/x-pack/auditbeat/auditbeat.reference.yml index 21a705968b22..9bb0450f0fae 100644 --- a/x-pack/auditbeat/auditbeat.reference.yml +++ b/x-pack/auditbeat/auditbeat.reference.yml @@ -1271,6 +1271,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/x-pack/filebeat/filebeat.reference.yml b/x-pack/filebeat/filebeat.reference.yml index 5d0ecd9ee325..d6d7176e22a4 100644 --- a/x-pack/filebeat/filebeat.reference.yml +++ b/x-pack/filebeat/filebeat.reference.yml @@ -3187,6 +3187,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/x-pack/functionbeat/functionbeat.reference.yml b/x-pack/functionbeat/functionbeat.reference.yml index e8255bd2824c..c613458c9d78 100644 --- a/x-pack/functionbeat/functionbeat.reference.yml +++ b/x-pack/functionbeat/functionbeat.reference.yml @@ -1130,6 +1130,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/x-pack/heartbeat/heartbeat.reference.yml b/x-pack/heartbeat/heartbeat.reference.yml index ea0580e28548..8950cbe8ada8 100644 --- a/x-pack/heartbeat/heartbeat.reference.yml +++ b/x-pack/heartbeat/heartbeat.reference.yml @@ -1368,6 +1368,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index 4efdcaf2f2bd..f1c48539b1db 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -2443,6 +2443,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true diff --git a/x-pack/winlogbeat/winlogbeat.reference.yml b/x-pack/winlogbeat/winlogbeat.reference.yml index c452c1729fce..3f40bccbece7 100644 --- a/x-pack/winlogbeat/winlogbeat.reference.yml +++ b/x-pack/winlogbeat/winlogbeat.reference.yml @@ -1180,6 +1180,10 @@ setup.kibana: # Optional Kibana space ID. #space.id: "" + # Custom HTTP headers to add to each request + #headers: + # X-My-Header: Contents of the header + # Use SSL settings for HTTPS. #ssl.enabled: true