From c1160e3ca099c2479ee289f169e433a8c1cd8d00 Mon Sep 17 00:00:00 2001 From: Chris Mark Date: Wed, 29 Apr 2020 12:31:50 +0300 Subject: [PATCH] Enable keystore for autodiscover static configuration (#16306) --- CHANGELOG.next.asciidoc | 1 + filebeat/autodiscover/builder/hints/logs.go | 4 +- filebeat/beater/filebeat.go | 1 + .../autodiscover/builder/hints/monitors.go | 4 +- heartbeat/beater/heartbeat.go | 13 ++- .../autodiscover/appenders/config/config.go | 2 +- libbeat/autodiscover/autodiscover.go | 13 +-- libbeat/autodiscover/autodiscover_test.go | 19 ++-- libbeat/autodiscover/provider.go | 7 +- .../autodiscover/providers/docker/docker.go | 7 +- .../docker/docker_integration_test.go | 9 +- .../autodiscover/providers/jolokia/jolokia.go | 7 +- .../providers/kubernetes/kubernetes.go | 7 +- .../providers/kubernetes/node_test.go | 5 + .../providers/kubernetes/pod_test.go | 6 + .../providers/kubernetes/service_test.go | 5 + libbeat/autodiscover/template/config.go | 18 ++- libbeat/autodiscover/template/config_test.go | 87 +++++++++++++++ libbeat/beat/beat.go | 3 + libbeat/cmd/instance/beat.go | 1 + libbeat/docs/shared-autodiscover.asciidoc | 6 + .../autodiscover/builder/hints/metrics.go | 5 +- .../builder/hints/metrics_test.go | 104 ++++++++++++++++++ metricbeat/beater/metricbeat.go | 7 +- .../docs/autodiscover-docker-config.asciidoc | 21 ++++ metricbeat/docs/autodiscover-hints.asciidoc | 4 +- .../autodiscover-kubernetes-config.asciidoc | 21 ++++ .../providers/aws/ec2/provider.go | 9 +- .../providers/aws/ec2/provider_test.go | 4 +- .../providers/aws/elb/provider.go | 9 +- .../providers/aws/elb/provider_test.go | 4 +- 31 files changed, 367 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index b9de5ff716af..bcb358e8ef16 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -204,6 +204,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Add optional regex based cid extractor to `add_kubernetes_metadata` processor. {pull}17360[17360] - Add `urldecode` processor to for decoding URL-encoded fields. {pull}17505[17505] - Add support for AWS IAM `role_arn` in credentials config. {pull}17658[17658] {issue}12464[12464] +- Add keystore support for autodiscover static configurations. {pull]16306[16306] - Add Kerberos support to Elasticsearch output. {pull}17927[17927] *Auditbeat* diff --git a/filebeat/autodiscover/builder/hints/logs.go b/filebeat/autodiscover/builder/hints/logs.go index 05ec4ac7b8fe..e2f37caee74e 100644 --- a/filebeat/autodiscover/builder/hints/logs.go +++ b/filebeat/autodiscover/builder/hints/logs.go @@ -109,7 +109,7 @@ func (l *logHints) CreateConfig(event bus.Event) []*common.Config { } logp.Debug("hints.builder", "generated config %+v", configs) // Apply information in event to the template to generate the final config - return template.ApplyConfigTemplate(event, configs) + return template.ApplyConfigTemplate(event, configs, false) } tempCfg := common.MapStr{} @@ -163,7 +163,7 @@ func (l *logHints) CreateConfig(event bus.Event) []*common.Config { logp.Debug("hints.builder", "generated config %+v", config) // Apply information in event to the template to generate the final config - return template.ApplyConfigTemplate(event, []*common.Config{config}) + return template.ApplyConfigTemplate(event, []*common.Config{config}, false) } func (l *logHints) getMultiline(hints common.MapStr) common.MapStr { diff --git a/filebeat/beater/filebeat.go b/filebeat/beater/filebeat.go index c339c0a6cc0d..b16dad08895c 100644 --- a/filebeat/beater/filebeat.go +++ b/filebeat/beater/filebeat.go @@ -317,6 +317,7 @@ func (fb *Filebeat) Run(b *beat.Beat) error { ), autodiscover.QueryConfig(), config.Autodiscover, + b.Keystore, ) if err != nil { return err diff --git a/heartbeat/autodiscover/builder/hints/monitors.go b/heartbeat/autodiscover/builder/hints/monitors.go index ba89d81b4563..836b5a9326c5 100644 --- a/heartbeat/autodiscover/builder/hints/monitors.go +++ b/heartbeat/autodiscover/builder/hints/monitors.go @@ -91,7 +91,7 @@ func (hb *heartbeatHints) CreateConfig(event bus.Event) []*common.Config { } hb.logger.Debugf("generated config %+v", configs) // Apply information in event to the template to generate the final config - return template.ApplyConfigTemplate(event, configs) + return template.ApplyConfigTemplate(event, configs, false) } tempCfg := common.MapStr{} @@ -121,7 +121,7 @@ func (hb *heartbeatHints) CreateConfig(event bus.Event) []*common.Config { } // Apply information in event to the template to generate the final config - return template.ApplyConfigTemplate(event, configs) + return template.ApplyConfigTemplate(event, configs, false) } func (hb *heartbeatHints) getType(hints common.MapStr) common.MapStr { diff --git a/heartbeat/beater/heartbeat.go b/heartbeat/beater/heartbeat.go index dbdfe1dd740f..1ad682fc4962 100644 --- a/heartbeat/beater/heartbeat.go +++ b/heartbeat/beater/heartbeat.go @@ -156,7 +156,18 @@ func (bt *Heartbeat) RunReloadableMonitors(b *beat.Beat) (err error) { // makeAutodiscover creates an autodiscover object ready to be started. func (bt *Heartbeat) makeAutodiscover(b *beat.Beat) (*autodiscover.Autodiscover, error) { - return autodiscover.NewAutodiscover("heartbeat", b.Publisher, bt.dynamicFactory, autodiscover.QueryConfig(), bt.config.Autodiscover) + autodiscover, err := autodiscover.NewAutodiscover( + "heartbeat", + b.Publisher, + bt.dynamicFactory, + autodiscover.QueryConfig(), + bt.config.Autodiscover, + b.Keystore, + ) + if err != nil { + return nil, err + } + return autodiscover, nil } // Stop stops the beat. diff --git a/libbeat/autodiscover/appenders/config/config.go b/libbeat/autodiscover/appenders/config/config.go index 018ee1b587d8..60f8a543f4a0 100644 --- a/libbeat/autodiscover/appenders/config/config.go +++ b/libbeat/autodiscover/appenders/config/config.go @@ -104,7 +104,7 @@ func (c *configAppender) Append(event bus.Event) { } // Apply the template - template.ApplyConfigTemplate(event, cfgs) + template.ApplyConfigTemplate(event, cfgs, false) } // Replace old config with newly appended configs diff --git a/libbeat/autodiscover/autodiscover.go b/libbeat/autodiscover/autodiscover.go index c4941c4b176f..668a350b865c 100644 --- a/libbeat/autodiscover/autodiscover.go +++ b/libbeat/autodiscover/autodiscover.go @@ -29,6 +29,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/reload" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -72,6 +73,7 @@ func NewAutodiscover( factory cfgfile.RunnerFactory, configurer EventConfigurer, config *Config, + keystore keystore.Keystore, ) (*Autodiscover, error) { logger := logp.NewLogger("autodiscover") @@ -81,7 +83,7 @@ func NewAutodiscover( // Init providers var providers []Provider for _, providerCfg := range config.Providers { - provider, err := Registry.BuildProvider(bus, providerCfg) + provider, err := Registry.BuildProvider(bus, providerCfg, keystore) if err != nil { return nil, errors.Wrap(err, "error in autodiscover provider settings") } @@ -191,10 +193,7 @@ func (a *Autodiscover) handleStart(event bus.Event) bool { if a.logger.IsDebug() { for _, c := range configs { - rc := map[string]interface{}{} - c.Unpack(&rc) - - a.logger.Debugf("Generated config: %+v", rc) + a.logger.Debugf("Generated config: %+v", common.DebugString(c, true)) } } @@ -202,7 +201,7 @@ func (a *Autodiscover) handleStart(event bus.Event) bool { for _, config := range configs { hash, err := cfgfile.HashConfig(config) if err != nil { - a.logger.Debugf("Could not hash config %v: %v", config, err) + a.logger.Debugf("Could not hash config %v: %v", common.DebugString(config, true), err) continue } @@ -216,7 +215,7 @@ func (a *Autodiscover) handleStart(event bus.Event) bool { dynFields := a.meta.Store(hash, meta) if a.configs[eventID][hash] != nil { - a.logger.Debugf("Config %v is already running", config) + a.logger.Debugf("Config %v is already running", common.DebugString(config, true)) continue } diff --git a/libbeat/autodiscover/autodiscover_test.go b/libbeat/autodiscover/autodiscover_test.go index 182cd99f3cb5..23a3fe14da32 100644 --- a/libbeat/autodiscover/autodiscover_test.go +++ b/libbeat/autodiscover/autodiscover_test.go @@ -30,6 +30,7 @@ import ( "github.com/elastic/beats/v7/libbeat/cfgfile" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/tests/resources" ) @@ -142,7 +143,7 @@ func TestAutodiscover(t *testing.T) { // Register mock autodiscover provider busChan := make(chan bus.Bus, 1) Registry = NewRegistry() - Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config) (Provider, error) { + Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { // intercept bus to mock events busChan <- b @@ -164,9 +165,9 @@ func TestAutodiscover(t *testing.T) { config := Config{ Providers: []*common.Config{providerConfig}, } - + k, _ := keystore.NewFileKeystore("test") // Create autodiscover manager - autodiscover, err := NewAutodiscover("test", nil, &adapter, &adapter, &config) + autodiscover, err := NewAutodiscover("test", nil, &adapter, &adapter, &config, k) if err != nil { t.Fatal(err) } @@ -266,7 +267,7 @@ func TestAutodiscoverHash(t *testing.T) { busChan := make(chan bus.Bus, 1) Registry = NewRegistry() - Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config) (Provider, error) { + Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { // intercept bus to mock events busChan <- b @@ -291,9 +292,9 @@ func TestAutodiscoverHash(t *testing.T) { config := Config{ Providers: []*common.Config{providerConfig}, } - + k, _ := keystore.NewFileKeystore("test") // Create autodiscover manager - autodiscover, err := NewAutodiscover("test", nil, &adapter, &adapter, &config) + autodiscover, err := NewAutodiscover("test", nil, &adapter, &adapter, &config, k) if err != nil { t.Fatal(err) } @@ -332,7 +333,7 @@ func TestAutodiscoverWithConfigCheckFailures(t *testing.T) { // Register mock autodiscover provider busChan := make(chan bus.Bus, 1) Registry = NewRegistry() - Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config) (Provider, error) { + Registry.AddProvider("mock", func(b bus.Bus, uuid uuid.UUID, c *common.Config, k keystore.Keystore) (Provider, error) { // intercept bus to mock events busChan <- b @@ -357,9 +358,9 @@ func TestAutodiscoverWithConfigCheckFailures(t *testing.T) { config := Config{ Providers: []*common.Config{providerConfig}, } - + k, _ := keystore.NewFileKeystore("test") // Create autodiscover manager - autodiscover, err := NewAutodiscover("test", nil, &adapter, &adapter, &config) + autodiscover, err := NewAutodiscover("test", nil, &adapter, &adapter, &config, k) if err != nil { t.Fatal(err) } diff --git a/libbeat/autodiscover/provider.go b/libbeat/autodiscover/provider.go index f7bfefc69d05..510e09ab4bf4 100644 --- a/libbeat/autodiscover/provider.go +++ b/libbeat/autodiscover/provider.go @@ -26,6 +26,7 @@ import ( "github.com/elastic/beats/v7/libbeat/cfgfile" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" ) // Provider for autodiscover @@ -34,7 +35,7 @@ type Provider interface { } // ProviderBuilder creates a new provider based on the given config and returns it -type ProviderBuilder func(bus.Bus, uuid.UUID, *common.Config) (Provider, error) +type ProviderBuilder func(bus.Bus, uuid.UUID, *common.Config, keystore.Keystore) (Provider, error) // AddProvider registers a new ProviderBuilder func (r *registry) AddProvider(name string, provider ProviderBuilder) error { @@ -69,7 +70,7 @@ func (r *registry) GetProvider(name string) ProviderBuilder { } // BuildProvider reads provider configuration and instantiate one -func (r *registry) BuildProvider(bus bus.Bus, c *common.Config) (Provider, error) { +func (r *registry) BuildProvider(bus bus.Bus, c *common.Config, keystore keystore.Keystore) (Provider, error) { var config ProviderConfig err := c.Unpack(&config) if err != nil { @@ -86,5 +87,5 @@ func (r *registry) BuildProvider(bus bus.Bus, c *common.Config) (Provider, error return nil, err } - return builder(bus, uuid, c) + return builder(bus, uuid, c, keystore) } diff --git a/libbeat/autodiscover/providers/docker/docker.go b/libbeat/autodiscover/providers/docker/docker.go index 42a551ebf728..9bfa13000b1b 100644 --- a/libbeat/autodiscover/providers/docker/docker.go +++ b/libbeat/autodiscover/providers/docker/docker.go @@ -33,6 +33,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/docker" "github.com/elastic/beats/v7/libbeat/common/safemapstr" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -55,10 +56,11 @@ type Provider struct { stoppers map[string]*time.Timer stopTrigger chan *dockerContainerMetadata logger *logp.Logger + keystore keystore.Keystore } // AutodiscoverBuilder builds and returns an autodiscover provider -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodiscover.Provider, error) { +func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { logger := logp.NewLogger("docker") errWrap := func(err error) error { @@ -115,6 +117,7 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodis stoppers: make(map[string]*time.Timer), stopTrigger: make(chan *dockerContainerMetadata), logger: logger, + keystore: keystore, }, nil } @@ -303,6 +306,8 @@ func (d *Provider) emitContainer(container *docker.Container, meta *dockerMetada } func (d *Provider) publish(event bus.Event) { + // attach keystore to the event to be consumed by the static configs + event["keystore"] = d.keystore // Try to match a config if config := d.templates.GetConfig(event); config != nil { event["config"] = config diff --git a/libbeat/autodiscover/providers/docker/docker_integration_test.go b/libbeat/autodiscover/providers/docker/docker_integration_test.go index b8afbafbb62b..0e10af438ff8 100644 --- a/libbeat/autodiscover/providers/docker/docker_integration_test.go +++ b/libbeat/autodiscover/providers/docker/docker_integration_test.go @@ -23,14 +23,14 @@ import ( "testing" "time" - "github.com/elastic/beats/v7/libbeat/autodiscover/template" - "github.com/elastic/beats/v7/libbeat/logp" - "github.com/gofrs/uuid" "github.com/stretchr/testify/assert" + "github.com/elastic/beats/v7/libbeat/autodiscover/template" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" + "github.com/elastic/beats/v7/libbeat/logp" dk "github.com/elastic/beats/v7/libbeat/tests/docker" ) @@ -53,7 +53,8 @@ func TestDockerStart(t *testing.T) { s := &template.MapperSettings{nil, nil} config.Templates = *s - provider, err := AutodiscoverBuilder(bus, UUID, common.MustNewConfigFrom(config)) + k, _ := keystore.NewFileKeystore("test") + provider, err := AutodiscoverBuilder(bus, UUID, common.MustNewConfigFrom(config), k) if err != nil { t.Fatal(err) } diff --git a/libbeat/autodiscover/providers/jolokia/jolokia.go b/libbeat/autodiscover/providers/jolokia/jolokia.go index b370d747b893..4a18ffffec9d 100644 --- a/libbeat/autodiscover/providers/jolokia/jolokia.go +++ b/libbeat/autodiscover/providers/jolokia/jolokia.go @@ -27,6 +27,7 @@ import ( "github.com/elastic/beats/v7/libbeat/autodiscover/template" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" ) func init() { @@ -48,11 +49,12 @@ type Provider struct { appenders autodiscover.Appenders templates template.Mapper discovery DiscoveryProber + keystore keystore.Keystore } // AutodiscoverBuilder builds a Jolokia Discovery autodiscover provider, it fails if // there is some problem with the configuration -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodiscover.Provider, error) { +func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { errWrap := func(err error) error { return errors.Wrap(err, "error setting up jolokia autodiscover provider") } @@ -92,6 +94,7 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodis builders: builders, appenders: appenders, discovery: discovery, + keystore: keystore, }, nil } @@ -106,6 +109,8 @@ func (p *Provider) Start() { } func (p *Provider) publish(event bus.Event) { + // attach keystore to the event to be consumed by the static configs + event["keystore"] = p.keystore if config := p.templates.GetConfig(event); config != nil { event["config"] = config } else if config := p.builders.GetConfig(event); config != nil { diff --git a/libbeat/autodiscover/providers/kubernetes/kubernetes.go b/libbeat/autodiscover/providers/kubernetes/kubernetes.go index ec3480fa00b7..4a4a4566f8e6 100644 --- a/libbeat/autodiscover/providers/kubernetes/kubernetes.go +++ b/libbeat/autodiscover/providers/kubernetes/kubernetes.go @@ -30,6 +30,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/kubernetes" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -54,10 +55,11 @@ type Provider struct { appenders autodiscover.Appenders logger *logp.Logger eventer Eventer + keystore keystore.Keystore } // AutodiscoverBuilder builds and returns an autodiscover provider -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodiscover.Provider, error) { +func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { logger := logp.NewLogger("autodiscover") errWrap := func(err error) error { @@ -97,6 +99,7 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodis builders: builders, appenders: appenders, logger: logger, + keystore: keystore, } switch config.Resource { @@ -135,6 +138,8 @@ func (p *Provider) String() string { } func (p *Provider) publish(event bus.Event) { + // attach keystore to the event to be consumed by the static configs + event["keystore"] = p.keystore // Try to match a config if config := p.templates.GetConfig(event); config != nil { event["config"] = config diff --git a/libbeat/autodiscover/providers/kubernetes/node_test.go b/libbeat/autodiscover/providers/kubernetes/node_test.go index 0685adfe1bdd..f2fbe78dba6e 100644 --- a/libbeat/autodiscover/providers/kubernetes/node_test.go +++ b/libbeat/autodiscover/providers/kubernetes/node_test.go @@ -33,6 +33,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/kubernetes" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -112,6 +113,7 @@ func TestGenerateHints_Node(t *testing.T) { } func TestEmitEvent_Node(t *testing.T) { + k, _ := keystore.NewFileKeystore("test") name := "metricbeat" nodeIP := "192.168.0.1" uid := "005f3b90-4b9d-12f8-acf0-31020a840133" @@ -160,6 +162,7 @@ func TestEmitEvent_Node(t *testing.T) { "host": "192.168.0.1", "id": uid, "provider": UUID, + "keystore": k, "kubernetes": common.MapStr{ "node": common.MapStr{ "name": "metricbeat", @@ -219,6 +222,7 @@ func TestEmitEvent_Node(t *testing.T) { "host": "", "id": uid, "provider": UUID, + "keystore": k, "kubernetes": common.MapStr{ "node": common.MapStr{ "name": "metricbeat", @@ -252,6 +256,7 @@ func TestEmitEvent_Node(t *testing.T) { bus: bus.New(logp.NewLogger("bus"), "test"), templates: mapper, logger: logp.NewLogger("kubernetes"), + keystore: k, } no := &node{ diff --git a/libbeat/autodiscover/providers/kubernetes/pod_test.go b/libbeat/autodiscover/providers/kubernetes/pod_test.go index f63dbdf1e734..05b50987b2e8 100644 --- a/libbeat/autodiscover/providers/kubernetes/pod_test.go +++ b/libbeat/autodiscover/providers/kubernetes/pod_test.go @@ -33,6 +33,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/kubernetes" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -332,6 +333,7 @@ func TestGenerateHints(t *testing.T) { } func TestEmitEvent(t *testing.T) { + k, _ := keystore.NewFileKeystore("test") name := "filebeat" namespace := "default" podIP := "127.0.0.1" @@ -395,6 +397,7 @@ func TestEmitEvent(t *testing.T) { "host": "127.0.0.1", "id": cid, "provider": UUID, + "keystore": k, "kubernetes": common.MapStr{ "container": common.MapStr{ "id": "foobar", @@ -527,6 +530,7 @@ func TestEmitEvent(t *testing.T) { "host": "", "id": cid, "provider": UUID, + "keystore": k, "kubernetes": common.MapStr{ "container": common.MapStr{ "id": "", @@ -596,6 +600,7 @@ func TestEmitEvent(t *testing.T) { "host": "127.0.0.1", "id": cid, "provider": UUID, + "keystore": k, "kubernetes": common.MapStr{ "container": common.MapStr{ "id": "", @@ -645,6 +650,7 @@ func TestEmitEvent(t *testing.T) { bus: bus.New(logp.NewLogger("bus"), "test"), templates: mapper, logger: logp.NewLogger("kubernetes"), + keystore: k, } pod := &pod{ diff --git a/libbeat/autodiscover/providers/kubernetes/service_test.go b/libbeat/autodiscover/providers/kubernetes/service_test.go index 6d6582b3ff2d..0e3c8ddb0a83 100644 --- a/libbeat/autodiscover/providers/kubernetes/service_test.go +++ b/libbeat/autodiscover/providers/kubernetes/service_test.go @@ -33,6 +33,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/kubernetes" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" ) @@ -233,6 +234,7 @@ func TestGenerateHints_Service(t *testing.T) { } func TestEmitEvent_Service(t *testing.T) { + k, _ := keystore.NewFileKeystore("test") name := "metricbeat" namespace := "default" clusterIP := "192.168.0.1" @@ -280,6 +282,7 @@ func TestEmitEvent_Service(t *testing.T) { "host": "192.168.0.1", "id": uid, "provider": UUID, + "keystore": k, "port": 8080, "kubernetes": common.MapStr{ "service": common.MapStr{ @@ -369,6 +372,7 @@ func TestEmitEvent_Service(t *testing.T) { "id": uid, "port": 8080, "provider": UUID, + "keystore": k, "kubernetes": common.MapStr{ "service": common.MapStr{ "name": "metricbeat", @@ -405,6 +409,7 @@ func TestEmitEvent_Service(t *testing.T) { bus: bus.New(logp.NewLogger("bus"), "test"), templates: mapper, logger: logp.NewLogger("kubernetes"), + keystore: k, } service := &service{ diff --git a/libbeat/autodiscover/template/config.go b/libbeat/autodiscover/template/config.go index 151f76dde0f3..0ce05526ecb5 100644 --- a/libbeat/autodiscover/template/config.go +++ b/libbeat/autodiscover/template/config.go @@ -21,6 +21,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/conditions" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/go-ucfg" ) @@ -81,7 +82,7 @@ func (c Mapper) GetConfig(event bus.Event) []*common.Config { continue } - configs := ApplyConfigTemplate(event, mapping.Configs) + configs := ApplyConfigTemplate(event, mapping.Configs, true) if configs != nil { result = append(result, configs...) } @@ -90,7 +91,7 @@ func (c Mapper) GetConfig(event bus.Event) []*common.Config { } // ApplyConfigTemplate takes a set of templated configs and applys information in an event map -func ApplyConfigTemplate(event bus.Event, configs []*common.Config) []*common.Config { +func ApplyConfigTemplate(event bus.Event, configs []*common.Config, keystoreEnabled bool) []*common.Config { var result []*common.Config // unpack input vars, err := ucfg.NewFrom(map[string]interface{}{ @@ -105,6 +106,19 @@ func ApplyConfigTemplate(event bus.Event, configs []*common.Config) []*common.Co ucfg.ResolveEnv, ucfg.VarExp, } + + if keystoreEnabled { + if val, ok := event["keystore"]; ok { + eventKeystore := val.(keystore.Keystore) + opts = append(opts, ucfg.Resolve(keystore.ResolverWrap(eventKeystore))) + delete(event, "keystore") + } + } else { + if _, ok := event["keystore"]; ok { + delete(event, "keystore") + } + } + for _, config := range configs { c, err := ucfg.NewFrom(config, opts...) if err != nil { diff --git a/libbeat/autodiscover/template/config_test.go b/libbeat/autodiscover/template/config_test.go index 570de15a840b..ccb27a7127af 100644 --- a/libbeat/autodiscover/template/config_test.go +++ b/libbeat/autodiscover/template/config_test.go @@ -18,12 +18,16 @@ package template import ( + "os" + "path/filepath" "testing" + "github.com/docker/docker/pkg/ioutils" "github.com/stretchr/testify/assert" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" ) func TestConfigsMapping(t *testing.T) { @@ -93,6 +97,61 @@ func TestConfigsMapping(t *testing.T) { } } +func TestConfigsMappingKeystore(t *testing.T) { + secret := "mapping_secret" + //expected config + config, _ := common.NewConfigFrom(map[string]interface{}{ + "correct": "config", + "password": secret, + }) + + path := getTemporaryKeystoreFile() + defer os.Remove(path) + // store the secret + keystore := createAnExistingKeystore(path, secret) + + tests := []struct { + mapping string + event bus.Event + expected []*common.Config + }{ + // Match config + { + mapping: ` +- condition.equals: + foo: 3 + config: + - correct: config + password: "${PASSWORD}"`, + event: bus.Event{ + "foo": 3, + "keystore": keystore, + }, + expected: []*common.Config{config}, + }, + } + + for _, test := range tests { + var mappings MapperSettings + config, err := common.NewConfigWithYAML([]byte(test.mapping), "") + if err != nil { + t.Fatal(err) + } + + if err := config.Unpack(&mappings); err != nil { + t.Fatal(err) + } + + mapper, err := NewConfigMapper(mappings) + if err != nil { + t.Fatal(err) + } + + res := mapper.GetConfig(test.event) + assert.Equal(t, test.expected, res) + } +} + func TestNilConditionConfig(t *testing.T) { var mappings MapperSettings data := ` @@ -111,3 +170,31 @@ func TestNilConditionConfig(t *testing.T) { assert.NoError(t, err) assert.Nil(t, mappings[0].ConditionConfig) } + +// create a keystore with an existing key +/// `PASSWORD` with the value of `secret` variable. +func createAnExistingKeystore(path string, secret string) keystore.Keystore { + keyStore, err := keystore.NewFileKeystore(path) + // Fail fast in the test suite + if err != nil { + panic(err) + } + + writableKeystore, err := keystore.AsWritableKeystore(keyStore) + if err != nil { + panic(err) + } + + writableKeystore.Store("PASSWORD", []byte(secret)) + writableKeystore.Save() + return keyStore +} + +// create a temporary file on disk to save the keystore. +func getTemporaryKeystoreFile() string { + path, err := ioutils.TempDir("", "testing") + if err != nil { + panic(err) + } + return filepath.Join(path, "keystore") +} diff --git a/libbeat/beat/beat.go b/libbeat/beat/beat.go index 3aaed4c66413..75585ba89920 100644 --- a/libbeat/beat/beat.go +++ b/libbeat/beat/beat.go @@ -19,6 +19,7 @@ package beat import ( "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/management" ) @@ -66,6 +67,8 @@ type Beat struct { Fields []byte // Data from fields.yml ConfigManager management.ConfigManager // config manager + + Keystore keystore.Keystore } // BeatConfig struct contains the basic configuration of every beat diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index a9e59173633e..e2b4d7d66302 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -584,6 +584,7 @@ func (b *Beat) configure(settings Settings) error { } b.keystore = store + b.Beat.Keystore = store err = cloudid.OverwriteSettings(cfg) if err != nil { return err diff --git a/libbeat/docs/shared-autodiscover.asciidoc b/libbeat/docs/shared-autodiscover.asciidoc index a3911a65490b..22a72a9b52ed 100644 --- a/libbeat/docs/shared-autodiscover.asciidoc +++ b/libbeat/docs/shared-autodiscover.asciidoc @@ -18,6 +18,7 @@ to set conditions that, when met, launch specific configurations. On start, {beatname_uc} will scan existing containers and launch the proper configs for them. Then it will watch for new start/stop events. This ensures you don't need to worry about state, but only define your desired configs. +ifdef::autodiscoverDocker[] [float] ===== Docker @@ -124,6 +125,10 @@ running configuration for a container, 60s by default. ======================================= endif::[] +endif::autodiscoverDocker[] + + +ifdef::autodiscoverKubernetes[] [float] ===== Kubernetes @@ -243,6 +248,7 @@ running configuration for a container, 60s by default. include::../../{beatname_lc}/docs/autodiscover-kubernetes-config.asciidoc[] +endif::autodiscoverKubernetes[] [float] ===== Manually Defining Ports with Kubernetes diff --git a/metricbeat/autodiscover/builder/hints/metrics.go b/metricbeat/autodiscover/builder/hints/metrics.go index 3e859b23d118..1647fb9fbc75 100644 --- a/metricbeat/autodiscover/builder/hints/metrics.go +++ b/metricbeat/autodiscover/builder/hints/metrics.go @@ -84,6 +84,7 @@ func (m *metricHints) CreateConfig(event bus.Event) []*common.Config { } modulesConfig := m.getModules(hints) + // here we handle raw configs if provided if modulesConfig != nil { configs := []*common.Config{} for _, cfg := range modulesConfig { @@ -93,7 +94,7 @@ func (m *metricHints) CreateConfig(event bus.Event) []*common.Config { } logp.Debug("hints.builder", "generated config %+v", configs) // Apply information in event to the template to generate the final config - return template.ApplyConfigTemplate(event, configs) + return template.ApplyConfigTemplate(event, configs, false) } @@ -154,7 +155,7 @@ func (m *metricHints) CreateConfig(event bus.Event) []*common.Config { // Apply information in event to the template to generate the final config // This especially helps in a scenario where endpoints are configured as: // co.elastic.metrics/hosts= "${data.host}:9090" - return template.ApplyConfigTemplate(event, config) + return template.ApplyConfigTemplate(event, config, false) } func (m *metricHints) getModule(hints common.MapStr) string { diff --git a/metricbeat/autodiscover/builder/hints/metrics_test.go b/metricbeat/autodiscover/builder/hints/metrics_test.go index f3f9d5a5200a..4b3f7e0430b3 100644 --- a/metricbeat/autodiscover/builder/hints/metrics_test.go +++ b/metricbeat/autodiscover/builder/hints/metrics_test.go @@ -18,13 +18,17 @@ package hints import ( + "os" + "path/filepath" "sort" "testing" + "github.com/docker/docker/pkg/ioutils" "github.com/stretchr/testify/assert" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/metricbeat/mb" ) @@ -324,6 +328,78 @@ func TestGenerateHints(t *testing.T) { } } +func TestGenerateHintsDoesNotAccessKeystore(t *testing.T) { + path := getTemporaryKeystoreFile() + defer os.Remove(path) + // store the secret + keystore := createAnExistingKeystore(path, "stored_secret") + os.Setenv("PASSWORD", "env_secret") + + tests := []struct { + message string + event bus.Event + len int + result common.MapStr + }{ + { + message: "Module, namespace, host hint should return valid config", + event: bus.Event{ + "host": "1.2.3.4", + "port": 9090, + "hints": common.MapStr{ + "metrics": common.MapStr{ + "module": "mockmoduledefaults", + "hosts": "${data.host}:9090", + "password": "${PASSWORD}", + }, + }, + "keystore": keystore, + }, + len: 1, + result: common.MapStr{ + "module": "mockmoduledefaults", + "metricsets": []string{"default"}, + "hosts": []interface{}{"1.2.3.4:9090"}, + "timeout": "3s", + "period": "1m", + "enabled": true, + "password": "env_secret", + }, + }, + } + for _, test := range tests { + mockRegister := mb.NewRegister() + mockRegister.MustAddMetricSet("mockmoduledefaults", "default", NewMockMetricSet, mb.DefaultMetricSet()) + + m := metricHints{ + Key: defaultConfig().Key, + Registry: mockRegister, + } + cfgs := m.CreateConfig(test.event) + assert.Equal(t, len(cfgs), test.len) + if len(cfgs) != 0 { + config := common.MapStr{} + err := cfgs[0].Unpack(&config) + assert.Nil(t, err, test.message) + + // metricsets order is random, order it for tests + if v, err := config.GetValue("metricsets"); err == nil { + if msets, ok := v.([]interface{}); ok { + metricsets := make([]string, len(msets)) + for i, v := range msets { + metricsets[i] = v.(string) + } + sort.Strings(metricsets) + config["metricsets"] = metricsets + } + } + + assert.Equal(t, test.result, config, test.message) + } + + } +} + type MockMetricSet struct { mb.BaseMetricSet } @@ -335,3 +411,31 @@ func NewMockMetricSet(base mb.BaseMetricSet) (mb.MetricSet, error) { func (ms *MockMetricSet) Fetch(report mb.Reporter) { } + +// create a keystore with an existing key +/// `PASSWORD` with the value of `secret` variable. +func createAnExistingKeystore(path string, secret string) keystore.Keystore { + keyStore, err := keystore.NewFileKeystore(path) + // Fail fast in the test suite + if err != nil { + panic(err) + } + + writableKeystore, err := keystore.AsWritableKeystore(keyStore) + if err != nil { + panic(err) + } + + writableKeystore.Store("PASSWORD", []byte(secret)) + writableKeystore.Save() + return keyStore +} + +// create a temporary file on disk to save the keystore. +func getTemporaryKeystoreFile() string { + path, err := ioutils.TempDir("", "testing") + if err != nil { + panic(err) + } + return filepath.Join(path, "keystore") +} diff --git a/metricbeat/beater/metricbeat.go b/metricbeat/beater/metricbeat.go index 050e7f265c15..fbf9d23110fb 100644 --- a/metricbeat/beater/metricbeat.go +++ b/metricbeat/beater/metricbeat.go @@ -181,7 +181,12 @@ func newMetricbeat(b *beat.Beat, c *common.Config, options ...Option) (*Metricbe if config.Autodiscover != nil { var err error metricbeat.autodiscover, err = autodiscover.NewAutodiscover( - "metricbeat", b.Publisher, factory, autodiscover.QueryConfig(), config.Autodiscover) + "metricbeat", + b.Publisher, + factory, autodiscover.QueryConfig(), + config.Autodiscover, + b.Keystore, + ) if err != nil { return nil, err } diff --git a/metricbeat/docs/autodiscover-docker-config.asciidoc b/metricbeat/docs/autodiscover-docker-config.asciidoc index 79dce08e7a6b..bd026ec0c697 100644 --- a/metricbeat/docs/autodiscover-docker-config.asciidoc +++ b/metricbeat/docs/autodiscover-docker-config.asciidoc @@ -19,3 +19,24 @@ metricbeat.autodiscover: This configuration launches a `redis` module for all containers running an image with `redis` in the name. `labels.dedot` defaults to be `true` for docker autodiscover, which means dots in docker labels are replaced with '_' by default. +Also Metricbeat autodiscover supports leveraging <> in order to retrieve sensitive data like passwords. +Here is an example of how a configuration using keystore would look like: + +["source","yaml",subs="attributes"] +------------------------------------------------------------------------------------- +metricbeat.autodiscover: + providers: + - type: docker + labels.dedot: true + templates: + - condition: + contains: + docker.container.image: redis + config: + - module: redis + metricsets: ["info", "keyspace"] + hosts: "${data.host}:6379" + password: "${REDIS_PASSWORD}" +------------------------------------------------------------------------------------- + +where `REDIS_PASSWORD` is a key stored in local keystore of Metricbeat. diff --git a/metricbeat/docs/autodiscover-hints.asciidoc b/metricbeat/docs/autodiscover-hints.asciidoc index 1bc56d8f54dc..a34b623bd367 100644 --- a/metricbeat/docs/autodiscover-hints.asciidoc +++ b/metricbeat/docs/autodiscover-hints.asciidoc @@ -43,7 +43,9 @@ The username to use for authentication [float] ===== `co.elastic.metrics/password` -The password to use for authentication. It is recommended to retrieve this sensitive information from an ENV variable or a keystore and avoid placing passwords in plain text +The password to use for authentication. It is recommended to retrieve this sensitive information from an ENV variable +and avoid placing passwords in plain text. Unlike static autodiscover configuration, hints based autodiscover has +no access to the keystore of Metricbeat since it could be a potential security issue. [float] ===== `co.elastic.metrics/ssl.*` diff --git a/metricbeat/docs/autodiscover-kubernetes-config.asciidoc b/metricbeat/docs/autodiscover-kubernetes-config.asciidoc index 81e4ad159497..f3e6a74cdfbf 100644 --- a/metricbeat/docs/autodiscover-kubernetes-config.asciidoc +++ b/metricbeat/docs/autodiscover-kubernetes-config.asciidoc @@ -17,3 +17,24 @@ metricbeat.autodiscover: ------------------------------------------------------------------------------------- This configuration launches a `prometheus` module for all containers of pods annotated `prometheus.io/scrape=true`. + +Also Metricbeat autodiscover supports leveraging <> in order to retrieve sensitive data like passwords. +Here is an example of how a configuration using keystore would look like: + +["source","yaml",subs="attributes"] +------------------------------------------------------------------------------------- +metricbeat.autodiscover: + providers: + - type: kubernetes + templates: + - condition: + contains: + kubernetes.labels.app: "redis" + config: + - module: redis + metricsets: ["info", "keyspace"] + hosts: "${data.host}:6379" + password: "${REDIS_PASSWORD}" +------------------------------------------------------------------------------------- + +where `REDIS_PASSWORD` is a key stored in local keystore of Metricbeat. diff --git a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go index 15d8015e52c9..4d457c46a8cb 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go +++ b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider.go @@ -15,6 +15,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" awsauto "github.com/elastic/beats/v7/x-pack/libbeat/autodiscover/providers/aws" awscommon "github.com/elastic/beats/v7/x-pack/libbeat/common/aws" @@ -33,10 +34,11 @@ type Provider struct { stopListener bus.Listener watcher *watcher uuid uuid.UUID + keystore keystore.Keystore } // AutodiscoverBuilder is the main builder for this provider. -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodiscover.Provider, error) { +func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { cfgwarn.Experimental("aws_ec2 autodiscover is experimental") config := awsauto.DefaultConfig() @@ -78,12 +80,12 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodis config.AWSConfig.Endpoint, "ec2", region, awsCfg))) } - return internalBuilder(uuid, bus, config, newAPIFetcher(clients)) + return internalBuilder(uuid, bus, config, newAPIFetcher(clients), keystore) } // internalBuilder is mainly intended for testing via mocks and stubs. // it can be configured to use a fetcher that doesn't actually hit the AWS API. -func internalBuilder(uuid uuid.UUID, bus bus.Bus, config *awsauto.Config, fetcher fetcher) (*Provider, error) { +func internalBuilder(uuid uuid.UUID, bus bus.Bus, config *awsauto.Config, fetcher fetcher, keystore keystore.Keystore) (*Provider, error) { mapper, err := template.NewConfigMapper(config.Templates) if err != nil { return nil, err @@ -94,6 +96,7 @@ func internalBuilder(uuid uuid.UUID, bus bus.Bus, config *awsauto.Config, fetche bus: bus, templates: &mapper, uuid: uuid, + keystore: keystore, } p.watcher = newWatcher( diff --git a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider_test.go b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider_test.go index 255ae2e141bc..b22321eeb230 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/ec2/provider_test.go +++ b/x-pack/libbeat/autodiscover/providers/aws/ec2/provider_test.go @@ -15,6 +15,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" awsauto "github.com/elastic/beats/v7/x-pack/libbeat/autodiscover/providers/aws" "github.com/elastic/beats/v7/x-pack/libbeat/autodiscover/providers/aws/test" @@ -33,7 +34,8 @@ func Test_internalBuilder(t *testing.T) { } uuid, _ := uuid.NewV4() - provider, err := internalBuilder(uuid, pBus, cfg, fetcher) + k, _ := keystore.NewFileKeystore("test") + provider, err := internalBuilder(uuid, pBus, cfg, fetcher, k) require.NoError(t, err) startListener := pBus.Subscribe("start") diff --git a/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go b/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go index 8513e0f9d2ac..522b5ba9a4f3 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go +++ b/x-pack/libbeat/autodiscover/providers/aws/elb/provider.go @@ -15,6 +15,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" awsauto "github.com/elastic/beats/v7/x-pack/libbeat/autodiscover/providers/aws" awscommon "github.com/elastic/beats/v7/x-pack/libbeat/common/aws" @@ -35,10 +36,11 @@ type Provider struct { stopListener bus.Listener watcher *watcher uuid uuid.UUID + keystore keystore.Keystore } // AutodiscoverBuilder is the main builder for this provider. -func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodiscover.Provider, error) { +func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore keystore.Keystore) (autodiscover.Provider, error) { cfgwarn.Experimental("aws_elb autodiscover is experimental") config := awsauto.DefaultConfig() @@ -85,12 +87,12 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config) (autodis config.AWSConfig.Endpoint, "elasticloadbalancing", region, awsCfg))) } - return internalBuilder(uuid, bus, config, newAPIFetcher(clients)) + return internalBuilder(uuid, bus, config, newAPIFetcher(clients), keystore) } // internalBuilder is mainly intended for testing via mocks and stubs. // it can be configured to use a fetcher that doesn't actually hit the AWS API. -func internalBuilder(uuid uuid.UUID, bus bus.Bus, config *awsauto.Config, fetcher fetcher) (*Provider, error) { +func internalBuilder(uuid uuid.UUID, bus bus.Bus, config *awsauto.Config, fetcher fetcher, keystore keystore.Keystore) (*Provider, error) { mapper, err := template.NewConfigMapper(config.Templates) if err != nil { return nil, err @@ -101,6 +103,7 @@ func internalBuilder(uuid uuid.UUID, bus bus.Bus, config *awsauto.Config, fetche bus: bus, templates: &mapper, uuid: uuid, + keystore: keystore, } p.watcher = newWatcher( diff --git a/x-pack/libbeat/autodiscover/providers/aws/elb/provider_test.go b/x-pack/libbeat/autodiscover/providers/aws/elb/provider_test.go index e6012c39d33d..d6f9a918377e 100644 --- a/x-pack/libbeat/autodiscover/providers/aws/elb/provider_test.go +++ b/x-pack/libbeat/autodiscover/providers/aws/elb/provider_test.go @@ -16,6 +16,7 @@ import ( "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/bus" + "github.com/elastic/beats/v7/libbeat/keystore" "github.com/elastic/beats/v7/libbeat/logp" awsauto "github.com/elastic/beats/v7/x-pack/libbeat/autodiscover/providers/aws" ) @@ -74,7 +75,8 @@ func Test_internalBuilder(t *testing.T) { } uuid, _ := uuid.NewV4() - provider, err := internalBuilder(uuid, pBus, cfg, fetcher) + k, _ := keystore.NewFileKeystore("test") + provider, err := internalBuilder(uuid, pBus, cfg, fetcher, k) require.NoError(t, err) startListener := pBus.Subscribe("start")