Skip to content

Commit

Permalink
Refuse to store dotted keys to prevent cyclic reference in our config…
Browse files Browse the repository at this point in the history
…uration. (#6077)

The following reference can make the configuration parse go into an
infinite loop and panic.
```
filebeat_name: ${filebeat_name}
```
  • Loading branch information
ph authored and ruflin committed Jan 16, 2018
1 parent 91fcb93 commit 0cdcf4f
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
12 changes: 12 additions & 0 deletions libbeat/keystore/file_keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"os"
"path/filepath"
"runtime"
"strings"
"sync"

"golang.org/x/crypto/pbkdf2"
Expand Down Expand Up @@ -88,6 +89,9 @@ func (k *FileKeystore) Retrieve(key string) (*SecureString, error) {

// Store add the key pair to the secret store and mark the store as dirty.
func (k *FileKeystore) Store(key string, value []byte) error {
if err := k.validateKey(key); err != nil {
return err
}
k.Lock()
defer k.Unlock()

Expand Down Expand Up @@ -382,3 +386,11 @@ func (k *FileKeystore) checkPermissions(f string) error {
func (k *FileKeystore) hashPassword(password, salt []byte) []byte {
return pbkdf2.Key(password, salt, iterationsCount, keyLength, sha512.New)
}

func (k *FileKeystore) validateKey(key string) error {
if strings.IndexAny(key, ".") != -1 {
return fmt.Errorf("invalid key format. '.' in keys are not supported yet. key: %s", key)
}

return nil
}
20 changes: 16 additions & 4 deletions libbeat/keystore/file_keystore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,21 @@ import (
"github.com/elastic/beats/libbeat/common"
)

var keyValue = "output.elasticsearch.password"
var keyValue = "output_elasticsearch_password"
var secretValue = []byte("secret")

func TestInvalidKey(t *testing.T) {
path := GetTemporaryKeystoreFile()
defer os.Remove(path)

keystore, err := NewFileKeystore(path)
assert.NoError(t, err)
err = keystore.Store("output.elasticsearch.password", secretValue)
if assert.Error(t, err) {
assert.Equal(t, err.Error(), "invalid key format. '.' in keys are not supported yet. key: output.elasticsearch.password")
}
}

func TestCanCreateAKeyStore(t *testing.T) {
path := GetTemporaryKeystoreFile()
defer os.Remove(path)
Expand Down Expand Up @@ -185,18 +197,18 @@ func TestGetConfig(t *testing.T) {
keystore := CreateAnExistingKeystore(path)

// Add a bit more data of different type
keystore.Store("super.nested", []byte("hello"))
keystore.Store("super_nested", []byte("hello"))
keystore.Save()

cfg, err := keystore.GetConfig()
assert.NotNil(t, cfg)
assert.NoError(t, err)

secret, err := cfg.String("output.elasticsearch.password", 0)
secret, err := cfg.String("output_elasticsearch_password", 0)
assert.NoError(t, err)
assert.Equal(t, secret, "secret")

port, err := cfg.String("super.nested", 0)
port, err := cfg.String("super_nested", 0)
assert.Equal(t, port, "hello")
}

Expand Down
2 changes: 1 addition & 1 deletion libbeat/keystore/keystore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestResolverWhenTheKeyExist(t *testing.T) {
keystore := CreateAnExistingKeystore(path)

resolver := ResolverWrap(keystore)
v, err := resolver("output.elasticsearch.password")
v, err := resolver("output_elasticsearch_password")
assert.NoError(t, err)
assert.Equal(t, v, "secret")
}

0 comments on commit 0cdcf4f

Please sign in to comment.