Disable auth gracefully without impacting existing watchers.

Signed-off-by: Lan Liang <gcslyp@gmail.com>
This commit is contained in:
Lan Liang 2023-07-14 10:22:25 +08:00
parent d4f779a643
commit 960cd26bef
3 changed files with 50 additions and 1 deletions

View File

@ -264,6 +264,7 @@ func (c *Client) getToken(ctx context.Context) error {
resp, err := c.Auth.Authenticate(ctx, c.Username, c.Password) resp, err := c.Auth.Authenticate(ctx, c.Username, c.Password)
if err != nil { if err != nil {
if err == rpctypes.ErrAuthNotEnabled { if err == rpctypes.ErrAuthNotEnabled {
c.authTokenBundle.UpdateAuthToken("")
return nil return nil
} }
return err return err

View File

@ -1160,6 +1160,9 @@ func (as *authStore) AuthInfoFromTLS(ctx context.Context) (ai *AuthInfo) {
} }
func (as *authStore) AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error) { func (as *authStore) AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error) {
if !as.IsAuthEnabled() {
return nil, nil
}
md, ok := metadata.FromIncomingContext(ctx) md, ok := metadata.FromIncomingContext(ctx)
if !ok { if !ok {
return nil, nil return nil, nil

View File

@ -27,13 +27,14 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.etcd.io/etcd/client/v3" clientv3 "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 TestCtlV3AuthGracefulDisable(t *testing.T) { testCtl(t, authGracefulDisableTest) }
func TestCtlV3AuthStatus(t *testing.T) { testCtl(t, authStatusTest) } func TestCtlV3AuthStatus(t *testing.T) { testCtl(t, authStatusTest) }
func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) } func TestCtlV3AuthWriteKey(t *testing.T) { testCtl(t, authCredWriteKeyTest) }
func TestCtlV3AuthRoleUpdate(t *testing.T) { testCtl(t, authRoleUpdateTest) } 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 { func ctlV3AuthDisable(cx ctlCtx) error {
cmdArgs := append(cx.PrefixArgs(), "auth", "disable") cmdArgs := append(cx.PrefixArgs(), "auth", "disable")
return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Disabled") return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Disabled")