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

Add k8s keystore backend #18096

Merged
merged 21 commits into from
May 27, 2020
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add k8s Keystore for static configs too
Signed-off-by: chrismark <[email protected]>
ChrsMark committed Apr 30, 2020
commit c68fe18e2ba648bb219bab78e522a2c921caf48b
35 changes: 12 additions & 23 deletions libbeat/autodiscover/builder.go
Original file line number Diff line number Diff line change
@@ -23,7 +23,6 @@ import (
"strings"

"github.com/elastic/go-ucfg"
k8s "k8s.io/client-go/kubernetes"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/libbeat/common/bus"
@@ -39,7 +38,7 @@ type Builder interface {
// Builders is a struct of Builder list objects and a common Keystore object
type Builders struct {
Builders []Builder
client k8s.Interface
kubernetesKeystoresRegistry *keystore.KubernetesKeystoresRegistry
ChrsMark marked this conversation as resolved.
Show resolved Hide resolved
}

// BuilderConstructor is a func used to generate a Builder object
@@ -98,10 +97,12 @@ func (b Builders) GetConfig(event bus.Event) []*common.Config {
configs := []*common.Config{}
var opts []ucfg.Option

k8sKeystore := getK8sKeystore(event, b.client)
if k8sKeystore != nil {
opts = []ucfg.Option{
ucfg.Resolve(keystore.ResolverWrap(k8sKeystore)),
if b.kubernetesKeystoresRegistry != nil {
k8sKeystore := b.kubernetesKeystoresRegistry.GetK8sKeystore(event)
if k8sKeystore != nil {
opts = []ucfg.Option{
ucfg.Resolve(keystore.ResolverWrap(k8sKeystore)),
}
}
}
for _, builder := range b.Builders {
@@ -113,26 +114,14 @@ func (b Builders) GetConfig(event bus.Event) []*common.Config {
return configs
}

func getK8sKeystore(event bus.Event, client k8s.Interface) keystore.Keystore {
namespace := ""
if val, ok := event["kubernetes"]; ok {
kubernetesMeta := val.(common.MapStr)
ns, err := kubernetesMeta.GetValue("namespace")
if err != nil {
return nil
}
namespace = ns.(string)
}
if namespace != "" {
k8sKeystore, _ := keystore.Factoryk8s(namespace, client)
return k8sKeystore
}
return nil
// GetValue extracts given key from an Event
func (b Builders) SetKubernetesKeystoresRegistry(k8sKeystoresRegistry *keystore.KubernetesKeystoresRegistry) {
b.kubernetesKeystoresRegistry = k8sKeystoresRegistry
}

// NewBuilders instances the given list of builders. hintsCfg holds `hints` settings
// for simplified mode (single 'hints' builder)
func NewBuilders(bConfigs []*common.Config, hintsCfg *common.Config, client k8s.Interface) (Builders, error) {
func NewBuilders(bConfigs []*common.Config, hintsCfg *common.Config) (Builders, error) {
var builders Builders
if hintsCfg.Enabled() {
if len(bConfigs) > 0 {
@@ -151,6 +140,6 @@ func NewBuilders(bConfigs []*common.Config, hintsCfg *common.Config, client k8s.
}
builders.Builders = append(builders.Builders, builder)
}
builders.client = client

return builders, nil
}
2 changes: 1 addition & 1 deletion libbeat/autodiscover/providers/docker/docker.go
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore
return nil, errWrap(fmt.Errorf("no configs or hints defined for autodiscover provider"))
}

builders, err := autodiscover.NewBuilders(config.Builders, config.Hints, nil)
builders, err := autodiscover.NewBuilders(config.Builders, config.Hints)
if err != nil {
return nil, errWrap(err)
}
2 changes: 1 addition & 1 deletion libbeat/autodiscover/providers/jolokia/jolokia.go
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keystore
return nil, errWrap(fmt.Errorf("no configs defined for autodiscover provider"))
}

builders, err := autodiscover.NewBuilders(config.Builders, nil, nil)
builders, err := autodiscover.NewBuilders(config.Builders, nil)
if err != nil {
return nil, errWrap(err)
}
6 changes: 5 additions & 1 deletion libbeat/autodiscover/providers/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keyStore
return nil, errWrap(err)
}

builders, err := autodiscover.NewBuilders(config.Builders, config.Hints, client)
builders, err := autodiscover.NewBuilders(config.Builders, config.Hints)
if err != nil {
return nil, errWrap(err)
}
@@ -91,6 +91,10 @@ func AutodiscoverBuilder(bus bus.Bus, uuid uuid.UUID, c *common.Config, keyStore
return nil, errWrap(err)
}

k8sKeystoresRegistry := keystore.NewKubernetesKeystoresRegistry(logger, client)
mapper.SetKubernetesKeystoresRegistry(k8sKeystoresRegistry)
builders.SetKubernetesKeystoresRegistry(k8sKeystoresRegistry)
ChrsMark marked this conversation as resolved.
Show resolved Hide resolved

p := &Provider{
config: config,
bus: bus,
14 changes: 14 additions & 0 deletions libbeat/autodiscover/template/config.go
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ import (
type Mapper struct {
ConditionMaps []*ConditionMap
keystore keystore.Keystore
kubernetesKeystoresRegistry *keystore.KubernetesKeystoresRegistry
ChrsMark marked this conversation as resolved.
Show resolved Hide resolved
}

// ConditionMap maps a condition to the configs to use when it's triggered
@@ -74,6 +75,11 @@ func (e Event) GetValue(key string) (interface{}, error) {
return val, nil
}

// GetValue extracts given key from an Event
func (c Mapper) SetKubernetesKeystoresRegistry(k8sKeystoresRegistry *keystore.KubernetesKeystoresRegistry) {
c.kubernetesKeystoresRegistry = k8sKeystoresRegistry
}

// GetConfig returns a matching Config if any, nil otherwise
func (c Mapper) GetConfig(event bus.Event) []*common.Config {
var result []*common.Config
@@ -83,6 +89,14 @@ func (c Mapper) GetConfig(event bus.Event) []*common.Config {
ucfg.Resolve(keystore.ResolverWrap(c.keystore)),
}
}
if c.kubernetesKeystoresRegistry != nil {
k8sKeystore := c.kubernetesKeystoresRegistry.GetK8sKeystore(event)
if k8sKeystore != nil {
opts = []ucfg.Option{
ucfg.Resolve(keystore.ResolverWrap(k8sKeystore)),
}
}
}
ChrsMark marked this conversation as resolved.
Show resolved Hide resolved
for _, mapping := range c.ConditionMaps {
// An empty condition matches everything
conditionOk := mapping.Condition == nil || mapping.Condition.Check(Event(event))
2 changes: 1 addition & 1 deletion libbeat/autodiscover/template/config_test.go
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ func TestConfigsMapping(t *testing.T) {
t.Fatal(err)
}

mapper, err := NewConfigMapper(mappings, nil)
mapper, err := NewConfigMapper(mappings, nil, nil)
if err != nil {
t.Fatal(err)
}
82 changes: 82 additions & 0 deletions libbeat/keystore/kubernetes_keystore.go
Original file line number Diff line number Diff line change
@@ -19,6 +19,8 @@ package keystore

import (
"fmt"
"github.com/elastic/beats/libbeat/common/bus"
"github.com/elastic/beats/libbeat/logp"
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -27,6 +29,14 @@ import (
"github.com/elastic/beats/libbeat/common"
)

type KubernetesKeystores map[string]Keystore

type KubernetesKeystoresRegistry struct {
kubernetesKeystores KubernetesKeystores
logger *logp.Logger
client k8s.Interface
}

// KubernetesSecretsKeystore allows to retrieve passwords from Kubernetes secrets for a given namespace.
type KubernetesSecretsKeystore struct {
namespace string
@@ -39,6 +49,47 @@ func Factoryk8s(keystoreNamespace string, ks8client k8s.Interface) (Keystore, er
return keystore, err
}

func NewKubernetesKeystoresRegistry(logger *logp.Logger, client k8s.Interface) *KubernetesKeystoresRegistry {
return &KubernetesKeystoresRegistry{
kubernetesKeystores: KubernetesKeystores{},
logger: logger,
client: client,
}
}

// GetK8sKeystore return a KubernetesSecretsKeystore if it already exists for a given namespace of creates a new one.
func (kr *KubernetesKeystoresRegistry) GetK8sKeystore(event bus.Event) Keystore {
namespace := ""
if val, ok := event["kubernetes"]; ok {
kubernetesMeta := val.(common.MapStr)
ns, err := kubernetesMeta.GetValue("namespace")
if err != nil {
kr.logger.Debugf("Cannot retrieve kubernetes namespace from event: %s", event)
return nil
}
namespace = ns.(string)
}
if namespace != "" {
// either retrieve already stored keystore or create a new one for the namespace
storedKeystore := kr.lookupForKeystore(namespace)
if storedKeystore != nil {
return storedKeystore
}
k8sKeystore, _ := Factoryk8s(namespace, kr.client)
kr.kubernetesKeystores["namespace"] = k8sKeystore
return k8sKeystore
}
return nil
}

func (kr *KubernetesKeystoresRegistry) lookupForKeystore(keystoreNamespace string) (Keystore) {
if keystore, ok := kr.kubernetesKeystores[keystoreNamespace]; ok {
return keystore
}
return nil
}


// NewKubernetesSecretsKeystore returns an new k8s Keystore
func NewKubernetesSecretsKeystore(keystoreNamespace string, ks8client k8s.Interface) (Keystore, error) {
keystore := KubernetesSecretsKeystore{
@@ -76,3 +127,34 @@ func (k *KubernetesSecretsKeystore) GetConfig() (*common.Config, error) {
func (k *KubernetesSecretsKeystore) IsPersisted() bool {
return true
}

func (b Builders) getK8sKeystore(event bus.Event, client k8s.Interface, k8sKeystores map[string]keystore.Keystore) keystore.Keystore {
namespace := ""
if val, ok := event["kubernetes"]; ok {
kubernetesMeta := val.(common.MapStr)
ns, err := kubernetesMeta.GetValue("namespace")
if err != nil {
b.logger.Debugf("Cannot retrieve kubernetes namespace from event: %s", event)
return nil
}
namespace = ns.(string)
}
if namespace != "" {
// either retrieve already stored keystore or create a new one for the namespace
storedKeystore := b.lookupForKeystore(namespace)
if storedKeystore != nil {
return storedKeystore
}
k8sKeystore, _ := keystore.Factoryk8s(namespace, client)
b.k8sKeystores["namespace"] = k8sKeystore
return k8sKeystore
}
return nil
}

func (b Builders) lookupForKeystore(keystoreNamespace string) (keystore.Keystore) {
if keystore, ok := b.k8sKeystores[keystoreNamespace]; ok {
return keystore
}
return nil
}