"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "tests/e2e/ctl_v3_auth_test.go" between
etcd-3.5.5.tar.gz and etcd-3.5.6.tar.gz

About: etcd is a distributed reliable key-value store for the most critical data of a distributed system (written in "Go").

ctl_v3_auth_test.go  (etcd-3.5.5):ctl_v3_auth_test.go  (etcd-3.5.6)
skipping to change at line 20 skipping to change at line 20
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package e2e package e2e
import ( import (
"context" "context"
"fmt" "fmt"
"net/url"
"os" "os"
"path/filepath"
"syscall" "syscall"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/client/v3"
) )
func TestCtlV3AuthEnable(t *testing.T) { func TestCtlV3AuthEnable(t *testing.T) {
testCtl(t, authEnableTest) testCtl(t, authEnableTest)
} }
func TestCtlV3AuthDisable(t *testing.T) { testCtl(t, authDisableTest ) } func TestCtlV3AuthDisable(t *testing.T) { testCtl(t, authDisableTest ) }
func TestCtlV3AuthStatus(t *testing.T) { testCtl(t, authStatusTest) } func TestCtlV3AuthStatus(t *testing.T) { testCtl(t, authStatusTest) }
func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKe yTest) } func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKe yTest) }
func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateT est) } func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateT est) }
skipping to change at line 75 skipping to change at line 80
func TestCtlV3AuthDefrag(t *testing.T) { testCtl(t, authTestDefrag) } func TestCtlV3AuthDefrag(t *testing.T) { testCtl(t, authTestDefrag) }
func TestCtlV3AuthEndpointHealth(t *testing.T) { func TestCtlV3AuthEndpointHealth(t *testing.T) {
testCtl(t, authTestEndpointHealth, withQuorum()) testCtl(t, authTestEndpointHealth, withQuorum())
} }
func TestCtlV3AuthSnapshot(t *testing.T) { testCtl(t, authTestSnapsho t) } func TestCtlV3AuthSnapshot(t *testing.T) { testCtl(t, authTestSnapsho t) }
func TestCtlV3AuthSnapshotJWT(t *testing.T) { testCtl(t, authTestSnapsho t, withCfg(*newConfigJWT())) } func TestCtlV3AuthSnapshotJWT(t *testing.T) { testCtl(t, authTestSnapsho t, withCfg(*newConfigJWT())) }
func TestCtlV3AuthJWTExpire(t *testing.T) { testCtl(t, authTestJWTExpi re, withCfg(*newConfigJWT())) } func TestCtlV3AuthJWTExpire(t *testing.T) { testCtl(t, authTestJWTExpi re, withCfg(*newConfigJWT())) }
func TestCtlV3AuthRevisionConsistency(t *testing.T) { testCtl(t, authTestRevisio nConsistency) } func TestCtlV3AuthRevisionConsistency(t *testing.T) { testCtl(t, authTestRevisio nConsistency) }
func TestCtlV3AuthTestCacheReload(t *testing.T) { testCtl(t, authTestCacheRe load) } func TestCtlV3AuthTestCacheReload(t *testing.T) { testCtl(t, authTestCacheRe load) }
func TestCtlV3AuthRecoverFromSnapshot(t *testing.T) {
testCtl(t, authTestRecoverSnapshot, withCfg(*newConfigNoTLS()), withQuoru
m(), withSnapshotCount(5))
}
func authEnableTest(cx ctlCtx) { func authEnableTest(cx ctlCtx) {
if err := authEnable(cx); err != nil { if err := authEnable(cx); err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
} }
func authEnable(cx ctlCtx) error { func authEnable(cx ctlCtx) error {
// create root user with root role // create root user with root role
if err := ctlV3User(cx, []string{"add", "root", "--interactive=false"}, " User root created", []string{"root"}); err != nil { if err := ctlV3User(cx, []string{"add", "root", "--interactive=false"}, " User root created", []string{"root"}); err != nil {
return fmt.Errorf("failed to create root user %v", err) return fmt.Errorf("failed to create root user %v", err)
} }
if err := ctlV3User(cx, []string{"grant-role", "root", "root"}, "Role roo t is granted to user root", nil); err != nil { if err := ctlV3User(cx, []string{"grant-role", "root", "root"}, "Role roo t is granted to user root", nil); err != nil {
return fmt.Errorf("failed to grant root user root role %v", err) return fmt.Errorf("failed to grant root user root role %v", err)
} }
if err := ctlV3AuthEnable(cx); err != nil { if err := ctlV3AuthEnable(cx); err != nil {
return fmt.Errorf("authEnableTest ctlV3AuthEnable error (%v)", er r) return fmt.Errorf("authEnableTest ctlV3AuthEnable error (%v)", er r)
} }
return nil return nil
} }
func applyTLSWithRootCommonName() func() {
var (
oldCertPath = certPath
oldPrivateKeyPath = privateKeyPath
oldCaPath = caPath
newCertPath = filepath.Join(fixturesDir, "CommonName-root.c
rt")
newPrivateKeyPath = filepath.Join(fixturesDir, "CommonName-root.k
ey")
newCaPath = filepath.Join(fixturesDir, "CommonName-root.c
rt")
)
certPath = newCertPath
privateKeyPath = newPrivateKeyPath
caPath = newCaPath
return func() {
certPath = oldCertPath
privateKeyPath = oldPrivateKeyPath
caPath = oldCaPath
}
}
func ctlV3AuthEnable(cx ctlCtx) error { func ctlV3AuthEnable(cx ctlCtx) error {
cmdArgs := append(cx.PrefixArgs(), "auth", "enable") cmdArgs := append(cx.PrefixArgs(), "auth", "enable")
return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Enabled ") return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Enabled ")
} }
func authDisableTest(cx ctlCtx) { func authDisableTest(cx ctlCtx) {
// a key that isn't granted to test-user // a key that isn't granted to test-user
if err := ctlV3Put(cx, "hoo", "a", ""); err != nil { if err := ctlV3Put(cx, "hoo", "a", ""); err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
skipping to change at line 1292 skipping to change at line 1323
node0.WithStopSignal(syscall.SIGINT) node0.WithStopSignal(syscall.SIGINT)
if err := node0.Restart(); err != nil { if err := node0.Restart(); err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
// nothing has changed, but it fails without refreshing cache after resta rt // nothing has changed, but it fails without refreshing cache after resta rt
if _, err = c2.Put(context.TODO(), "foo", "bar2"); err != nil { if _, err = c2.Put(context.TODO(), "foo", "bar2"); err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
} }
// Verify that etcd works after recovering from a snapshot.
// Refer to https://github.com/etcd-io/etcd/issues/14571.
func authTestRecoverSnapshot(cx ctlCtx) {
roles := []authRole{
{
role: "role0",
permission: clientv3.PermissionType(clientv3.PermReadWrit
e),
key: "foo",
},
}
users := []authUser{
{
user: "root",
pass: "rootPass",
role: "root",
},
{
user: "user0",
pass: "user0Pass",
role: "role0",
},
}
cx.t.Log("setup and enable auth")
setupAuth(cx, roles, users)
// create a client with root user
cx.t.Log("create a client with root user")
cliRoot, err := clientv3.New(clientv3.Config{Endpoints: cx.epc.EndpointsV
3(), Username: "root", Password: "rootPass", DialTimeout: 3 * time.Second})
if err != nil {
cx.t.Fatal(err)
}
defer cliRoot.Close()
// write more than SnapshotCount keys, so that at least one snapshot is c
reated
cx.t.Log("Write enough key/value to trigger a snapshot")
for i := 0; i <= 6; i++ {
if _, err := cliRoot.Put(context.TODO(), fmt.Sprintf("key_%d", i)
, fmt.Sprintf("value_%d", i)); err != nil {
cx.t.Fatalf("failed to Put (%v)", err)
}
}
// add a new member into the cluster
// Refer to https://github.com/etcd-io/etcd/blob/17cb291f1515d0a4d712acdf
396a1f2874f172bf/tests/e2e/cluster_test.go#L238
var (
idx = 3
name = fmt.Sprintf("test-%d", idx)
port = cx.cfg.basePort + 5*idx
curlHost = fmt.Sprintf("localhost:%d", port)
nodeClientURL = url.URL{Scheme: cx.cfg.clientScheme(), Host: cur
lHost}
nodePeerURL = url.URL{Scheme: cx.cfg.peerScheme(), Host: fmt.S
printf("localhost:%d", port+1)}
initialCluster = cx.epc.procs[0].Config().initialCluster + "," +
fmt.Sprintf("%s=%s", name, nodePeerURL.String())
)
cx.t.Logf("Adding a new member: %s", nodePeerURL.String())
// Must wait at least 5 seconds, otherwise it will always get an
// "etcdserver: unhealthy cluster" response, please refer to link below,
// https://github.com/etcd-io/etcd/blob/17cb291f1515d0a4d712acdf396a1f287
4f172bf/server/etcdserver/server.go#L1611
assert.Eventually(cx.t, func() bool {
if _, err := cliRoot.MemberAdd(context.TODO(), []string{nodePeerU
RL.String()}); err != nil {
cx.t.Logf("Failed to add member, peelURL: %s, error: %v",
nodePeerURL.String(), err)
return false
}
return true
}, 8*time.Second, 2*time.Second)
cx.t.Logf("Starting the new member: %s", nodePeerURL.String())
newProc, err := runEtcdNode(name, cx.t.TempDir(), nodeClientURL.String(),
nodePeerURL.String(), "existing", initialCluster)
require.NoError(cx.t, err)
defer newProc.Stop()
// create a client with user "user0", and connects to the new member
cx.t.Log("create a client with user 'user0'")
cliUser, err := clientv3.New(clientv3.Config{Endpoints: []string{nodeClie
ntURL.String()}, Username: "user0", Password: "user0Pass", DialTimeout: 3 * time
.Second})
if err != nil {
cx.t.Fatal(err)
}
defer cliUser.Close()
// write data using the cliUser, expect no error
cx.t.Log("Write a key/value using user 'user0'")
_, err = cliUser.Put(context.TODO(), "foo", "bar")
require.NoError(cx.t, err)
//verify all nodes have the same revision and hash
var endpoints []string
for _, proc := range cx.epc.procs {
endpoints = append(endpoints, proc.Config().acurl)
}
endpoints = append(endpoints, nodeClientURL.String())
cx.t.Log("Verify all members have the same revision and hash")
assert.Eventually(cx.t, func() bool {
hashKvs, err := hashKVs(endpoints, cliRoot)
if err != nil {
cx.t.Logf("failed to get HashKV: %v", err)
return false
}
if len(hashKvs) != 4 {
cx.t.Logf("expected 4 hashkv responses, but got: %d", len
(hashKvs))
return false
}
if !(hashKvs[0].Header.Revision == hashKvs[1].Header.Revision &&
hashKvs[0].Header.Revision == hashKvs[2].Header.Revision
&&
hashKvs[0].Header.Revision == hashKvs[3].Header.Revision)
{
cx.t.Logf("Got different revisions, [%d, %d, %d, %d]",
hashKvs[0].Header.Revision,
hashKvs[1].Header.Revision,
hashKvs[2].Header.Revision,
hashKvs[3].Header.Revision)
return false
}
assert.Equal(cx.t, hashKvs[0].Hash, hashKvs[1].Hash)
assert.Equal(cx.t, hashKvs[0].Hash, hashKvs[2].Hash)
assert.Equal(cx.t, hashKvs[0].Hash, hashKvs[3].Hash)
return true
}, 5*time.Second, 100*time.Millisecond)
}
type authRole struct {
role string
permission clientv3.PermissionType
key string
keyEnd string
}
type authUser struct {
user string
pass string
role string
}
func setupAuth(cx ctlCtx, roles []authRole, users []authUser) {
endpoint := cx.epc.procs[0].EndpointsV3()[0]
// create a client
c, err := clientv3.New(clientv3.Config{Endpoints: []string{endpoint}, Dia
lTimeout: 3 * time.Second})
if err != nil {
cx.t.Fatal(err)
}
defer c.Close()
// create roles
for _, r := range roles {
// add role
if _, err = c.RoleAdd(context.TODO(), r.role); err != nil {
cx.t.Fatal(err)
}
// grant permission to role
if _, err = c.RoleGrantPermission(context.TODO(), r.role, r.key,
r.keyEnd, r.permission); err != nil {
cx.t.Fatal(err)
}
}
// create users
for _, u := range users {
// add user
if _, err = c.UserAdd(context.TODO(), u.user, u.pass); err != nil
{
cx.t.Fatal(err)
}
// grant role to user
if _, err = c.UserGrantRole(context.TODO(), u.user, u.role); err
!= nil {
cx.t.Fatal(err)
}
}
// enable auth
if _, err = c.AuthEnable(context.TODO()); err != nil {
cx.t.Fatal(err)
}
}
func hashKVs(endpoints []string, cli *clientv3.Client) ([]*clientv3.HashKVRespon
se, error) {
var retHashKVs []*clientv3.HashKVResponse
for _, ep := range endpoints {
resp, err := cli.HashKV(context.TODO(), ep, 0)
if err != nil {
return nil, err
}
retHashKVs = append(retHashKVs, resp)
}
return retHashKVs, nil
}
 End of changes. 6 change blocks. 
0 lines changed or deleted 35 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)