2016-05-13 06:51:48 +03:00
|
|
|
// Copyright 2016 The etcd Authors
|
2016-04-14 21:42:57 +03:00
|
|
|
//
|
|
|
|
// 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 e2e
|
|
|
|
|
2016-06-09 20:05:26 +03:00
|
|
|
import (
|
|
|
|
"fmt"
|
2017-07-15 02:03:04 +03:00
|
|
|
"os"
|
2016-06-09 20:05:26 +03:00
|
|
|
"testing"
|
2017-10-11 05:50:10 +03:00
|
|
|
"time"
|
2016-09-13 06:22:53 +03:00
|
|
|
|
2019-04-27 00:17:16 +03:00
|
|
|
"go.etcd.io/etcd/v3/clientv3"
|
2016-06-09 20:05:26 +03:00
|
|
|
)
|
2016-04-14 21:42:57 +03:00
|
|
|
|
2016-06-21 09:03:04 +03:00
|
|
|
func TestCtlV3AuthEnable(t *testing.T) { testCtl(t, authEnableTest) }
|
|
|
|
func TestCtlV3AuthDisable(t *testing.T) { testCtl(t, authDisableTest) }
|
|
|
|
func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) }
|
|
|
|
func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateTest) }
|
|
|
|
func TestCtlV3AuthUserDeleteDuringOps(t *testing.T) { testCtl(t, authUserDeleteDuringOpsTest) }
|
2016-06-21 09:13:59 +03:00
|
|
|
func TestCtlV3AuthRoleRevokeDuringOps(t *testing.T) { testCtl(t, authRoleRevokeDuringOpsTest) }
|
2016-08-19 09:09:55 +03:00
|
|
|
func TestCtlV3AuthTxn(t *testing.T) { testCtl(t, authTestTxn) }
|
2018-05-04 23:16:39 +03:00
|
|
|
func TestCtlV3AuthTxnJWT(t *testing.T) { testCtl(t, authTestTxn, withCfg(configJWT)) }
|
2017-09-07 10:24:12 +03:00
|
|
|
func TestCtlV3AuthPrefixPerm(t *testing.T) { testCtl(t, authTestPrefixPerm) }
|
2016-11-28 11:18:34 +03:00
|
|
|
func TestCtlV3AuthMemberAdd(t *testing.T) { testCtl(t, authTestMemberAdd) }
|
|
|
|
func TestCtlV3AuthMemberRemove(t *testing.T) {
|
|
|
|
testCtl(t, authTestMemberRemove, withQuorum(), withNoStrictReconfig())
|
|
|
|
}
|
2017-03-17 09:55:02 +03:00
|
|
|
func TestCtlV3AuthMemberUpdate(t *testing.T) { testCtl(t, authTestMemberUpdate) }
|
|
|
|
func TestCtlV3AuthCertCN(t *testing.T) { testCtl(t, authTestCertCN, withCfg(configClientTLSCertAuth)) }
|
|
|
|
func TestCtlV3AuthRevokeWithDelete(t *testing.T) { testCtl(t, authTestRevokeWithDelete) }
|
2017-03-17 10:10:28 +03:00
|
|
|
func TestCtlV3AuthInvalidMgmt(t *testing.T) { testCtl(t, authTestInvalidMgmt) }
|
2017-04-03 11:49:47 +03:00
|
|
|
func TestCtlV3AuthFromKeyPerm(t *testing.T) { testCtl(t, authTestFromKeyPerm) }
|
2017-04-25 08:49:55 +03:00
|
|
|
func TestCtlV3AuthAndWatch(t *testing.T) { testCtl(t, authTestWatch) }
|
2018-05-04 23:16:39 +03:00
|
|
|
func TestCtlV3AuthAndWatchJWT(t *testing.T) { testCtl(t, authTestWatch, withCfg(configJWT)) }
|
2016-04-14 21:42:57 +03:00
|
|
|
|
2017-12-15 06:21:07 +03:00
|
|
|
func TestCtlV3AuthLeaseTestKeepAlive(t *testing.T) { testCtl(t, authLeaseTestKeepAlive) }
|
|
|
|
func TestCtlV3AuthLeaseTestTimeToLiveExpired(t *testing.T) { testCtl(t, authLeaseTestTimeToLiveExpired) }
|
2018-02-11 22:34:55 +03:00
|
|
|
func TestCtlV3AuthLeaseGrantLeases(t *testing.T) { testCtl(t, authLeaseTestLeaseGrantLeases) }
|
2018-05-04 23:16:39 +03:00
|
|
|
func TestCtlV3AuthLeaseGrantLeasesJWT(t *testing.T) {
|
|
|
|
testCtl(t, authLeaseTestLeaseGrantLeases, withCfg(configJWT))
|
|
|
|
}
|
|
|
|
func TestCtlV3AuthLeaseRevoke(t *testing.T) { testCtl(t, authLeaseTestLeaseRevoke) }
|
2017-12-15 06:21:07 +03:00
|
|
|
|
2017-06-07 02:21:00 +03:00
|
|
|
func TestCtlV3AuthRoleGet(t *testing.T) { testCtl(t, authTestRoleGet) }
|
2017-06-27 08:20:35 +03:00
|
|
|
func TestCtlV3AuthUserGet(t *testing.T) { testCtl(t, authTestUserGet) }
|
2017-06-07 02:21:00 +03:00
|
|
|
func TestCtlV3AuthRoleList(t *testing.T) { testCtl(t, authTestRoleList) }
|
|
|
|
|
2017-07-15 02:03:04 +03:00
|
|
|
func TestCtlV3AuthDefrag(t *testing.T) { testCtl(t, authTestDefrag) }
|
|
|
|
func TestCtlV3AuthEndpointHealth(t *testing.T) {
|
|
|
|
testCtl(t, authTestEndpointHealth, withQuorum())
|
|
|
|
}
|
2018-05-04 23:16:39 +03:00
|
|
|
func TestCtlV3AuthSnapshot(t *testing.T) { testCtl(t, authTestSnapshot) }
|
|
|
|
func TestCtlV3AuthSnapshotJWT(t *testing.T) { testCtl(t, authTestSnapshot, withCfg(configJWT)) }
|
2017-09-25 09:43:22 +03:00
|
|
|
func TestCtlV3AuthCertCNAndUsername(t *testing.T) {
|
|
|
|
testCtl(t, authTestCertCNAndUsername, withCfg(configClientTLSCertAuth))
|
|
|
|
}
|
2017-10-11 05:50:10 +03:00
|
|
|
func TestCtlV3AuthJWTExpire(t *testing.T) { testCtl(t, authTestJWTExpire, withCfg(configJWT)) }
|
2017-07-15 02:03:04 +03:00
|
|
|
|
2016-04-14 21:42:57 +03:00
|
|
|
func authEnableTest(cx ctlCtx) {
|
2016-06-09 20:05:26 +03:00
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authEnable(cx ctlCtx) error {
|
2016-06-08 07:44:54 +03:00
|
|
|
// create root user with root role
|
|
|
|
if err := ctlV3User(cx, []string{"add", "root", "--interactive=false"}, "User root created", []string{"root"}); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
return fmt.Errorf("failed to create root user %v", err)
|
2016-06-08 07:44:54 +03:00
|
|
|
}
|
|
|
|
if err := ctlV3User(cx, []string{"grant-role", "root", "root"}, "Role root is granted to user root", nil); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
return fmt.Errorf("failed to grant root user root role %v", err)
|
2016-06-08 07:44:54 +03:00
|
|
|
}
|
2016-04-14 21:42:57 +03:00
|
|
|
if err := ctlV3AuthEnable(cx); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
return fmt.Errorf("authEnableTest ctlV3AuthEnable error (%v)", err)
|
2016-04-14 21:42:57 +03:00
|
|
|
}
|
2016-06-09 20:05:26 +03:00
|
|
|
return nil
|
2016-04-14 21:42:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func ctlV3AuthEnable(cx ctlCtx) error {
|
|
|
|
cmdArgs := append(cx.PrefixArgs(), "auth", "enable")
|
|
|
|
return spawnWithExpect(cmdArgs, "Authentication Enabled")
|
|
|
|
}
|
2016-05-07 21:24:43 +03:00
|
|
|
|
|
|
|
func authDisableTest(cx ctlCtx) {
|
2016-06-22 09:54:04 +03:00
|
|
|
// a key that isn't granted to test-user
|
|
|
|
if err := ctlV3Put(cx, "hoo", "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)
|
|
|
|
|
|
|
|
// test-user doesn't have the permission, it must fail
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
2016-05-07 21:24:43 +03:00
|
|
|
if err := ctlV3AuthDisable(cx); err != nil {
|
|
|
|
cx.t.Fatalf("authDisableTest ctlV3AuthDisable error (%v)", err)
|
|
|
|
}
|
2016-06-22 09:54:04 +03:00
|
|
|
|
2017-04-18 10:00:53 +03:00
|
|
|
// now ErrAuthNotEnabled of Authenticate() is simply ignored
|
2016-06-22 09:54:04 +03:00
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
2017-04-18 10:00:53 +03:00
|
|
|
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
|
2016-06-22 09:54:04 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// now the key can be accessed
|
|
|
|
cx.user, cx.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)
|
|
|
|
}
|
2016-05-07 21:24:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func ctlV3AuthDisable(cx ctlCtx) error {
|
|
|
|
cmdArgs := append(cx.PrefixArgs(), "auth", "disable")
|
|
|
|
return spawnWithExpect(cmdArgs, "Authentication Disabled")
|
|
|
|
}
|
2016-06-09 20:05:26 +03:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2016-09-06 05:32:25 +03:00
|
|
|
// confirm root role can access to all keys
|
|
|
|
if err := ctlV3Put(cx, "foo", "bar", ""); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
2016-09-06 05:32:25 +03:00
|
|
|
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try invalid user
|
|
|
|
cx.user, cx.pass = "a", "b"
|
|
|
|
if err := ctlV3PutFailAuth(cx, "foo", "bar"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
// confirm put failed
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
2016-09-06 05:32:25 +03:00
|
|
|
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try good user
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
2016-09-06 05:32:25 +03:00
|
|
|
if err := ctlV3Put(cx, "foo", "bar2", ""); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
// confirm put succeeded
|
2016-09-06 05:32:25 +03:00
|
|
|
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try bad password
|
|
|
|
cx.user, cx.pass = "test-user", "badpass"
|
|
|
|
if err := ctlV3PutFailAuth(cx, "foo", "baz"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
// confirm put failed
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
2016-09-06 05:32:25 +03:00
|
|
|
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar2"}}...); err != nil {
|
2016-06-09 20:05:26 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-20 10:31:22 +03:00
|
|
|
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"
|
|
|
|
if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// grant a new key
|
|
|
|
cx.user, cx.pass = "root", "root"
|
2016-09-13 06:22:53 +03:00
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "hoo", "", false}); err != nil {
|
2016-06-20 10:31:22 +03:00
|
|
|
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"
|
2017-04-03 11:49:47 +03:00
|
|
|
if err := ctlV3RoleRevokePermission(cx, "test-role", "hoo", "", false); err != nil {
|
2016-06-20 10:31:22 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try put to the revoked key
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3PutFailPerm(cx, "hoo", "bar"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// confirm a key still granted can be accessed
|
|
|
|
if err := ctlV3Get(cx, []string{"foo"}, []kv{{"foo", "bar"}}...); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-21 09:03:04 +03:00
|
|
|
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"
|
|
|
|
if err := ctlV3PutFailAuth(cx, "foo", "baz"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-21 09:13:59 +03:00
|
|
|
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
|
2016-09-13 06:22:53 +03:00
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role2", grantingPerm{true, true, "hoo", "", false}); err != nil {
|
2016-06-21 09:13:59 +03:00
|
|
|
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"
|
|
|
|
if err := ctlV3PutFailPerm(cx, "foo", "baz"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-09 20:05:26 +03:00
|
|
|
func ctlV3PutFailAuth(cx ctlCtx, key, val string) error {
|
|
|
|
return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "authentication failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
func ctlV3PutFailPerm(cx ctlCtx, key, val string) error {
|
|
|
|
return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "permission denied")
|
|
|
|
}
|
|
|
|
|
|
|
|
func authSetupTestUser(cx ctlCtx) {
|
|
|
|
if err := ctlV3User(cx, []string{"add", "test-user", "--interactive=false"}, "User test-user created", []string{"pass"}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role"}, "Role test-role is granted to user test-user", nil); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
cmd := append(cx.PrefixArgs(), "role", "grant-permission", "test-role", "readwrite", "foo")
|
|
|
|
if err := spawnWithExpect(cmd, "Role test-role updated"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2016-08-19 09:09:55 +03:00
|
|
|
|
|
|
|
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 {
|
2016-09-13 06:22:53 +03:00
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, key, "", false}); err != nil {
|
2016-08-19 09:09:55 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// now test txn
|
|
|
|
cx.interactive = true
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
|
|
|
|
rqs := txnRequests{
|
|
|
|
compare: []string{`version("c2") = "1"`},
|
|
|
|
ifSucess: []string{"get s2"},
|
|
|
|
ifFail: []string{"get f2"},
|
|
|
|
results: []string{"SUCCESS", "s2", "v"},
|
|
|
|
}
|
|
|
|
if err := ctlV3Txn(cx, rqs); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// a key of compare case isn't granted
|
|
|
|
rqs = txnRequests{
|
|
|
|
compare: []string{`version("c1") = "1"`},
|
|
|
|
ifSucess: []string{"get s2"},
|
|
|
|
ifFail: []string{"get f2"},
|
2017-07-14 00:26:13 +03:00
|
|
|
results: []string{"Error: etcdserver: permission denied"},
|
2016-08-19 09:09:55 +03:00
|
|
|
}
|
|
|
|
if err := ctlV3Txn(cx, rqs); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// a key of success case isn't granted
|
|
|
|
rqs = txnRequests{
|
|
|
|
compare: []string{`version("c2") = "1"`},
|
|
|
|
ifSucess: []string{"get s1"},
|
|
|
|
ifFail: []string{"get f2"},
|
2017-07-14 00:26:13 +03:00
|
|
|
results: []string{"Error: etcdserver: permission denied"},
|
2016-08-19 09:09:55 +03:00
|
|
|
}
|
|
|
|
if err := ctlV3Txn(cx, rqs); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// a key of failure case isn't granted
|
|
|
|
rqs = txnRequests{
|
|
|
|
compare: []string{`version("c2") = "1"`},
|
|
|
|
ifSucess: []string{"get s2"},
|
|
|
|
ifFail: []string{"get f1"},
|
2017-07-14 00:26:13 +03:00
|
|
|
results: []string{"Error: etcdserver: permission denied"},
|
2016-08-19 09:09:55 +03:00
|
|
|
}
|
|
|
|
if err := ctlV3Txn(cx, rqs); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2016-09-13 06:22:53 +03:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := ctlV3PutFailPerm(cx, clientv3.GetPrefixRangeEnd(prefix), "baz"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
2017-09-07 10:24:12 +03:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
}
|
2016-09-13 06:22:53 +03:00
|
|
|
}
|
2016-11-28 11:18:34 +03:00
|
|
|
|
|
|
|
func authTestMemberAdd(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11)
|
2017-03-21 17:50:16 +03:00
|
|
|
// ordinary user cannot add a new member
|
2016-11-28 11:18:34 +03:00
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3MemberAdd(cx, peerURL); err == nil {
|
2017-03-21 17:50:16 +03:00
|
|
|
cx.t.Fatalf("ordinary user must not be allowed to add a member")
|
2016-11-28 11:18:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// root can add a new member
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3MemberAdd(cx, peerURL); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authTestMemberRemove(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
2017-03-18 02:22:30 +03:00
|
|
|
ep, memIDToRemove, clusterID := cx.memberToRemove()
|
2016-11-28 11:18:34 +03:00
|
|
|
|
2017-03-21 17:50:16 +03:00
|
|
|
// ordinary user cannot remove a member
|
2016-11-28 11:18:34 +03:00
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
2017-03-18 02:22:30 +03:00
|
|
|
if err := ctlV3MemberRemove(cx, ep, memIDToRemove, clusterID); err == nil {
|
2017-03-21 17:50:16 +03:00
|
|
|
cx.t.Fatalf("ordinary user must not be allowed to remove a member")
|
2016-11-28 11:18:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// root can remove a member
|
|
|
|
cx.user, cx.pass = "root", "root"
|
2017-03-18 02:22:30 +03:00
|
|
|
if err := ctlV3MemberRemove(cx, ep, memIDToRemove, clusterID); err != nil {
|
2016-11-28 11:18:34 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authTestMemberUpdate(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
mr, err := getMemberList(cx)
|
|
|
|
if err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2017-03-21 17:50:16 +03:00
|
|
|
// ordinary user cannot update a member
|
2016-11-28 11:18:34 +03:00
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
peerURL := fmt.Sprintf("http://localhost:%d", etcdProcessBasePort+11)
|
|
|
|
memberID := fmt.Sprintf("%x", mr.Members[0].ID)
|
|
|
|
if err = ctlV3MemberUpdate(cx, memberID, peerURL); err == nil {
|
2017-03-21 17:50:16 +03:00
|
|
|
cx.t.Fatalf("ordinary user must not be allowed to update a member")
|
2016-11-28 11:18:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// root can update a member
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err = ctlV3MemberUpdate(cx, memberID, peerURL); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2016-11-21 10:42:46 +03:00
|
|
|
|
|
|
|
func authTestCertCN(cx ctlCtx) {
|
2017-09-25 09:43:22 +03:00
|
|
|
if err := authEnable(cx); err != nil {
|
2016-11-21 10:42:46 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
2017-09-25 09:43:22 +03:00
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
|
2016-11-21 10:42:46 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
2017-09-25 09:43:22 +03:00
|
|
|
if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil {
|
2016-11-21 10:42:46 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
2017-09-25 09:43:22 +03:00
|
|
|
if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role"}, "Role test-role is granted to user example.com", nil); err != nil {
|
2016-11-21 10:42:46 +03:00
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// grant a new key
|
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "hoo", "", false}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try a granted key
|
|
|
|
cx.user, cx.pass = "", ""
|
|
|
|
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
|
2017-09-25 09:43:22 +03:00
|
|
|
cx.t.Error(err)
|
2016-11-21 10:42:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// try a non granted key
|
|
|
|
cx.user, cx.pass = "", ""
|
2017-09-25 09:43:22 +03:00
|
|
|
if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
|
|
|
|
cx.t.Error(err)
|
2016-11-21 10:42:46 +03:00
|
|
|
}
|
|
|
|
}
|
2017-03-17 09:55:02 +03:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
2017-03-17 10:10:28 +03:00
|
|
|
|
|
|
|
func authTestInvalidMgmt(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2017-07-14 00:26:13 +03:00
|
|
|
if err := ctlV3Role(cx, []string{"delete", "root"}, "Error: etcdserver: invalid auth management"); err == nil {
|
2017-03-17 10:10:28 +03:00
|
|
|
cx.t.Fatal("deleting the role root must not be allowed")
|
|
|
|
}
|
|
|
|
|
2017-07-14 00:26:13 +03:00
|
|
|
if err := ctlV3User(cx, []string{"revoke-role", "root", "root"}, "Error: etcdserver: invalid auth management", []string{}); err == nil {
|
2017-03-17 10:10:28 +03:00
|
|
|
cx.t.Fatal("revoking the role root from the user root must not be allowed")
|
|
|
|
}
|
|
|
|
}
|
2017-04-03 11:49:47 +03:00
|
|
|
|
|
|
|
func authTestFromKeyPerm(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
// grant keys after z to test-user
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "z", "\x00", false}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try the granted open ended permission
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
key := fmt.Sprintf("z%d", i)
|
|
|
|
if err := ctlV3Put(cx, key, "val", ""); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
largeKey := ""
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
largeKey += "\xff"
|
|
|
|
if err := ctlV3Put(cx, largeKey, "val", ""); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// try a non granted key
|
|
|
|
if err := ctlV3PutFailPerm(cx, "x", "baz"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// revoke the open ended permission
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3RoleRevokePermission(cx, "test-role", "z", "", true); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try the revoked open ended permission
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
2017-09-07 10:24:12 +03:00
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
key := fmt.Sprintf("z%d", i)
|
|
|
|
if err := ctlV3PutFailPerm(cx, key, "val"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// grant the entire keys
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "", "\x00", false}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try keys, of course it must be allowed because test-role has a permission of the entire keys
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
key := fmt.Sprintf("z%d", i)
|
|
|
|
if err := ctlV3Put(cx, key, "val", ""); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// revoke the entire keys
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3RoleRevokePermission(cx, "test-role", "", "", true); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try the revoked entire key permission
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
2017-04-03 11:49:47 +03:00
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
key := fmt.Sprintf("z%d", i)
|
|
|
|
if err := ctlV3PutFailPerm(cx, key, "val"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-25 08:49:55 +03:00
|
|
|
|
2017-12-15 06:21:07 +03:00
|
|
|
func authLeaseTestKeepAlive(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
// put with TTL 10 seconds and keep-alive
|
|
|
|
leaseID, err := ctlV3LeaseGrant(cx, 10)
|
|
|
|
if err != nil {
|
|
|
|
cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseGrant error (%v)", err)
|
|
|
|
}
|
|
|
|
if err := ctlV3Put(cx, "key", "val", leaseID); err != nil {
|
|
|
|
cx.t.Fatalf("leaseTestKeepAlive: ctlV3Put error (%v)", err)
|
|
|
|
}
|
|
|
|
if err := ctlV3LeaseKeepAlive(cx, leaseID); err != nil {
|
|
|
|
cx.t.Fatalf("leaseTestKeepAlive: ctlV3LeaseKeepAlive error (%v)", err)
|
|
|
|
}
|
|
|
|
if err := ctlV3Get(cx, []string{"key"}, kv{"key", "val"}); err != nil {
|
|
|
|
cx.t.Fatalf("leaseTestKeepAlive: ctlV3Get error (%v)", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authLeaseTestTimeToLiveExpired(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
ttl := 3
|
|
|
|
if err := leaseTestTimeToLiveExpire(cx, ttl); err != nil {
|
2018-02-11 22:34:55 +03:00
|
|
|
cx.t.Fatalf("leaseTestTimeToLiveExpire: error (%v)", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authLeaseTestLeaseGrantLeases(cx ctlCtx) {
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
if err := leaseTestGrantLeasesList(cx); err != nil {
|
|
|
|
cx.t.Fatalf("authLeaseTestLeaseGrantLeases: error (%v)", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authLeaseTestLeaseRevoke(cx ctlCtx) {
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
2019-02-15 20:36:00 +03:00
|
|
|
// 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)
|
2017-12-15 06:21:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-25 08:49:55 +03:00
|
|
|
func authTestWatch(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
// grant a key range
|
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "key", "key4", false}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
puts []kv
|
|
|
|
args []string
|
|
|
|
|
2017-11-27 10:56:03 +03:00
|
|
|
wkv []kvExec
|
2017-04-25 08:49:55 +03:00
|
|
|
want bool
|
|
|
|
}{
|
|
|
|
{ // watch 1 key, should be successful
|
|
|
|
[]kv{{"key", "value"}},
|
|
|
|
[]string{"key", "--rev", "1"},
|
2017-11-27 10:56:03 +03:00
|
|
|
[]kvExec{{key: "key", val: "value"}},
|
2017-04-25 08:49:55 +03:00
|
|
|
true,
|
|
|
|
},
|
|
|
|
{ // watch 3 keys by range, should be successful
|
|
|
|
[]kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
|
|
|
|
[]string{"key", "key3", "--rev", "1"},
|
2017-11-27 10:56:03 +03:00
|
|
|
[]kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
|
2017-04-25 08:49:55 +03:00
|
|
|
true,
|
|
|
|
},
|
|
|
|
|
|
|
|
{ // watch 1 key, should not be successful
|
|
|
|
[]kv{},
|
|
|
|
[]string{"key5", "--rev", "1"},
|
2017-11-27 10:56:03 +03:00
|
|
|
[]kvExec{},
|
2017-04-25 08:49:55 +03:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
{ // watch 3 keys by range, should not be successful
|
|
|
|
[]kv{},
|
|
|
|
[]string{"key", "key6", "--rev", "1"},
|
2017-11-27 10:56:03 +03:00
|
|
|
[]kvExec{},
|
2017-04-25 08:49:55 +03:00
|
|
|
false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
for i, tt := range tests {
|
|
|
|
donec := make(chan struct{})
|
|
|
|
go func(i int, puts []kv) {
|
|
|
|
defer close(donec)
|
|
|
|
for j := range puts {
|
|
|
|
if err := ctlV3Put(cx, puts[j].key, puts[j].val, ""); err != nil {
|
|
|
|
cx.t.Fatalf("watchTest #%d-%d: ctlV3Put error (%v)", i, j, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}(i, tt.puts)
|
|
|
|
|
|
|
|
var err error
|
|
|
|
if tt.want {
|
|
|
|
err = ctlV3Watch(cx, tt.args, tt.wkv...)
|
|
|
|
} else {
|
|
|
|
err = ctlV3WatchFailPerm(cx, tt.args)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
|
|
|
|
cx.t.Errorf("watchTest #%d: ctlV3Watch error (%v)", i, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
<-donec
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-06-07 02:21:00 +03:00
|
|
|
|
|
|
|
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 := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), expected...); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
2017-06-27 08:20:35 +03:00
|
|
|
|
|
|
|
// test-user can get the information of test-role because it belongs to the role
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), 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{
|
2017-07-14 00:26:13 +03:00
|
|
|
"Error: etcdserver: permission denied",
|
2017-06-27 08:20:35 +03:00
|
|
|
}
|
|
|
|
if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "root"), expected...); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), 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 := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), expected...); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// test-user cannot get the information of root
|
|
|
|
expected = []string{
|
2017-07-14 00:26:13 +03:00
|
|
|
"Error: etcdserver: permission denied",
|
2017-06-27 08:20:35 +03:00
|
|
|
}
|
|
|
|
if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "root"), expected...); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
2017-06-07 02:21:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func authTestRoleList(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "list"), "test-role"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2017-07-15 02:03:04 +03:00
|
|
|
|
|
|
|
func authTestDefrag(cx ctlCtx) {
|
|
|
|
maintenanceInitKeys(cx)
|
|
|
|
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
// ordinary user cannot defrag
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3Defrag(cx); err == nil {
|
|
|
|
cx.t.Fatal("ordinary user should not be able to issue a defrag request")
|
|
|
|
}
|
|
|
|
|
|
|
|
// root can defrag
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3Defrag(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authTestSnapshot(cx ctlCtx) {
|
|
|
|
maintenanceInitKeys(cx)
|
|
|
|
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
2018-05-10 01:14:23 +03:00
|
|
|
fpath := "test-auth.snapshot"
|
2017-07-15 02:03:04 +03:00
|
|
|
defer os.RemoveAll(fpath)
|
|
|
|
|
|
|
|
// ordinary user cannot save a snapshot
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3SnapshotSave(cx, fpath); err == nil {
|
|
|
|
cx.t.Fatal("ordinary user should not be able to save a snapshot")
|
|
|
|
}
|
|
|
|
|
|
|
|
// root can save a snapshot
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3SnapshotSave(cx, fpath); err != nil {
|
|
|
|
cx.t.Fatalf("snapshotTest ctlV3SnapshotSave error (%v)", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
st, err := getSnapshotStatus(cx, fpath)
|
|
|
|
if err != nil {
|
|
|
|
cx.t.Fatalf("snapshotTest getSnapshotStatus error (%v)", err)
|
|
|
|
}
|
|
|
|
if st.Revision != 4 {
|
|
|
|
cx.t.Fatalf("expected 4, got %d", st.Revision)
|
|
|
|
}
|
|
|
|
if st.TotalKey < 3 {
|
|
|
|
cx.t.Fatalf("expected at least 3, got %d", st.TotalKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func authTestEndpointHealth(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
if err := ctlV3EndpointHealth(cx); err != nil {
|
|
|
|
cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// health checking with an ordinary user "succeeds" since permission denial goes through consensus
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3EndpointHealth(cx); err != nil {
|
|
|
|
cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// succeed if permissions granted for ordinary user
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "health", "", false}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3EndpointHealth(cx); err != nil {
|
|
|
|
cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
|
|
|
|
}
|
|
|
|
}
|
2017-09-25 09:43:22 +03:00
|
|
|
|
|
|
|
func authTestCertCNAndUsername(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), "Role test-role-cn created"); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role-cn"}, "Role test-role-cn is granted to user example.com", nil); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// grant a new key for CN based user
|
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role-cn", grantingPerm{true, true, "hoo", "", false}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// grant a new key for username based user
|
|
|
|
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "bar", "", false}); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try a granted key for CN based user
|
|
|
|
cx.user, cx.pass = "", ""
|
|
|
|
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
|
|
|
|
cx.t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try a granted key for username based user
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3Put(cx, "bar", "bar", ""); err != nil {
|
|
|
|
cx.t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// try a non granted key for both of them
|
|
|
|
cx.user, cx.pass = "", ""
|
|
|
|
if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
|
|
|
|
cx.t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "test-user", "pass"
|
|
|
|
if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
|
|
|
|
cx.t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
2017-10-11 05:50:10 +03:00
|
|
|
|
|
|
|
func authTestJWTExpire(cx ctlCtx) {
|
|
|
|
if err := authEnable(cx); err != nil {
|
|
|
|
cx.t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cx.user, cx.pass = "root", "root"
|
|
|
|
authSetupTestUser(cx)
|
|
|
|
|
|
|
|
// try a granted key
|
|
|
|
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
|
|
|
|
cx.t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// wait an expiration of my JWT token
|
|
|
|
<-time.After(3 * time.Second)
|
|
|
|
|
|
|
|
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
|
|
|
|
cx.t.Error(err)
|
|
|
|
}
|
|
|
|
}
|