mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
migrate e2e & integration role_test to common
This commit is contained in:
parent
545f04f90d
commit
e004c91d36
168
tests/common/role_test.go
Normal file
168
tests/common/role_test.go
Normal file
@ -0,0 +1,168 @@
|
||||
// Copyright 2022 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/tests/v3/framework/config"
|
||||
"go.etcd.io/etcd/tests/v3/framework/testutils"
|
||||
)
|
||||
|
||||
func TestRoleAdd_Simple(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
tcs := []struct {
|
||||
name string
|
||||
config config.ClusterConfig
|
||||
}{
|
||||
{
|
||||
name: "NoTLS",
|
||||
config: config.ClusterConfig{ClusterSize: 1},
|
||||
},
|
||||
{
|
||||
name: "PeerTLS",
|
||||
config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.ManualTLS},
|
||||
},
|
||||
{
|
||||
name: "PeerAutoTLS",
|
||||
config: config.ClusterConfig{ClusterSize: 3, PeerTLS: config.AutoTLS},
|
||||
},
|
||||
{
|
||||
name: "ClientTLS",
|
||||
config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.ManualTLS},
|
||||
},
|
||||
{
|
||||
name: "ClientAutoTLS",
|
||||
config: config.ClusterConfig{ClusterSize: 1, ClientTLS: config.AutoTLS},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
clus := testRunner.NewCluster(t, tc.config)
|
||||
defer clus.Close()
|
||||
cc := clus.Client()
|
||||
|
||||
testutils.ExecuteWithTimeout(t, 10*time.Second, func() {
|
||||
_, err := cc.RoleAdd("root")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoleAdd_Error(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 1})
|
||||
defer clus.Close()
|
||||
cc := clus.Client()
|
||||
testutils.ExecuteWithTimeout(t, 10*time.Second, func() {
|
||||
_, err := cc.RoleAdd("test-role")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
_, err = cc.RoleAdd("test-role")
|
||||
if err == nil || !strings.Contains(err.Error(), rpctypes.ErrRoleAlreadyExist.Error()) {
|
||||
t.Fatalf("want (%v) error, but got (%v)", rpctypes.ErrRoleAlreadyExist, err)
|
||||
}
|
||||
_, err = cc.RoleAdd("")
|
||||
if err == nil || !strings.Contains(err.Error(), rpctypes.ErrRoleEmpty.Error()) {
|
||||
t.Fatalf("want (%v) error, but got (%v)", rpctypes.ErrRoleEmpty, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRootRole(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 1})
|
||||
defer clus.Close()
|
||||
cc := clus.Client()
|
||||
testutils.ExecuteWithTimeout(t, 10*time.Second, func() {
|
||||
_, err := cc.RoleAdd("root")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
resp, err := cc.RoleGet("root")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
t.Logf("get role resp %+v", resp)
|
||||
// granting to root should be refused by server and a no-op
|
||||
_, err = cc.RoleGrantPermission("root", "foo", "", clientv3.PermissionType(clientv3.PermReadWrite))
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
resp2, err := cc.RoleGet("root")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
t.Logf("get role resp %+v", resp2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoleGrantRevokePermission(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 1})
|
||||
defer clus.Close()
|
||||
cc := clus.Client()
|
||||
testutils.ExecuteWithTimeout(t, 10*time.Second, func() {
|
||||
_, err := cc.RoleAdd("role1")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
_, err = cc.RoleGrantPermission("role1", "bar", "", clientv3.PermissionType(clientv3.PermRead))
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
_, err = cc.RoleGrantPermission("role1", "bar", "", clientv3.PermissionType(clientv3.PermWrite))
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
_, err = cc.RoleGrantPermission("role1", "bar", "foo", clientv3.PermissionType(clientv3.PermReadWrite))
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
_, err = cc.RoleRevokePermission("role1", "foo", "")
|
||||
if err == nil || !strings.Contains(err.Error(), rpctypes.ErrPermissionNotGranted.Error()) {
|
||||
t.Fatalf("want error (%v), but got (%v)", rpctypes.ErrPermissionNotGranted, err)
|
||||
}
|
||||
_, err = cc.RoleRevokePermission("role1", "bar", "foo")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoleDelete(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
clus := testRunner.NewCluster(t, config.ClusterConfig{ClusterSize: 1})
|
||||
defer clus.Close()
|
||||
cc := clus.Client()
|
||||
testutils.ExecuteWithTimeout(t, 10*time.Second, func() {
|
||||
_, err := cc.RoleAdd("role1")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
_, err = cc.RoleDelete("role1")
|
||||
if err != nil {
|
||||
t.Fatalf("want no error, but got (%v)", err)
|
||||
}
|
||||
})
|
||||
}
|
@ -21,17 +21,10 @@ import (
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
func TestCtlV3RoleAdd(t *testing.T) { testCtl(t, roleAddTest) }
|
||||
func TestCtlV3RootRoleGet(t *testing.T) { testCtl(t, rootRoleGetTest) }
|
||||
func TestCtlV3RoleAddNoTLS(t *testing.T) { testCtl(t, roleAddTest, withCfg(*e2e.NewConfigNoTLS())) }
|
||||
func TestCtlV3RoleAddClientTLS(t *testing.T) {
|
||||
testCtl(t, roleAddTest, withCfg(*e2e.NewConfigClientTLS()))
|
||||
}
|
||||
func TestCtlV3RoleAddPeerTLS(t *testing.T) { testCtl(t, roleAddTest, withCfg(*e2e.NewConfigPeerTLS())) }
|
||||
// TestCtlV3RoleAddTimeout tests add role with 0 grpc dial timeout while it tolerates dial timeout error.
|
||||
// This is unique in e2e test
|
||||
func TestCtlV3RoleAddTimeout(t *testing.T) { testCtl(t, roleAddTest, withDialTimeout(0)) }
|
||||
|
||||
func TestCtlV3RoleGrant(t *testing.T) { testCtl(t, roleGrantTest) }
|
||||
|
||||
func roleAddTest(cx ctlCtx) {
|
||||
cmdSet := []struct {
|
||||
args []string
|
||||
@ -58,94 +51,6 @@ func roleAddTest(cx ctlCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
func rootRoleGetTest(cx ctlCtx) {
|
||||
cmdSet := []struct {
|
||||
args []string
|
||||
expectedStr interface{}
|
||||
}{
|
||||
// Add a role of root .
|
||||
{
|
||||
args: []string{"add", "root"},
|
||||
expectedStr: "Role root created",
|
||||
},
|
||||
// get root role should always return [, <open ended>
|
||||
{
|
||||
args: []string{"get", "root"},
|
||||
expectedStr: []string{"Role root\r\n", "KV Read:\r\n", "\t[, <open ended>\r\n", "KV Write:\r\n", "\t[, <open ended>\r\n"},
|
||||
},
|
||||
// granting to root should be refused by server
|
||||
{
|
||||
args: []string{"grant-permission", "root", "readwrite", "foo"},
|
||||
expectedStr: "Role root updated",
|
||||
},
|
||||
{
|
||||
args: []string{"get", "root"},
|
||||
expectedStr: []string{"Role root\r\n", "KV Read:\r\n", "\t[, <open ended>\r\n", "KV Write:\r\n", "\t[, <open ended>\r\n"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, cmd := range cmdSet {
|
||||
if _, ok := cmd.expectedStr.(string); ok {
|
||||
if err := ctlV3Role(cx, cmd.args, cmd.expectedStr.(string)); err != nil {
|
||||
if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
|
||||
cx.t.Fatalf("roleAddTest #%d: ctlV3Role error (%v)", i, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := ctlV3RoleMultiExpect(cx, cmd.args, cmd.expectedStr.([]string)...); err != nil {
|
||||
if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
|
||||
cx.t.Fatalf("roleAddTest #%d: ctlV3Role error (%v)", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func roleGrantTest(cx ctlCtx) {
|
||||
cmdSet := []struct {
|
||||
args []string
|
||||
expectedStr string
|
||||
}{
|
||||
// Add a role.
|
||||
{
|
||||
args: []string{"add", "root"},
|
||||
expectedStr: "Role root created",
|
||||
},
|
||||
// Grant read permission to the role.
|
||||
{
|
||||
args: []string{"grant", "root", "read", "foo"},
|
||||
expectedStr: "Role root updated",
|
||||
},
|
||||
// Grant write permission to the role.
|
||||
{
|
||||
args: []string{"grant", "root", "write", "foo"},
|
||||
expectedStr: "Role root updated",
|
||||
},
|
||||
// Grant rw permission to the role.
|
||||
{
|
||||
args: []string{"grant", "root", "readwrite", "foo"},
|
||||
expectedStr: "Role root updated",
|
||||
},
|
||||
// Try granting invalid permission to the role.
|
||||
{
|
||||
args: []string{"grant", "root", "123", "foo"},
|
||||
expectedStr: "invalid permission type",
|
||||
},
|
||||
}
|
||||
|
||||
for i, cmd := range cmdSet {
|
||||
if err := ctlV3Role(cx, cmd.args, cmd.expectedStr); err != nil {
|
||||
cx.t.Fatalf("roleGrantTest #%d: ctlV3Role error (%v)", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ctlV3RoleMultiExpect(cx ctlCtx, args []string, expStr ...string) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "role")
|
||||
cmdArgs = append(cmdArgs, args...)
|
||||
|
||||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, expStr...)
|
||||
}
|
||||
func ctlV3Role(cx ctlCtx, args []string, expStr string) error {
|
||||
cmdArgs := append(cx.PrefixArgs(), "role")
|
||||
cmdArgs = append(cmdArgs, args...)
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/authpb"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/tests/v3/framework/config"
|
||||
)
|
||||
@ -507,3 +508,53 @@ func (ctl *EtcdctlV3) UserChangePass(user, newPass string) error {
|
||||
_, err = cmd.Expect("Password updated")
|
||||
return err
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) RoleAdd(name string) (*clientv3.AuthRoleAddResponse, error) {
|
||||
var resp clientv3.AuthRoleAddResponse
|
||||
err := ctl.spawnJsonCmd(&resp, "role", "add", name)
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) RoleGrantPermission(name string, key, rangeEnd string, permType clientv3.PermissionType) (*clientv3.AuthRoleGrantPermissionResponse, error) {
|
||||
permissionType := authpb.Permission_Type_name[int32(permType)]
|
||||
var resp clientv3.AuthRoleGrantPermissionResponse
|
||||
err := ctl.spawnJsonCmd(&resp, "role", "grant-permission", name, permissionType, key, rangeEnd)
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) RoleGet(role string) (*clientv3.AuthRoleGetResponse, error) {
|
||||
var resp clientv3.AuthRoleGetResponse
|
||||
err := ctl.spawnJsonCmd(&resp, "role", "get", role)
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) RoleList() (*clientv3.AuthRoleListResponse, error) {
|
||||
var resp clientv3.AuthRoleListResponse
|
||||
err := ctl.spawnJsonCmd(&resp, "role", "list")
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) RoleRevokePermission(role string, key, rangeEnd string) (*clientv3.AuthRoleRevokePermissionResponse, error) {
|
||||
var resp clientv3.AuthRoleRevokePermissionResponse
|
||||
err := ctl.spawnJsonCmd(&resp, "role", "revoke-permission", role, key, rangeEnd)
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) RoleDelete(role string) (*clientv3.AuthRoleDeleteResponse, error) {
|
||||
var resp clientv3.AuthRoleDeleteResponse
|
||||
err := ctl.spawnJsonCmd(&resp, "role", "delete", role)
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
func (ctl *EtcdctlV3) spawnJsonCmd(output interface{}, args ...string) error {
|
||||
args = append(args, "-w", "json")
|
||||
cmd, err := SpawnCmd(append(ctl.cmdArgs(), args...), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
line, err := cmd.Expect("header")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal([]byte(line), output)
|
||||
}
|
||||
|
@ -311,3 +311,27 @@ func (c integrationClient) UserChangePass(user, newPass string) error {
|
||||
_, err := c.Client.UserChangePassword(context.Background(), user, newPass)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c integrationClient) RoleAdd(name string) (*clientv3.AuthRoleAddResponse, error) {
|
||||
return c.Client.RoleAdd(context.Background(), name)
|
||||
}
|
||||
|
||||
func (c integrationClient) RoleGrantPermission(name string, key, rangeEnd string, permType clientv3.PermissionType) (*clientv3.AuthRoleGrantPermissionResponse, error) {
|
||||
return c.Client.RoleGrantPermission(context.Background(), name, key, rangeEnd, permType)
|
||||
}
|
||||
|
||||
func (c integrationClient) RoleGet(role string) (*clientv3.AuthRoleGetResponse, error) {
|
||||
return c.Client.RoleGet(context.Background(), role)
|
||||
}
|
||||
|
||||
func (c integrationClient) RoleList() (*clientv3.AuthRoleListResponse, error) {
|
||||
return c.Client.RoleList(context.Background())
|
||||
}
|
||||
|
||||
func (c integrationClient) RoleRevokePermission(role string, key, rangeEnd string) (*clientv3.AuthRoleRevokePermissionResponse, error) {
|
||||
return c.Client.RoleRevokePermission(context.Background(), role, key, rangeEnd)
|
||||
}
|
||||
|
||||
func (c integrationClient) RoleDelete(role string) (*clientv3.AuthRoleDeleteResponse, error) {
|
||||
return c.Client.RoleDelete(context.Background(), role)
|
||||
}
|
||||
|
@ -60,4 +60,10 @@ type Client interface {
|
||||
UserList() (*clientv3.AuthUserListResponse, error)
|
||||
UserDelete(name string) (*clientv3.AuthUserDeleteResponse, error)
|
||||
UserChangePass(user, newPass string) error
|
||||
RoleAdd(name string) (*clientv3.AuthRoleAddResponse, error)
|
||||
RoleGrantPermission(name string, key, rangeEnd string, permType clientv3.PermissionType) (*clientv3.AuthRoleGrantPermissionResponse, error)
|
||||
RoleGet(role string) (*clientv3.AuthRoleGetResponse, error)
|
||||
RoleList() (*clientv3.AuthRoleListResponse, error)
|
||||
RoleRevokePermission(role string, key, rangeEnd string) (*clientv3.AuthRoleRevokePermissionResponse, error)
|
||||
RoleDelete(role string) (*clientv3.AuthRoleDeleteResponse, error)
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package clientv3test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
|
||||
integration2 "go.etcd.io/etcd/tests/v3/framework/integration"
|
||||
)
|
||||
|
||||
func TestRoleError(t *testing.T) {
|
||||
integration2.BeforeTest(t)
|
||||
|
||||
clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1})
|
||||
defer clus.Terminate(t)
|
||||
|
||||
authapi := clus.RandClient()
|
||||
|
||||
_, err := authapi.RoleAdd(context.TODO(), "test-role")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = authapi.RoleAdd(context.TODO(), "test-role")
|
||||
if err != rpctypes.ErrRoleAlreadyExist {
|
||||
t.Fatalf("expected %v, got %v", rpctypes.ErrRoleAlreadyExist, err)
|
||||
}
|
||||
|
||||
_, err = authapi.RoleAdd(context.TODO(), "")
|
||||
if err != rpctypes.ErrRoleEmpty {
|
||||
t.Fatalf("expected %v, got %v", rpctypes.ErrRoleEmpty, err)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user