Skip to content

Commit

Permalink
Fixes in-memory keyring initialization so gossip encryption still works.
Browse files Browse the repository at this point in the history
Fixes #3243.
  • Loading branch information
slackpad committed Jul 15, 2017
1 parent 218ac4c commit 0e6aa4f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 13 deletions.
28 changes: 23 additions & 5 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,10 +794,9 @@ func (a *Agent) consulConfig() (*consul.Config, error) {
// Setup the loggers
base.LogOutput = a.LogOutput

if !a.config.DisableKeyringFile {
if err := a.setupKeyrings(base); err != nil {
return nil, fmt.Errorf("Failed to configure keyring: %v", err)
}
// This will set up the LAN keyring, as well as the WAN for servers.
if err := a.setupKeyrings(base); err != nil {
return nil, fmt.Errorf("Failed to configure keyring: %v", err)
}

return base, nil
Expand Down Expand Up @@ -1026,6 +1025,26 @@ func (a *Agent) setupNodeID(config *Config) error {

// setupKeyrings is used to initialize and load keyrings during agent startup
func (a *Agent) setupKeyrings(config *consul.Config) error {
// If the keyring file is disabled then just poke the provided key
// into the in-memory keyring.
if a.config.DisableKeyringFile {
if a.config.EncryptKey == "" {
return nil
}

keys := []string{a.config.EncryptKey}
if err := loadKeyring(config.SerfLANConfig, keys); err != nil {
return err
}
if a.config.Server {
if err := loadKeyring(config.SerfWANConfig, keys); err != nil {
return err
}
}
return nil
}

// Otherwise, we need to deal with the keyring files.
fileLAN := filepath.Join(a.config.DataDir, SerfLANKeyring)
fileWAN := filepath.Join(a.config.DataDir, SerfWANKeyring)

Expand Down Expand Up @@ -1061,7 +1080,6 @@ LOAD:
}
}

// Success!
return nil
}

Expand Down
15 changes: 7 additions & 8 deletions agent/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,22 @@ func loadKeyringFile(c *serf.Config) error {
return err
}

// Read in the keyring file data
keyringData, err := ioutil.ReadFile(c.KeyringFile)
if err != nil {
return err
}

// Decode keyring JSON
keys := make([]string, 0)
if err := json.Unmarshal(keyringData, &keys); err != nil {
return err
}

// Decode base64 values
return loadKeyring(c, keys)
}

// loadKeyring takes a list of base64-encoded strings and installs them in the
// given Serf's keyring.
func loadKeyring(c *serf.Config, keys []string) error {
keysDecoded := make([][]byte, len(keys))
for i, key := range keys {
keyBytes, err := base64.StdEncoding.DecodeString(key)
Expand All @@ -91,20 +94,16 @@ func loadKeyringFile(c *serf.Config) error {
keysDecoded[i] = keyBytes
}

// Guard against empty keyring
if len(keysDecoded) == 0 {
return fmt.Errorf("no keys present in keyring file: %s", c.KeyringFile)
return fmt.Errorf("no keys present in keyring: %s", c.KeyringFile)
}

// Create the keyring
keyring, err := memberlist.NewKeyring(keysDecoded, keysDecoded[0])
if err != nil {
return err
}

c.MemberlistConfig.Keyring = keyring

// Success!
return nil
}

Expand Down
69 changes: 69 additions & 0 deletions agent/keyring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,75 @@ func TestAgent_LoadKeyrings(t *testing.T) {
}
}

func TestAgent_InmemKeyrings(t *testing.T) {
t.Parallel()
key := "tbLJg26ZJyJ9pK3qhc9jig=="

// Should be no configured keyring file by default
a1 := NewTestAgent(t.Name(), nil)
defer a1.Shutdown()

c1 := a1.Config.ConsulConfig
if c1.SerfLANConfig.KeyringFile != "" {
t.Fatalf("bad: %#v", c1.SerfLANConfig.KeyringFile)
}
if c1.SerfLANConfig.MemberlistConfig.Keyring != nil {
t.Fatalf("keyring should not be loaded")
}
if c1.SerfWANConfig.KeyringFile != "" {
t.Fatalf("bad: %#v", c1.SerfLANConfig.KeyringFile)
}
if c1.SerfWANConfig.MemberlistConfig.Keyring != nil {
t.Fatalf("keyring should not be loaded")
}

cfg2 := TestConfig()
cfg2.EncryptKey = key
cfg2.DisableKeyringFile = true

// Server should auto-load LAN and WAN keyring
a2 := &TestAgent{Name: t.Name(), Config: cfg2}
a2.Start()
defer a2.Shutdown()

c2 := a2.Config.ConsulConfig
if c2.SerfLANConfig.KeyringFile != "" {
t.Fatalf("should not have keyring file")
}
if c2.SerfLANConfig.MemberlistConfig.Keyring == nil {
t.Fatalf("keyring should be loaded")
}
if c2.SerfWANConfig.KeyringFile != "" {
t.Fatalf("should not have keyring file")
}
if c2.SerfWANConfig.MemberlistConfig.Keyring == nil {
t.Fatalf("keyring should be loaded")
}

// Client should auto-load only the LAN keyring
cfg3 := TestConfig()
cfg3.EncryptKey = key
cfg3.DisableKeyringFile = true
cfg3.Server = false
a3 := &TestAgent{Name: t.Name(), Config: cfg3}
a3.Start()
defer a3.Shutdown()

c3 := a3.Config.ConsulConfig
if c3.SerfLANConfig.KeyringFile != "" {
t.Fatalf("should not have keyring file")
}
if c3.SerfLANConfig.MemberlistConfig.Keyring == nil {
t.Fatalf("keyring should be loaded")
}
if c3.SerfWANConfig.KeyringFile != "" {
t.Fatalf("bad: %#v", c3.SerfWANConfig.KeyringFile)
}
if c3.SerfWANConfig.MemberlistConfig.Keyring != nil {
t.Fatalf("keyring should not be loaded")
}
}

func TestAgent_InitKeyring(t *testing.T) {
t.Parallel()
key1 := "tbLJg26ZJyJ9pK3qhc9jig=="
Expand Down

0 comments on commit 0e6aa4f

Please sign in to comment.