From ab75f8e0fc5ea2094a84e1de843c4cc7d7038c35 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Thu, 24 Nov 2016 16:34:29 +0900 Subject: [PATCH] etcdserver: let maintenance services require root role --- etcdserver/api/v3rpc/maintenance.go | 44 ++++++++++++++++++++++++++++- etcdserver/v3_server.go | 6 ++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/etcdserver/api/v3rpc/maintenance.go b/etcdserver/api/v3rpc/maintenance.go index 20af20fc3117..6edd04a53624 100644 --- a/etcdserver/api/v3rpc/maintenance.go +++ b/etcdserver/api/v3rpc/maintenance.go @@ -18,6 +18,7 @@ import ( "crypto/sha256" "io" + "github.com/coreos/etcd/auth" "github.com/coreos/etcd/etcdserver" pb "github.com/coreos/etcd/etcdserver/etcdserverpb" "github.com/coreos/etcd/mvcc" @@ -45,19 +46,45 @@ type RaftStatusGetter interface { Leader() types.ID } +type AuthGetter interface { + AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) + AuthStore() auth.AuthStore +} + type maintenanceServer struct { rg RaftStatusGetter kg KVGetter bg BackendGetter a Alarmer + ag AuthGetter hdr header } func NewMaintenanceServer(s *etcdserver.EtcdServer) pb.MaintenanceServer { - return &maintenanceServer{rg: s, kg: s, bg: s, a: s, hdr: newHeader(s)} + return &maintenanceServer{rg: s, kg: s, bg: s, a: s, ag: s, hdr: newHeader(s)} +} + +func (ms *maintenanceServer) isAuthenticated(ctx context.Context) error { + authInfo, err := ms.ag.AuthInfoFromCtx(ctx) + if err != nil { + return err + } + + as := ms.ag.AuthStore() + err = as.IsAdminPermitted(authInfo) + if err != nil { + return err + } + + return nil } func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) { + if err := ms.isAuthenticated(ctx); err != nil { + plog.Warningf("invalid Degragment request was issued: %s", err) + return nil, err + } + plog.Noticef("starting to defragment the storage backend...") err := ms.bg.Backend().Defrag() if err != nil { @@ -69,6 +96,11 @@ func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRe } func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error { + if err := ms.isAuthenticated(srv.Context()); err != nil { + plog.Warningf("invalid Snapshot request was issued: %s", err) + return err + } + snap := ms.bg.Backend().Snapshot() pr, pw := io.Pipe() @@ -114,6 +146,11 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance } func (ms *maintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) { + if err := ms.isAuthenticated(ctx); err != nil { + plog.Warningf("invalid Hash request was issued: %s", err) + return nil, err + } + h, rev, err := ms.kg.KV().Hash() if err != nil { return nil, togRPCError(err) @@ -128,6 +165,11 @@ func (ms *maintenanceServer) Alarm(ctx context.Context, ar *pb.AlarmRequest) (*p } func (ms *maintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) { + if err := ms.isAuthenticated(ctx); err != nil { + plog.Warningf("invalid Status request was issued: %s", err) + return nil, err + } + resp := &pb.StatusResponse{ Header: &pb.ResponseHeader{Revision: ms.hdr.rev()}, Version: version.Version, diff --git a/etcdserver/v3_server.go b/etcdserver/v3_server.go index e18bac950485..e90817ce290b 100644 --- a/etcdserver/v3_server.go +++ b/etcdserver/v3_server.go @@ -639,7 +639,7 @@ func (s *EtcdServer) isValidSimpleToken(token string) bool { } } -func (s *EtcdServer) authInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) { +func (s *EtcdServer) AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) { md, ok := metadata.FromContext(ctx) if !ok { return nil, nil @@ -666,7 +666,7 @@ func (s *EtcdServer) authInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error // doSerialize handles the auth logic, with permissions checked by "chk", for a serialized request "get". Returns a non-nil error on authentication failure. func (s *EtcdServer) doSerialize(ctx context.Context, chk func(*auth.AuthInfo) error, get func()) error { for { - ai, err := s.authInfoFromCtx(ctx) + ai, err := s.AuthInfoFromCtx(ctx) if err != nil { return err } @@ -701,7 +701,7 @@ func (s *EtcdServer) processInternalRaftRequestOnce(ctx context.Context, r pb.In ID: s.reqIDGen.Next(), } - authInfo, err := s.authInfoFromCtx(ctx) + authInfo, err := s.AuthInfoFromCtx(ctx) if err != nil { return nil, err }