From 9a2553fe2f3d9a851b591f4ac871368b7cef689b Mon Sep 17 00:00:00 2001 From: Chao Chen Date: Mon, 27 Mar 2023 17:35:07 -0700 Subject: [PATCH] migrate auth tests to common #7 Signed-off-by: Chao Chen --- bill-of-materials.json | 2 +- tests/common/auth_test.go | 93 ++++++++++++++++++++++++++ tests/common/auth_util.go | 16 +++++ tests/e2e/ctl_v3_auth_test.go | 119 +--------------------------------- 4 files changed, 113 insertions(+), 117 deletions(-) diff --git a/bill-of-materials.json b/bill-of-materials.json index bf9574041..db45756dc 100644 --- a/bill-of-materials.json +++ b/bill-of-materials.json @@ -396,7 +396,7 @@ ] }, { - "project": "github.com/stretchr/testify/assert", + "project": "github.com/stretchr/testify", "licenses": [ { "type": "MIT License", diff --git a/tests/common/auth_test.go b/tests/common/auth_test.go index 78b97fc9c..6b54ca296 100644 --- a/tests/common/auth_test.go +++ b/tests/common/auth_test.go @@ -629,6 +629,99 @@ func TestAuthTestInvalidMgmt(t *testing.T) { }) } +func TestAuthLeaseRevoke(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.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth") + rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword))) + + lresp, err := rootAuthClient.Grant(ctx, 10) + require.NoError(t, err) + err = rootAuthClient.Put(ctx, "key", "value", config.PutOptions{LeaseID: lresp.ID}) + require.NoError(t, err) + + _, err = rootAuthClient.Revoke(ctx, lresp.ID) + require.NoError(t, err) + + _, err = rootAuthClient.Get(ctx, "key", config.GetOptions{}) + require.NoError(t, err) + }) +} + +func TestAuthRoleGet(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.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))) + + resp, err := rootAuthClient.RoleGet(ctx, testRoleName) + require.NoError(t, err) + requireRolePermissionEqual(t, testRole, resp.Perm) + + // test-user can get the information of test-role because it belongs to the role + resp, err = testUserAuthClient.RoleGet(ctx, testRoleName) + require.NoError(t, err) + requireRolePermissionEqual(t, testRole, resp.Perm) + // test-user cannot get the information of root because it doesn't belong to the role + _, err = testUserAuthClient.RoleGet(ctx, rootRoleName) + require.ErrorContains(t, err, PermissionDenied) + }) +} + +func TestAuthUserGet(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.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))) + + resp, err := rootAuthClient.UserGet(ctx, testUserName) + require.NoError(t, err) + requireUserRolesEqual(t, testUser, resp.Roles) + + // test-user can get the information of test-user itself + resp, err = testUserAuthClient.UserGet(ctx, testUserName) + require.NoError(t, err) + requireUserRolesEqual(t, testUser, resp.Roles) + // test-user cannot get the information of root + _, err = testUserAuthClient.UserGet(ctx, rootUserName) + require.ErrorContains(t, err, PermissionDenied) + }) +} + +func TestAuthRoleList(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.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth") + rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword))) + + resp, err := rootAuthClient.RoleList(ctx) + require.NoError(t, err) + requireUserRolesEqual(t, testUser, resp.Roles) + }) +} + func mustAbsPath(path string) string { abs, err := filepath.Abs(path) if err != nil { diff --git a/tests/common/auth_util.go b/tests/common/auth_util.go index c75f20cd3..e70a87db8 100644 --- a/tests/common/auth_util.go +++ b/tests/common/auth_util.go @@ -17,7 +17,11 @@ package common import ( "context" "fmt" + "testing" + "github.com/stretchr/testify/require" + + "go.etcd.io/etcd/api/v3/authpb" clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/tests/v3/framework/config" "go.etcd.io/etcd/tests/v3/framework/interfaces" @@ -106,3 +110,15 @@ func setupAuth(c interfaces.Client, roles []authRole, users []authUser) error { return nil } + +func requireRolePermissionEqual(t *testing.T, expectRole authRole, actual []*authpb.Permission) { + require.Equal(t, 1, len(actual)) + require.Equal(t, expectRole.permission, clientv3.PermissionType(actual[0].PermType)) + require.Equal(t, expectRole.key, string(actual[0].Key)) + require.Equal(t, expectRole.keyEnd, string(actual[0].RangeEnd)) +} + +func requireUserRolesEqual(t *testing.T, expectUser authUser, actual []string) { + require.Equal(t, 1, len(actual)) + require.Equal(t, expectUser.role, actual[0]) +} diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index d0de934df..a0a90cb0a 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -29,14 +29,10 @@ import ( func TestCtlV3AuthMemberUpdate(t *testing.T) { testCtl(t, authTestMemberUpdate) } func TestCtlV3AuthFromKeyPerm(t *testing.T) { testCtl(t, authTestFromKeyPerm) } -func TestCtlV3AuthAndWatch(t *testing.T) { testCtl(t, authTestWatch) } -func TestCtlV3AuthAndWatchJWT(t *testing.T) { testCtl(t, authTestWatch, withCfg(*e2e.NewConfigJWT())) } -func TestCtlV3AuthLeaseRevoke(t *testing.T) { testCtl(t, authLeaseTestLeaseRevoke) } - -func TestCtlV3AuthRoleGet(t *testing.T) { testCtl(t, authTestRoleGet) } -func TestCtlV3AuthUserGet(t *testing.T) { testCtl(t, authTestUserGet) } -func TestCtlV3AuthRoleList(t *testing.T) { testCtl(t, authTestRoleList) } +// TestCtlV3AuthAndWatch TODO https://github.com/etcd-io/etcd/issues/7988 is the blocker of migration to common/auth_test.go +func TestCtlV3AuthAndWatch(t *testing.T) { testCtl(t, authTestWatch) } +func TestCtlV3AuthAndWatchJWT(t *testing.T) { testCtl(t, authTestWatch, withCfg(*e2e.NewConfigJWT())) } func TestCtlV3AuthDefrag(t *testing.T) { testCtl(t, authTestDefrag) } func TestCtlV3AuthEndpointHealth(t *testing.T) { @@ -230,44 +226,6 @@ func authTestFromKeyPerm(cx ctlCtx) { } } -func leaseTestGrantLeasesList(cx ctlCtx) error { - id, err := ctlV3LeaseGrant(cx, 10) - if err != nil { - return fmt.Errorf("ctlV3LeaseGrant error (%v)", err) - } - - cmdArgs := append(cx.PrefixArgs(), "lease", "list") - proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap) - if err != nil { - return fmt.Errorf("lease list failed (%v)", err) - } - _, err = proc.Expect(id) - if err != nil { - return fmt.Errorf("lease id not in returned list (%v)", err) - } - return proc.Close() -} - -func authLeaseTestLeaseRevoke(cx ctlCtx) { - cx.user, cx.pass = "root", "root" - authSetupTestUser(cx) - - // put with TTL 10 seconds and revoke - leaseID, err := ctlV3LeaseGrant(cx, 10) - if err != nil { - cx.t.Fatalf("ctlV3LeaseGrant error (%v)", err) - } - if err := ctlV3Put(cx, "key", "val", leaseID); err != nil { - cx.t.Fatalf("ctlV3Put error (%v)", err) - } - if err := ctlV3LeaseRevoke(cx, leaseID); err != nil { - cx.t.Fatalf("ctlV3LeaseRevoke error (%v)", err) - } - if err := ctlV3GetWithErr(cx, []string{"key"}, []string{"retrying of unary invoker failed"}); err != nil { // expect errors - cx.t.Fatalf("ctlV3GetWithErr error (%v)", err) - } -} - func authTestWatch(cx ctlCtx) { if err := authEnable(cx); err != nil { cx.t.Fatal(err) @@ -344,77 +302,6 @@ func authTestWatch(cx ctlCtx) { } -func authTestRoleGet(cx ctlCtx) { - if err := authEnable(cx); err != nil { - cx.t.Fatal(err) - } - cx.user, cx.pass = "root", "root" - authSetupTestUser(cx) - - expected := []string{ - "Role test-role", - "KV Read:", "foo", - "KV Write:", "foo", - } - if err := e2e.SpawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), cx.envMap, expected...); err != nil { - cx.t.Fatal(err) - } - - // test-user can get the information of test-role because it belongs to the role - cx.user, cx.pass = "test-user", "pass" - if err := e2e.SpawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), cx.envMap, expected...); err != nil { - cx.t.Fatal(err) - } - - // test-user cannot get the information of root because it doesn't belong to the role - expected = []string{ - "Error: etcdserver: permission denied", - } - err := e2e.SpawnWithExpects(append(cx.PrefixArgs(), "role", "get", "root"), cx.envMap, expected...) - require.ErrorContains(cx.t, err, "permission denied") -} - -func authTestUserGet(cx ctlCtx) { - if err := authEnable(cx); err != nil { - cx.t.Fatal(err) - } - cx.user, cx.pass = "root", "root" - authSetupTestUser(cx) - - expected := []string{ - "User: test-user", - "Roles: test-role", - } - - if err := e2e.SpawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), cx.envMap, expected...); err != nil { - cx.t.Fatal(err) - } - - // test-user can get the information of test-user itself - cx.user, cx.pass = "test-user", "pass" - if err := e2e.SpawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), cx.envMap, expected...); err != nil { - cx.t.Fatal(err) - } - - // test-user cannot get the information of root - expected = []string{ - "Error: etcdserver: permission denied", - } - err := e2e.SpawnWithExpects(append(cx.PrefixArgs(), "user", "get", "root"), cx.envMap, expected...) - require.ErrorContains(cx.t, err, "permission denied") -} - -func authTestRoleList(cx ctlCtx) { - if err := authEnable(cx); err != nil { - cx.t.Fatal(err) - } - cx.user, cx.pass = "root", "root" - authSetupTestUser(cx) - if err := e2e.SpawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "list"), cx.envMap, "test-role"); err != nil { - cx.t.Fatal(err) - } -} - func authTestDefrag(cx ctlCtx) { maintenanceInitKeys(cx)