diff --git a/etcdserver/etcdhttp/client_auth.go b/etcdserver/etcdhttp/client_auth.go index 99a0d0647..f43d540e4 100644 --- a/etcdserver/etcdhttp/client_auth.go +++ b/etcdserver/etcdhttp/client_auth.go @@ -76,9 +76,14 @@ func hasKeyPrefixAccess(sec auth.Store, r *http.Request, key string, recursive b if !sec.AuthEnabled() { return true } + if r.Header.Get("Authorization") == "" { + plog.Warningf("auth: no authorization provided, checking guest access") + return hasGuestAccess(sec, r, key) + } username, password, ok := netutil.BasicAuth(r) if !ok { - return hasGuestAccess(sec, r, key) + plog.Warningf("auth: malformed basic auth encoding") + return false } user, err := sec.GetUser(username) if err != nil { diff --git a/etcdserver/etcdhttp/client_auth_test.go b/etcdserver/etcdhttp/client_auth_test.go index b9890527b..1ee2e0fb1 100644 --- a/etcdserver/etcdhttp/client_auth_test.go +++ b/etcdserver/etcdhttp/client_auth_test.go @@ -238,6 +238,28 @@ func TestAuthFlow(t *testing.T) { wcode: http.StatusOK, wbody: ``, }, + { + req: (func() *http.Request { + req := mustJSONRequest(t, "DELETE", "enable", "") + req.SetBasicAuth("root", "bad") + return req + })(), + store: mockAuthStore{ + enabled: true, + user: &auth.User{ + User: "root", + Password: goodPassword, + Roles: []string{"root"}, + }, + roles: map[string]*auth.Role{ + "root": { + Role: "guest", + }, + }, + }, + wcode: http.StatusUnauthorized, + wbody: `{"message":"Insufficient credentials"}`, + }, } for i, tt := range testCases { @@ -470,6 +492,36 @@ func TestPrefixAccess(t *testing.T) { hasKeyPrefixAccess: true, hasRecursiveAccess: false, }, + { + key: "/foo", + req: (func() *http.Request { + req := mustJSONRequest(t, "GET", "somepath", "") + req.Header.Set("Authorization", "malformedencoding") + return req + })(), + store: &mockAuthStore{ + enabled: true, + user: &auth.User{ + User: "root", + Password: goodPassword, + Roles: []string{"root"}, + }, + roles: map[string]*auth.Role{ + "guest": { + Role: "guest", + Permissions: auth.Permissions{ + KV: auth.RWPermission{ + Read: []string{"/foo*"}, + Write: []string{"/foo*"}, + }, + }, + }, + }, + }, + hasRoot: false, + hasKeyPrefixAccess: false, + hasRecursiveAccess: false, + }, } for i, tt := range table {