From 960cd26befe265896b331415da4ca2c9895bde15 Mon Sep 17 00:00:00 2001 From: Lan Liang Date: Fri, 14 Jul 2023 10:22:25 +0800 Subject: [PATCH] Backport #13577 Disable auth gracefully without impacting existing watchers. Signed-off-by: Lan Liang --- client/v3/client.go | 1 + server/auth/store.go | 3 +++ tests/e2e/ctl_v3_auth_test.go | 47 ++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/client/v3/client.go b/client/v3/client.go index 4dfae89c6..60cbdf214 100644 --- a/client/v3/client.go +++ b/client/v3/client.go @@ -264,6 +264,7 @@ func (c *Client) getToken(ctx context.Context) error { resp, err := c.Auth.Authenticate(ctx, c.Username, c.Password) if err != nil { if err == rpctypes.ErrAuthNotEnabled { + c.authTokenBundle.UpdateAuthToken("") return nil } return err diff --git a/server/auth/store.go b/server/auth/store.go index 9b4297f21..67c5694cd 100644 --- a/server/auth/store.go +++ b/server/auth/store.go @@ -1160,6 +1160,9 @@ func (as *authStore) AuthInfoFromTLS(ctx context.Context) (ai *AuthInfo) { } func (as *authStore) AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error) { + if !as.IsAuthEnabled() { + return nil, nil + } md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, nil diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index ac7e90e04..0a08b3654 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -27,13 +27,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" ) func TestCtlV3AuthEnable(t *testing.T) { testCtl(t, authEnableTest) } func TestCtlV3AuthDisable(t *testing.T) { testCtl(t, authDisableTest) } +func TestCtlV3AuthGracefulDisable(t *testing.T) { testCtl(t, authGracefulDisableTest) } func TestCtlV3AuthStatus(t *testing.T) { testCtl(t, authStatusTest) } func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) } func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateTest) } @@ -170,6 +171,50 @@ func authDisableTest(cx ctlCtx) { } } +func authGracefulDisableTest(cx ctlCtx) { + if err := authEnable(cx); err != nil { + cx.t.Fatal(err) + } + + cx.user, cx.pass = "root", "root" + + donec := make(chan struct{}) + + go func() { + defer close(donec) + + // sleep a bit to let the watcher connects while auth is still enabled + time.Sleep(1000 * time.Millisecond) + + // now disable auth... + if err := ctlV3AuthDisable(cx); err != nil { + cx.t.Fatalf("authGracefulDisableTest ctlV3AuthDisable error (%v)", err) + } + + // ...and restart the node + node0 := cx.epc.procs[0] + node0.WithStopSignal(syscall.SIGINT) + if rerr := node0.Restart(); rerr != nil { + cx.t.Fatal(rerr) + } + + // the watcher should still work after reconnecting + if perr := ctlV3Put(cx, "key", "value", ""); perr != nil { + cx.t.Errorf("authGracefulDisableTest ctlV3Put error (%v)", perr) + } + }() + + err := ctlV3Watch(cx, []string{"key"}, kvExec{key: "key", val: "value"}) + + if err != nil { + if cx.dialTimeout > 0 && !isGRPCTimedout(err) { + cx.t.Errorf("authGracefulDisableTest ctlV3Watch error (%v)", err) + } + } + + <-donec +} + func ctlV3AuthDisable(cx ctlCtx) error { cmdArgs := append(cx.PrefixArgs(), "auth", "disable") return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Disabled")