Skip to content

Commit

Permalink
[Elastic Agent] Add ability to communicate with Kibana through servic…
Browse files Browse the repository at this point in the history
…e token (elastic#28096)

* Add ability to communicate with Kibana through service token. Add ability to pass service token to container subcommand.

* Add changelog entry.

* Fix go fmt.
  • Loading branch information
blakerouse authored and wiwen committed Nov 1, 2021
1 parent 9742125 commit 2e6fc0d
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 36 deletions.
28 changes: 17 additions & 11 deletions libbeat/kibana/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ var (
)

type Connection struct {
URL string
Username string
Password string
APIKey string
Headers http.Header
URL string
Username string
Password string
APIKey string
ServiceToken string
Headers http.Header

HTTP *http.Client
Version common.Version
Expand Down Expand Up @@ -196,12 +197,13 @@ func NewClientWithConfigDefault(config *ClientConfig, defaultPort int, beatname

client := &Client{
Connection: Connection{
URL: kibanaURL,
Username: username,
Password: password,
APIKey: config.APIKey,
Headers: headers,
HTTP: rt,
URL: kibanaURL,
Username: username,
Password: password,
APIKey: config.APIKey,
ServiceToken: config.ServiceToken,
Headers: headers,
HTTP: rt,
},
log: log,
}
Expand Down Expand Up @@ -267,6 +269,10 @@ func (conn *Connection) SendWithContext(ctx context.Context, method, extraPath s
v := "ApiKey " + base64.StdEncoding.EncodeToString([]byte(conn.APIKey))
req.Header.Set("Authorization", v)
}
if conn.ServiceToken != "" {
v := "Bearer " + conn.ServiceToken
req.Header.Set("Authorization", v)
}

addHeaders(req.Header, conn.Headers)
addHeaders(req.Header, headers)
Expand Down
32 changes: 17 additions & 15 deletions libbeat/kibana/client_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ 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"`
APIKey string `config:"api_key" yaml:"api_key,omitempty"`
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"`
APIKey string `config:"api_key" yaml:"api_key,omitempty"`
ServiceToken string `config:"service_token" yaml:"service_token,omitempty"`

// Headers holds headers to include in every request sent to Kibana.
Headers map[string]string `config:"headers" yaml:"headers,omitempty"`
Expand All @@ -44,14 +45,15 @@ type ClientConfig struct {
// DefaultClientConfig connects to a locally running kibana over HTTP
func DefaultClientConfig() ClientConfig {
return ClientConfig{
Protocol: "http",
Host: "localhost:5601",
Path: "",
SpaceID: "",
Username: "",
Password: "",
APIKey: "",
Transport: httpcommon.DefaultHTTPTransportSettings(),
Protocol: "http",
Host: "localhost:5601",
Path: "",
SpaceID: "",
Username: "",
Password: "",
APIKey: "",
ServiceToken: "",
Transport: httpcommon.DefaultHTTPTransportSettings(),
}
}

Expand Down
6 changes: 6 additions & 0 deletions libbeat/kibana/client_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ func TestClientConfigValdiate(t *testing.T) {
APIKey: "api-key",
},
err: nil,
}, {
name: "service_token",
c: &ClientConfig{
ServiceToken: "service_token",
},
err: nil,
}, {
name: "username and api_key",
c: &ClientConfig{
Expand Down
20 changes: 20 additions & 0 deletions libbeat/kibana/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ func TestSuccess(t *testing.T) {
assert.NoError(t, err)
}

func TestServiceToken(t *testing.T) {
serviceToken := "fakeservicetoken"

kibanaTs := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{}`))

assert.Equal(t, "Bearer "+serviceToken, r.Header.Get("Authorization"))
}))
defer kibanaTs.Close()

conn := Connection{
URL: kibanaTs.URL,
HTTP: http.DefaultClient,
ServiceToken: serviceToken,
}
code, _, err := conn.Request(http.MethodPost, "", url.Values{}, http.Header{"foo": []string{"bar"}}, nil)
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) {
Expand Down
1 change: 1 addition & 0 deletions x-pack/elastic-agent/CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,4 @@
- Agent now adapts the beats queue size based on output settings. {issue}26638[26638] {pull}27429[27429]
- Support ephemeral containers in Kubernetes dynamic provider. {issue}27020[#27020] {pull}27707[27707]
- Add complete k8s metadata through composable provider. {pull}27691[27691]
- Add `KIBANA_FLEET_SERVICE_TOKEN` to Elastic Agent container. {pull}28096[28096]
1 change: 1 addition & 0 deletions x-pack/elastic-agent/pkg/agent/cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ func kibanaClient(cfg kibanaConfig, headers map[string]string) (*kibana.Client,
Host: cfg.Fleet.Host,
Username: cfg.Fleet.Username,
Password: cfg.Fleet.Password,
ServiceToken: cfg.Fleet.ServiceToken,
IgnoreVersion: true,
Transport: transport,
Headers: headers,
Expand Down
22 changes: 12 additions & 10 deletions x-pack/elastic-agent/pkg/agent/cmd/setup_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ type kibanaConfig struct {
}

type kibanaFleetConfig struct {
CA string `config:"ca"`
Host string `config:"host"`
Password string `config:"password"`
Setup bool `config:"setup"`
Username string `config:"username"`
CA string `config:"ca"`
Host string `config:"host"`
Password string `config:"password"`
Setup bool `config:"setup"`
Username string `config:"username"`
ServiceToken string `config:"service_token"`
}

func defaultAccessConfig() (setupConfig, error) {
Expand Down Expand Up @@ -104,11 +105,12 @@ func defaultAccessConfig() (setupConfig, error) {
// Remove FLEET_SETUP in 8.x
// The FLEET_SETUP environment variable boolean is a fallback to the old name. The name was updated to
// reflect that its setting up Fleet in Kibana versus setting up Fleet Server.
Setup: envBool("KIBANA_FLEET_SETUP", "FLEET_SETUP"),
Host: envWithDefault("http://kibana:5601", "KIBANA_FLEET_HOST", "KIBANA_HOST"),
Username: envWithDefault("elastic", "KIBANA_FLEET_USERNAME", "KIBANA_USERNAME", "ELASTICSEARCH_USERNAME"),
Password: envWithDefault("changeme", "KIBANA_FLEET_PASSWORD", "KIBANA_PASSWORD", "ELASTICSEARCH_PASSWORD"),
CA: envWithDefault("", "KIBANA_FLEET_CA", "KIBANA_CA", "ELASTICSEARCH_CA"),
Setup: envBool("KIBANA_FLEET_SETUP", "FLEET_SETUP"),
Host: envWithDefault("http://kibana:5601", "KIBANA_FLEET_HOST", "KIBANA_HOST"),
Username: envWithDefault("elastic", "KIBANA_FLEET_USERNAME", "KIBANA_USERNAME", "ELASTICSEARCH_USERNAME"),
Password: envWithDefault("changeme", "KIBANA_FLEET_PASSWORD", "KIBANA_PASSWORD", "ELASTICSEARCH_PASSWORD"),
ServiceToken: envWithDefault("", "KIBANA_FLEET_SERVICE_TOKEN", "FLEET_SERVER_SERVICE_TOKEN"),
CA: envWithDefault("", "KIBANA_FLEET_CA", "KIBANA_CA", "ELASTICSEARCH_CA"),
},
RetrySleepDuration: retrySleepDuration,
RetryMaxCount: retryMaxCount,
Expand Down

0 comments on commit 2e6fc0d

Please sign in to comment.