Skip to content

Commit

Permalink
Allow a keystore to be send with functionbeat files
Browse files Browse the repository at this point in the history
Add a new interface in the keystore package named Packager, this allow a
keystore to return the raw bytes of the keys and values store in it.

This is used with core.MakeZip() to create the package that will be send
to the lambda function.

Fixes: elastic#9009
  • Loading branch information
ph committed Jan 30, 2019
1 parent a47330c commit f0084f3
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 20 deletions.
17 changes: 13 additions & 4 deletions libbeat/cmd/instance/beat.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,7 @@ func (b *Beat) configure(settings Settings) error {

// We have to initialize the keystore before any unpack or merging the cloud
// options.
keystoreCfg, _ := cfg.Child("keystore", -1)
defaultPathConfig, _ := cfg.String("path.config", -1)
defaultPathConfig = filepath.Join(defaultPathConfig, fmt.Sprintf("%s.keystore", b.Info.Beat))
store, err := keystore.Factory(keystoreCfg, defaultPathConfig)
store, err := LoadKeystore(cfg, b.Info.Beat)
if err != nil {
return fmt.Errorf("could not initialize the keystore: %v", err)
}
Expand Down Expand Up @@ -1008,3 +1005,15 @@ func obfuscateConfigOpts() []ucfg.Option {
ucfg.ResolveNOOP,
}
}

// LoadKeystore returns the appropriate keystore based on the configuration.
func LoadKeystore(cfg *common.Config, name string) (keystore.Keystore, error) {
keystoreCfg, _ := cfg.Child("keystore", -1)
defaultPathConfig, _ := cfg.String("path.config", -1)
defaultPathConfig = filepath.Join(defaultPathConfig, fmt.Sprintf("%s.keystore", name))
store, err := keystore.Factory(keystoreCfg, defaultPathConfig)
if err != nil {
return nil, fmt.Errorf("could not initialize the keystore: %v", err)
}
return store, nil
}
45 changes: 32 additions & 13 deletions libbeat/keystore/file_keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,41 +234,53 @@ func (k *FileKeystore) doSave(override bool) error {
return nil
}

func (k *FileKeystore) load() error {
k.Lock()
defer k.Unlock()

func (k *FileKeystore) loadRaw() ([]byte, error) {
f, err := os.OpenFile(k.Path, os.O_RDONLY, filePermission)
if err != nil {
if os.IsNotExist(err) {
return nil
return nil, nil
}
return err
return nil, err
}
defer f.Close()

if common.IsStrictPerms() {
if err := k.checkPermissions(k.Path); err != nil {
return err
return nil, err
}
}

raw, err := ioutil.ReadAll(f)
if err != nil {
return err
return nil, err
}

v := raw[0:len(version)]
if !bytes.Equal(v, version) {
return fmt.Errorf("keystore format doesn't match expected version: '%s' got '%s'", version, v)
return nil, fmt.Errorf("keystore format doesn't match expected version: '%s' got '%s'", version, v)
}

base64Content := raw[len(version):]
if len(base64Content) == 0 {
return fmt.Errorf("corrupt or empty keystore")
if len(raw) <= len(version) {
return nil, fmt.Errorf("corrupt or empty keystore")
}

base64Decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(base64Content))
return raw, nil
}

func (k *FileKeystore) load() error {
k.Lock()
defer k.Unlock()

raw, err := k.loadRaw()
if err != nil {
return err
}

if len(raw) == 0 {
return nil
}

base64Decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(raw[len(version):]))
plaintext, err := k.decrypt(base64Decoder)
if err != nil {
return fmt.Errorf("could not decrypt the keystore: %v", err)
Expand Down Expand Up @@ -396,6 +408,13 @@ func (k *FileKeystore) checkPermissions(f string) error {
return nil
}

// Package returns the bytes of the encrypted keystore.
func (k *FileKeystore) Package() ([]byte, error) {
k.Lock()
defer k.Unlock()
return k.loadRaw()
}

func (k *FileKeystore) hashPassword(password, salt []byte) []byte {
return pbkdf2.Key(password, salt, iterationsCount, keyLength, sha512.New)
}
5 changes: 5 additions & 0 deletions libbeat/keystore/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ type Keystore interface {
Save() error
}

// Packager defines a keystore that can be uploaded.
type Packager interface {
Package() ([]byte, error)
}

// Factory Create the right keystore with the configured options.
func Factory(cfg *common.Config, defaultPath string) (Keystore, error) {
config := defaultConfig
Expand Down
47 changes: 44 additions & 3 deletions x-pack/functionbeat/core/makezip.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
package core

import (
"fmt"

yaml "gopkg.in/yaml.v2"

"github.com/elastic/beats/libbeat/cfgfile"
"github.com/elastic/beats/libbeat/cmd/instance"
"github.com/elastic/beats/libbeat/common"
"github.com/elastic/beats/libbeat/keystore"
"github.com/elastic/beats/x-pack/functionbeat/config"
"github.com/elastic/beats/x-pack/functionbeat/core/bundle"
)
Expand Down Expand Up @@ -43,16 +48,52 @@ func MakeZip() ([]byte, error) {
if err != nil {
return nil, err
}

resources := []bundle.Resource{
&bundle.MemoryFile{Path: "functionbeat.yml", Raw: rawConfig, FileMode: 0766},
&bundle.LocalFile{Path: "pkg/functionbeat", FileMode: 0755},
}

rawKeystore, err := keystoreRaw()
if err != nil {
return nil, err
}

if len(rawKeystore) > 0 {
resources = append(resources, &bundle.MemoryFile{
Path: "data/functionbeat.keystore",
Raw: rawKeystore,
FileMode: 0600,
})
}

bundle := bundle.NewZipWithLimits(
packageUncompressedLimit,
packageCompressedLimit,
&bundle.MemoryFile{Path: "functionbeat.yml", Raw: rawConfig, FileMode: 0766},
&bundle.LocalFile{Path: "pkg/functionbeat", FileMode: 0755},
)
resources...)

content, err := bundle.Bytes()
if err != nil {
return nil, err
}
return content, nil
}

func keystoreRaw() ([]byte, error) {
cfg, err := cfgfile.Load("", common.NewConfig())
if err != nil {
return nil, fmt.Errorf("error loading config file: %v", err)
}

store, err := instance.LoadKeystore(cfg, "functionbeat")
if err != nil {
return nil, err
}

packager, ok := store.(keystore.Packager)
if !ok {
return nil, fmt.Errorf("keystore cannot be packaged")
}

return packager.Package()
}

0 comments on commit f0084f3

Please sign in to comment.