Skip to content

Commit

Permalink
libbeat/kibana: add ClientConfig.Headers (#20580)
Browse files Browse the repository at this point in the history
* libbeat/kibana: add ClientConfig.Headers

Add configurable headers to include in every
request sent to Kibana. This is needed in some
security applications, for authenticating the
Beat.

* Add setup.kibana.headers to config/docs

* libbeat/kibana: prevent overridding Content-Type

... and Accept, and kbn-xsrf
  • Loading branch information
axw authored Aug 20, 2020
1 parent 5f42d21 commit 38fc1ed
Show file tree
Hide file tree
Showing 18 changed files with 142 additions and 14 deletions.
4 changes: 4 additions & 0 deletions auditbeat/auditbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions filebeat/filebeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions heartbeat/heartbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions journalbeat/journalbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions libbeat/_meta/config/setup.kibana.reference.yml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
12 changes: 12 additions & 0 deletions libbeat/docs/shared-kibana-config.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
23 changes: 17 additions & 6 deletions libbeat/kibana/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Connection struct {
URL string
Username string
Password string
Headers http.Header

HTTP *http.Client
Version common.Version
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
20 changes: 12 additions & 8 deletions libbeat/kibana/client_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
45 changes: 45 additions & 0 deletions libbeat/kibana/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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"))

}
4 changes: 4 additions & 0 deletions metricbeat/metricbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions packetbeat/packetbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions winlogbeat/winlogbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions x-pack/auditbeat/auditbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions x-pack/filebeat/filebeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions x-pack/functionbeat/functionbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions x-pack/heartbeat/heartbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions x-pack/metricbeat/metricbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions x-pack/winlogbeat/winlogbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 38fc1ed

Please sign in to comment.