agent: clean up keyring file implementation

This commit is contained in:
Ryan Uber 2014-09-11 22:28:23 -07:00
parent 2e92e19760
commit 3e64ed70df
3 changed files with 58 additions and 37 deletions

View File

@ -19,6 +19,11 @@ import (
"github.com/hashicorp/serf/serf" "github.com/hashicorp/serf/serf"
) )
const (
serfLANKeyring = "serf/local.keyring"
serfWANKeyring = "serf/remote.keyring"
)
/* /*
The agent is the long running process that is run on every machine. The agent is the long running process that is run on every machine.
It exposes an RPC interface that is used by the CLI to control the It exposes an RPC interface that is used by the CLI to control the
@ -116,37 +121,14 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) {
// Setup encryption keyring files // Setup encryption keyring files
if config.PersistKeyring && config.EncryptKey != "" { if config.PersistKeyring && config.EncryptKey != "" {
serfDir := filepath.Join(config.DataDir, "serf") if config.Server {
if err := os.MkdirAll(serfDir, 0700); err != nil { if err := agent.initKeyringFile(serfWANKeyring); err != nil {
return nil, err
}
keys := []string{config.EncryptKey}
keyringBytes, err := json.MarshalIndent(keys, "", " ")
if err != nil {
return nil, err
}
paths := []string{
filepath.Join(serfDir, "keyring_lan"),
filepath.Join(serfDir, "keyring_wan"),
}
for _, path := range paths {
if _, err := os.Stat(path); err == nil {
continue
}
fh, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
return nil, err
}
defer fh.Close()
if _, err := fh.Write(keyringBytes); err != nil {
os.Remove(path)
return nil, err return nil, err
} }
} }
if err := agent.initKeyringFile(serfLANKeyring); err != nil {
return nil, err
}
} }
// Setup either the client or the server // Setup either the client or the server
@ -206,9 +188,8 @@ func (a *Agent) consulConfig() *consul.Config {
base.SerfWANConfig.MemberlistConfig.SecretKey = key base.SerfWANConfig.MemberlistConfig.SecretKey = key
} }
if a.config.PersistKeyring { if a.config.PersistKeyring {
lanKeyring := filepath.Join(base.DataDir, "serf", "keyring_lan") lanKeyring := filepath.Join(base.DataDir, serfLANKeyring)
wanKeyring := filepath.Join(base.DataDir, "serf", "keyring_wan") wanKeyring := filepath.Join(base.DataDir, serfWANKeyring)
base.SerfLANConfig.KeyringFile = lanKeyring base.SerfLANConfig.KeyringFile = lanKeyring
base.SerfWANConfig.KeyringFile = wanKeyring base.SerfWANConfig.KeyringFile = wanKeyring
} }
@ -825,3 +806,39 @@ func (a *Agent) RemoveKeyLAN(key string) (*serf.KeyResponse, error) {
km := a.client.KeyManagerLAN() km := a.client.KeyManagerLAN()
return km.RemoveKey(key) return km.RemoveKey(key)
} }
// initKeyringFile is used to create and initialize a persistent keyring file
// for gossip encryption keys. It is used at agent startup to dump the initial
// encryption key into a keyfile if persistence is enabled.
func (a *Agent) initKeyringFile(path string) error {
serfDir := filepath.Join(a.config.DataDir, "serf")
if err := os.MkdirAll(serfDir, 0700); err != nil {
return err
}
keys := []string{a.config.EncryptKey}
keyringBytes, err := json.MarshalIndent(keys, "", " ")
if err != nil {
return err
}
keyringFile := filepath.Join(a.config.DataDir, path)
// If the keyring file already exists, don't re-initialize
if _, err := os.Stat(keyringFile); err == nil {
return nil
}
fh, err := os.OpenFile(keyringFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer fh.Close()
if _, err := fh.Write(keyringBytes); err != nil {
os.Remove(keyringFile)
return err
}
return nil
}

View File

@ -220,7 +220,7 @@ func (c *Command) readConfig() *Config {
} }
// Warn if an encryption key is passed while a keyring already exists // Warn if an encryption key is passed while a keyring already exists
if config.EncryptKey != "" && config.CheckKeyringFiles() { if config.EncryptKey != "" && (config.PersistKeyring && config.CheckKeyringFiles()) {
c.Ui.Error(fmt.Sprintf( c.Ui.Error(fmt.Sprintf(
"WARNING: Keyring already exists, ignoring new key %s", "WARNING: Keyring already exists, ignoring new key %s",
config.EncryptKey)) config.EncryptKey))
@ -594,7 +594,10 @@ func (c *Command) Run(args []string) int {
} }
// Determine if gossip is encrypted // Determine if gossip is encrypted
gossipEncrypted := (config.EncryptKey != "" || config.CheckKeyringFiles()) gossipEncrypted := false
if config.EncryptKey != "" || (config.PersistKeyring && config.CheckKeyringFiles()) {
gossipEncrypted = true
}
// Let the agent know we've finished registration // Let the agent know we've finished registration
c.agent.StartSync() c.agent.StartSync()

View File

@ -418,12 +418,13 @@ func (c *Config) ClientListenerAddr(override string, port int) (string, error) {
// CheckKeyringFiles checks for existence of the keyring files for Serf // CheckKeyringFiles checks for existence of the keyring files for Serf
func (c *Config) CheckKeyringFiles() bool { func (c *Config) CheckKeyringFiles() bool {
serfDir := filepath.Join(c.DataDir, "serf") if _, err := os.Stat(filepath.Join(c.DataDir, serfLANKeyring)); err != nil {
if _, err := os.Stat(filepath.Join(serfDir, "keyring_lan")); err != nil {
return false return false
} }
if _, err := os.Stat(filepath.Join(serfDir, "keyring_wan")); err != nil { if c.Server {
return false if _, err := os.Stat(filepath.Join(c.DataDir, serfWANKeyring)); err != nil {
return false
}
} }
return true return true
} }