diff --git a/etcdctl/ctlv3/command/printer_simple.go b/etcdctl/ctlv3/command/printer_simple.go index e9a0b4103..14028c614 100644 --- a/etcdctl/ctlv3/command/printer_simple.go +++ b/etcdctl/ctlv3/command/printer_simple.go @@ -200,7 +200,7 @@ func (s *simplePrinter) RoleGet(role string, r v3.AuthRoleGetResponse) { } else { fmt.Printf("\t[%s, ", sKey) } - if v3.GetPrefixRangeEnd(sKey) == sRangeEnd { + if v3.GetPrefixRangeEnd(sKey) == sRangeEnd && len(sKey) > 0 { fmt.Printf(" (prefix %s)", sKey) } fmt.Printf("\n") diff --git a/server/auth/store.go b/server/auth/store.go index 2843de8cd..63ea7a76a 100644 --- a/server/auth/store.go +++ b/server/auth/store.go @@ -46,6 +46,8 @@ var ( revisionKey = []byte("authRevision") + rootPerm = authpb.Permission{PermType: authpb.READWRITE, Key: []byte{}, RangeEnd: []byte{0}} + 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") @@ -631,7 +633,11 @@ func (as *authStore) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, if role == nil { return nil, ErrRoleNotFound } - resp.Perm = append(resp.Perm, role.KeyPermission...) + if rootRole == string(role.Name) { + resp.Perm = append(resp.Perm, &rootPerm) + } else { + resp.Perm = append(resp.Perm, role.KeyPermission...) + } return &resp, nil } @@ -950,8 +956,8 @@ func delUser(tx backend.BatchTx, username string) { tx.UnsafeDelete(buckets.AuthUsers, []byte(username)) } -func getRole(lg *zap.Logger, tx backend.BatchTx, rolename string) *authpb.Role { - _, vs := tx.UnsafeRange(buckets.AuthRoles, []byte(rolename), nil, 0) +func getRole(lg *zap.Logger, tx backend.BatchTx, roleName string) *authpb.Role { + _, vs := tx.UnsafeRange(buckets.AuthRoles, []byte(roleName), nil, 0) if len(vs) == 0 { return nil } diff --git a/server/auth/store_test.go b/server/auth/store_test.go index c530ffe88..ec2aa9e82 100644 --- a/server/auth/store_test.go +++ b/server/auth/store_test.go @@ -18,7 +18,7 @@ import ( "context" "encoding/base64" "fmt" - "reflect" + "github.com/stretchr/testify/assert" "strings" "sync" "testing" @@ -384,9 +384,8 @@ func TestGetUser(t *testing.T) { t.Fatal("expect user not nil, got nil") } expected := []string{"role-test"} - if !reflect.DeepEqual(expected, u.Roles) { - t.Errorf("expected %v, got %v", expected, u.Roles) - } + + assert.Equal(t, expected, u.Roles) // check non existent user _, err = as.UserGet(&pb.AuthUserGetRequest{Name: "nouser"}) @@ -445,9 +444,40 @@ func TestRoleGrantPermission(t *testing.T) { t.Fatal(err) } - if !reflect.DeepEqual(perm, r.Perm[0]) { - t.Errorf("expected %v, got %v", perm, r.Perm[0]) + assert.Equal(t, perm, r.Perm[0]) +} + +func TestRootRoleGrantPermission(t *testing.T) { + as, tearDown := setupAuthStore(t) + defer tearDown(t) + + perm := &authpb.Permission{ + PermType: authpb.WRITE, + Key: []byte("Keys"), + RangeEnd: []byte("RangeEnd"), } + _, err := as.RoleGrantPermission(&pb.AuthRoleGrantPermissionRequest{ + Name: "root", + Perm: perm, + }) + + if err != nil { + t.Error(err) + } + + r, err := as.RoleGet(&pb.AuthRoleGetRequest{Role: "root"}) + if err != nil { + t.Fatal(err) + } + + //whatever grant permission to root, it always return root permission. + expectPerm := &authpb.Permission{ + PermType: authpb.READWRITE, + Key: []byte{}, + RangeEnd: []byte{0}, + } + + assert.Equal(t, expectPerm, r.Perm[0]) } func TestRoleRevokePermission(t *testing.T) { @@ -522,9 +552,8 @@ func TestUserRevokePermission(t *testing.T) { } expected := []string{"role-test", "role-test-1"} - if !reflect.DeepEqual(expected, u.Roles) { - t.Fatalf("expected %v, got %v", expected, u.Roles) - } + + assert.Equal(t, expected, u.Roles) _, err = as.UserRevokeRole(&pb.AuthUserRevokeRoleRequest{Name: "foo", Role: "role-test-1"}) if err != nil { @@ -537,9 +566,8 @@ func TestUserRevokePermission(t *testing.T) { } expected = []string{"role-test"} - if !reflect.DeepEqual(expected, u.Roles) { - t.Errorf("expected %v, got %v", expected, u.Roles) - } + + assert.Equal(t, expected, u.Roles) } func TestRoleDelete(t *testing.T) { @@ -555,9 +583,8 @@ func TestRoleDelete(t *testing.T) { t.Fatal(err) } expected := []string{"root"} - if !reflect.DeepEqual(expected, rl.Roles) { - t.Errorf("expected %v, got %v", expected, rl.Roles) - } + + assert.Equal(t, expected, rl.Roles) } func TestAuthInfoFromCtx(t *testing.T) { diff --git a/tests/e2e/ctl_v3_role_test.go b/tests/e2e/ctl_v3_role_test.go index c0779b49b..820b64783 100644 --- a/tests/e2e/ctl_v3_role_test.go +++ b/tests/e2e/ctl_v3_role_test.go @@ -76,7 +76,7 @@ func rootRoleGetTest(cx ctlCtx) { }, { args: []string{"get", "root"}, - expectedStr: []string{"Role root\r\n", "KV Read:\r\n", "\tfoo\r\n", "KV Write:\r\n", "\tfoo\r\n"}, + expectedStr: []string{"Role root\r\n", "KV Read:\r\n", "\t[, \r\n", "KV Write:\r\n", "\t[, \r\n"}, }, }