Skip to content

Commit 83bb20d

Browse files
authored
Merge pull request #21549 from etcd-io/cherry-pick-36/allow-non-admin-user-to-list-members
[release-3.6] etcdserver: allow non-admin to fetch member list and alarms
2 parents 8a1830c + c99cf0c commit 83bb20d

5 files changed

Lines changed: 40 additions & 28 deletions

File tree

server/etcdserver/api/v3rpc/auth.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,19 @@ func (aa *AuthAdmin) isPermitted(ctx context.Context) error {
185185

186186
return aa.ag.AuthStore().IsAdminPermitted(authInfo)
187187
}
188+
189+
func (aa *AuthAdmin) requireAuthInfo(ctx context.Context) error {
190+
if !aa.ag.AuthStore().IsAuthEnabled() {
191+
return nil
192+
}
193+
194+
authInfo, err := aa.ag.AuthInfoFromCtx(ctx)
195+
if err != nil {
196+
return err
197+
}
198+
199+
if authInfo == nil {
200+
return auth.ErrUserEmpty
201+
}
202+
return nil
203+
}

server/etcdserver/api/v3rpc/maintenance.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,15 @@ func (ams *authMaintenanceServer) HashKV(ctx context.Context, r *pb.HashKVReques
350350
}
351351

352352
func (ams *authMaintenanceServer) Alarm(ctx context.Context, ar *pb.AlarmRequest) (*pb.AlarmResponse, error) {
353-
if err := ams.isPermitted(ctx); err != nil {
354-
return nil, togRPCError(err)
353+
switch ar.GetAction() {
354+
case pb.AlarmRequest_GET:
355+
if err := ams.requireAuthInfo(ctx); err != nil {
356+
return nil, togRPCError(err)
357+
}
358+
default:
359+
if err := ams.isPermitted(ctx); err != nil {
360+
return nil, togRPCError(err)
361+
}
355362
}
356363
return ams.maintenanceServer.Alarm(ctx, ar)
357364
}

server/etcdserver/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1677,7 +1677,7 @@ func (s *EtcdServer) MemberList(ctx context.Context, r *pb.MemberListRequest) ([
16771677
}
16781678
}
16791679

1680-
if err := s.checkMembershipOperationPermission(ctx); err != nil {
1680+
if err := s.requireAuthInfo(ctx); err != nil {
16811681
return nil, err
16821682
}
16831683
return s.cluster.Members(), nil

tests/common/auth_test.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -691,9 +691,14 @@ func TestAuthMemberList(t *testing.T) {
691691
require.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth")
692692
rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword)))
693693
testUserAuthClient := testutils.MustClient(clus.Client(WithAuth(testUserName, testPassword)))
694+
anonAuthClient := testutils.MustClient(clus.Client())
694695

695696
_, err := testUserAuthClient.MemberList(ctx, false)
696-
require.ErrorContains(t, err, PermissionDenied)
697+
require.NoError(t, err)
698+
699+
_, err = anonAuthClient.MemberList(ctx, false)
700+
require.Error(t, err)
701+
require.ErrorContains(t, err, "etcdserver: user name is empty")
697702

698703
_, err = rootAuthClient.MemberList(ctx, false)
699704
require.NoError(t, err)
@@ -994,6 +999,7 @@ func TestAuthAlarm(t *testing.T) {
994999
require.NoErrorf(t, setupAuth(cc, []authRole{testRole}, []authUser{rootUser, testUser}), "failed to enable auth")
9951000
rootAuthClient := testutils.MustClient(clus.Client(WithAuth(rootUserName, rootPassword)))
9961001
testUserAuthClient := testutils.MustClient(clus.Client(WithAuth(testUserName, testPassword)))
1002+
anonAuthClient := testutils.MustClient(clus.Client())
9971003

9981004
for i := 0; ; i++ {
9991005
err := rootAuthClient.Put(ctx,
@@ -1006,9 +1012,6 @@ func TestAuthAlarm(t *testing.T) {
10061012
break
10071013
}
10081014

1009-
_, err := testUserAuthClient.AlarmList(ctx)
1010-
require.ErrorContains(t, err, PermissionDenied)
1011-
10121015
memberID := uint64(0)
10131016

10141017
for i := 0; i < 10; i++ {
@@ -1023,6 +1026,12 @@ func TestAuthAlarm(t *testing.T) {
10231026
}
10241027
require.NotEqualf(t, uint64(0), memberID, "expect to find alarm with non-zero member ID")
10251028

1029+
_, err := anonAuthClient.AlarmList(ctx)
1030+
require.ErrorContains(t, err, "etcdserver: user name is empty")
1031+
1032+
_, err = testUserAuthClient.AlarmList(ctx)
1033+
require.NoError(t, err)
1034+
10261035
_, err = testUserAuthClient.AlarmDisarm(ctx, &clientv3.AlarmMember{
10271036
MemberID: memberID,
10281037
Alarm: pb.AlarmType_NOSPACE,

tests/e2e/ctl_v3_auth_test.go

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package e2e
1616

1717
import (
18-
"context"
1918
"fmt"
2019
"os"
2120
"strings"
@@ -296,26 +295,7 @@ func authTestEndpointHealth(cx ctlCtx) {
296295
require.NoError(cx.t, ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "health", "", false}))
297296

298297
cx.user, cx.pass = "test-user", "pass"
299-
func(cx ctlCtx) {
300-
cmdArgs := append(cx.PrefixArgs(), "endpoint", "health")
301-
lines := make([]expect.ExpectedResponse, cx.epc.Cfg.ClusterSize)
302-
for i := range lines {
303-
lines[i] = expect.ExpectedResponse{
304-
Value: cx.epc.Procs[i].EndpointsGRPC()[0] + " is unhealthy: failed to commit proposal: Unable to fetch the alarm list",
305-
}
306-
}
307-
308-
proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap)
309-
require.NoErrorf(cx.t, err, "failed to spawn endpoint health command")
310-
defer func() {
311-
require.Errorf(cx.t, proc.Close(), "endpoint health command should reject all non-root users")
312-
}()
313-
314-
for _, line := range lines {
315-
_, lerr := proc.ExpectWithContext(context.TODO(), line)
316-
require.NoErrorf(cx.t, lerr, "endpoint health should fail with permission denied error")
317-
}
318-
}(cx)
298+
require.NoErrorf(cx.t, ctlV3EndpointHealth(cx), "endpointStatusTest ctlV3EndpointHealth error")
319299

320300
cmdArgs := append(cx.PrefixArgs(), "endpoint", "health", "--user=root:root", "--cluster")
321301
proc, err := e2e.SpawnCmd(cmdArgs, cx.envMap)

0 commit comments

Comments
 (0)