From ead5096fa94cdf16c947ccea17f7f35b295b628e Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Wed, 8 Jun 2016 17:11:26 -0700 Subject: [PATCH] auth, etcdserver: make auth tokens consistent for all nodes Currently auth tokens are generated in the replicated state machine layer randomly. It means one auth token generated in node A cannot be used for node B. It is problematic for load balancing and fail over. This commit moves the token generation logic from the state machine to API layer (before raft) and let all nodes share a single token. Log index of Raft is also added to a token for ensuring uniqueness of the token and detecting activation of the token in the cluster (some nodes can receive the token before generating and installing the token in its state machine). This commit also lets authStore have simple token related things. It is required because of unit test. The test requires cleaning of the state of the simple token things after one test (succeeding test can create duplicated token and it causes panic). --- Documentation/dev-guide/api_reference_v3.md | 4 +- auth/simple_token.go | 37 +-- auth/store.go | 43 +-- auth/store_test.go | 18 +- etcdserver/apply.go | 10 +- etcdserver/etcdserverpb/etcdserver.pb.go | 53 ++-- etcdserver/etcdserverpb/raft_internal.pb.go | 310 ++++++++++++++++---- etcdserver/etcdserverpb/raft_internal.proto | 14 +- etcdserver/server.go | 11 + etcdserver/v3_server.go | 49 +++- 10 files changed, 415 insertions(+), 134 deletions(-) diff --git a/Documentation/dev-guide/api_reference_v3.md b/Documentation/dev-guide/api_reference_v3.md index ca5fd3994..f008bfb46 100644 --- a/Documentation/dev-guide/api_reference_v3.md +++ b/Documentation/dev-guide/api_reference_v3.md @@ -203,6 +203,7 @@ Empty field. | ----- | ----------- | ---- | | role | | string | | key | | string | +| range_end | | string | @@ -755,8 +756,9 @@ Permission is a single entity | Field | Description | Type | | ----- | ----------- | ---- | -| key | | bytes | | permType | | Type | +| key | | bytes | +| range_end | | bytes | diff --git a/auth/simple_token.go b/auth/simple_token.go index b2579116b..df2a78e2a 100644 --- a/auth/simple_token.go +++ b/auth/simple_token.go @@ -20,7 +20,6 @@ package auth import ( "crypto/rand" "math/big" - "sync" ) const ( @@ -28,16 +27,7 @@ const ( defaultSimpleTokenLength = 16 ) -var ( - simpleTokensMu sync.RWMutex - simpleTokens map[string]string // token -> username -) - -func init() { - simpleTokens = make(map[string]string) -} - -func genSimpleToken() (string, error) { +func (as *authStore) GenSimpleToken() (string, error) { ret := make([]byte, defaultSimpleTokenLength) for i := 0; i < defaultSimpleTokenLength; i++ { @@ -52,25 +42,14 @@ func genSimpleToken() (string, error) { return string(ret), nil } -func genSimpleTokenForUser(username string) (string, error) { - var token string - var err error +func (as *authStore) assignSimpleTokenToUser(username, token string) { + as.simpleTokensMu.Lock() - for { - // generating random numbers in RSM would't a good idea - token, err = genSimpleToken() - if err != nil { - return "", err - } - - if _, ok := simpleTokens[token]; !ok { - break - } + _, ok := as.simpleTokens[token] + if ok { + plog.Panicf("token %s is alredy used", token) } - simpleTokensMu.Lock() - simpleTokens[token] = username - simpleTokensMu.Unlock() - - return token, nil + as.simpleTokens[token] = username + as.simpleTokensMu.Unlock() } diff --git a/auth/store.go b/auth/store.go index 398eacc9a..f762b437d 100644 --- a/auth/store.go +++ b/auth/store.go @@ -17,6 +17,7 @@ package auth import ( "bytes" "errors" + "fmt" "sort" "strings" "sync" @@ -26,6 +27,7 @@ import ( "github.com/coreos/etcd/mvcc/backend" "github.com/coreos/pkg/capnslog" "golang.org/x/crypto/bcrypt" + "golang.org/x/net/context" ) var ( @@ -63,11 +65,8 @@ type AuthStore interface { // AuthDisable turns off the authentication feature AuthDisable() - // Authenticate does authentication based on given user name and password, - // and returns a token for successful case. - // Note that the generated token is valid only for the member the client - // connected to within fixed time duration. Reauth is required after the duration. - Authenticate(name string, password string) (*pb.AuthenticateResponse, error) + // Authenticate does authentication based on given user name and password + Authenticate(ctx context.Context, username, password string) (*pb.AuthenticateResponse, error) // Recover recovers the state of auth store from the given backend Recover(b backend.Backend) @@ -116,6 +115,9 @@ type AuthStore interface { // IsAdminPermitted checks admin permission of the user IsAdminPermitted(username string) bool + + // GenSimpleToken produces a simple random string + GenSimpleToken() (string, error) } type authStore struct { @@ -124,6 +126,9 @@ type authStore struct { enabledMu sync.RWMutex rangePermCache map[string]*unifiedRangePermissions // username -> unifiedRangePermissions + + simpleTokensMu sync.RWMutex + simpleTokens map[string]string // token -> username } func (as *authStore) AuthEnable() error { @@ -172,28 +177,29 @@ func (as *authStore) AuthDisable() { plog.Noticef("Authentication disabled") } -func (as *authStore) Authenticate(name string, password string) (*pb.AuthenticateResponse, error) { +func (as *authStore) Authenticate(ctx context.Context, username, password string) (*pb.AuthenticateResponse, error) { + // TODO(mitake): after adding jwt support, branching based on values of ctx is required + index := ctx.Value("index").(uint64) + simpleToken := ctx.Value("simpleToken").(string) + tx := as.be.BatchTx() tx.Lock() defer tx.Unlock() - user := getUser(tx, name) + user := getUser(tx, username) if user == nil { return nil, ErrAuthFailed } if bcrypt.CompareHashAndPassword(user.Password, []byte(password)) != nil { - plog.Noticef("authentication failed, invalid password for user %s", name) + plog.Noticef("authentication failed, invalid password for user %s", username) return &pb.AuthenticateResponse{}, ErrAuthFailed } - token, err := genSimpleTokenForUser(name) - if err != nil { - plog.Errorf("failed to generate simple token: %s", err) - return nil, err - } + token := fmt.Sprintf("%s.%d", simpleToken, index) + as.assignSimpleTokenToUser(username, token) - plog.Infof("authorized %s, token is %s", name, token) + plog.Infof("authorized %s, token is %s", username, token) return &pb.AuthenticateResponse{Token: token}, nil } @@ -482,9 +488,9 @@ func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, } func (as *authStore) UsernameFromToken(token string) (string, bool) { - simpleTokensMu.RLock() - defer simpleTokensMu.RUnlock() - t, ok := simpleTokens[token] + as.simpleTokensMu.RLock() + defer as.simpleTokensMu.RUnlock() + t, ok := as.simpleTokens[token] return t, ok } @@ -680,7 +686,8 @@ func NewAuthStore(be backend.Backend) *authStore { be.ForceCommit() return &authStore{ - be: be, + be: be, + simpleTokens: make(map[string]string), } } diff --git a/auth/store_test.go b/auth/store_test.go index ccf04a03a..37a4440f7 100644 --- a/auth/store_test.go +++ b/auth/store_test.go @@ -20,6 +20,7 @@ import ( pb "github.com/coreos/etcd/etcdserver/etcdserverpb" "github.com/coreos/etcd/mvcc/backend" + "golang.org/x/net/context" ) func TestUserAdd(t *testing.T) { @@ -60,7 +61,8 @@ func TestAuthenticate(t *testing.T) { } // auth a non-existing user - _, err = as.Authenticate("foo-test", "bar") + ctx1 := context.WithValue(context.WithValue(context.TODO(), "index", uint64(1)), "simpleToken", "dummy") + _, err = as.Authenticate(ctx1, "foo-test", "bar") if err == nil { t.Fatalf("expected %v, got %v", ErrAuthFailed, err) } @@ -69,13 +71,15 @@ func TestAuthenticate(t *testing.T) { } // auth an existing user with correct password - _, err = as.Authenticate("foo", "bar") + ctx2 := context.WithValue(context.WithValue(context.TODO(), "index", uint64(2)), "simpleToken", "dummy") + _, err = as.Authenticate(ctx2, "foo", "bar") if err != nil { t.Fatal(err) } // auth an existing user but with wrong password - _, err = as.Authenticate("foo", "") + ctx3 := context.WithValue(context.WithValue(context.TODO(), "index", uint64(3)), "simpleToken", "dummy") + _, err = as.Authenticate(ctx3, "foo", "") if err == nil { t.Fatalf("expected %v, got %v", ErrAuthFailed, err) } @@ -129,7 +133,9 @@ func TestUserChangePassword(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = as.Authenticate("foo", "") + + ctx1 := context.WithValue(context.WithValue(context.TODO(), "index", uint64(1)), "simpleToken", "dummy") + _, err = as.Authenticate(ctx1, "foo", "") if err != nil { t.Fatal(err) } @@ -138,7 +144,9 @@ func TestUserChangePassword(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = as.Authenticate("foo", "bar") + + ctx2 := context.WithValue(context.WithValue(context.TODO(), "index", uint64(2)), "simpleToken", "dummy") + _, err = as.Authenticate(ctx2, "foo", "bar") if err != nil { t.Fatal(err) } diff --git a/etcdserver/apply.go b/etcdserver/apply.go index 7143cd53e..992207121 100644 --- a/etcdserver/apply.go +++ b/etcdserver/apply.go @@ -26,6 +26,7 @@ import ( "github.com/coreos/etcd/mvcc/mvccpb" "github.com/coreos/etcd/pkg/types" "github.com/gogo/protobuf/proto" + "golang.org/x/net/context" ) const ( @@ -59,7 +60,7 @@ type applierV3 interface { AuthEnable() (*pb.AuthEnableResponse, error) AuthDisable() (*pb.AuthDisableResponse, error) - Authenticate(r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) + Authenticate(ctx context.Context, username, password string) (*pb.AuthenticateResponse, error) UserAdd(ua *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) UserDelete(ua *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) UserChangePassword(ua *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) @@ -117,7 +118,8 @@ func (s *EtcdServer) applyV3Request(r *pb.InternalRaftRequest) *applyResult { case r.AuthDisable != nil: ar.resp, ar.err = s.applyV3.AuthDisable() case r.Authenticate != nil: - ar.resp, ar.err = s.applyV3.Authenticate(r.Authenticate) + ctx := context.WithValue(context.WithValue(context.TODO(), "index", s.consistIndex.ConsistentIndex()), "simpleToken", r.Authenticate.SimpleToken) + ar.resp, ar.err = s.applyV3.Authenticate(ctx, r.Authenticate.Name, r.Authenticate.Password) case r.AuthUserAdd != nil: ar.resp, ar.err = s.applyV3.UserAdd(r.AuthUserAdd) case r.AuthUserDelete != nil: @@ -541,8 +543,8 @@ func (a *applierV3backend) AuthDisable() (*pb.AuthDisableResponse, error) { return &pb.AuthDisableResponse{}, nil } -func (a *applierV3backend) Authenticate(r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) { - return a.s.AuthStore().Authenticate(r.Name, r.Password) +func (a *applierV3backend) Authenticate(ctx context.Context, username, password string) (*pb.AuthenticateResponse, error) { + return a.s.AuthStore().Authenticate(ctx, username, password) } func (a *applierV3backend) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) { diff --git a/etcdserver/etcdserverpb/etcdserver.pb.go b/etcdserver/etcdserverpb/etcdserver.pb.go index cd0cf1833..c7a2cdba2 100644 --- a/etcdserver/etcdserverpb/etcdserver.pb.go +++ b/etcdserver/etcdserverpb/etcdserver.pb.go @@ -16,6 +16,7 @@ RequestHeader InternalRaftRequest EmptyResponse + InternalAuthenticateRequest ResponseHeader RangeRequest RangeResponse @@ -1006,30 +1007,30 @@ var ( ) var fileDescriptorEtcdserver = []byte{ - // 398 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x5c, 0x92, 0xd1, 0x6e, 0xd3, 0x30, - 0x14, 0x86, 0xe7, 0xd6, 0x4d, 0x1b, 0x33, 0xa0, 0x58, 0x13, 0x3a, 0x9a, 0x50, 0xa8, 0x2a, 0x2e, - 0x7a, 0x05, 0xef, 0x30, 0xba, 0x8b, 0x4a, 0x0c, 0x8d, 0x0e, 0x8d, 0x6b, 0xd3, 0x1c, 0x56, 0x4b, - 0x49, 0x9c, 0xd9, 0x27, 0xa1, 0x6f, 0xc0, 0xab, 0xf5, 0x92, 0x27, 0x40, 0xd0, 0x27, 0x41, 0x76, - 0x96, 0x62, 0x76, 0x67, 0x7d, 0xff, 0xef, 0xdf, 0xbf, 0xed, 0x23, 0xa6, 0x48, 0x9b, 0xdc, 0xa1, - 0x6d, 0xd1, 0xbe, 0xad, 0xad, 0x21, 0x23, 0x4f, 0xff, 0x91, 0xfa, 0xeb, 0xf9, 0xd9, 0x9d, 0xb9, - 0x33, 0x41, 0x78, 0xe7, 0x57, 0x9d, 0x67, 0xfe, 0x83, 0x8b, 0xf1, 0x1a, 0xef, 0x1b, 0x74, 0x24, - 0xcf, 0xc4, 0x60, 0xb5, 0x04, 0x36, 0x63, 0x0b, 0x7e, 0xc1, 0xf7, 0xbf, 0x5e, 0x9f, 0xac, 0x07, - 0x7a, 0x29, 0x5f, 0x89, 0xe4, 0x0a, 0x69, 0x6b, 0x72, 0x18, 0xcc, 0xd8, 0x22, 0x7d, 0x50, 0x92, - 0x32, 0x30, 0x09, 0x82, 0x5f, 0x2b, 0xda, 0xc2, 0x30, 0xd2, 0x78, 0xad, 0x68, 0x2b, 0x5f, 0x8a, - 0xe1, 0xad, 0x2a, 0x80, 0x47, 0xc2, 0xb0, 0x55, 0x85, 0xe7, 0x4b, 0x6d, 0x61, 0x34, 0x63, 0x8b, - 0x49, 0xcf, 0x73, 0x6d, 0xe5, 0x5c, 0xa4, 0xd7, 0x16, 0xdb, 0x5b, 0x55, 0x34, 0x08, 0x49, 0xb4, - 0x2b, 0xad, 0x7b, 0xdc, 0x7b, 0x56, 0x55, 0x8e, 0x3b, 0x18, 0x47, 0x45, 0x83, 0x27, 0xe0, 0xde, - 0x73, 0xb9, 0xd3, 0x8e, 0x60, 0x72, 0x3c, 0x85, 0x75, 0x9e, 0x80, 0xe5, 0x1b, 0x21, 0x2e, 0x77, - 0xb5, 0xb6, 0x8a, 0xb4, 0xa9, 0x20, 0x9d, 0xb1, 0xc5, 0xf0, 0x21, 0x48, 0xe0, 0x91, 0xfb, 0xbb, - 0x7d, 0x51, 0x9a, 0x40, 0x44, 0x55, 0xf9, 0x77, 0xa5, 0x49, 0x9e, 0x8b, 0xd1, 0x8d, 0xae, 0x36, - 0x08, 0x4f, 0xa2, 0x0e, 0x23, 0xe7, 0x91, 0x3f, 0x7f, 0x8d, 0x9b, 0xc6, 0x3a, 0xdd, 0x22, 0x9c, - 0x46, 0x5b, 0x53, 0xdb, 0x63, 0xff, 0xa6, 0x37, 0xc6, 0x12, 0xe6, 0xf0, 0x34, 0x32, 0x24, 0x2e, - 0x30, 0xaf, 0x7e, 0x6a, 0x8c, 0x6d, 0x4a, 0x78, 0x16, 0xab, 0xf7, 0x81, 0xf9, 0x56, 0x9f, 0x75, - 0x89, 0xf0, 0x3c, 0x6a, 0xcd, 0x49, 0x97, 0x5d, 0x2a, 0x59, 0x54, 0x25, 0x4c, 0xff, 0x4b, 0x0d, - 0x4c, 0x66, 0xfe, 0xa3, 0xbf, 0x59, 0x74, 0x5b, 0x78, 0x11, 0xbd, 0xca, 0xd8, 0x76, 0x70, 0xfe, - 0x41, 0x4c, 0xae, 0x90, 0x54, 0xae, 0x48, 0xf9, 0xa4, 0x8f, 0x26, 0xc7, 0x47, 0xd3, 0x90, 0x54, - 0x81, 0xf9, 0x1b, 0xbe, 0x2f, 0x1a, 0x47, 0x68, 0x57, 0xcb, 0x30, 0x14, 0xc7, 0x5f, 0xd8, 0xf4, - 0xf8, 0x62, 0xba, 0xff, 0x93, 0x9d, 0xec, 0x0f, 0x19, 0xfb, 0x79, 0xc8, 0xd8, 0xef, 0x43, 0xc6, - 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x8e, 0x1a, 0x0d, 0xa0, 0x02, 0x00, 0x00, + // 388 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x5c, 0x92, 0xd1, 0xee, 0xd2, 0x30, + 0x14, 0xc6, 0xff, 0xdb, 0xca, 0x60, 0x15, 0x15, 0x1b, 0x62, 0x4e, 0x88, 0x41, 0x43, 0xbc, 0xf0, + 0x4a, 0xdf, 0x01, 0xe1, 0x82, 0x44, 0x0d, 0x82, 0xd1, 0xeb, 0xba, 0x1d, 0xa1, 0x09, 0x5b, 0x47, + 0xdb, 0x4d, 0xde, 0xc0, 0x57, 0xe3, 0xd2, 0x27, 0x30, 0xea, 0x93, 0xd8, 0x16, 0x86, 0xd5, 0x8b, + 0x26, 0xcb, 0xef, 0xfb, 0xce, 0xe9, 0xd7, 0x73, 0x46, 0x47, 0x68, 0xf2, 0x42, 0xa3, 0x6a, 0x51, + 0xbd, 0xac, 0x95, 0x34, 0x92, 0x0d, 0xff, 0x92, 0xfa, 0xf3, 0x64, 0xbc, 0x93, 0x3b, 0xe9, 0x85, + 0x57, 0xee, 0xeb, 0xe2, 0x99, 0x7d, 0x23, 0xb4, 0xbf, 0xc1, 0x63, 0x83, 0xda, 0xb0, 0x31, 0x8d, + 0x57, 0x0b, 0x88, 0x9e, 0x45, 0x2f, 0xc8, 0x9c, 0x9c, 0x7f, 0x3c, 0xbd, 0xdb, 0xc4, 0x62, 0xc1, + 0x9e, 0xd0, 0xf4, 0x2d, 0x9a, 0xbd, 0x2c, 0x20, 0xb6, 0x4a, 0x76, 0x55, 0xd2, 0xd2, 0x33, 0x06, + 0x94, 0xac, 0xb9, 0xd9, 0x43, 0x12, 0x68, 0xa4, 0xb6, 0x84, 0x3d, 0xa6, 0xc9, 0x47, 0x7e, 0x00, + 0x12, 0x08, 0x49, 0xcb, 0x0f, 0x8e, 0x2f, 0x84, 0x82, 0x9e, 0xe5, 0x83, 0x8e, 0x17, 0x42, 0xb1, + 0x19, 0xcd, 0xd6, 0x0a, 0x5b, 0x5b, 0xd3, 0x20, 0xa4, 0x41, 0x55, 0x56, 0x77, 0xb8, 0xf3, 0xac, + 0xaa, 0x02, 0x4f, 0xd0, 0x0f, 0x82, 0x7a, 0x8f, 0xc7, 0x9d, 0x67, 0x79, 0x12, 0xda, 0xc0, 0xe0, + 0x76, 0x4b, 0x74, 0xf1, 0x78, 0xcc, 0x9e, 0x53, 0xba, 0x3c, 0xd5, 0x42, 0x71, 0x23, 0x64, 0x05, + 0x99, 0x35, 0x25, 0xd7, 0x46, 0x14, 0x6f, 0xdc, 0xbd, 0xed, 0x13, 0x17, 0x06, 0x68, 0x10, 0x95, + 0x7c, 0xb5, 0x84, 0x4d, 0x68, 0x6f, 0x2b, 0xaa, 0x1c, 0xe1, 0x5e, 0x90, 0xa1, 0xa7, 0x1d, 0x72, + 0xf7, 0x6f, 0x30, 0x6f, 0x94, 0x16, 0x2d, 0xc2, 0x30, 0x28, 0xcd, 0x54, 0x87, 0xdd, 0x4c, 0xb7, + 0x52, 0x19, 0x2c, 0xe0, 0x7e, 0x60, 0x48, 0xb5, 0x67, 0x4e, 0x7d, 0xdf, 0x48, 0xd5, 0x94, 0xf0, + 0x20, 0x54, 0x8f, 0x9e, 0xb9, 0x54, 0x1f, 0x44, 0x89, 0xf0, 0x30, 0x48, 0x4d, 0x8c, 0x25, 0xbe, + 0xab, 0x51, 0xc8, 0x4b, 0x18, 0xfd, 0xd3, 0xd5, 0x33, 0x36, 0x75, 0x8b, 0xfe, 0xa2, 0x50, 0xef, + 0xe1, 0x51, 0x30, 0x95, 0xbe, 0xba, 0xc0, 0xd9, 0x1b, 0x3a, 0xb0, 0x7b, 0xe6, 0x05, 0x37, 0xdc, + 0x75, 0x7a, 0x27, 0x0b, 0xfc, 0xef, 0x6f, 0x48, 0x2b, 0xcf, 0xdc, 0x0b, 0x5f, 0x1f, 0x1a, 0x6d, + 0x50, 0x59, 0x43, 0x1c, 0x6e, 0x21, 0xef, 0xf0, 0x7c, 0x74, 0xfe, 0x35, 0xbd, 0x3b, 0xff, 0x9e, + 0x46, 0xdf, 0xed, 0xf9, 0x69, 0xcf, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x8e, 0x1a, 0x0d, + 0xa0, 0x02, 0x00, 0x00, } diff --git a/etcdserver/etcdserverpb/raft_internal.pb.go b/etcdserver/etcdserverpb/raft_internal.pb.go index 5d6016160..6a1109802 100644 --- a/etcdserver/etcdserverpb/raft_internal.pb.go +++ b/etcdserver/etcdserverpb/raft_internal.pb.go @@ -46,7 +46,7 @@ type InternalRaftRequest struct { Alarm *AlarmRequest `protobuf:"bytes,10,opt,name=alarm" json:"alarm,omitempty"` AuthEnable *AuthEnableRequest `protobuf:"bytes,1000,opt,name=auth_enable,json=authEnable" json:"auth_enable,omitempty"` AuthDisable *AuthDisableRequest `protobuf:"bytes,1011,opt,name=auth_disable,json=authDisable" json:"auth_disable,omitempty"` - Authenticate *AuthenticateRequest `protobuf:"bytes,1012,opt,name=authenticate" json:"authenticate,omitempty"` + Authenticate *InternalAuthenticateRequest `protobuf:"bytes,1012,opt,name=authenticate" json:"authenticate,omitempty"` AuthUserAdd *AuthUserAddRequest `protobuf:"bytes,1100,opt,name=auth_user_add,json=authUserAdd" json:"auth_user_add,omitempty"` AuthUserDelete *AuthUserDeleteRequest `protobuf:"bytes,1101,opt,name=auth_user_delete,json=authUserDelete" json:"auth_user_delete,omitempty"` AuthUserGet *AuthUserGetRequest `protobuf:"bytes,1102,opt,name=auth_user_get,json=authUserGet" json:"auth_user_get,omitempty"` @@ -73,10 +73,28 @@ func (m *EmptyResponse) String() string { return proto.CompactTextStr func (*EmptyResponse) ProtoMessage() {} func (*EmptyResponse) Descriptor() ([]byte, []int) { return fileDescriptorRaftInternal, []int{2} } +// What is the difference between AuthenticateRequest (defined in rpc.proto) and InternalAuthenticateRequest? +// InternalAuthenticateRequest has a member that is filled by etcdserver and shouldn't be user-facing. +// For avoiding misusage the field, we have an internal version of AuthenticateRequest. +type InternalAuthenticateRequest struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + // simple_token is generated in API layer (etcdserver/v3_server.go) + SimpleToken string `protobuf:"bytes,3,opt,name=simple_token,json=simpleToken,proto3" json:"simple_token,omitempty"` +} + +func (m *InternalAuthenticateRequest) Reset() { *m = InternalAuthenticateRequest{} } +func (m *InternalAuthenticateRequest) String() string { return proto.CompactTextString(m) } +func (*InternalAuthenticateRequest) ProtoMessage() {} +func (*InternalAuthenticateRequest) Descriptor() ([]byte, []int) { + return fileDescriptorRaftInternal, []int{3} +} + func init() { proto.RegisterType((*RequestHeader)(nil), "etcdserverpb.RequestHeader") proto.RegisterType((*InternalRaftRequest)(nil), "etcdserverpb.InternalRaftRequest") proto.RegisterType((*EmptyResponse)(nil), "etcdserverpb.EmptyResponse") + proto.RegisterType((*InternalAuthenticateRequest)(nil), "etcdserverpb.InternalAuthenticateRequest") } func (m *RequestHeader) Marshal() (data []byte, err error) { size := m.Size() @@ -418,6 +436,42 @@ func (m *EmptyResponse) MarshalTo(data []byte) (int, error) { return i, nil } +func (m *InternalAuthenticateRequest) Marshal() (data []byte, err error) { + size := m.Size() + data = make([]byte, size) + n, err := m.MarshalTo(data) + if err != nil { + return nil, err + } + return data[:n], nil +} + +func (m *InternalAuthenticateRequest) MarshalTo(data []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Name) > 0 { + data[i] = 0xa + i++ + i = encodeVarintRaftInternal(data, i, uint64(len(m.Name))) + i += copy(data[i:], m.Name) + } + if len(m.Password) > 0 { + data[i] = 0x12 + i++ + i = encodeVarintRaftInternal(data, i, uint64(len(m.Password))) + i += copy(data[i:], m.Password) + } + if len(m.SimpleToken) > 0 { + data[i] = 0x1a + i++ + i = encodeVarintRaftInternal(data, i, uint64(len(m.SimpleToken))) + i += copy(data[i:], m.SimpleToken) + } + return i, nil +} + func encodeFixed64RaftInternal(data []byte, offset int, v uint64) int { data[offset] = uint8(v) data[offset+1] = uint8(v >> 8) @@ -569,6 +623,24 @@ func (m *EmptyResponse) Size() (n int) { return n } +func (m *InternalAuthenticateRequest) Size() (n int) { + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovRaftInternal(uint64(l)) + } + l = len(m.Password) + if l > 0 { + n += 1 + l + sovRaftInternal(uint64(l)) + } + l = len(m.SimpleToken) + if l > 0 { + n += 1 + l + sovRaftInternal(uint64(l)) + } + return n +} + func sovRaftInternal(x uint64) (n int) { for { n++ @@ -1151,7 +1223,7 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error { return io.ErrUnexpectedEOF } if m.Authenticate == nil { - m.Authenticate = &AuthenticateRequest{} + m.Authenticate = &InternalAuthenticateRequest{} } if err := m.Authenticate.Unmarshal(data[iNdEx:postIndex]); err != nil { return err @@ -1591,6 +1663,143 @@ func (m *EmptyResponse) Unmarshal(data []byte) error { } return nil } +func (m *InternalAuthenticateRequest) Unmarshal(data []byte) error { + l := len(data) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaftInternal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: InternalAuthenticateRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: InternalAuthenticateRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaftInternal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRaftInternal + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaftInternal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRaftInternal + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Password = string(data[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SimpleToken", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaftInternal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRaftInternal + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SimpleToken = string(data[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRaftInternal(data[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRaftInternal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipRaftInternal(data []byte) (n int, err error) { l := len(data) iNdEx := 0 @@ -1697,51 +1906,54 @@ var ( ) var fileDescriptorRaftInternal = []byte{ - // 725 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x95, 0x5b, 0x4f, 0x13, 0x41, - 0x14, 0xc7, 0x6d, 0xb9, 0x76, 0x4a, 0x11, 0x07, 0xd0, 0xb1, 0x24, 0x15, 0x31, 0x2a, 0xf1, 0x82, - 0x06, 0x1e, 0x7d, 0xd0, 0x4a, 0x11, 0x49, 0x8c, 0x21, 0x1b, 0x4d, 0x4c, 0x7c, 0xd8, 0x0c, 0xdd, - 0x43, 0x5b, 0xdd, 0xee, 0xae, 0xb3, 0xd3, 0x8a, 0xdf, 0xca, 0xdb, 0x87, 0xe0, 0xc1, 0x0b, 0xfa, - 0x09, 0xb4, 0x4f, 0xbe, 0xeb, 0x07, 0x30, 0x73, 0xd9, 0xd9, 0x6e, 0x3b, 0xcb, 0xdb, 0x72, 0xce, - 0xff, 0xfc, 0xce, 0x39, 0xf3, 0x9f, 0xa1, 0x68, 0x91, 0xd1, 0x43, 0xee, 0x76, 0x02, 0x0e, 0x2c, - 0xa0, 0xfe, 0x46, 0xc4, 0x42, 0x1e, 0xe2, 0x39, 0xe0, 0x4d, 0x2f, 0x06, 0xd6, 0x07, 0x16, 0x1d, - 0x54, 0x97, 0x5a, 0x61, 0x2b, 0x94, 0x89, 0x3b, 0xe2, 0x4b, 0x69, 0xaa, 0x0b, 0xa9, 0x46, 0x47, - 0x4a, 0x2c, 0x6a, 0xaa, 0xcf, 0xb5, 0x7b, 0xa8, 0xe2, 0xc0, 0x9b, 0x1e, 0xc4, 0xfc, 0x31, 0x50, - 0x0f, 0x18, 0x9e, 0x47, 0xc5, 0xbd, 0x06, 0x29, 0xac, 0x16, 0xd6, 0x27, 0x9d, 0x62, 0xa7, 0x81, - 0xab, 0x68, 0xb6, 0x17, 0x8b, 0x96, 0x5d, 0x20, 0xc5, 0xd5, 0xc2, 0x7a, 0xc9, 0x31, 0x7f, 0xaf, - 0xfd, 0xac, 0xa0, 0xc5, 0x3d, 0x3d, 0x90, 0x43, 0x0f, 0xb9, 0x26, 0x8d, 0x31, 0xae, 0xa2, 0x62, - 0x7f, 0x53, 0x56, 0x97, 0x37, 0x97, 0x37, 0x86, 0x47, 0xde, 0xd0, 0x25, 0x4e, 0xb1, 0xbf, 0x89, - 0xef, 0xa2, 0x29, 0x46, 0x83, 0x16, 0x90, 0x09, 0xa9, 0xac, 0x8e, 0x28, 0x45, 0x2a, 0x91, 0x2b, - 0x21, 0xbe, 0x81, 0x26, 0xa2, 0x1e, 0x27, 0x93, 0x52, 0x4f, 0xb2, 0xfa, 0xfd, 0x5e, 0x32, 0x8f, - 0x23, 0x44, 0x78, 0x1b, 0xcd, 0x79, 0xe0, 0x03, 0x07, 0x57, 0x35, 0x99, 0x92, 0x45, 0xab, 0xd9, - 0xa2, 0x86, 0x54, 0x64, 0x5a, 0x95, 0xbd, 0x34, 0x26, 0x1a, 0xf2, 0xa3, 0x80, 0x4c, 0xdb, 0x1a, - 0x3e, 0x3b, 0x0a, 0x4c, 0x43, 0x7e, 0x14, 0xe0, 0xfb, 0x08, 0x35, 0xc3, 0x6e, 0x44, 0x9b, 0xbc, - 0x13, 0x06, 0x64, 0x46, 0x96, 0x5c, 0xca, 0x96, 0x6c, 0x9b, 0x7c, 0x52, 0x39, 0x54, 0x82, 0x1f, - 0xa0, 0xb2, 0x0f, 0x34, 0x06, 0xb7, 0xc5, 0x68, 0xc0, 0xc9, 0xac, 0x8d, 0xf0, 0x44, 0x08, 0x76, - 0x45, 0xde, 0x10, 0x7c, 0x13, 0x12, 0x3b, 0x2b, 0x02, 0x83, 0x7e, 0xf8, 0x1a, 0x48, 0xc9, 0xb6, - 0xb3, 0x44, 0x38, 0x52, 0x60, 0x76, 0xf6, 0xd3, 0x98, 0xb0, 0x85, 0xfa, 0x94, 0x75, 0x09, 0xb2, - 0xd9, 0x52, 0x17, 0x29, 0x63, 0x8b, 0x14, 0xe2, 0x2d, 0x34, 0xdd, 0x96, 0xb7, 0x89, 0x78, 0xb2, - 0x64, 0xc5, 0xea, 0xb9, 0xba, 0x70, 0x8e, 0x96, 0xe2, 0x3a, 0x2a, 0xd3, 0x1e, 0x6f, 0xbb, 0x10, - 0xd0, 0x03, 0x1f, 0xc8, 0x1f, 0xeb, 0x81, 0xd5, 0x7b, 0xbc, 0xbd, 0x23, 0x05, 0x66, 0x5d, 0x6a, - 0x42, 0xb8, 0x81, 0xe6, 0x24, 0xc2, 0xeb, 0xc4, 0x92, 0xf1, 0x77, 0xc6, 0xb6, 0xaf, 0x60, 0x34, - 0x94, 0xc2, 0xec, 0x4b, 0xd3, 0x18, 0x7e, 0xa4, 0x28, 0x10, 0xf0, 0x4e, 0x93, 0x72, 0x20, 0xff, - 0x14, 0xe5, 0xf2, 0x38, 0x25, 0x91, 0x24, 0x98, 0x4c, 0x1d, 0xde, 0x41, 0x15, 0x39, 0x8d, 0x78, - 0x2e, 0x2e, 0xf5, 0x3c, 0xf2, 0x65, 0x36, 0x6f, 0x9c, 0xe7, 0x31, 0xb0, 0xba, 0xe7, 0x65, 0xc6, - 0xd1, 0x31, 0xfc, 0x14, 0x2d, 0xa4, 0x18, 0x75, 0x17, 0xc9, 0x57, 0x45, 0xba, 0x62, 0x27, 0xe9, - 0x4b, 0xac, 0x61, 0xf3, 0x34, 0x13, 0xce, 0x8e, 0xd5, 0x02, 0x4e, 0xbe, 0x9d, 0x3a, 0xd6, 0x2e, - 0xf0, 0xb1, 0xb1, 0x76, 0x81, 0xe3, 0x16, 0xba, 0x98, 0x62, 0x9a, 0x6d, 0xf1, 0x3a, 0xdc, 0x88, - 0xc6, 0xf1, 0xdb, 0x90, 0x79, 0xe4, 0xbb, 0x42, 0xde, 0xb4, 0x23, 0xb7, 0xa5, 0x7a, 0x5f, 0x8b, - 0x13, 0xfa, 0x79, 0x6a, 0x4d, 0xe3, 0x17, 0x68, 0x69, 0x68, 0x5e, 0x71, 0xad, 0x5d, 0x16, 0xfa, - 0x40, 0x4e, 0x54, 0x8f, 0x6b, 0x39, 0x63, 0xcb, 0x27, 0x11, 0xa6, 0x16, 0x9f, 0xa3, 0xa3, 0x19, - 0xfc, 0x12, 0x2d, 0xa7, 0x64, 0xf5, 0x42, 0x14, 0xfa, 0x87, 0x42, 0x5f, 0xb7, 0xa3, 0xf5, 0x53, - 0x19, 0x62, 0x63, 0x3a, 0x96, 0x32, 0xc7, 0x2c, 0x80, 0xd2, 0xfd, 0xf7, 0xa5, 0xbc, 0x63, 0x16, - 0xfa, 0x51, 0xf7, 0x75, 0xcc, 0xb8, 0x2f, 0x31, 0xda, 0xfd, 0x0f, 0xa5, 0x3c, 0xf7, 0x45, 0x95, - 0xc5, 0xfd, 0x34, 0x9c, 0x1d, 0x4b, 0xb8, 0xff, 0xf1, 0xd4, 0xb1, 0x46, 0xdd, 0xd7, 0x31, 0xfc, - 0x0a, 0x55, 0x87, 0x30, 0xd2, 0x94, 0x08, 0x58, 0xb7, 0x13, 0xc7, 0xe2, 0x7f, 0xdd, 0x27, 0xc5, - 0xbc, 0x95, 0xc3, 0x14, 0xf2, 0x7d, 0xa3, 0x4e, 0xf8, 0x17, 0xa8, 0x3d, 0x8f, 0xbb, 0x68, 0x25, - 0xed, 0xa5, 0x6d, 0x1a, 0x6a, 0xf6, 0x59, 0x35, 0xbb, 0x6d, 0x6f, 0xa6, 0x1c, 0x19, 0xef, 0x46, - 0x68, 0x8e, 0x60, 0xed, 0x2c, 0xaa, 0xec, 0x74, 0x23, 0xfe, 0xce, 0x81, 0x38, 0x0a, 0x83, 0x18, - 0x1e, 0x2e, 0x1c, 0xff, 0xae, 0x9d, 0x39, 0x1e, 0xd4, 0x0a, 0x27, 0x83, 0x5a, 0xe1, 0xd7, 0xa0, - 0x56, 0x38, 0x98, 0x96, 0xbf, 0x9d, 0x5b, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xac, 0x8d, 0xf6, - 0xc5, 0x93, 0x07, 0x00, 0x00, + // 770 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x95, 0x4b, 0x6f, 0x13, 0x3b, + 0x14, 0xc7, 0x6f, 0xd2, 0x67, 0x9c, 0xa4, 0xb7, 0xd7, 0x6d, 0x2f, 0x26, 0x95, 0x4a, 0x09, 0xe2, + 0x0d, 0x05, 0xb5, 0x4b, 0x16, 0x10, 0x9a, 0xaa, 0x54, 0x42, 0xa8, 0x1a, 0x15, 0x09, 0x89, 0xc5, + 0xc8, 0xcd, 0x98, 0x74, 0x60, 0x5e, 0x78, 0x9c, 0x52, 0xbe, 0x15, 0xaf, 0x0f, 0xd1, 0x05, 0x8f, + 0xb2, 0x65, 0x05, 0xac, 0xd8, 0xc3, 0x07, 0xc0, 0xaf, 0xf1, 0xcc, 0x24, 0x4e, 0x17, 0x91, 0x66, + 0xce, 0xf9, 0x9f, 0xdf, 0x39, 0x9e, 0xbf, 0x1d, 0x83, 0x05, 0x8a, 0x9f, 0x31, 0xd7, 0x8f, 0x18, + 0xa1, 0x11, 0x0e, 0xd6, 0x12, 0x1a, 0xb3, 0x18, 0x36, 0x08, 0xeb, 0x79, 0x29, 0xa1, 0x87, 0x84, + 0x26, 0xfb, 0xad, 0xc5, 0x7e, 0xdc, 0x8f, 0x65, 0xe2, 0x96, 0x78, 0x52, 0x9a, 0xd6, 0x7c, 0xae, + 0xd1, 0x91, 0x1a, 0x4d, 0x7a, 0xea, 0xb1, 0x7d, 0x07, 0x34, 0x1d, 0xf2, 0x72, 0x40, 0x52, 0xf6, + 0x80, 0x60, 0x8f, 0x50, 0x38, 0x07, 0xaa, 0x3b, 0x5d, 0x54, 0x59, 0xad, 0x5c, 0x99, 0x74, 0xaa, + 0x7e, 0x17, 0xb6, 0xc0, 0xec, 0x20, 0x15, 0x2d, 0x43, 0x82, 0xaa, 0x3c, 0x5a, 0x73, 0xcc, 0x7b, + 0xfb, 0x5b, 0x13, 0x2c, 0xec, 0xe8, 0x81, 0x1c, 0x3e, 0x9d, 0x26, 0x8d, 0x30, 0x2e, 0x82, 0xea, + 0xe1, 0xba, 0xac, 0xae, 0xaf, 0x2f, 0xad, 0x15, 0x47, 0x5e, 0xd3, 0x25, 0x0e, 0x17, 0xc0, 0xdb, + 0x60, 0x8a, 0xe2, 0xa8, 0x4f, 0xd0, 0x84, 0x54, 0xb6, 0x86, 0x94, 0x22, 0x95, 0xc9, 0x95, 0x10, + 0x5e, 0x03, 0x13, 0xc9, 0x80, 0xa1, 0x49, 0xa9, 0x47, 0x65, 0xfd, 0xee, 0x20, 0x9b, 0xc7, 0x11, + 0x22, 0xb8, 0x09, 0x1a, 0x1e, 0x09, 0x08, 0x23, 0xae, 0x6a, 0x32, 0x25, 0x8b, 0x56, 0xcb, 0x45, + 0x5d, 0xa9, 0x28, 0xb5, 0xaa, 0x7b, 0x79, 0x4c, 0x34, 0x64, 0x47, 0x11, 0x9a, 0xb6, 0x35, 0xdc, + 0x3b, 0x8a, 0x4c, 0x43, 0x2e, 0x82, 0x77, 0x01, 0xe8, 0xc5, 0x61, 0x82, 0x7b, 0xcc, 0x8f, 0x23, + 0x34, 0x23, 0x4b, 0xce, 0x95, 0x4b, 0x36, 0x4d, 0x3e, 0xab, 0x2c, 0x94, 0xc0, 0x7b, 0xa0, 0x1e, + 0x10, 0x9c, 0x12, 0xb7, 0xcf, 0x27, 0x66, 0x68, 0xd6, 0x46, 0x78, 0x28, 0x04, 0xdb, 0x22, 0x6f, + 0x08, 0x81, 0x09, 0x89, 0x35, 0x2b, 0x02, 0x25, 0x87, 0xf1, 0x0b, 0x82, 0x6a, 0xb6, 0x35, 0x4b, + 0x84, 0x23, 0x05, 0x66, 0xcd, 0x41, 0x1e, 0x13, 0xb6, 0xe0, 0x00, 0xd3, 0x10, 0x01, 0x9b, 0x2d, + 0x1d, 0x91, 0x32, 0xb6, 0x48, 0x21, 0xdc, 0x00, 0xd3, 0x07, 0x72, 0x37, 0x21, 0x4f, 0x96, 0x2c, + 0x5b, 0x3d, 0x57, 0x1b, 0xce, 0xd1, 0x52, 0xd8, 0x01, 0x75, 0x3c, 0x60, 0x07, 0x2e, 0x89, 0xf0, + 0x7e, 0x40, 0xd0, 0x2f, 0xeb, 0x07, 0xeb, 0x70, 0xc5, 0x96, 0x14, 0x98, 0xe5, 0x62, 0x13, 0x82, + 0x5d, 0xd0, 0x90, 0x08, 0xcf, 0x4f, 0x25, 0xe3, 0xf7, 0x8c, 0x6d, 0xbd, 0x82, 0xd1, 0x55, 0x0a, + 0xb3, 0x5e, 0x9c, 0xc7, 0xe0, 0x23, 0x45, 0x21, 0x11, 0xf3, 0x7b, 0x98, 0x11, 0xf4, 0x47, 0x51, + 0xae, 0x96, 0x29, 0xd9, 0xbe, 0xef, 0x14, 0xa4, 0x19, 0xae, 0x54, 0x0f, 0xb7, 0x40, 0x53, 0x4e, + 0x25, 0x8e, 0x8d, 0x8b, 0x3d, 0x0f, 0x7d, 0x9c, 0x1d, 0x37, 0xd6, 0x63, 0xfe, 0xd6, 0xf1, 0xbc, + 0xd2, 0x58, 0x3a, 0xc6, 0xc7, 0x9a, 0xcf, 0x31, 0x6a, 0x4f, 0xa2, 0x4f, 0x8a, 0x74, 0xc1, 0x4e, + 0xd2, 0x9b, 0x59, 0xc3, 0xe6, 0x70, 0x29, 0x5c, 0x1e, 0xab, 0x4f, 0x18, 0xfa, 0x7c, 0xea, 0x58, + 0xdb, 0x84, 0x8d, 0x8c, 0xc5, 0x63, 0xb0, 0x0f, 0xce, 0xe6, 0x98, 0xde, 0x81, 0x38, 0x25, 0x6e, + 0x82, 0xd3, 0xf4, 0x55, 0x4c, 0x3d, 0xf4, 0x45, 0x21, 0xaf, 0xdb, 0x91, 0x9b, 0x52, 0xbd, 0xab, + 0xc5, 0x19, 0xfd, 0x7f, 0x6c, 0x4d, 0xc3, 0x27, 0x60, 0xb1, 0x30, 0xaf, 0xd8, 0xde, 0x2e, 0x8d, + 0xb9, 0xc9, 0x27, 0xaa, 0xc7, 0xa5, 0x31, 0x63, 0xcb, 0xa3, 0x11, 0xe7, 0x56, 0xff, 0x87, 0x87, + 0x33, 0xf0, 0x29, 0x58, 0xca, 0xc9, 0xea, 0xa4, 0x28, 0xf4, 0x57, 0x85, 0xbe, 0x6c, 0x47, 0xeb, + 0x23, 0x53, 0x60, 0x43, 0x3c, 0x92, 0x32, 0x9f, 0x59, 0x00, 0xa5, 0xfb, 0x6f, 0x6a, 0xe3, 0x3e, + 0xb3, 0xd0, 0x0f, 0xbb, 0xaf, 0x63, 0xc6, 0x7d, 0x89, 0xd1, 0xee, 0xbf, 0xad, 0x8d, 0x73, 0x5f, + 0x54, 0x59, 0xdc, 0xcf, 0xc3, 0xe5, 0xb1, 0x84, 0xfb, 0xef, 0x4e, 0x1d, 0x6b, 0xd8, 0x7d, 0x1d, + 0x83, 0xcf, 0x41, 0xab, 0x80, 0x91, 0xa6, 0x24, 0x84, 0x86, 0x7e, 0x9a, 0x8a, 0xff, 0xbc, 0xf7, + 0x8a, 0x79, 0x63, 0x0c, 0x53, 0xc8, 0x77, 0x8d, 0x3a, 0xe3, 0x9f, 0xc1, 0xf6, 0x3c, 0x0c, 0xc1, + 0x72, 0xde, 0x4b, 0xdb, 0x54, 0x68, 0xf6, 0x41, 0x35, 0xbb, 0x69, 0x6f, 0xa6, 0x1c, 0x19, 0xed, + 0x86, 0xf0, 0x18, 0x41, 0xfb, 0x5f, 0xd0, 0xdc, 0x0a, 0x13, 0xf6, 0xda, 0x21, 0x69, 0x12, 0x47, + 0x29, 0x69, 0x27, 0x60, 0xf9, 0x94, 0x43, 0x0f, 0x21, 0x98, 0x94, 0x97, 0x64, 0x45, 0x5e, 0x92, + 0xf2, 0x59, 0x5c, 0x9e, 0xe6, 0x2c, 0xe8, 0xcb, 0x33, 0x7b, 0x87, 0xe7, 0x41, 0x23, 0xf5, 0xc3, + 0x84, 0xaf, 0x85, 0xf1, 0xc6, 0x91, 0xbc, 0xf4, 0x6a, 0x4e, 0x5d, 0xc5, 0xf6, 0x44, 0xe8, 0xfe, + 0xfc, 0xf1, 0x8f, 0x95, 0x7f, 0x8e, 0x7f, 0xae, 0x54, 0x4e, 0xf8, 0xef, 0x3b, 0xff, 0xed, 0x4f, + 0xcb, 0x5b, 0x7b, 0xe3, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa6, 0x96, 0x31, 0x96, 0x0d, 0x08, + 0x00, 0x00, } diff --git a/etcdserver/etcdserverpb/raft_internal.proto b/etcdserver/etcdserverpb/raft_internal.proto index 2f8f1ded0..1b9ffadd9 100644 --- a/etcdserver/etcdserverpb/raft_internal.proto +++ b/etcdserver/etcdserverpb/raft_internal.proto @@ -38,7 +38,7 @@ message InternalRaftRequest { AuthEnableRequest auth_enable = 1000; AuthDisableRequest auth_disable = 1011; - AuthenticateRequest authenticate = 1012; + InternalAuthenticateRequest authenticate = 1012; AuthUserAddRequest auth_user_add = 1100; AuthUserDeleteRequest auth_user_delete = 1101; @@ -56,3 +56,15 @@ message InternalRaftRequest { message EmptyResponse { } + +// What is the difference between AuthenticateRequest (defined in rpc.proto) and InternalAuthenticateRequest? +// InternalAuthenticateRequest has a member that is filled by etcdserver and shouldn't be user-facing. +// For avoiding misusage the field, we have an internal version of AuthenticateRequest. +message InternalAuthenticateRequest { + string name = 1; + string password = 2; + + // simple_token is generated in API layer (etcdserver/v3_server.go) + string simple_token = 3; +} + diff --git a/etcdserver/server.go b/etcdserver/server.go index ef38d6785..5fdb049ca 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -214,6 +214,8 @@ type EtcdServer struct { // wg is used to wait for the go routines that depends on the server state // to exit when stopping the server. wg sync.WaitGroup + + appliedIndex uint64 } // NewServer creates a new EtcdServer from the supplied configuration. The @@ -1064,6 +1066,7 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { // set the consistent index of current executing entry s.consistIndex.setConsistentIndex(e.Index) ar := s.applyV3Request(&raftReq) + s.setAppliedIndex(e.Index) if ar.err != ErrNoSpace || len(s.alarmStore.Get(pb.AlarmType_NOSPACE)) > 0 { s.w.Trigger(id, ar) return @@ -1313,3 +1316,11 @@ func (s *EtcdServer) restoreAlarms() error { } return nil } + +func (s *EtcdServer) getAppliedIndex() uint64 { + return atomic.LoadUint64(&s.appliedIndex) +} + +func (s *EtcdServer) setAppliedIndex(v uint64) { + atomic.StoreUint64(&s.appliedIndex, v) +} diff --git a/etcdserver/v3_server.go b/etcdserver/v3_server.go index a06cd89fc..a057b5549 100644 --- a/etcdserver/v3_server.go +++ b/etcdserver/v3_server.go @@ -15,6 +15,8 @@ package etcdserver import ( + "strconv" + "strings" "time" "github.com/coreos/etcd/auth" @@ -271,7 +273,18 @@ func (s *EtcdServer) AuthDisable(ctx context.Context, r *pb.AuthDisableRequest) } func (s *EtcdServer) Authenticate(ctx context.Context, r *pb.AuthenticateRequest) (*pb.AuthenticateResponse, error) { - result, err := s.processInternalRaftRequest(ctx, pb.InternalRaftRequest{Authenticate: r}) + st, err := s.AuthStore().GenSimpleToken() + if err != nil { + return nil, err + } + + internalReq := &pb.InternalAuthenticateRequest{ + Name: r.Name, + Password: r.Password, + SimpleToken: st, + } + + result, err := s.processInternalRaftRequest(ctx, pb.InternalRaftRequest{Authenticate: internalReq}) if err != nil { return nil, err } @@ -402,6 +415,36 @@ func (s *EtcdServer) RoleDelete(ctx context.Context, r *pb.AuthRoleDeleteRequest return result.resp.(*pb.AuthRoleDeleteResponse), nil } +func (s *EtcdServer) isValidSimpleToken(token string) bool { + splitted := strings.Split(token, ".") + if len(splitted) != 2 { + return false + } + index, err := strconv.Atoi(splitted[1]) + if err != nil { + return false + } + + // CAUTION: below index synchronization is required because this node + // might not receive and apply the log entry of Authenticate() RPC. + authApplied := false + for i := 0; i < 10; i++ { + if uint64(index) <= s.getAppliedIndex() { + authApplied = true + break + } + + time.Sleep(100 * time.Millisecond) + } + + if !authApplied { + plog.Errorf("timeout of waiting Authenticate() RPC") + return false + } + + return true +} + func (s *EtcdServer) usernameFromCtx(ctx context.Context) (string, error) { md, ok := metadata.FromContext(ctx) if !ok { @@ -414,6 +457,10 @@ func (s *EtcdServer) usernameFromCtx(ctx context.Context) (string, error) { } token := ts[0] + if !s.isValidSimpleToken(token) { + return "", ErrInvalidAuthToken + } + username, uok := s.AuthStore().UsernameFromToken(token) if !uok { plog.Warningf("invalid auth token: %s", token)