Enhance the root permission, when root role exist, it always return rootPerm. (#13006)

etcdctl role grant-permission root readwrite foo.
see etcdctl role get root output.
Before:
Role root
KV Read:
        foo
KV Write:
        foo
After:
Role root
KV Read:
        [, <open ended>
KV Write:
        [, <open ended>
This commit is contained in:
赵延 2021-05-25 05:58:00 +08:00 committed by GitHub
parent d2e04a7171
commit 64b01a7a8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 20 deletions

View File

@ -200,7 +200,7 @@ func (s *simplePrinter) RoleGet(role string, r v3.AuthRoleGetResponse) {
} else { } else {
fmt.Printf("\t[%s, <open ended>", sKey) fmt.Printf("\t[%s, <open ended>", sKey)
} }
if v3.GetPrefixRangeEnd(sKey) == sRangeEnd { if v3.GetPrefixRangeEnd(sKey) == sRangeEnd && len(sKey) > 0 {
fmt.Printf(" (prefix %s)", sKey) fmt.Printf(" (prefix %s)", sKey)
} }
fmt.Printf("\n") fmt.Printf("\n")

View File

@ -46,6 +46,8 @@ var (
revisionKey = []byte("authRevision") revisionKey = []byte("authRevision")
rootPerm = authpb.Permission{PermType: authpb.READWRITE, Key: []byte{}, RangeEnd: []byte{0}}
ErrRootUserNotExist = errors.New("auth: root user does not exist") ErrRootUserNotExist = errors.New("auth: root user does not exist")
ErrRootRoleNotExist = errors.New("auth: root user does not have root role") ErrRootRoleNotExist = errors.New("auth: root user does not have root role")
ErrUserAlreadyExist = errors.New("auth: user already exists") ErrUserAlreadyExist = errors.New("auth: user already exists")
@ -631,7 +633,11 @@ func (as *authStore) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse,
if role == nil { if role == nil {
return nil, ErrRoleNotFound 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 return &resp, nil
} }
@ -950,8 +956,8 @@ func delUser(tx backend.BatchTx, username string) {
tx.UnsafeDelete(buckets.AuthUsers, []byte(username)) tx.UnsafeDelete(buckets.AuthUsers, []byte(username))
} }
func getRole(lg *zap.Logger, tx backend.BatchTx, rolename string) *authpb.Role { func getRole(lg *zap.Logger, tx backend.BatchTx, roleName string) *authpb.Role {
_, vs := tx.UnsafeRange(buckets.AuthRoles, []byte(rolename), nil, 0) _, vs := tx.UnsafeRange(buckets.AuthRoles, []byte(roleName), nil, 0)
if len(vs) == 0 { if len(vs) == 0 {
return nil return nil
} }

View File

@ -18,7 +18,7 @@ import (
"context" "context"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"reflect" "github.com/stretchr/testify/assert"
"strings" "strings"
"sync" "sync"
"testing" "testing"
@ -384,9 +384,8 @@ func TestGetUser(t *testing.T) {
t.Fatal("expect user not nil, got nil") t.Fatal("expect user not nil, got nil")
} }
expected := []string{"role-test"} 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 // check non existent user
_, err = as.UserGet(&pb.AuthUserGetRequest{Name: "nouser"}) _, err = as.UserGet(&pb.AuthUserGetRequest{Name: "nouser"})
@ -445,9 +444,40 @@ func TestRoleGrantPermission(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(perm, r.Perm[0]) { assert.Equal(t, perm, r.Perm[0])
t.Errorf("expected %v, got %v", 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) { func TestRoleRevokePermission(t *testing.T) {
@ -522,9 +552,8 @@ func TestUserRevokePermission(t *testing.T) {
} }
expected := []string{"role-test", "role-test-1"} 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"}) _, err = as.UserRevokeRole(&pb.AuthUserRevokeRoleRequest{Name: "foo", Role: "role-test-1"})
if err != nil { if err != nil {
@ -537,9 +566,8 @@ func TestUserRevokePermission(t *testing.T) {
} }
expected = []string{"role-test"} 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) { func TestRoleDelete(t *testing.T) {
@ -555,9 +583,8 @@ func TestRoleDelete(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
expected := []string{"root"} 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) { func TestAuthInfoFromCtx(t *testing.T) {

View File

@ -76,7 +76,7 @@ func rootRoleGetTest(cx ctlCtx) {
}, },
{ {
args: []string{"get", "root"}, 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[, <open ended>\r\n", "KV Write:\r\n", "\t[, <open ended>\r\n"},
}, },
} }