Skip to content

Commit

Permalink
Re-submit authentication data on reconnect
Browse files Browse the repository at this point in the history
In case when reconnection occurs, it is necessary to re-authenticate
with ZK because it "forgets" the authentication data.
  • Loading branch information
Pawel Rozlach committed Aug 30, 2016
1 parent 8c6a1d7 commit 3449f0a
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion zk/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ type Logger interface {
Printf(string, ...interface{})
}

type authCreds struct {
scheme string
auth []byte
}

type Conn struct {
lastZxid int64
sessionID int64
Expand All @@ -81,6 +86,9 @@ type Conn struct {
recvTimeout time.Duration
connectTimeout time.Duration

creds []authCreds
credsMu sync.Mutex // protects server

sendChan chan *request
requests map[int32]*request // Xid -> pending request
requestsLock sync.Mutex
Expand Down Expand Up @@ -357,6 +365,20 @@ func (c *Conn) loop() {
wg.Done()
}()

c.credsMu.Lock()
if len(c.creds) > 0 {
c.logger.Printf("Re-submitting %d credentials after reconnect",
len(c.creds))
for _, cred := range c.creds {
err := c.addAuthInner(cred.scheme, cred.auth)
if err != nil {
c.logger.Printf("Credential re-submit failed: %s", err)
// FIXME(prozlach): lets ignore it here for now
}
}
}
c.credsMu.Unlock()

c.sendSetWatches()
wg.Wait()
}
Expand Down Expand Up @@ -722,11 +744,37 @@ func (c *Conn) request(opcode int32, req interface{}, res interface{}, recvFunc
return r.zxid, r.err
}

func (c *Conn) AddAuth(scheme string, auth []byte) error {
func (c *Conn) addAuthInner(scheme string, auth []byte) error {
_, err := c.request(opSetAuth, &setAuthRequest{Type: 0, Scheme: scheme, Auth: auth}, &setAuthResponse{}, nil)
return err
}

func (c *Conn) AddAuth(scheme string, auth []byte) error {
err := c.addAuthInner(scheme, auth)

if err != nil {
return err
}

// Remember authdata so that it can be re-submitted on reconnect
//
// FIXME(prozlach): For now we treat "userfoo:passbar" and "userfoo:passbar2"
// as two different entries, which will be re-submitted on reconnet. Some
// research is needed on how ZK treats these cases and
// then maybe switch to something like "map[username] = password" to allow
// only single password for given user with users being unique.
obj := authCreds{
scheme: scheme,
auth: auth,
}

c.credsMu.Lock()
c.creds = append(c.creds, obj)
c.credsMu.Unlock()

return nil
}

func (c *Conn) Children(path string) ([]string, *Stat, error) {
res := &getChildren2Response{}
_, err := c.request(opGetChildren2, &getChildren2Request{Path: path, Watch: false}, res, nil)
Expand Down

0 comments on commit 3449f0a

Please sign in to comment.