From c967715d93d616ac81a0b0773cb5a9f27b928ffb Mon Sep 17 00:00:00 2001 From: Benjamin Wang Date: Tue, 1 Nov 2022 05:08:11 +0800 Subject: [PATCH] auth: protect all maintainence APIs when auth is enabled All maintenance APIs require admin privilege when auth is enabled, otherwise, the request will be rejected. If auth isn't enabled, then no such requirement any more. Signed-off-by: Benjamin Wang --- server/etcdserver/api/v3rpc/auth.go | 21 ++++++++++++ server/etcdserver/api/v3rpc/maintenance.go | 39 ++++++++++------------ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/server/etcdserver/api/v3rpc/auth.go b/server/etcdserver/api/v3rpc/auth.go index d986037a1..6c5db76cb 100644 --- a/server/etcdserver/api/v3rpc/auth.go +++ b/server/etcdserver/api/v3rpc/auth.go @@ -18,6 +18,7 @@ import ( "context" pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/server/v3/auth" "go.etcd.io/etcd/server/v3/etcdserver" ) @@ -164,3 +165,23 @@ func (as *AuthServer) UserChangePassword(ctx context.Context, r *pb.AuthUserChan } return resp, nil } + +type AuthGetter interface { + AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) + AuthStore() auth.AuthStore +} + +type AuthAdmin struct { + ag AuthGetter +} + +// isPermitted verifies the user has admin privilege. +// Only users with "root" role are permitted. +func (aa *AuthAdmin) isPermitted(ctx context.Context) error { + authInfo, err := aa.ag.AuthInfoFromCtx(ctx) + if err != nil { + return err + } + + return aa.ag.AuthStore().IsAdminPermitted(authInfo) +} diff --git a/server/etcdserver/api/v3rpc/maintenance.go b/server/etcdserver/api/v3rpc/maintenance.go index f8b61d3f9..af1f2acb1 100644 --- a/server/etcdserver/api/v3rpc/maintenance.go +++ b/server/etcdserver/api/v3rpc/maintenance.go @@ -25,7 +25,6 @@ import ( "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/server/v3/auth" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/apply" "go.etcd.io/etcd/server/v3/etcdserver/errors" @@ -60,11 +59,6 @@ type LeaderTransferrer interface { MoveLeader(ctx context.Context, lead, target uint64) error } -type AuthGetter interface { - AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) - AuthStore() auth.AuthStore -} - type ClusterStatusGetter interface { IsLearner() bool } @@ -87,7 +81,7 @@ func NewMaintenanceServer(s *etcdserver.EtcdServer) pb.MaintenanceServer { if srv.lg == nil { srv.lg = zap.NewNop() } - return &authMaintenanceServer{srv, s} + return &authMaintenanceServer{srv, &AuthAdmin{s}} } func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) { @@ -274,20 +268,11 @@ func (ms *maintenanceServer) Downgrade(ctx context.Context, r *pb.DowngradeReque type authMaintenanceServer struct { *maintenanceServer - ag AuthGetter -} - -func (ams *authMaintenanceServer) isAuthenticated(ctx context.Context) error { - authInfo, err := ams.ag.AuthInfoFromCtx(ctx) - if err != nil { - return err - } - - return ams.ag.AuthStore().IsAdminPermitted(authInfo) + *AuthAdmin } func (ams *authMaintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) { - if err := ams.isAuthenticated(ctx); err != nil { + if err := ams.isPermitted(ctx); err != nil { return nil, err } @@ -295,7 +280,7 @@ func (ams *authMaintenanceServer) Defragment(ctx context.Context, sr *pb.Defragm } func (ams *authMaintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error { - if err := ams.isAuthenticated(srv.Context()); err != nil { + if err := ams.isPermitted(srv.Context()); err != nil { return err } @@ -303,7 +288,7 @@ func (ams *authMaintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Mainte } func (ams *authMaintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) { - if err := ams.isAuthenticated(ctx); err != nil { + if err := ams.isPermitted(ctx); err != nil { return nil, err } @@ -311,20 +296,32 @@ func (ams *authMaintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) ( } func (ams *authMaintenanceServer) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) { - if err := ams.isAuthenticated(ctx); err != nil { + if err := ams.isPermitted(ctx); err != nil { return nil, err } return ams.maintenanceServer.HashKV(ctx, r) } func (ams *authMaintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) { + if err := ams.isPermitted(ctx); err != nil { + return nil, err + } + return ams.maintenanceServer.Status(ctx, ar) } func (ams *authMaintenanceServer) MoveLeader(ctx context.Context, tr *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) { + if err := ams.isPermitted(ctx); err != nil { + return nil, err + } + return ams.maintenanceServer.MoveLeader(ctx, tr) } func (ams *authMaintenanceServer) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) { + if err := ams.isPermitted(ctx); err != nil { + return nil, err + } + return ams.maintenanceServer.Downgrade(ctx, r) }