agent: refactor keyring loader

pull/336/head
Ryan Uber 2014-09-11 19:52:16 -07:00
parent cea2b49c15
commit fcb0961436
4 changed files with 39 additions and 32 deletions

View File

@ -115,7 +115,7 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) {
agent.state.Init(config, agent.logger) agent.state.Init(config, agent.logger)
// Setup encryption keyring files // Setup encryption keyring files
if !config.DisableKeyring && config.EncryptKey != "" { if config.PersistKeyring && config.EncryptKey != "" {
serfDir := filepath.Join(config.DataDir, "serf") serfDir := filepath.Join(config.DataDir, "serf")
if err := os.MkdirAll(serfDir, 0700); err != nil { if err := os.MkdirAll(serfDir, 0700); err != nil {
return nil, err return nil, err
@ -200,20 +200,17 @@ func (a *Agent) consulConfig() *consul.Config {
if a.config.DataDir != "" { if a.config.DataDir != "" {
base.DataDir = 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() key, _ := a.config.EncryptBytes()
base.SerfLANConfig.MemberlistConfig.SecretKey = key base.SerfLANConfig.MemberlistConfig.SecretKey = key
base.SerfWANConfig.MemberlistConfig.SecretKey = key base.SerfWANConfig.MemberlistConfig.SecretKey = key
} }
if !a.config.DisableKeyring { if a.config.PersistKeyring {
lanKeyring := filepath.Join(base.DataDir, "serf", "keyring_lan") lanKeyring := filepath.Join(base.DataDir, "serf", "keyring_lan")
wanKeyring := filepath.Join(base.DataDir, "serf", "keyring_wan") wanKeyring := filepath.Join(base.DataDir, "serf", "keyring_wan")
base.SerfLANConfig.KeyringFile = lanKeyring base.SerfLANConfig.KeyringFile = lanKeyring
base.SerfWANConfig.KeyringFile = wanKeyring base.SerfWANConfig.KeyringFile = wanKeyring
base.SerfLANConfig.MemberlistConfig.Keyring = loadKeyringFile(lanKeyring)
base.SerfWANConfig.MemberlistConfig.Keyring = loadKeyringFile(wanKeyring)
} }
if a.config.NodeName != "" { if a.config.NodeName != "" {
base.NodeName = 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 // Setup the loggers
base.LogOutput = a.logOutput base.LogOutput = a.logOutput
return base return base
@ -313,6 +307,16 @@ func (a *Agent) consulConfig() *consul.Config {
// setupServer is used to initialize the Consul server // setupServer is used to initialize the Consul server
func (a *Agent) setupServer() error { 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()) server, err := consul.NewServer(a.consulConfig())
if err != nil { if err != nil {
return fmt.Errorf("Failed to start Consul server: %v", err) 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 // loadKeyringFile will load a keyring out of a file
func loadKeyringFile(keyringFile string) *memberlist.Keyring { func loadKeyringFile(c *serf.Config) error {
if _, err := os.Stat(keyringFile); err != nil { if c.KeyringFile == "" {
return nil return nil
} }
if _, err := os.Stat(c.KeyringFile); err != nil {
return err
}
// Read in the keyring file data // Read in the keyring file data
keyringData, err := ioutil.ReadFile(keyringFile) keyringData, err := ioutil.ReadFile(c.KeyringFile)
if err != nil { if err != nil {
return nil return err
} }
// Decode keyring JSON // Decode keyring JSON
keys := make([]string, 0) keys := make([]string, 0)
if err := json.Unmarshal(keyringData, &keys); err != nil { if err := json.Unmarshal(keyringData, &keys); err != nil {
return nil return err
} }
// Decode base64 values // Decode base64 values
@ -725,7 +733,7 @@ func loadKeyringFile(keyringFile string) *memberlist.Keyring {
for i, key := range keys { for i, key := range keys {
keyBytes, err := base64.StdEncoding.DecodeString(key) keyBytes, err := base64.StdEncoding.DecodeString(key)
if err != nil { if err != nil {
return nil return err
} }
keysDecoded[i] = keyBytes keysDecoded[i] = keyBytes
} }
@ -733,11 +741,13 @@ func loadKeyringFile(keyringFile string) *memberlist.Keyring {
// Create the keyring // Create the keyring
keyring, err := memberlist.NewKeyring(keysDecoded, keysDecoded[0]) keyring, err := memberlist.NewKeyring(keysDecoded, keysDecoded[0])
if err != nil { if err != nil {
return nil return err
} }
c.MemberlistConfig.Keyring = keyring
// Success! // Success!
return keyring return nil
} }
// ListKeysLAN returns the keys installed on the LAN gossip pool // ListKeysLAN returns the keys installed on the LAN gossip pool

View File

@ -67,7 +67,7 @@ func (c *Command) readConfig() *Config {
cmdFlags.StringVar(&cmdConfig.UiDir, "ui-dir", "", "path to the web UI directory") 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.PidFile, "pid-file", "", "path to file to store PID")
cmdFlags.StringVar(&cmdConfig.EncryptKey, "encrypt", "", "gossip encryption key") 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.Server, "server", false, "run agent as server")
cmdFlags.BoolVar(&cmdConfig.Bootstrap, "bootstrap", false, "enable server bootstrap mode") 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 -data-dir=path Path to a data directory to store agent state
-dc=east-aws Datacenter of the agent -dc=east-aws Datacenter of the agent
-encrypt=key Provides the gossip encryption key -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. -join=1.2.3.4 Address of an agent to join at start time.
Can be specified multiple times. Can be specified multiple times.
-join-wan=1.2.3.4 Address of an agent to join -wan at start time. -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. -log-level=info Log level of the agent.
-node=hostname Name of this node. Must be unique in the cluster -node=hostname Name of this node. Must be unique in the cluster
-protocol=N Sets the protocol version. Defaults to latest. -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. -rejoin Ignores a previous leave and attempts to rejoin the cluster.
-server Switches agent to server mode. -server Switches agent to server mode.
-syslog Enables logging to syslog -syslog Enables logging to syslog

View File

@ -104,13 +104,13 @@ type Config struct {
// recursors array. // recursors array.
DNSRecursor string `mapstructure:"recursor"` 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 // DNSRecursors can be set to allow the DNS servers to recursively
// resolve non-consul domains // resolve non-consul domains
DNSRecursors []string `mapstructure:"recursors"` DNSRecursors []string `mapstructure:"recursors"`
// Disable use of an encryption keyring.
DisableKeyring bool `mapstructure:"disable_keyring"`
// DNS configuration // DNS configuration
DNSConfig DNSConfig `mapstructure:"dns_config"` DNSConfig DNSConfig `mapstructure:"dns_config"`
@ -150,6 +150,11 @@ type Config struct {
// the TERM signal. Defaults false. This can be changed on reload. // the TERM signal. Defaults false. This can be changed on reload.
LeaveOnTerm bool `mapstructure:"leave_on_terminate"` 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 // SkipLeaveOnInt controls if Serf skips a graceful leave when receiving
// the INT signal. Defaults false. This can be changed on reload. // the INT signal. Defaults false. This can be changed on reload.
SkipLeaveOnInt bool `mapstructure:"skip_leave_on_interrupt"` SkipLeaveOnInt bool `mapstructure:"skip_leave_on_interrupt"`
@ -691,8 +696,8 @@ func MergeConfig(a, b *Config) *Config {
if b.EncryptKey != "" { if b.EncryptKey != "" {
result.EncryptKey = b.EncryptKey result.EncryptKey = b.EncryptKey
} }
if b.DisableKeyring { if b.PersistKeyring {
result.DisableKeyring = true result.PersistKeyring = true
} }
if b.LogLevel != "" { if b.LogLevel != "" {
result.LogLevel = b.LogLevel result.LogLevel = b.LogLevel

View File

@ -165,11 +165,6 @@ type Config struct {
// UserEventHandler callback can be used to handle incoming // UserEventHandler callback can be used to handle incoming
// user events. This function should not block. // user events. This function should not block.
UserEventHandler func(serf.UserEvent) 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 // CheckVersion is used to check if the ProtocolVersion is valid