diff --git a/agent/agent.go b/agent/agent.go index e81b91fc31b1..d65525767ace 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -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 @@ -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) @@ -1061,7 +1080,6 @@ LOAD: } } - // Success! return nil } diff --git a/agent/keyring.go b/agent/keyring.go index e1171d45eeb3..18b2bc3736ec 100644 --- a/agent/keyring.go +++ b/agent/keyring.go @@ -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) @@ -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 } diff --git a/agent/keyring_test.go b/agent/keyring_test.go index ac37364588e1..f2b74f841f7f 100644 --- a/agent/keyring_test.go +++ b/agent/keyring_test.go @@ -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=="