diff --git a/command/agent/agent.go b/command/agent/agent.go index 456415f964..5453f4ad95 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -115,7 +115,7 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) { agent.state.Init(config, agent.logger) // Setup encryption keyring files - if !config.DisableKeyring && config.EncryptKey != "" { + if config.PersistKeyring && config.EncryptKey != "" { serfDir := filepath.Join(config.DataDir, "serf") if err := os.MkdirAll(serfDir, 0700); err != nil { return nil, err @@ -200,20 +200,17 @@ func (a *Agent) consulConfig() *consul.Config { if a.config.DataDir != "" { base.DataDir = a.config.DataDir } - if a.config.EncryptKey != "" && a.config.DisableKeyring { + if a.config.EncryptKey != "" && !a.config.PersistKeyring { key, _ := a.config.EncryptBytes() base.SerfLANConfig.MemberlistConfig.SecretKey = key base.SerfWANConfig.MemberlistConfig.SecretKey = key } - if !a.config.DisableKeyring { + if a.config.PersistKeyring { lanKeyring := filepath.Join(base.DataDir, "serf", "keyring_lan") wanKeyring := filepath.Join(base.DataDir, "serf", "keyring_wan") base.SerfLANConfig.KeyringFile = lanKeyring base.SerfWANConfig.KeyringFile = wanKeyring - - base.SerfLANConfig.MemberlistConfig.Keyring = loadKeyringFile(lanKeyring) - base.SerfWANConfig.MemberlistConfig.Keyring = loadKeyringFile(wanKeyring) } if a.config.NodeName != "" { base.NodeName = a.config.NodeName @@ -303,9 +300,6 @@ func (a *Agent) consulConfig() *consul.Config { } } - // Setup gossip keyring configuration - base.DisableKeyring = a.config.DisableKeyring - // Setup the loggers base.LogOutput = a.logOutput return base @@ -313,6 +307,16 @@ func (a *Agent) consulConfig() *consul.Config { // setupServer is used to initialize the Consul server func (a *Agent) setupServer() error { + config := a.consulConfig() + + // Load a keyring file, if present + if err := loadKeyringFile(config.SerfLANConfig); err != nil { + return err + } + if err := loadKeyringFile(config.SerfWANConfig); err != nil { + return err + } + server, err := consul.NewServer(a.consulConfig()) if err != nil { return fmt.Errorf("Failed to start Consul server: %v", err) @@ -703,21 +707,25 @@ func (a *Agent) deletePid() error { } // loadKeyringFile will load a keyring out of a file -func loadKeyringFile(keyringFile string) *memberlist.Keyring { - if _, err := os.Stat(keyringFile); err != nil { +func loadKeyringFile(c *serf.Config) error { + if c.KeyringFile == "" { return nil } + if _, err := os.Stat(c.KeyringFile); err != nil { + return err + } + // Read in the keyring file data - keyringData, err := ioutil.ReadFile(keyringFile) + keyringData, err := ioutil.ReadFile(c.KeyringFile) if err != nil { - return nil + return err } // Decode keyring JSON keys := make([]string, 0) if err := json.Unmarshal(keyringData, &keys); err != nil { - return nil + return err } // Decode base64 values @@ -725,7 +733,7 @@ func loadKeyringFile(keyringFile string) *memberlist.Keyring { for i, key := range keys { keyBytes, err := base64.StdEncoding.DecodeString(key) if err != nil { - return nil + return err } keysDecoded[i] = keyBytes } @@ -733,11 +741,13 @@ func loadKeyringFile(keyringFile string) *memberlist.Keyring { // Create the keyring keyring, err := memberlist.NewKeyring(keysDecoded, keysDecoded[0]) if err != nil { - return nil + return err } + c.MemberlistConfig.Keyring = keyring + // Success! - return keyring + return nil } // ListKeysLAN returns the keys installed on the LAN gossip pool diff --git a/command/agent/command.go b/command/agent/command.go index 649cded48f..6f1da6cf7a 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -67,7 +67,7 @@ func (c *Command) readConfig() *Config { cmdFlags.StringVar(&cmdConfig.UiDir, "ui-dir", "", "path to the web UI directory") cmdFlags.StringVar(&cmdConfig.PidFile, "pid-file", "", "path to file to store PID") cmdFlags.StringVar(&cmdConfig.EncryptKey, "encrypt", "", "gossip encryption key") - cmdFlags.BoolVar(&cmdConfig.DisableKeyring, "disable-keyring", false, "disable use of encryption keyring") + cmdFlags.BoolVar(&cmdConfig.PersistKeyring, "persist-keyring", false, "persist keyring changes") cmdFlags.BoolVar(&cmdConfig.Server, "server", false, "run agent as server") cmdFlags.BoolVar(&cmdConfig.Bootstrap, "bootstrap", false, "enable server bootstrap mode") @@ -802,10 +802,6 @@ Options: -data-dir=path Path to a data directory to store agent state -dc=east-aws Datacenter of the agent -encrypt=key Provides the gossip encryption key - -disable-keyring Disables the use of an encryption keyring. The - Default behavior is to persist encryption keys using - a keyring file, and reload the keys on subsequent - starts. This argument disables keyring persistence. -join=1.2.3.4 Address of an agent to join at start time. Can be specified multiple times. -join-wan=1.2.3.4 Address of an agent to join -wan at start time. @@ -823,6 +819,7 @@ Options: -log-level=info Log level of the agent. -node=hostname Name of this node. Must be unique in the cluster -protocol=N Sets the protocol version. Defaults to latest. + -persist-keyring Enable encryption keyring persistence. -rejoin Ignores a previous leave and attempts to rejoin the cluster. -server Switches agent to server mode. -syslog Enables logging to syslog diff --git a/command/agent/config.go b/command/agent/config.go index 2fad1db399..cb35961674 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -104,13 +104,13 @@ type Config struct { // recursors array. DNSRecursor string `mapstructure:"recursor"` - // Disable use of an encryption keyring. - DisableKeyring bool `mapstructure:"disable_keyring"` - // DNSRecursors can be set to allow the DNS servers to recursively // resolve non-consul domains DNSRecursors []string `mapstructure:"recursors"` + // Disable use of an encryption keyring. + DisableKeyring bool `mapstructure:"disable_keyring"` + // DNS configuration DNSConfig DNSConfig `mapstructure:"dns_config"` @@ -150,6 +150,11 @@ type Config struct { // the TERM signal. Defaults false. This can be changed on reload. LeaveOnTerm bool `mapstructure:"leave_on_terminate"` + // Enable keyring persistence. There are currently two keyrings; one for + // the LAN serf cluster and the other for the WAN. Each will maintain its + // own keyring file in the agent's data directory. + PersistKeyring bool `mapstructure:"persist_keyring"` + // SkipLeaveOnInt controls if Serf skips a graceful leave when receiving // the INT signal. Defaults false. This can be changed on reload. SkipLeaveOnInt bool `mapstructure:"skip_leave_on_interrupt"` @@ -691,8 +696,8 @@ func MergeConfig(a, b *Config) *Config { if b.EncryptKey != "" { result.EncryptKey = b.EncryptKey } - if b.DisableKeyring { - result.DisableKeyring = true + if b.PersistKeyring { + result.PersistKeyring = true } if b.LogLevel != "" { result.LogLevel = b.LogLevel diff --git a/consul/config.go b/consul/config.go index 10acaab2c6..9cb1944cbc 100644 --- a/consul/config.go +++ b/consul/config.go @@ -165,11 +165,6 @@ type Config struct { // UserEventHandler callback can be used to handle incoming // user events. This function should not block. UserEventHandler func(serf.UserEvent) - - // DisableKeyring is used to disable persisting the encryption keyring to - // filesystem. By default, if encryption is enabled, Consul will create a - // file inside of the DataDir to keep track of changes made to the ring. - DisableKeyring bool } // CheckVersion is used to check if the ProtocolVersion is valid