func (nDB *NetworkDB) clusterInit() error { config := memberlist.DefaultLANConfig() config.Name = nDB.config.NodeName config.BindAddr = nDB.config.BindAddr if nDB.config.BindPort != 0 { config.BindPort = nDB.config.BindPort } config.ProtocolVersion = memberlist.ProtocolVersionMax config.Delegate = &delegate{nDB: nDB} config.Events = &eventDelegate{nDB: nDB} config.LogOutput = &logWriter{} var err error if len(nDB.config.Keys) > 0 { for i, key := range nDB.config.Keys { logrus.Debugf("Encryption key %d: %s", i+1, hex.EncodeToString(key)[0:5]) } nDB.keyring, err = memberlist.NewKeyring(nDB.config.Keys, nDB.config.Keys[0]) if err != nil { return err } config.Keyring = nDB.keyring } nDB.networkBroadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { return len(nDB.nodes) }, RetransmitMult: config.RetransmitMult, } mlist, err := memberlist.Create(config) if err != nil { return fmt.Errorf("failed to create memberlist: %v", err) } nDB.stopCh = make(chan struct{}) nDB.memberlist = mlist nDB.mConfig = config for _, trigger := range []struct { interval time.Duration fn func() }{ {reapInterval, nDB.reapState}, {config.GossipInterval, nDB.gossip}, {config.PushPullInterval, nDB.bulkSyncTables}, } { t := time.NewTicker(trigger.interval) go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn) nDB.tickers = append(nDB.tickers, t) } return nil }
// loadKeyringFile will load a keyring out of a file func (a *Agent) loadKeyringFile(keyringFile string) error { // Avoid passing an encryption key and a keyring file at the same time if len(a.agentConf.EncryptKey) > 0 { return fmt.Errorf("Encryption key not allowed while using a keyring") } if _, err := os.Stat(keyringFile); err != nil { return err } // Read in the keyring file data keyringData, err := ioutil.ReadFile(keyringFile) if err != nil { return fmt.Errorf("Failed to read keyring file: %s", err) } // Decode keyring JSON keys := make([]string, 0) if err := json.Unmarshal(keyringData, &keys); err != nil { return fmt.Errorf("Failed to decode keyring file: %s", err) } // Decode base64 values keysDecoded := make([][]byte, len(keys)) for i, key := range keys { keyBytes, err := base64.StdEncoding.DecodeString(key) if err != nil { return fmt.Errorf("Failed to decode key from keyring: %s", err) } keysDecoded[i] = keyBytes } // Guard against empty keyring file if len(keysDecoded) == 0 { return fmt.Errorf("Keyring file contains no keys") } // Create the keyring keyring, err := memberlist.NewKeyring(keysDecoded, keysDecoded[0]) if err != nil { return fmt.Errorf("Failed to restore keyring: %s", err) } a.conf.MemberlistConfig.Keyring = keyring a.logger.Printf("[INFO] agent: Restored keyring with %d keys from %s", len(keys), keyringFile) // Success! return nil }
// loadKeyringFile will load a gossip encryption keyring out of a file. The file // must be in JSON format and contain a list of encryption key strings. 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(c.KeyringFile) if err != nil { return err } // Decode keyring JSON keys := make([]string, 0) if err := json.Unmarshal(keyringData, &keys); err != nil { return err } // Decode base64 values keysDecoded := make([][]byte, len(keys)) for i, key := range keys { keyBytes, err := base64.StdEncoding.DecodeString(key) if err != nil { return err } keysDecoded[i] = keyBytes } // Guard against empty keyring if len(keysDecoded) == 0 { return fmt.Errorf("no keys present in keyring file: %s", c.KeyringFile) } // Create the keyring keyring, err := memberlist.NewKeyring(keysDecoded, keysDecoded[0]) if err != nil { return err } c.MemberlistConfig.Keyring = keyring // Success! return nil }
func testKeyring() (*memberlist.Keyring, error) { keys := []string{ "enjTwAFRe4IE71bOFhirzQ==", "csT9mxI7aTf9ap3HLBbdmA==", "noha2tVc0OyD/2LtCBoAOQ==", } keysDecoded := make([][]byte, len(keys)) for i, key := range keys { decoded, err := base64.StdEncoding.DecodeString(key) if err != nil { return nil, err } keysDecoded[i] = decoded } return memberlist.NewKeyring(keysDecoded, keysDecoded[0]) }
func testKeysCommandAgent(t *testing.T) *agent.Agent { key1, err := base64.StdEncoding.DecodeString("SNCg1bQSoCdGVlEx+TgfBw==") if err != nil { t.Fatalf("err: %s", err) } key2, err := base64.StdEncoding.DecodeString("vbitCcJNwNP4aEWHgofjMg==") if err != nil { t.Fatalf("err: %s", err) } keyring, err := memberlist.NewKeyring([][]byte{key1, key2}, key1) if err != nil { t.Fatalf("err: %s", err) } agentConf := agent.DefaultConfig() serfConf := serf.DefaultConfig() serfConf.MemberlistConfig.Keyring = keyring a1 := testAgentWithConfig(t, agentConf, serfConf) return a1 }
func TestSerf_WriteKeyringFile(t *testing.T) { existing := "jbuQMI4gMUeh1PPmKOtiBg==" newKey := "eodFZZjm7pPwIZ0Miy7boQ==" td, err := ioutil.TempDir("", "serf") if err != nil { t.Fatalf("err: %s", err) } defer os.RemoveAll(td) keyringFile := filepath.Join(td, "tags.json") existingBytes, err := base64.StdEncoding.DecodeString(existing) if err != nil { t.Fatalf("err: %s", err) } keys := [][]byte{existingBytes} keyring, err := memberlist.NewKeyring(keys, existingBytes) if err != nil { t.Fatalf("err: %s", err) } s1Config := testConfig() s1Config.MemberlistConfig.Keyring = keyring s1Config.KeyringFile = keyringFile s1, err := Create(s1Config) if err != nil { t.Fatalf("err: %s", err) } defer s1.Shutdown() manager := s1.KeyManager() if _, err := manager.InstallKey(newKey); err != nil { t.Fatalf("err: %s", err) } content, err := ioutil.ReadFile(keyringFile) if err != nil { t.Fatalf("err: %s", err) } lines := strings.Split(string(content), "\n") if len(lines) != 4 { t.Fatalf("bad: %v", lines) } // Ensure both the original key and the new key are present in the file if !strings.Contains(string(content), existing) { t.Fatalf("key not found in keyring file: %s", existing) } if !strings.Contains(string(content), newKey) { t.Fatalf("key not found in keyring file: %s", newKey) } // Ensure the existing key remains primary. This is in position 1 because // the file writer will use json.MarshalIndent(), leaving the first line as // the opening bracket. if !strings.Contains(lines[1], existing) { t.Fatalf("expected key to be primary: %s", existing) } // Swap primary keys if _, err := manager.UseKey(newKey); err != nil { t.Fatalf("err: %s", err) } content, err = ioutil.ReadFile(keyringFile) if err != nil { t.Fatalf("err: %s", err) } lines = strings.Split(string(content), "\n") if len(lines) != 4 { t.Fatalf("bad: %v", lines) } // Key order should have changed in keyring file if !strings.Contains(lines[1], newKey) { t.Fatalf("expected key to be primary: %s", newKey) } // Remove the old key if _, err := manager.RemoveKey(existing); err != nil { t.Fatalf("err: %s", err) } content, err = ioutil.ReadFile(keyringFile) if err != nil { t.Fatalf("err: %s", err) } lines = strings.Split(string(content), "\n") if len(lines) != 3 { t.Fatalf("bad: %v", lines) } // Only the new key should now be present in the keyring file if len(lines) != 3 { t.Fatalf("bad: %v", lines) } if !strings.Contains(lines[1], newKey) { t.Fatalf("expected key to be primary: %s", newKey) } }
func (nDB *NetworkDB) clusterInit() error { config := memberlist.DefaultLANConfig() config.Name = nDB.config.NodeName config.BindAddr = nDB.config.BindAddr config.AdvertiseAddr = nDB.config.AdvertiseAddr if nDB.config.BindPort != 0 { config.BindPort = nDB.config.BindPort } config.ProtocolVersion = memberlist.ProtocolVersionMax config.Delegate = &delegate{nDB: nDB} config.Events = &eventDelegate{nDB: nDB} // custom logger that does not add time or date, so they are not // duplicated by logrus config.Logger = log.New(&logWriter{}, "", 0) var err error if len(nDB.config.Keys) > 0 { for i, key := range nDB.config.Keys { logrus.Debugf("Encryption key %d: %s", i+1, hex.EncodeToString(key)[0:5]) } nDB.keyring, err = memberlist.NewKeyring(nDB.config.Keys, nDB.config.Keys[0]) if err != nil { return err } config.Keyring = nDB.keyring } nDB.networkBroadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { nDB.RLock() num := len(nDB.nodes) nDB.RUnlock() return num }, RetransmitMult: config.RetransmitMult, } nDB.nodeBroadcasts = &memberlist.TransmitLimitedQueue{ NumNodes: func() int { nDB.RLock() num := len(nDB.nodes) nDB.RUnlock() return num }, RetransmitMult: config.RetransmitMult, } mlist, err := memberlist.Create(config) if err != nil { return fmt.Errorf("failed to create memberlist: %v", err) } nDB.stopCh = make(chan struct{}) nDB.memberlist = mlist for _, trigger := range []struct { interval time.Duration fn func() }{ {reapPeriod, nDB.reapState}, {config.GossipInterval, nDB.gossip}, {config.PushPullInterval, nDB.bulkSyncTables}, {retryInterval, nDB.reconnectNode}, {nodeReapPeriod, nDB.reapDeadNode}, } { t := time.NewTicker(trigger.interval) go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn) nDB.tickers = append(nDB.tickers, t) } return nil }