Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.x](backport #28096) [Elastic Agent] Add ability to communicate with Kibana through service token #28349

Merged
merged 1 commit into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -194,12 +195,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,
},
}

Expand Down Expand Up @@ -264,6 +266,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