Browse Source

auth: correct initialization in NewAuthStore()

Because of my own silly mistake, current NewAuthStore() doesn't
initialize authStore in a correct manner. For example, after recovery
from snapshot, it cannot revive the flag of enabled/disabled. This
commit fixes the problem.

Fix https://github.com/coreos/etcd/issues/7165
Hitoshi Mitake 9 years ago
parent
commit
9976d869c1
2 changed files with 35 additions and 14 deletions
  1. 32 14
      auth/store.go
  2. 3 0
      auth/store_test.go

+ 32 - 14
auth/store.go

@@ -182,6 +182,17 @@ type authStore struct {
 	indexWaiter func(uint64) <-chan struct{}
 	indexWaiter func(uint64) <-chan struct{}
 }
 }
 
 
+func newDeleterFunc(as *authStore) func(string) {
+	return func(t string) {
+		as.simpleTokensMu.Lock()
+		defer as.simpleTokensMu.Unlock()
+		if username, ok := as.simpleTokens[t]; ok {
+			plog.Infof("deleting token %s for user %s", t, username)
+			delete(as.simpleTokens, t)
+		}
+	}
+}
+
 func (as *authStore) AuthEnable() error {
 func (as *authStore) AuthEnable() error {
 	as.enabledMu.Lock()
 	as.enabledMu.Lock()
 	defer as.enabledMu.Unlock()
 	defer as.enabledMu.Unlock()
@@ -210,15 +221,7 @@ func (as *authStore) AuthEnable() error {
 
 
 	as.enabled = true
 	as.enabled = true
 
 
-	tokenDeleteFunc := func(t string) {
-		as.simpleTokensMu.Lock()
-		defer as.simpleTokensMu.Unlock()
-		if username, ok := as.simpleTokens[t]; ok {
-			plog.Infof("deleting token %s for user %s", t, username)
-			delete(as.simpleTokens, t)
-		}
-	}
-	as.simpleTokenKeeper = NewSimpleTokenTTLKeeper(tokenDeleteFunc)
+	as.simpleTokenKeeper = NewSimpleTokenTTLKeeper(newDeleterFunc(as))
 
 
 	as.rangePermCache = make(map[string]*unifiedRangePermissions)
 	as.rangePermCache = make(map[string]*unifiedRangePermissions)
 
 
@@ -892,11 +895,25 @@ func NewAuthStore(be backend.Backend, indexWaiter func(uint64) <-chan struct{})
 	tx.UnsafeCreateBucket(authUsersBucketName)
 	tx.UnsafeCreateBucket(authUsersBucketName)
 	tx.UnsafeCreateBucket(authRolesBucketName)
 	tx.UnsafeCreateBucket(authRolesBucketName)
 
 
+	enabled := false
+	_, vs := tx.UnsafeRange(authBucketName, enableFlagKey, nil, 0)
+	if len(vs) == 1 {
+		if bytes.Equal(vs[0], authEnabled) {
+			enabled = true
+		}
+	}
+
 	as := &authStore{
 	as := &authStore{
-		be:           be,
-		simpleTokens: make(map[string]string),
-		revision:     0,
-		indexWaiter:  indexWaiter,
+		be:             be,
+		simpleTokens:   make(map[string]string),
+		revision:       getRevision(tx),
+		indexWaiter:    indexWaiter,
+		enabled:        enabled,
+		rangePermCache: make(map[string]*unifiedRangePermissions),
+	}
+
+	if enabled {
+		as.simpleTokenKeeper = NewSimpleTokenTTLKeeper(newDeleterFunc(as))
 	}
 	}
 
 
 	as.commitRevision(tx)
 	as.commitRevision(tx)
@@ -926,7 +943,8 @@ func (as *authStore) commitRevision(tx backend.BatchTx) {
 func getRevision(tx backend.BatchTx) uint64 {
 func getRevision(tx backend.BatchTx) uint64 {
 	_, vs := tx.UnsafeRange(authBucketName, []byte(revisionKey), nil, 0)
 	_, vs := tx.UnsafeRange(authBucketName, []byte(revisionKey), nil, 0)
 	if len(vs) != 1 {
 	if len(vs) != 1 {
-		plog.Panicf("failed to get the key of auth store revision")
+		// this can happen in the initialization phase
+		return 0
 	}
 	}
 
 
 	return binary.BigEndian.Uint64(vs[0])
 	return binary.BigEndian.Uint64(vs[0])

+ 3 - 0
auth/store_test.go

@@ -517,6 +517,9 @@ func TestRecoverFromSnapshot(t *testing.T) {
 	as.Close()
 	as.Close()
 
 
 	as2 := NewAuthStore(as.be, dummyIndexWaiter)
 	as2 := NewAuthStore(as.be, dummyIndexWaiter)
+	defer func(a *authStore) {
+		a.Close()
+	}(as2)
 
 
 	if !as2.isAuthEnabled() {
 	if !as2.isAuthEnabled() {
 		t.Fatal("recovering authStore from existing backend failed")
 		t.Fatal("recovering authStore from existing backend failed")