mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
v2http: allow empty role for GET /users
Fix https://github.com/coreos/etcd/issues/5246.
This commit is contained in:
parent
879cfe7666
commit
3c2d0a229c
@ -285,6 +285,10 @@ type userWithRoles struct {
|
||||
Roles []auth.Role `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
type usersCollections struct {
|
||||
Users []userWithRoles `json:"users"`
|
||||
}
|
||||
|
||||
func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
||||
if !allowMethod(w, r.Method, "GET") {
|
||||
return
|
||||
@ -311,9 +315,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var usersCollections struct {
|
||||
Users []userWithRoles `json:"users"`
|
||||
}
|
||||
ucs := usersCollections{}
|
||||
for _, userName := range users {
|
||||
var user auth.User
|
||||
user, err = sh.sec.GetUser(userName)
|
||||
@ -327,15 +329,14 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
||||
var role auth.Role
|
||||
role, err = sh.sec.GetRole(roleName)
|
||||
if err != nil {
|
||||
writeError(w, r, err)
|
||||
return
|
||||
continue
|
||||
}
|
||||
uwr.Roles = append(uwr.Roles, role)
|
||||
}
|
||||
|
||||
usersCollections.Users = append(usersCollections.Users, uwr)
|
||||
ucs.Users = append(ucs.Users, uwr)
|
||||
}
|
||||
err = json.NewEncoder(w).Encode(usersCollections)
|
||||
err = json.NewEncoder(w).Encode(ucs)
|
||||
|
||||
if err != nil {
|
||||
plog.Warningf("baseUsers error encoding on %s", r.URL)
|
||||
|
@ -15,10 +15,14 @@
|
||||
package v2http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -43,7 +47,14 @@ type mockAuthStore struct {
|
||||
enabled bool
|
||||
}
|
||||
|
||||
func (s *mockAuthStore) AllUsers() ([]string, error) { return []string{"alice", "bob", "root"}, s.err }
|
||||
func (s *mockAuthStore) AllUsers() ([]string, error) {
|
||||
var us []string
|
||||
for u := range s.users {
|
||||
us = append(us, u)
|
||||
}
|
||||
sort.Strings(us)
|
||||
return us, s.err
|
||||
}
|
||||
func (s *mockAuthStore) GetUser(name string) (auth.User, error) {
|
||||
u, ok := s.users[name]
|
||||
if !ok {
|
||||
@ -67,9 +78,15 @@ func (s *mockAuthStore) UpdateUser(user auth.User) (auth.User, error) {
|
||||
func (s *mockAuthStore) AllRoles() ([]string, error) {
|
||||
return []string{"awesome", "guest", "root"}, s.err
|
||||
}
|
||||
func (s *mockAuthStore) GetRole(name string) (auth.Role, error) { return *s.roles[name], s.err }
|
||||
func (s *mockAuthStore) CreateRole(role auth.Role) error { return s.err }
|
||||
func (s *mockAuthStore) DeleteRole(name string) error { return s.err }
|
||||
func (s *mockAuthStore) GetRole(name string) (auth.Role, error) {
|
||||
r, ok := s.roles[name]
|
||||
if ok {
|
||||
return *r, s.err
|
||||
}
|
||||
return auth.Role{}, fmt.Errorf("%q does not exist (%v)", name, s.err)
|
||||
}
|
||||
func (s *mockAuthStore) CreateRole(role auth.Role) error { return s.err }
|
||||
func (s *mockAuthStore) DeleteRole(name string) error { return s.err }
|
||||
func (s *mockAuthStore) UpdateRole(role auth.Role) (auth.Role, error) {
|
||||
return *s.roles[role.Role], s.err
|
||||
}
|
||||
@ -361,6 +378,61 @@ func TestAuthFlow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUserGrantedWithNonexistingRole(t *testing.T) {
|
||||
sh := &authHandler{
|
||||
sec: &mockAuthStore{
|
||||
users: map[string]*auth.User{
|
||||
"root": {
|
||||
User: "root",
|
||||
Roles: []string{"root", "foo"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"root": {
|
||||
Role: "root",
|
||||
},
|
||||
},
|
||||
},
|
||||
cluster: &fakeCluster{id: 1},
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(sh.baseUsers))
|
||||
defer srv.Close()
|
||||
|
||||
req, err := http.NewRequest("GET", "", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req.URL, err = url.Parse(srv.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
cli := http.DefaultClient
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var uc usersCollections
|
||||
if err := json.NewDecoder(resp.Body).Decode(&uc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(uc.Users) != 1 {
|
||||
t.Fatalf("expected 1 user, got %+v", uc.Users)
|
||||
}
|
||||
if uc.Users[0].User != "root" {
|
||||
t.Fatalf("expected 'root', got %q", uc.Users[0].User)
|
||||
}
|
||||
if len(uc.Users[0].Roles) != 1 {
|
||||
t.Fatalf("expected 1 role, got %+v", uc.Users[0].Roles)
|
||||
}
|
||||
if uc.Users[0].Roles[0].Role != "root" {
|
||||
t.Fatalf("expected 'root', got %q", uc.Users[0].Roles[0].Role)
|
||||
}
|
||||
}
|
||||
|
||||
func mustAuthRequest(method, username, password string) *http.Request {
|
||||
req, err := http.NewRequest(method, "path", strings.NewReader(""))
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user