Merge pull request #5586 from xiang90/root

auth: add root user and root role
This commit is contained in:
Xiang Li 2016-06-09 00:23:45 -07:00
commit fb0df211f0
5 changed files with 61 additions and 8 deletions

View File

@ -37,6 +37,8 @@ var (
plog = capnslog.NewPackageLogger("github.com/coreos/etcd", "auth")
ErrRootUserNotExist = errors.New("auth: root user does not exist")
ErrRootRoleNotExist = errors.New("auth: root user does not have root role")
ErrUserAlreadyExist = errors.New("auth: user already exists")
ErrUserNotFound = errors.New("auth: user not found")
ErrRoleAlreadyExist = errors.New("auth: role already exists")
@ -47,9 +49,14 @@ var (
ErrPermissionNotGranted = errors.New("auth: permission is not granted to the role")
)
const (
rootUser = "root"
rootRole = "root"
)
type AuthStore interface {
// AuthEnable turns on the authentication feature
AuthEnable()
AuthEnable() error
// AuthDisable turns off the authentication feature
AuthDisable()
@ -114,15 +121,34 @@ type authStore struct {
rangePermCache map[string]*unifiedRangePermissions // username -> unifiedRangePermissions
}
func (as *authStore) AuthEnable() {
func (as *authStore) AuthEnable() error {
value := []byte{1}
b := as.be
tx := b.BatchTx()
tx.Lock()
defer func() {
tx.Unlock()
b.ForceCommit()
}()
u := getUser(tx, rootUser)
if u == nil {
return ErrRootUserNotExist
}
rootRoleExist := false
for _, r := range u.Roles {
if r == rootRole {
rootRoleExist = true
break
}
}
if !rootRoleExist {
return ErrRootRoleNotExist
}
tx.UnsafePut(authBucketName, enableFlagKey, value)
tx.Unlock()
b.ForceCommit()
as.enabledMu.Lock()
as.enabled = true
@ -131,6 +157,8 @@ func (as *authStore) AuthEnable() {
as.rangePermCache = make(map[string]*unifiedRangePermissions)
plog.Noticef("Authentication enabled")
return nil
}
func (as *authStore) AuthDisable() {
@ -284,9 +312,11 @@ func (as *authStore) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUser
return nil, ErrUserNotFound
}
_, vs := tx.UnsafeRange(authRolesBucketName, []byte(r.Role), nil, 0)
if len(vs) != 1 {
return nil, ErrRoleNotFound
if r.Role != rootRole {
_, vs := tx.UnsafeRange(authRolesBucketName, []byte(r.Role), nil, 0)
if len(vs) != 1 {
return nil, ErrRoleNotFound
}
}
idx := sort.SearchStrings(user.Roles, r.Role)

View File

@ -20,6 +20,15 @@ func TestCtlV3AuthEnable(t *testing.T) { testCtl(t, authEnableTest) }
func TestCtlV3AuthDisable(t *testing.T) { testCtl(t, authDisableTest) }
func authEnableTest(cx ctlCtx) {
// create root user with root role
if err := ctlV3User(cx, []string{"add", "root", "--interactive=false"}, "User root created", []string{"root"}); err != nil {
cx.t.Fatalf("failed to create root user %v", err)
}
if err := ctlV3User(cx, []string{"grant-role", "root", "root"}, "Role root is granted to user root", nil); err != nil {
cx.t.Fatalf("failed to grant root user root role %v", err)
}
if err := ctlV3AuthEnable(cx); err != nil {
cx.t.Fatalf("authEnableTest ctlV3AuthEnable error (%v)", err)
}

View File

@ -38,6 +38,8 @@ var (
ErrGRPCRequestTooLarge = grpc.Errorf(codes.InvalidArgument, "etcdserver: request is too large")
ErrGRPCRootUserNotExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: root user does not exist")
ErrGRPCRootRoleNotExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: root user does not have root role")
ErrGRPCUserAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name already exists")
ErrGRPCUserNotFound = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name not found")
ErrGRPCRoleAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: role name already exists")
@ -68,6 +70,8 @@ var (
grpc.ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge,
grpc.ErrorDesc(ErrGRPCRootUserNotExist): ErrGRPCRootUserNotExist,
grpc.ErrorDesc(ErrGRPCRootRoleNotExist): ErrGRPCRootRoleNotExist,
grpc.ErrorDesc(ErrGRPCUserAlreadyExist): ErrGRPCUserAlreadyExist,
grpc.ErrorDesc(ErrGRPCUserNotFound): ErrGRPCUserNotFound,
grpc.ErrorDesc(ErrGRPCRoleAlreadyExist): ErrGRPCRoleAlreadyExist,
@ -99,6 +103,8 @@ var (
ErrRequestTooLarge = Error(ErrGRPCRequestTooLarge)
ErrRootUserNotExist = Error(ErrGRPCRootUserNotExist)
ErrRootRoleNotExist = Error(ErrGRPCRootRoleNotExist)
ErrUserAlreadyExist = Error(ErrGRPCUserAlreadyExist)
ErrUserNotFound = Error(ErrGRPCUserNotFound)
ErrRoleAlreadyExist = Error(ErrGRPCRoleAlreadyExist)

View File

@ -37,6 +37,11 @@ func togRPCError(err error) error {
return rpctypes.ErrGRPCRequestTooLarge
case etcdserver.ErrNoSpace:
return rpctypes.ErrGRPCNoSpace
case auth.ErrRootUserNotExist:
return rpctypes.ErrGRPCRootUserNotExist
case auth.ErrRootRoleNotExist:
return rpctypes.ErrGRPCRootRoleNotExist
case auth.ErrUserAlreadyExist:
return rpctypes.ErrGRPCUserAlreadyExist
case auth.ErrUserNotFound:

View File

@ -521,7 +521,10 @@ func (a *applierV3Capped) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantRe
}
func (a *applierV3backend) AuthEnable() (*pb.AuthEnableResponse, error) {
a.s.AuthStore().AuthEnable()
err := a.s.AuthStore().AuthEnable()
if err != nil {
return nil, err
}
return &pb.AuthEnableResponse{}, nil
}