mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
migrate auto tests to common #3
Signed-off-by: Chao Chen <chaochn@amazon.com>
This commit is contained in:
parent
116a3150c0
commit
c36ea3fdcf
@ -16,13 +16,24 @@ package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/tests/v3/framework/config"
|
||||
"go.etcd.io/etcd/tests/v3/framework/testutils"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var defaultAuthToken = fmt.Sprintf("jwt,pub-key=%s,priv-key=%s,sign-method=RS256,ttl=1s",
|
||||
mustAbsPath("../fixtures/server.crt"), mustAbsPath("../fixtures/server.key.insecure"))
|
||||
|
||||
const (
|
||||
PermissionDenied = "etcdserver: permission denied"
|
||||
AuthenticationFailed = "etcdserver: authentication failed, invalid user ID or password"
|
||||
)
|
||||
|
||||
func TestAuthEnable(t *testing.T) {
|
||||
@ -131,3 +142,278 @@ func TestAuthStatus(t *testing.T) {
|
||||
require.Truef(t, resp.Enabled, "want enabled but got not enabled")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthRoleUpdate(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(config.ClusterConfig{ClusterSize: 1}))
|
||||
defer clus.Close()
|
||||
cc := testutils.MustClient(clus.Client())
|
||||
testutils.ExecuteUntil(ctx, t, func() {
|
||||
require.NoError(t, cc.Put(ctx, "foo", "bar", config.PutOptions{}))
|
||||
require.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth")
|
||||
|
||||
rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword)))
|
||||
testUserAuthClient := testutils.MustClient(clus.Client(WithAuth(testUserName, testPassword)))
|
||||
|
||||
require.ErrorContains(t, testUserAuthClient.Put(ctx, "hoo", "bar", config.PutOptions{}), PermissionDenied)
|
||||
// grant a new key
|
||||
_, err := rootAuthClient.RoleGrantPermission(ctx, testRoleName, "hoo", "", clientv3.PermissionType(clientv3.PermReadWrite))
|
||||
require.NoError(t, err)
|
||||
// try a newly granted key
|
||||
require.NoError(t, testUserAuthClient.Put(ctx, "hoo", "bar", config.PutOptions{}))
|
||||
// confirm put succeeded
|
||||
resp, err := testUserAuthClient.Get(ctx, "hoo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "hoo" || string(resp.Kvs[0].Value) != "bar" {
|
||||
t.Fatalf("want key value pair 'hoo' 'bar' but got %+v", resp.Kvs)
|
||||
}
|
||||
// revoke the newly granted key
|
||||
_, err = rootAuthClient.RoleRevokePermission(ctx, testRoleName, "hoo", "")
|
||||
require.NoError(t, err)
|
||||
// try put to the revoked key
|
||||
require.ErrorContains(t, testUserAuthClient.Put(ctx, "hoo", "bar", config.PutOptions{}), PermissionDenied)
|
||||
// confirm a key still granted can be accessed
|
||||
resp, err = testUserAuthClient.Get(ctx, "foo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "foo" || string(resp.Kvs[0].Value) != "bar" {
|
||||
t.Fatalf("want key value pair 'foo' 'bar' but got %+v", resp.Kvs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthUserDeleteDuringOps(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(config.ClusterConfig{ClusterSize: 1}))
|
||||
defer clus.Close()
|
||||
cc := testutils.MustClient(clus.Client())
|
||||
testutils.ExecuteUntil(ctx, t, func() {
|
||||
require.NoError(t, cc.Put(ctx, "foo", "bar", config.PutOptions{}))
|
||||
require.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth")
|
||||
|
||||
rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword)))
|
||||
testUserAuthClient := testutils.MustClient(clus.Client(WithAuth(testUserName, testPassword)))
|
||||
|
||||
// create a key
|
||||
require.NoError(t, testUserAuthClient.Put(ctx, "foo", "bar", config.PutOptions{}))
|
||||
// confirm put succeeded
|
||||
resp, err := testUserAuthClient.Get(ctx, "foo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "foo" || string(resp.Kvs[0].Value) != "bar" {
|
||||
t.Fatalf("want key value pair 'foo' 'bar' but got %+v", resp.Kvs)
|
||||
}
|
||||
// delete the user
|
||||
_, err = rootAuthClient.UserDelete(ctx, testUserName)
|
||||
require.NoError(t, err)
|
||||
// check the user is deleted
|
||||
err = testUserAuthClient.Put(ctx, "foo", "baz", config.PutOptions{})
|
||||
require.ErrorContains(t, err, AuthenticationFailed)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthRoleRevokeDuringOps(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(config.ClusterConfig{ClusterSize: 1}))
|
||||
defer clus.Close()
|
||||
cc := testutils.MustClient(clus.Client())
|
||||
testutils.ExecuteUntil(ctx, t, func() {
|
||||
require.NoError(t, cc.Put(ctx, "foo", "bar", config.PutOptions{}))
|
||||
require.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth")
|
||||
|
||||
rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword)))
|
||||
testUserAuthClient := testutils.MustClient(clus.Client(WithAuth(testUserName, testPassword)))
|
||||
|
||||
// create a key
|
||||
require.NoError(t, testUserAuthClient.Put(ctx, "foo", "bar", config.PutOptions{}))
|
||||
// confirm put succeeded
|
||||
resp, err := testUserAuthClient.Get(ctx, "foo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "foo" || string(resp.Kvs[0].Value) != "bar" {
|
||||
t.Fatalf("want key value pair 'foo' 'bar' but got %+v", resp.Kvs)
|
||||
}
|
||||
// create a new role
|
||||
_, err = rootAuthClient.RoleAdd(ctx, "test-role2")
|
||||
require.NoError(t, err)
|
||||
// grant a new key to the new role
|
||||
_, err = rootAuthClient.RoleGrantPermission(ctx, "test-role2", "hoo", "", clientv3.PermissionType(clientv3.PermReadWrite))
|
||||
require.NoError(t, err)
|
||||
// grant the new role to the user
|
||||
_, err = rootAuthClient.UserGrantRole(ctx, testUserName, "test-role2")
|
||||
require.NoError(t, err)
|
||||
|
||||
// try a newly granted key
|
||||
require.NoError(t, testUserAuthClient.Put(ctx, "hoo", "bar", config.PutOptions{}))
|
||||
// confirm put succeeded
|
||||
resp, err = testUserAuthClient.Get(ctx, "hoo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "hoo" || string(resp.Kvs[0].Value) != "bar" {
|
||||
t.Fatalf("want key value pair 'hoo' 'bar' but got %+v", resp.Kvs)
|
||||
}
|
||||
// revoke a role from the user
|
||||
_, err = rootAuthClient.UserRevokeRole(ctx, testUserName, testRoleName)
|
||||
require.NoError(t, err)
|
||||
// check the role is revoked and permission is lost from the user
|
||||
require.ErrorContains(t, testUserAuthClient.Put(ctx, "foo", "baz", config.PutOptions{}), PermissionDenied)
|
||||
|
||||
// try a key that can be accessed from the remaining role
|
||||
require.NoError(t, testUserAuthClient.Put(ctx, "hoo", "bar2", config.PutOptions{}))
|
||||
// confirm put succeeded
|
||||
resp, err = testUserAuthClient.Get(ctx, "hoo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "hoo" || string(resp.Kvs[0].Value) != "bar2" {
|
||||
t.Fatalf("want key value pair 'hoo' 'bar2' but got %+v", resp.Kvs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthWriteKey(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(config.ClusterConfig{ClusterSize: 1}))
|
||||
defer clus.Close()
|
||||
cc := testutils.MustClient(clus.Client())
|
||||
testutils.ExecuteUntil(ctx, t, func() {
|
||||
require.NoError(t, cc.Put(ctx, "foo", "a", config.PutOptions{}))
|
||||
require.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth")
|
||||
|
||||
rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword)))
|
||||
testUserAuthClient := testutils.MustClient(clus.Client(WithAuth(testUserName, testPassword)))
|
||||
|
||||
// confirm root role can access to all keys
|
||||
require.NoError(t, rootAuthClient.Put(ctx, "foo", "bar", config.PutOptions{}))
|
||||
resp, err := rootAuthClient.Get(ctx, "foo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "foo" || string(resp.Kvs[0].Value) != "bar" {
|
||||
t.Fatalf("want key value pair 'foo' 'bar' but got %+v", resp.Kvs)
|
||||
}
|
||||
// try invalid user
|
||||
_, err = clus.Client(WithAuth("a", "b"))
|
||||
require.ErrorContains(t, err, AuthenticationFailed)
|
||||
|
||||
// try good user
|
||||
require.NoError(t, testUserAuthClient.Put(ctx, "foo", "bar2", config.PutOptions{}))
|
||||
// confirm put succeeded
|
||||
resp, err = testUserAuthClient.Get(ctx, "foo", config.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
if len(resp.Kvs) != 1 || string(resp.Kvs[0].Key) != "foo" || string(resp.Kvs[0].Value) != "bar2" {
|
||||
t.Fatalf("want key value pair 'foo' 'bar2' but got %+v", resp.Kvs)
|
||||
}
|
||||
|
||||
// try bad password
|
||||
_, err = clus.Client(WithAuth(testUserName, "badpass"))
|
||||
require.ErrorContains(t, err, AuthenticationFailed)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthTxn(t *testing.T) {
|
||||
tcs := []struct {
|
||||
name string
|
||||
cfg config.ClusterConfig
|
||||
}{
|
||||
{
|
||||
"NoJWT",
|
||||
config.ClusterConfig{ClusterSize: 1},
|
||||
},
|
||||
{
|
||||
"JWT",
|
||||
config.ClusterConfig{ClusterSize: 1, AuthToken: defaultAuthToken},
|
||||
},
|
||||
}
|
||||
|
||||
reqs := []txnReq{
|
||||
{
|
||||
compare: []string{`version("c2") = "1"`},
|
||||
ifSuccess: []string{"get s2"},
|
||||
ifFail: []string{"get f2"},
|
||||
expectResults: []string{"SUCCESS", "s2", "v"},
|
||||
expectError: false,
|
||||
},
|
||||
// a key of compare case isn't granted
|
||||
{
|
||||
compare: []string{`version("c1") = "1"`},
|
||||
ifSuccess: []string{"get s2"},
|
||||
ifFail: []string{"get f2"},
|
||||
expectResults: []string{PermissionDenied},
|
||||
expectError: true,
|
||||
},
|
||||
// a key of success case isn't granted
|
||||
{
|
||||
compare: []string{`version("c2") = "1"`},
|
||||
ifSuccess: []string{"get s1"},
|
||||
ifFail: []string{"get f2"},
|
||||
expectResults: []string{PermissionDenied},
|
||||
expectError: true,
|
||||
},
|
||||
// a key of failure case isn't granted
|
||||
{
|
||||
compare: []string{`version("c2") = "1"`},
|
||||
ifSuccess: []string{"get s2"},
|
||||
ifFail: []string{"get f1"},
|
||||
expectResults: []string{PermissionDenied},
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
clus := testRunner.NewCluster(ctx, t, config.WithClusterConfig(tc.cfg))
|
||||
defer clus.Close()
|
||||
cc := testutils.MustClient(clus.Client())
|
||||
testutils.ExecuteUntil(ctx, t, func() {
|
||||
// keys with 1 suffix aren't granted to test-user
|
||||
keys := []string{"c1", "s1", "f1"}
|
||||
// keys with 2 suffix are granted to test-user, see Line 399
|
||||
grantedKeys := []string{"c2", "s2", "f2"}
|
||||
for _, key := range keys {
|
||||
if err := cc.Put(ctx, key, "v", config.PutOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, key := range grantedKeys {
|
||||
if err := cc.Put(ctx, key, "v", config.PutOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
require.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth")
|
||||
rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword)))
|
||||
testUserAuthClient := testutils.MustClient(clus.Client(WithAuth(testUserName, testPassword)))
|
||||
|
||||
// grant keys to test-user
|
||||
for _, key := range grantedKeys {
|
||||
if _, err := rootAuthClient.RoleGrantPermission(ctx, testRoleName, key, "", clientv3.PermissionType(clientv3.PermReadWrite)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, req := range reqs {
|
||||
resp, err := testUserAuthClient.Txn(ctx, req.compare, req.ifSuccess, req.ifFail, config.TxnOptions{
|
||||
Interactive: true,
|
||||
})
|
||||
if req.expectError {
|
||||
require.Contains(t, err.Error(), req.expectResults[0])
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, req.expectResults, getRespValues(resp))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustAbsPath(path string) string {
|
||||
abs, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return abs
|
||||
}
|
||||
|
@ -29,30 +29,31 @@ import (
|
||||
)
|
||||
|
||||
type txnReq struct {
|
||||
compare []string
|
||||
ifSuccess []string
|
||||
ifFail []string
|
||||
results []string
|
||||
compare []string
|
||||
ifSuccess []string
|
||||
ifFail []string
|
||||
expectResults []string
|
||||
expectError bool
|
||||
}
|
||||
|
||||
func TestTxnSucc(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
reqs := []txnReq{
|
||||
{
|
||||
compare: []string{`value("key1") != "value2"`, `value("key2") != "value1"`},
|
||||
ifSuccess: []string{"get key1", "get key2"},
|
||||
results: []string{"SUCCESS", "key1", "value1", "key2", "value2"},
|
||||
compare: []string{`value("key1") != "value2"`, `value("key2") != "value1"`},
|
||||
ifSuccess: []string{"get key1", "get key2"},
|
||||
expectResults: []string{"SUCCESS", "key1", "value1", "key2", "value2"},
|
||||
},
|
||||
{
|
||||
compare: []string{`version("key1") = "1"`, `version("key2") = "1"`},
|
||||
ifSuccess: []string{"get key1", "get key2", `put "key \"with\" space" "value \x23"`},
|
||||
ifFail: []string{`put key1 "fail"`, `put key2 "fail"`},
|
||||
results: []string{"SUCCESS", "key1", "value1", "key2", "value2", "OK"},
|
||||
compare: []string{`version("key1") = "1"`, `version("key2") = "1"`},
|
||||
ifSuccess: []string{"get key1", "get key2", `put "key \"with\" space" "value \x23"`},
|
||||
ifFail: []string{`put key1 "fail"`, `put key2 "fail"`},
|
||||
expectResults: []string{"SUCCESS", "key1", "value1", "key2", "value2", "OK"},
|
||||
},
|
||||
{
|
||||
compare: []string{`version("key \"with\" space") = "1"`},
|
||||
ifSuccess: []string{`get "key \"with\" space"`},
|
||||
results: []string{"SUCCESS", `key "with" space`, "value \x23"},
|
||||
compare: []string{`version("key \"with\" space") = "1"`},
|
||||
ifSuccess: []string{`get "key \"with\" space"`},
|
||||
expectResults: []string{"SUCCESS", `key "with" space`, "value \x23"},
|
||||
},
|
||||
}
|
||||
for _, cfg := range clusterTestCases() {
|
||||
@ -76,7 +77,7 @@ func TestTxnSucc(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Txn returned error: %s", err)
|
||||
}
|
||||
assert.Equal(t, req.results, getRespValues(resp))
|
||||
assert.Equal(t, req.expectResults, getRespValues(resp))
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -87,16 +88,16 @@ func TestTxnFail(t *testing.T) {
|
||||
testRunner.BeforeTest(t)
|
||||
reqs := []txnReq{
|
||||
{
|
||||
compare: []string{`version("key") < "0"`},
|
||||
ifSuccess: []string{`put key "success"`},
|
||||
ifFail: []string{`put key "fail"`},
|
||||
results: []string{"FAILURE", "OK"},
|
||||
compare: []string{`version("key") < "0"`},
|
||||
ifSuccess: []string{`put key "success"`},
|
||||
ifFail: []string{`put key "fail"`},
|
||||
expectResults: []string{"FAILURE", "OK"},
|
||||
},
|
||||
{
|
||||
compare: []string{`value("key1") != "value1"`},
|
||||
ifSuccess: []string{`put key1 "success"`},
|
||||
ifFail: []string{`put key1 "fail"`},
|
||||
results: []string{"FAILURE", "OK"},
|
||||
compare: []string{`value("key1") != "value1"`},
|
||||
ifSuccess: []string{`put key1 "success"`},
|
||||
ifFail: []string{`put key1 "fail"`},
|
||||
expectResults: []string{"FAILURE", "OK"},
|
||||
},
|
||||
}
|
||||
for _, cfg := range clusterTestCases() {
|
||||
@ -117,7 +118,7 @@ func TestTxnFail(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Txn returned error: %s", err)
|
||||
}
|
||||
assert.Equal(t, req.results, getRespValues(resp))
|
||||
assert.Equal(t, req.expectResults, getRespValues(resp))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -27,14 +27,8 @@ import (
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
)
|
||||
|
||||
func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) }
|
||||
func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateTest) }
|
||||
func TestCtlV3AuthUserDeleteDuringOps(t *testing.T) { testCtl(t, authUserDeleteDuringOpsTest) }
|
||||
func TestCtlV3AuthRoleRevokeDuringOps(t *testing.T) { testCtl(t, authRoleRevokeDuringOpsTest) }
|
||||
func TestCtlV3AuthTxn(t *testing.T) { testCtl(t, authTestTxn) }
|
||||
func TestCtlV3AuthTxnJWT(t *testing.T) { testCtl(t, authTestTxn, withCfg(*e2e.NewConfigJWT())) }
|
||||
func TestCtlV3AuthPrefixPerm(t *testing.T) { testCtl(t, authTestPrefixPerm) }
|
||||
func TestCtlV3AuthMemberAdd(t *testing.T) { testCtl(t, authTestMemberAdd) }
|
||||
func TestCtlV3AuthPrefixPerm(t *testing.T) { testCtl(t, authTestPrefixPerm) }
|
||||
func TestCtlV3AuthMemberAdd(t *testing.T) { testCtl(t, authTestMemberAdd) }
|
||||
func TestCtlV3AuthMemberRemove(t *testing.T) {
|
||||
testCtl(t, authTestMemberRemove, withQuorum(), withDisableStrictReconfig())
|
||||
}
|
||||
@ -92,218 +86,6 @@ func ctlV3AuthEnable(cx ctlCtx) error {
|
||||
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Enabled")
|
||||
}
|
||||
|
||||
func authCredWriteKeyTest(cx ctlCtx) {
|
||||
// baseline key to check for failed puts
|
||||
if err := ctlV3Put(cx, "foo", "a", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := authEnable(cx); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
cx.user, cx.pass = "root", "root"
|
||||
authSetupTestUser(cx)
|
||||
|
||||
// confirm root role can access to all keys
|
||||
if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// try invalid user
|
||||
cx.user, cx.pass = "a", "b"
|
||||
err := ctlV3PutFailAuth(cx, "foo", "bar")
|
||||
require.ErrorContains(cx.t, err, "authentication failed")
|
||||
|
||||
// confirm put failed
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// try good user
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Put(cx, "foo", "bar2", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// confirm put succeeded
|
||||
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// try bad password
|
||||
cx.user, cx.pass = "test-user", "badpass"
|
||||
err = ctlV3PutFailAuth(cx, "foo", "baz")
|
||||
require.ErrorContains(cx.t, err, "authentication failed")
|
||||
|
||||
// confirm put failed
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func authRoleUpdateTest(cx ctlCtx) {
|
||||
if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := authEnable(cx); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
cx.user, cx.pass = "root", "root"
|
||||
authSetupTestUser(cx)
|
||||
|
||||
// try put to not granted key
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
err := ctlV3PutFailPerm(cx, "hoo", "bar")
|
||||
require.ErrorContains(cx.t, err, "permission denied")
|
||||
|
||||
// grant a new key
|
||||
cx.user, cx.pass = "root", "root"
|
||||
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "hoo", "", false}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// try a newly granted key
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// confirm put succeeded
|
||||
if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// revoke the newly granted key
|
||||
cx.user, cx.pass = "root", "root"
|
||||
if err := ctlV3RoleRevokePermission(cx, "test-role", "hoo", "", false); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// try put to the revoked key
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
err = ctlV3PutFailPerm(cx, "hoo", "bar")
|
||||
require.ErrorContains(cx.t, err, "permission denied")
|
||||
|
||||
// confirm a key still granted can be accessed
|
||||
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func authUserDeleteDuringOpsTest(cx ctlCtx) {
|
||||
if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := authEnable(cx); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
cx.user, cx.pass = "root", "root"
|
||||
authSetupTestUser(cx)
|
||||
|
||||
// create a key
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// confirm put succeeded
|
||||
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// delete the user
|
||||
cx.user, cx.pass = "root", "root"
|
||||
err := ctlV3User(cx, []string{"delete", "test-user"}, "User test-user deleted", []string{})
|
||||
if err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// check the user is deleted
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
err = ctlV3PutFailAuth(cx, "foo", "baz")
|
||||
require.ErrorContains(cx.t, err, "authentication failed")
|
||||
}
|
||||
|
||||
func authRoleRevokeDuringOpsTest(cx ctlCtx) {
|
||||
if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := authEnable(cx); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
cx.user, cx.pass = "root", "root"
|
||||
authSetupTestUser(cx)
|
||||
|
||||
// create a key
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// confirm put succeeded
|
||||
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// create a new role
|
||||
cx.user, cx.pass = "root", "root"
|
||||
if err := ctlV3Role(cx, []string{"add", "test-role2"}, "Role test-role2 created"); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// grant a new key to the new role
|
||||
if err := ctlV3RoleGrantPermission(cx, "test-role2", grantingPerm{true, true, "hoo", "", false}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// grant the new role to the user
|
||||
if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role2"}, "Role test-role2 is granted to user test-user", nil); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// try a newly granted key
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// confirm put succeeded
|
||||
if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// revoke a role from the user
|
||||
cx.user, cx.pass = "root", "root"
|
||||
err := ctlV3User(cx, []string{"revoke-role", "test-user", "test-role"}, "Role test-role is revoked from user test-user", []string{})
|
||||
if err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// check the role is revoked and permission is lost from the user
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
err = ctlV3PutFailPerm(cx, "foo", "baz")
|
||||
require.ErrorContains(cx.t, err, "permission denied")
|
||||
|
||||
// try a key that can be accessed from the remaining role
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
if err := ctlV3Put(cx, "hoo", "bar2", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
// confirm put succeeded
|
||||
if err := ctlV3Get(cx, []string{"hoo"}, []kv{{"hoo", "bar2"}}...); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func ctlV3PutFailAuth(cx ctlCtx, key, val string) error {
|
||||
return e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "put", key, val), cx.envMap, "authentication failed")
|
||||
}
|
||||
|
||||
func ctlV3PutFailPerm(cx ctlCtx, key, val string) error {
|
||||
return e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "put", key, val), cx.envMap, "permission denied")
|
||||
}
|
||||
@ -324,87 +106,6 @@ func authSetupTestUser(cx ctlCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
func authTestTxn(cx ctlCtx) {
|
||||
// keys with 1 suffix aren't granted to test-user
|
||||
// keys with 2 suffix are granted to test-user
|
||||
|
||||
keys := []string{"c1", "s1", "f1"}
|
||||
grantedKeys := []string{"c2", "s2", "f2"}
|
||||
for _, key := range keys {
|
||||
if err := ctlV3Put(cx, key, "v", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, key := range grantedKeys {
|
||||
if err := ctlV3Put(cx, key, "v", ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := authEnable(cx); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
cx.user, cx.pass = "root", "root"
|
||||
authSetupTestUser(cx)
|
||||
|
||||
// grant keys to test-user
|
||||
cx.user, cx.pass = "root", "root"
|
||||
for _, key := range grantedKeys {
|
||||
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, key, "", false}); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// now test txn
|
||||
cx.interactive = true
|
||||
cx.user, cx.pass = "test-user", "pass"
|
||||
|
||||
rqs := txnRequests{
|
||||
compare: []string{`version("c2") = "1"`},
|
||||
ifSuccess: []string{"get s2"},
|
||||
ifFail: []string{"get f2"},
|
||||
results: []string{"SUCCESS", "s2", "v"},
|
||||
}
|
||||
if err := ctlV3Txn(cx, rqs, false); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// a key of compare case isn't granted
|
||||
rqs = txnRequests{
|
||||
compare: []string{`version("c1") = "1"`},
|
||||
ifSuccess: []string{"get s2"},
|
||||
ifFail: []string{"get f2"},
|
||||
results: []string{"Error: etcdserver: permission denied"},
|
||||
}
|
||||
if err := ctlV3Txn(cx, rqs, true); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// a key of success case isn't granted
|
||||
rqs = txnRequests{
|
||||
compare: []string{`version("c2") = "1"`},
|
||||
ifSuccess: []string{"get s1"},
|
||||
ifFail: []string{"get f2"},
|
||||
results: []string{"Error: etcdserver: permission denied"},
|
||||
}
|
||||
if err := ctlV3Txn(cx, rqs, true); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// a key of failure case isn't granted
|
||||
rqs = txnRequests{
|
||||
compare: []string{`version("c2") = "1"`},
|
||||
ifSuccess: []string{"get s2"},
|
||||
ifFail: []string{"get f1"},
|
||||
results: []string{"Error: etcdserver: permission denied"},
|
||||
}
|
||||
if err := ctlV3Txn(cx, rqs, true); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func authTestPrefixPerm(cx ctlCtx) {
|
||||
if err := authEnable(cx); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
|
Loading…
x
Reference in New Issue
Block a user