|
|
|
@ -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 |
|
|
|
|
} |
|
|
|
|