From 65da65c3c7d71e555dc120502e1e31ecefea1a47 Mon Sep 17 00:00:00 2001 From: Matt Reiferson Date: Sat, 18 Jul 2015 16:10:11 -0700 Subject: [PATCH] nsqd: share TLS key with serf --- nsqd/gossip.go | 46 +++++++++++++++++++++++++++++++++++++++++++++- nsqd/nsqd.go | 5 ++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/nsqd/gossip.go b/nsqd/gossip.go index 951286ae3..845ce1baf 100644 --- a/nsqd/gossip.go +++ b/nsqd/gossip.go @@ -2,6 +2,8 @@ package nsqd import ( "bytes" + "crypto/rand" + "encoding/base64" "encoding/json" "net" "os" @@ -62,7 +64,8 @@ func initSerf(opts *Options, tcpAddr *net.TCPAddr, httpAddr *net.TCPAddr, httpsAddr *net.TCPAddr, - broadcastAddr *net.TCPAddr) (*serf.Serf, error) { + broadcastAddr *net.TCPAddr, + key []byte) (*serf.Serf, error) { hostname, err := os.Hostname() if err != nil { @@ -93,6 +96,9 @@ func initSerf(opts *Options, serfConfig.MemberlistConfig.GossipInterval = 100 * time.Millisecond serfConfig.MemberlistConfig.GossipNodes = 5 serfConfig.MemberlistConfig.LogOutput = logWriter{opts.Logger, []byte("memberlist:")} + if len(key) != 0 { + serfConfig.MemberlistConfig.SecretKey = key + } serfConfig.EventCh = serfEventChan serfConfig.EventBuffer = 1024 serfConfig.ReconnectTimeout = time.Hour @@ -286,6 +292,13 @@ func (n *NSQD) gossipLoop() { var topicName string var channelName string + if n.serf.EncryptionEnabled() { + err := n.rotateGossipKey() + n.logf("FATAL: could not rotate gossip key - %s", err) + n.Exit() + return + } + regossipTicker := time.NewTicker(n.getOpts().GossipRegossipInterval) if len(n.getOpts().GossipSeedAddresses) > 0 { @@ -363,3 +376,34 @@ exit: regossipTicker.Stop() n.logf("GOSSIP: exiting") } + +func (n *NSQD) initialGossipKey() []byte { + var key []byte + if n.tlsConfig != nil && len(n.tlsConfig.Certificates) > 0 { + key = n.tlsConfig.Certificates[0].Leaf.Signature + } + if n.gossipKey == nil { + n.gossipKey = key + } + return key +} + +func (n *NSQD) rotateGossipKey() error { + if n.gossipKey == nil { + return nil + } + + key := make([]byte, 32) + _, err := rand.Reader.Read(key) + strKey := base64.StdEncoding.EncodeToString(key) + _, err = n.serf.KeyManager().InstallKey(strKey) + if err != nil { + return err + } + _, err = n.serf.KeyManager().UseKey(strKey) + if err != nil { + return err + } + _, err = n.serf.KeyManager().RemoveKey(string(n.gossipKey)) + return err +} diff --git a/nsqd/nsqd.go b/nsqd/nsqd.go index b266ea372..d975db5eb 100644 --- a/nsqd/nsqd.go +++ b/nsqd/nsqd.go @@ -66,6 +66,7 @@ type NSQD struct { serf *serf.Serf serfEventChan chan serf.Event gossipChan chan interface{} + gossipKey []byte rdb *registrationdb.RegistrationDB idChan chan MessageID @@ -295,7 +296,9 @@ func (n *NSQD) Main() { n.RealTCPAddr(), n.RealHTTPAddr(), httpsAddr, - broadcastAddr) + broadcastAddr, + n.initialGossipKey(), + ) if err != nil { n.logf("FATAL: failed to initialize Serf - %s", err) os.Exit(1)