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"
)
const (
serfLANKeyring = "serf/local.keyring"
serfWANKeyring = "serf/remote.keyring"
)
/*
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
@ -116,37 +121,14 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) {
// Setup encryption keyring files
if config.PersistKeyring && config.EncryptKey != "" {
serfDir := filepath.Join(config.DataDir, "serf")
if err := os.MkdirAll(serfDir, 0700); 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)
if config.Server {
if err := agent.initKeyringFile(serfWANKeyring); err != nil {
return nil, err
}
}
if err := agent.initKeyringFile(serfLANKeyring); err != nil {
return nil, err
}
}
// Setup either the client or the server
@ -206,9 +188,8 @@ func (a *Agent) consulConfig() *consul.Config {
base.SerfWANConfig.MemberlistConfig.SecretKey = key
}
if a.config.PersistKeyring {
lanKeyring := filepath.Join(base.DataDir, "serf", "keyring_lan")
wanKeyring := filepath.Join(base.DataDir, "serf", "keyring_wan")
lanKeyring := filepath.Join(base.DataDir, serfLANKeyring)
wanKeyring := filepath.Join(base.DataDir, serfWANKeyring)
base.SerfLANConfig.KeyringFile = lanKeyring
base.SerfWANConfig.KeyringFile = wanKeyring
}
@ -825,3 +806,39 @@ func (a *Agent) RemoveKeyLAN(key string) (*serf.KeyResponse, error) {
km := a.client.KeyManagerLAN()
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
if config.EncryptKey != "" && config.CheckKeyringFiles() {
if config.EncryptKey != "" && (config.PersistKeyring && config.CheckKeyringFiles()) {
c.Ui.Error(fmt.Sprintf(
"WARNING: Keyring already exists, ignoring new key %s",
config.EncryptKey))
@ -594,7 +594,10 @@ func (c *Command) Run(args []string) int {
}
// 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
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
func (c *Config) CheckKeyringFiles() bool {
serfDir := filepath.Join(c.DataDir, "serf")
if _, err := os.Stat(filepath.Join(serfDir, "keyring_lan")); err != nil {
if _, err := os.Stat(filepath.Join(c.DataDir, serfLANKeyring)); err != nil {
return false
}
if _, err := os.Stat(filepath.Join(serfDir, "keyring_wan")); err != nil {
return false
if c.Server {
if _, err := os.Stat(filepath.Join(c.DataDir, serfWANKeyring)); err != nil {
return false
}
}
return true
}