From 47cef60ac4f0c683951e355ba9e4903b27c6e83f Mon Sep 17 00:00:00 2001 From: Lan Liang Date: Fri, 14 Jul 2023 12:47:49 +0800 Subject: [PATCH] Backport #13577 Disable auth gracefully without impacting existing watchers. Signed-off-by: Lan Liang --- auth/store.go | 3 +++ clientv3/client.go | 1 + tests/e2e/ctl_v3_auth_test.go | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/auth/store.go b/auth/store.go index 5b69f601d91..2611dce8c94 100644 --- a/auth/store.go +++ b/auth/store.go @@ -1302,6 +1302,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/clientv3/client.go b/clientv3/client.go index e2003bcfb88..77ebb2f6cf6 100644 --- a/clientv3/client.go +++ b/clientv3/client.go @@ -299,6 +299,7 @@ func (c *Client) getToken(ctx context.Context) error { if err != nil { // return err without retrying other endpoints if err == rpctypes.ErrAuthNotEnabled { + c.authTokenBundle.UpdateAuthToken("") return err } continue diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index cee25732273..34d97037bc8 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -28,6 +28,7 @@ import ( 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 TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) } func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateTest) } func TestCtlV3AuthUserDeleteDuringOps(t *testing.T) { testCtl(t, authUserDeleteDuringOpsTest) } @@ -158,6 +159,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 spawnWithExpect(cmdArgs, "Authentication Disabled")