mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #3408 from MSamman/extend-auth-api
etcdserver: extend auth api
This commit is contained in:
commit
ea3dbfed60
@ -124,7 +124,7 @@ The User JSON object is formed as follows:
|
||||
|
||||
Password is only passed when necessary.
|
||||
|
||||
**Get a list of users**
|
||||
**Get a List of Users**
|
||||
|
||||
GET/HEAD /v2/auth/users
|
||||
|
||||
@ -137,7 +137,36 @@ GET/HEAD /v2/auth/users
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"users": ["alice", "bob", "eve"]
|
||||
"users": [
|
||||
{
|
||||
"user": "alice",
|
||||
"roles": [
|
||||
{
|
||||
"role": "root",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["*"],
|
||||
"write": ["*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"user": "bob",
|
||||
"roles": [
|
||||
{
|
||||
"role": "guest",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["*"],
|
||||
"write": ["*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Get User Details**
|
||||
@ -155,7 +184,26 @@ GET/HEAD /v2/auth/users/alice
|
||||
200 Body:
|
||||
{
|
||||
"user" : "alice",
|
||||
"roles" : ["fleet", "etcd"]
|
||||
"roles" : [
|
||||
{
|
||||
"role": "fleet",
|
||||
"permissions" : {
|
||||
"kv" : {
|
||||
"read": [ "/fleet/" ],
|
||||
"write": [ "/fleet/" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "etcd",
|
||||
"permissions" : {
|
||||
"kv" : {
|
||||
"read": [ "*" ],
|
||||
"write": [ "*" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Create Or Update A User**
|
||||
@ -213,22 +261,6 @@ A full role structure may look like this. A Permission List structure is used fo
|
||||
}
|
||||
```
|
||||
|
||||
**Get a list of Roles**
|
||||
|
||||
GET/HEAD /v2/auth/roles
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
200 Headers:
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"roles": ["fleet", "etcd", "quay"]
|
||||
}
|
||||
|
||||
**Get Role Details**
|
||||
|
||||
GET/HEAD /v2/auth/roles/fleet
|
||||
@ -252,6 +284,50 @@ GET/HEAD /v2/auth/roles/fleet
|
||||
}
|
||||
}
|
||||
|
||||
**Get a list of Roles**
|
||||
|
||||
GET/HEAD /v2/auth/roles
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
200 Headers:
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"role": "fleet",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["/fleet/"],
|
||||
"write": ["/fleet/"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "etcd",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["*"],
|
||||
"write": ["*"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "quay",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["*"],
|
||||
"write": ["*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Create Or Update A Role**
|
||||
|
||||
PUT /v2/auth/roles/rkt
|
||||
|
@ -147,11 +147,10 @@ func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
||||
writeNoAuth(w)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var rolesCollections struct {
|
||||
Roles []string `json:"roles"`
|
||||
}
|
||||
|
||||
roles, err := sh.sec.AllRoles()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
@ -161,10 +160,30 @@ func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
||||
roles = make([]string, 0)
|
||||
}
|
||||
|
||||
rolesCollections.Roles = roles
|
||||
err = r.ParseForm()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var rolesCollections struct {
|
||||
Roles []auth.Role `json:"roles"`
|
||||
}
|
||||
for _, roleName := range roles {
|
||||
var role auth.Role
|
||||
role, err = sh.sec.GetRole(roleName)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
rolesCollections.Roles = append(rolesCollections.Roles, role)
|
||||
}
|
||||
err = json.NewEncoder(w).Encode(rolesCollections)
|
||||
|
||||
if err != nil {
|
||||
plog.Warningf("baseRoles error encoding on %s", r.URL)
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,6 +278,11 @@ func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role stri
|
||||
}
|
||||
}
|
||||
|
||||
type userWithRoles struct {
|
||||
User string `json:"user"`
|
||||
Roles []auth.Role `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
||||
if !allowMethod(w, r.Method, "GET") {
|
||||
return
|
||||
@ -269,9 +293,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var usersCollections struct {
|
||||
Users []string `json:"users"`
|
||||
}
|
||||
|
||||
users, err := sh.sec.AllUsers()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
@ -281,10 +303,42 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
||||
users = make([]string, 0)
|
||||
}
|
||||
|
||||
usersCollections.Users = users
|
||||
err = r.ParseForm()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
var usersCollections struct {
|
||||
Users []userWithRoles `json:"users"`
|
||||
}
|
||||
for _, userName := range users {
|
||||
var user auth.User
|
||||
user, err = sh.sec.GetUser(userName)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
uwr := userWithRoles{User: user.User}
|
||||
for _, roleName := range user.Roles {
|
||||
var role auth.Role
|
||||
role, err = sh.sec.GetRole(roleName)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
uwr.Roles = append(uwr.Roles, role)
|
||||
}
|
||||
|
||||
usersCollections.Users = append(usersCollections.Users, uwr)
|
||||
}
|
||||
err = json.NewEncoder(w).Encode(usersCollections)
|
||||
|
||||
if err != nil {
|
||||
plog.Warningf("baseUsers error encoding on %s", r.URL)
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,9 +376,25 @@ func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user stri
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
u.Password = ""
|
||||
|
||||
err = json.NewEncoder(w).Encode(u)
|
||||
err = r.ParseForm()
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
uwr := userWithRoles{User: u.User}
|
||||
for _, roleName := range u.Roles {
|
||||
var role auth.Role
|
||||
role, err = sh.sec.GetRole(roleName)
|
||||
if err != nil {
|
||||
writeError(w, err)
|
||||
return
|
||||
}
|
||||
uwr.Roles = append(uwr.Roles, role)
|
||||
}
|
||||
err = json.NewEncoder(w).Encode(uwr)
|
||||
|
||||
if err != nil {
|
||||
plog.Warningf("forUser error encoding on %s", r.URL)
|
||||
return
|
||||
|
@ -37,16 +37,22 @@ func mustJSONRequest(t *testing.T, method string, p string, body string) *http.R
|
||||
}
|
||||
|
||||
type mockAuthStore struct {
|
||||
user *auth.User
|
||||
users map[string]*auth.User
|
||||
roles map[string]*auth.Role
|
||||
err error
|
||||
enabled bool
|
||||
}
|
||||
|
||||
func (s *mockAuthStore) AllUsers() ([]string, error) { return []string{"alice", "bob", "root"}, s.err }
|
||||
func (s *mockAuthStore) GetUser(name string) (auth.User, error) { return *s.user, s.err }
|
||||
func (s *mockAuthStore) AllUsers() ([]string, error) { return []string{"alice", "bob", "root"}, s.err }
|
||||
func (s *mockAuthStore) GetUser(name string) (auth.User, error) {
|
||||
u, ok := s.users[name]
|
||||
if !ok {
|
||||
return auth.User{}, s.err
|
||||
}
|
||||
return *u, s.err
|
||||
}
|
||||
func (s *mockAuthStore) CreateOrUpdateUser(user auth.User) (out auth.User, created bool, err error) {
|
||||
if s.user == nil {
|
||||
if s.users == nil {
|
||||
u, err := s.CreateUser(user)
|
||||
return u, true, err
|
||||
}
|
||||
@ -55,7 +61,9 @@ func (s *mockAuthStore) CreateOrUpdateUser(user auth.User) (out auth.User, creat
|
||||
}
|
||||
func (s *mockAuthStore) CreateUser(user auth.User) (auth.User, error) { return user, s.err }
|
||||
func (s *mockAuthStore) DeleteUser(name string) error { return s.err }
|
||||
func (s *mockAuthStore) UpdateUser(user auth.User) (auth.User, error) { return *s.user, s.err }
|
||||
func (s *mockAuthStore) UpdateUser(user auth.User) (auth.User, error) {
|
||||
return *s.users[user.User], s.err
|
||||
}
|
||||
func (s *mockAuthStore) AllRoles() ([]string, error) {
|
||||
return []string{"awesome", "guest", "root"}, s.err
|
||||
}
|
||||
@ -95,22 +103,64 @@ func TestAuthFlow(t *testing.T) {
|
||||
},
|
||||
// Users
|
||||
{
|
||||
req: mustJSONRequest(t, "GET", "users", ""),
|
||||
store: mockAuthStore{},
|
||||
req: mustJSONRequest(t, "GET", "users", ""),
|
||||
store: mockAuthStore{
|
||||
users: map[string]*auth.User{
|
||||
"alice": {
|
||||
User: "alice",
|
||||
Roles: []string{"alicerole", "guest"},
|
||||
Password: "wheeee",
|
||||
},
|
||||
"bob": {
|
||||
User: "bob",
|
||||
Roles: []string{"guest"},
|
||||
Password: "wheeee",
|
||||
},
|
||||
"root": {
|
||||
User: "root",
|
||||
Roles: []string{"root"},
|
||||
Password: "wheeee",
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"alicerole": {
|
||||
Role: "alicerole",
|
||||
},
|
||||
"guest": {
|
||||
Role: "guest",
|
||||
},
|
||||
"root": {
|
||||
Role: "root",
|
||||
},
|
||||
},
|
||||
},
|
||||
wcode: http.StatusOK,
|
||||
wbody: `{"users":["alice","bob","root"]}`,
|
||||
wbody: `{"users":[` +
|
||||
`{"user":"alice","roles":[` +
|
||||
`{"role":"alicerole","permissions":{"kv":{"read":null,"write":null}}},` +
|
||||
`{"role":"guest","permissions":{"kv":{"read":null,"write":null}}}` +
|
||||
`]},` +
|
||||
`{"user":"bob","roles":[{"role":"guest","permissions":{"kv":{"read":null,"write":null}}}]},` +
|
||||
`{"user":"root","roles":[{"role":"root","permissions":{"kv":{"read":null,"write":null}}}]}]}`,
|
||||
},
|
||||
{
|
||||
req: mustJSONRequest(t, "GET", "users/alice", ""),
|
||||
store: mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "alice",
|
||||
Roles: []string{"alicerole", "guest"},
|
||||
Password: "wheeee",
|
||||
users: map[string]*auth.User{
|
||||
"alice": {
|
||||
User: "alice",
|
||||
Roles: []string{"alicerole"},
|
||||
Password: "wheeee",
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"alicerole": {
|
||||
Role: "alicerole",
|
||||
},
|
||||
},
|
||||
},
|
||||
wcode: http.StatusOK,
|
||||
wbody: `{"user":"alice","roles":["alicerole","guest"]}`,
|
||||
wbody: `{"user":"alice","roles":[{"role":"alicerole","permissions":{"kv":{"read":null,"write":null}}}]}`,
|
||||
},
|
||||
{
|
||||
req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "alice", "password": "goodpassword"}`),
|
||||
@ -127,10 +177,12 @@ func TestAuthFlow(t *testing.T) {
|
||||
{
|
||||
req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "alice", "password": "goodpassword"}`),
|
||||
store: mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "alice",
|
||||
Roles: []string{"alicerole", "guest"},
|
||||
Password: "wheeee",
|
||||
users: map[string]*auth.User{
|
||||
"alice": {
|
||||
User: "alice",
|
||||
Roles: []string{"alicerole", "guest"},
|
||||
Password: "wheeee",
|
||||
},
|
||||
},
|
||||
},
|
||||
wcode: http.StatusOK,
|
||||
@ -139,10 +191,12 @@ func TestAuthFlow(t *testing.T) {
|
||||
{
|
||||
req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "alice", "grant": ["alicerole"]}`),
|
||||
store: mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "alice",
|
||||
Roles: []string{"alicerole", "guest"},
|
||||
Password: "wheeee",
|
||||
users: map[string]*auth.User{
|
||||
"alice": {
|
||||
User: "alice",
|
||||
Roles: []string{"alicerole", "guest"},
|
||||
Password: "wheeee",
|
||||
},
|
||||
},
|
||||
},
|
||||
wcode: http.StatusOK,
|
||||
@ -151,13 +205,12 @@ func TestAuthFlow(t *testing.T) {
|
||||
{
|
||||
req: mustJSONRequest(t, "GET", "users/alice", ``),
|
||||
store: mockAuthStore{
|
||||
user: &auth.User{},
|
||||
err: auth.Error{Status: http.StatusNotFound, Errmsg: "auth: User alice doesn't exist."},
|
||||
users: map[string]*auth.User{},
|
||||
err: auth.Error{Status: http.StatusNotFound, Errmsg: "auth: User alice doesn't exist."},
|
||||
},
|
||||
wcode: http.StatusNotFound,
|
||||
wbody: `{"message":"auth: User alice doesn't exist."}`,
|
||||
},
|
||||
// Roles
|
||||
{
|
||||
req: mustJSONRequest(t, "GET", "roles/manager", ""),
|
||||
store: mockAuthStore{
|
||||
@ -195,10 +248,24 @@ func TestAuthFlow(t *testing.T) {
|
||||
wbody: `{"role":"manager","permissions":{"kv":{"read":null,"write":null}}}`,
|
||||
},
|
||||
{
|
||||
req: mustJSONRequest(t, "GET", "roles", ""),
|
||||
store: mockAuthStore{},
|
||||
req: mustJSONRequest(t, "GET", "roles", ""),
|
||||
store: mockAuthStore{
|
||||
roles: map[string]*auth.Role{
|
||||
"awesome": {
|
||||
Role: "awesome",
|
||||
},
|
||||
"guest": {
|
||||
Role: "guest",
|
||||
},
|
||||
"root": {
|
||||
Role: "root",
|
||||
},
|
||||
},
|
||||
},
|
||||
wcode: http.StatusOK,
|
||||
wbody: `{"roles":["awesome","guest","root"]}`,
|
||||
wbody: `{"roles":[{"role":"awesome","permissions":{"kv":{"read":null,"write":null}}},` +
|
||||
`{"role":"guest","permissions":{"kv":{"read":null,"write":null}}},` +
|
||||
`{"role":"root","permissions":{"kv":{"read":null,"write":null}}}]}`,
|
||||
},
|
||||
{
|
||||
req: mustJSONRequest(t, "GET", "enable", ""),
|
||||
@ -224,10 +291,12 @@ func TestAuthFlow(t *testing.T) {
|
||||
})(),
|
||||
store: mockAuthStore{
|
||||
enabled: true,
|
||||
user: &auth.User{
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
users: map[string]*auth.User{
|
||||
"root": {
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"root": {
|
||||
@ -246,10 +315,12 @@ func TestAuthFlow(t *testing.T) {
|
||||
})(),
|
||||
store: mockAuthStore{
|
||||
enabled: true,
|
||||
user: &auth.User{
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
users: map[string]*auth.User{
|
||||
"root": {
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"root": {
|
||||
@ -304,10 +375,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/foo",
|
||||
req: mustAuthRequest("GET", "root", "good"),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
users: map[string]*auth.User{
|
||||
"root": {
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"root": {
|
||||
@ -324,10 +397,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/foo",
|
||||
req: mustAuthRequest("GET", "user", "good"),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
users: map[string]*auth.User{
|
||||
"user": {
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"foorole": {
|
||||
@ -350,10 +425,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/foo",
|
||||
req: mustAuthRequest("GET", "user", "good"),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
users: map[string]*auth.User{
|
||||
"user": {
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"foorole": {
|
||||
@ -376,10 +453,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/foo",
|
||||
req: mustAuthRequest("GET", "user", "bad"),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
users: map[string]*auth.User{
|
||||
"user": {
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"foorole": {
|
||||
@ -402,7 +481,7 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/foo",
|
||||
req: mustAuthRequest("GET", "user", "good"),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{},
|
||||
users: map[string]*auth.User{},
|
||||
err: errors.New("Not the user"),
|
||||
enabled: true,
|
||||
},
|
||||
@ -414,10 +493,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/foo",
|
||||
req: mustJSONRequest(t, "GET", "somepath", ""),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
users: map[string]*auth.User{
|
||||
"user": {
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"guest": {
|
||||
@ -440,10 +521,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/bar",
|
||||
req: mustJSONRequest(t, "GET", "somepath", ""),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
users: map[string]*auth.User{
|
||||
"user": {
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"foorole"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"guest": {
|
||||
@ -467,10 +550,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
key: "/foo",
|
||||
req: mustAuthRequest("GET", "user", "good"),
|
||||
store: &mockAuthStore{
|
||||
user: &auth.User{
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"role1", "role2"},
|
||||
users: map[string]*auth.User{
|
||||
"user": {
|
||||
User: "user",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"role1", "role2"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"role1": {
|
||||
@ -501,10 +586,12 @@ func TestPrefixAccess(t *testing.T) {
|
||||
})(),
|
||||
store: &mockAuthStore{
|
||||
enabled: true,
|
||||
user: &auth.User{
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
users: map[string]*auth.User{
|
||||
"root": {
|
||||
User: "root",
|
||||
Password: goodPassword,
|
||||
Roles: []string{"root"},
|
||||
},
|
||||
},
|
||||
roles: map[string]*auth.Role{
|
||||
"guest": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user