diff --git a/tests/common/auth_test.go b/tests/common/auth_test.go index 4e149f957d7..31715660d81 100644 --- a/tests/common/auth_test.go +++ b/tests/common/auth_test.go @@ -410,6 +410,71 @@ func TestAuthTxn(t *testing.T) { } } +func TestAuthPrefixPerm(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))) + prefix := "/prefix/" // directory like prefix + // grant keys to test-user + _, err := rootAuthClient.RoleGrantPermission(ctx, "test-role", prefix, clientv3.GetPrefixRangeEnd(prefix), clientv3.PermissionType(clientv3.PermReadWrite)) + require.NoError(t, err) + // try a prefix granted permission + for i := 0; i < 10; i++ { + key := fmt.Sprintf("%s%d", prefix, i) + require.NoError(t, testUserAuthClient.Put(ctx, key, "val", config.PutOptions{})) + } + // expect put 'key with prefix end "/prefix0"' value failed + require.ErrorContains(t, testUserAuthClient.Put(ctx, clientv3.GetPrefixRangeEnd(prefix), "baz", config.PutOptions{}), PermissionDenied) + + // grant the prefix2 keys to test-user + prefix2 := "/prefix2/" + _, err = rootAuthClient.RoleGrantPermission(ctx, "test-role", prefix2, clientv3.GetPrefixRangeEnd(prefix2), clientv3.PermissionType(clientv3.PermReadWrite)) + require.NoError(t, err) + for i := 0; i < 10; i++ { + key := fmt.Sprintf("%s%d", prefix2, i) + require.NoError(t, testUserAuthClient.Put(ctx, key, "val", config.PutOptions{})) + } + }) +} + +func TestAuthRevokeWithDelete(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))) + // create a new role + newTestRoleName := "test-role2" + _, err := rootAuthClient.RoleAdd(ctx, newTestRoleName) + require.NoError(t, err) + // grant the new role to the user + _, err = rootAuthClient.UserGrantRole(ctx, testUserName, newTestRoleName) + require.NoError(t, err) + // check the result + resp, err := rootAuthClient.UserGet(ctx, testUserName) + require.NoError(t, err) + require.ElementsMatch(t, resp.Roles, []string{testRoleName, newTestRoleName}) + // delete the role, test-role2 must be revoked from test-user + _, err = rootAuthClient.RoleDelete(ctx, newTestRoleName) + require.NoError(t, err) + // check the result + resp, err = rootAuthClient.UserGet(ctx, testUserName) + require.NoError(t, err) + require.ElementsMatch(t, resp.Roles, []string{testRoleName}) + }) +} + func mustAbsPath(path string) string { abs, err := filepath.Abs(path) if err != nil { diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index 24034758208..da76da40185 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -27,17 +27,15 @@ import ( "go.etcd.io/etcd/tests/v3/framework/e2e" ) -func TestCtlV3AuthPrefixPerm(t *testing.T) { testCtl(t, authTestPrefixPerm) } -func TestCtlV3AuthMemberAdd(t *testing.T) { testCtl(t, authTestMemberAdd) } +func TestCtlV3AuthMemberAdd(t *testing.T) { testCtl(t, authTestMemberAdd) } func TestCtlV3AuthMemberRemove(t *testing.T) { testCtl(t, authTestMemberRemove, withQuorum(), withDisableStrictReconfig()) } -func TestCtlV3AuthMemberUpdate(t *testing.T) { testCtl(t, authTestMemberUpdate) } -func TestCtlV3AuthRevokeWithDelete(t *testing.T) { testCtl(t, authTestRevokeWithDelete) } -func TestCtlV3AuthInvalidMgmt(t *testing.T) { testCtl(t, authTestInvalidMgmt) } -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 TestCtlV3AuthMemberUpdate(t *testing.T) { testCtl(t, authTestMemberUpdate) } +func TestCtlV3AuthInvalidMgmt(t *testing.T) { testCtl(t, authTestInvalidMgmt) } +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 TestCtlV3AuthLeaseTestKeepAlive(t *testing.T) { testCtl(t, authLeaseTestKeepAlive) } func TestCtlV3AuthLeaseTestTimeToLiveExpired(t *testing.T) { @@ -106,49 +104,6 @@ func authSetupTestUser(cx ctlCtx) { } } -func authTestPrefixPerm(cx ctlCtx) { - if err := authEnable(cx); err != nil { - cx.t.Fatal(err) - } - - cx.user, cx.pass = "root", "root" - authSetupTestUser(cx) - - prefix := "/prefix/" // directory like prefix - // grant keys to test-user - cx.user, cx.pass = "root", "root" - if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, prefix, "", true}); err != nil { - cx.t.Fatal(err) - } - - // try a prefix granted permission - cx.user, cx.pass = "test-user", "pass" - for i := 0; i < 10; i++ { - key := fmt.Sprintf("%s%d", prefix, i) - if err := ctlV3Put(cx, key, "val", ""); err != nil { - cx.t.Fatal(err) - } - } - - err := ctlV3PutFailPerm(cx, clientv3.GetPrefixRangeEnd(prefix), "baz") - require.ErrorContains(cx.t, err, "permission denied") - - // grant the entire keys to test-user - cx.user, cx.pass = "root", "root" - if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "", "", true}); err != nil { - cx.t.Fatal(err) - } - - prefix2 := "/prefix2/" - cx.user, cx.pass = "test-user", "pass" - for i := 0; i < 10; i++ { - key := fmt.Sprintf("%s%d", prefix2, i) - if err := ctlV3Put(cx, key, "val", ""); err != nil { - cx.t.Fatal(err) - } - } -} - func authTestMemberAdd(cx ctlCtx) { if err := authEnable(cx); err != nil { cx.t.Fatal(err) @@ -255,41 +210,6 @@ func authTestCertCN(cx ctlCtx) { require.ErrorContains(cx.t, err, "permission denied") } -func authTestRevokeWithDelete(cx ctlCtx) { - if err := authEnable(cx); err != nil { - cx.t.Fatal(err) - } - - cx.user, cx.pass = "root", "root" - authSetupTestUser(cx) - - // 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 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) - } - - // check the result - if err := ctlV3User(cx, []string{"get", "test-user"}, "Roles: test-role test-role2", nil); err != nil { - cx.t.Fatal(err) - } - - // delete the role, test-role2 must be revoked from test-user - if err := ctlV3Role(cx, []string{"delete", "test-role2"}, "Role test-role2 deleted"); err != nil { - cx.t.Fatal(err) - } - - // check the result - if err := ctlV3User(cx, []string{"get", "test-user"}, "Roles: test-role", nil); err != nil { - cx.t.Fatal(err) - } -} - func authTestInvalidMgmt(cx ctlCtx) { if err := authEnable(cx); err != nil { cx.t.Fatal(err)