Browse Source

Merge pull request #5613 from xiang90/rootrole

*: add admin permission checking
Xiang Li 9 years ago
parent
commit
6e32e8501a
2 changed files with 71 additions and 8 deletions
  1. 30 8
      auth/store.go
  2. 41 0
      etcdserver/apply.go

+ 30 - 8
auth/store.go

@@ -111,6 +111,9 @@ type AuthStore interface {
 
 
 	// IsRangePermitted checks range permission of the user
 	// IsRangePermitted checks range permission of the user
 	IsRangePermitted(header *pb.RequestHeader, key, rangeEnd string) bool
 	IsRangePermitted(header *pb.RequestHeader, key, rangeEnd string) bool
+
+	// IsAdminPermitted checks admin permission of the user
+	IsAdminPermitted(username string) bool
 }
 }
 
 
 type authStore struct {
 type authStore struct {
@@ -137,14 +140,7 @@ func (as *authStore) AuthEnable() error {
 		return ErrRootUserNotExist
 		return ErrRootUserNotExist
 	}
 	}
 
 
-	rootRoleExist := false
-	for _, r := range u.Roles {
-		if r == rootRole {
-			rootRoleExist = true
-			break
-		}
-	}
-	if !rootRoleExist {
+	if !hasRootRole(u) {
 		return ErrRootRoleNotExist
 		return ErrRootRoleNotExist
 	}
 	}
 
 
@@ -664,6 +660,23 @@ func (as *authStore) IsRangePermitted(header *pb.RequestHeader, key, rangeEnd st
 	return as.isOpPermitted(header.Username, key, rangeEnd, false, true)
 	return as.isOpPermitted(header.Username, key, rangeEnd, false, true)
 }
 }
 
 
+func (as *authStore) IsAdminPermitted(username string) bool {
+	if !as.isAuthEnabled() {
+		return true
+	}
+
+	tx := as.be.BatchTx()
+	tx.Lock()
+	defer tx.Unlock()
+
+	u := getUser(tx, username)
+	if u == nil {
+		return false
+	}
+
+	return hasRootRole(u)
+}
+
 func getUser(tx backend.BatchTx, username string) *authpb.User {
 func getUser(tx backend.BatchTx, username string) *authpb.User {
 	_, vs := tx.UnsafeRange(authUsersBucketName, []byte(username), nil, 0)
 	_, vs := tx.UnsafeRange(authUsersBucketName, []byte(username), nil, 0)
 	if len(vs) == 0 {
 	if len(vs) == 0 {
@@ -699,3 +712,12 @@ func NewAuthStore(be backend.Backend) *authStore {
 		be: be,
 		be: be,
 	}
 	}
 }
 }
+
+func hasRootRole(u *authpb.User) bool {
+	for _, r := range u.Roles {
+		if r == rootRole {
+			return true
+		}
+	}
+	return false
+}

+ 41 - 0
etcdserver/apply.go

@@ -79,6 +79,13 @@ type applierV3backend struct {
 
 
 func (s *EtcdServer) applyV3Request(r *pb.InternalRaftRequest) *applyResult {
 func (s *EtcdServer) applyV3Request(r *pb.InternalRaftRequest) *applyResult {
 	ar := &applyResult{}
 	ar := &applyResult{}
+	username := r.Header.Username
+
+	if needAdminPermission(r) && !s.AuthStore().IsAdminPermitted(username) {
+		ar.err = auth.ErrPermissionDenied
+		return ar
+	}
+
 	switch {
 	switch {
 	case r.Range != nil:
 	case r.Range != nil:
 		if s.AuthStore().IsRangePermitted(r.Header, string(r.Range.Key), string(r.Range.RangeEnd)) {
 		if s.AuthStore().IsRangePermitted(r.Header, string(r.Range.Key), string(r.Range.RangeEnd)) {
@@ -104,6 +111,7 @@ func (s *EtcdServer) applyV3Request(r *pb.InternalRaftRequest) *applyResult {
 		ar.resp, ar.err = s.applyV3.LeaseRevoke(r.LeaseRevoke)
 		ar.resp, ar.err = s.applyV3.LeaseRevoke(r.LeaseRevoke)
 	case r.Alarm != nil:
 	case r.Alarm != nil:
 		ar.resp, ar.err = s.applyV3.Alarm(r.Alarm)
 		ar.resp, ar.err = s.applyV3.Alarm(r.Alarm)
+
 	case r.AuthEnable != nil:
 	case r.AuthEnable != nil:
 		ar.resp, ar.err = s.applyV3.AuthEnable()
 		ar.resp, ar.err = s.applyV3.AuthEnable()
 	case r.AuthDisable != nil:
 	case r.AuthDisable != nil:
@@ -710,3 +718,36 @@ func compareInt64(a, b int64) int {
 func isGteRange(rangeEnd []byte) bool {
 func isGteRange(rangeEnd []byte) bool {
 	return len(rangeEnd) == 1 && rangeEnd[0] == 0
 	return len(rangeEnd) == 1 && rangeEnd[0] == 0
 }
 }
+
+func needAdminPermission(r *pb.InternalRaftRequest) bool {
+	switch {
+	case r.AuthEnable != nil:
+		return true
+	case r.AuthDisable != nil:
+		return true
+	case r.AuthUserAdd != nil:
+		return true
+	case r.AuthUserDelete != nil:
+		return true
+	case r.AuthUserChangePassword != nil:
+		return true
+	case r.AuthUserGrantRole != nil:
+		return true
+	case r.AuthUserGet != nil:
+		return true
+	case r.AuthUserRevokeRole != nil:
+		return true
+	case r.AuthRoleAdd != nil:
+		return true
+	case r.AuthRoleGrantPermission != nil:
+		return true
+	case r.AuthRoleGet != nil:
+		return true
+	case r.AuthRoleRevokePermission != nil:
+		return true
+	case r.AuthRoleDelete != nil:
+		return true
+	default:
+		return false
+	}
+}