mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
Set the policy mapping for a user or group (#8036)
Add API to set policy mapping for a user or group Contains a breaking Admin APIs change. - Also enforce all applicable policies - Removes the previous /set-user-policy API Bump up peerRESTVersion Add get user info API to show groups of a user
This commit is contained in:
parent
bc79b435a2
commit
bf9b619d86
@ -1020,6 +1020,33 @@ func (a adminAPIHandlers) ListUsers(w http.ResponseWriter, r *http.Request) {
|
||||
writeSuccessResponseJSON(w, econfigData)
|
||||
}
|
||||
|
||||
// GetUserInfo - GET /minio/admin/v1/user-info
|
||||
func (a adminAPIHandlers) GetUserInfo(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "GetUserInfo")
|
||||
|
||||
objectAPI := validateAdminReq(ctx, w, r)
|
||||
if objectAPI == nil {
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
name := vars["accessKey"]
|
||||
|
||||
userInfo, err := globalIAMSys.GetUserInfo(name)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := json.Marshal(userInfo)
|
||||
if err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
writeSuccessResponseJSON(w, data)
|
||||
}
|
||||
|
||||
// UpdateGroupMembers - PUT /minio/admin/v1/update-group-members
|
||||
func (a adminAPIHandlers) UpdateGroupMembers(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "UpdateGroupMembers")
|
||||
@ -1353,9 +1380,9 @@ func (a adminAPIHandlers) AddCannedPolicy(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
}
|
||||
|
||||
// SetUserPolicy - PUT /minio/admin/v1/set-user-policy?accessKey=<access_key>&name=<policy_name>
|
||||
func (a adminAPIHandlers) SetUserPolicy(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "SetUserPolicy")
|
||||
// SetPolicyForUserOrGroup - PUT /minio/admin/v1/set-policy?policy=xxx&user-or-group=?[&is-group]
|
||||
func (a adminAPIHandlers) SetPolicyForUserOrGroup(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := newContext(r, w, "SetPolicyForUserOrGroup")
|
||||
|
||||
objectAPI := validateAdminReq(ctx, w, r)
|
||||
if objectAPI == nil {
|
||||
@ -1363,8 +1390,9 @@ func (a adminAPIHandlers) SetUserPolicy(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
accessKey := vars["accessKey"]
|
||||
policyName := vars["name"]
|
||||
policyName := vars["policyName"]
|
||||
entityName := vars["userOrGroup"]
|
||||
isGroup := vars["isGroup"] == "true"
|
||||
|
||||
// Deny if WORM is enabled
|
||||
if globalWORMEnabled {
|
||||
@ -1372,18 +1400,13 @@ func (a adminAPIHandlers) SetUserPolicy(w http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
// Custom IAM policies not allowed for admin user.
|
||||
if accessKey == globalServerConfig.GetCredential().AccessKey {
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL)
|
||||
if err := globalIAMSys.PolicyDBSet(entityName, policyName, isGroup); err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
if err := globalIAMSys.PolicyDBSet(accessKey, policyName, false); err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
}
|
||||
|
||||
// Notify all other Minio peers to reload user
|
||||
for _, nerr := range globalNotificationSys.LoadUser(accessKey, false) {
|
||||
// Notify all other MinIO peers to reload policy
|
||||
for _, nerr := range globalNotificationSys.LoadPolicyMapping(entityName, isGroup) {
|
||||
if nerr.Err != nil {
|
||||
logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String())
|
||||
logger.LogIf(ctx, nerr.Err)
|
||||
|
@ -96,20 +96,26 @@ func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool)
|
||||
|
||||
// Add user IAM
|
||||
adminV1Router.Methods(http.MethodPut).Path("/add-user").HandlerFunc(httpTraceHdrs(adminAPI.AddUser)).Queries("accessKey", "{accessKey:.*}")
|
||||
adminV1Router.Methods(http.MethodPut).Path("/set-user-policy").HandlerFunc(httpTraceHdrs(adminAPI.SetUserPolicy)).
|
||||
Queries("accessKey", "{accessKey:.*}").Queries("name", "{name:.*}")
|
||||
adminV1Router.Methods(http.MethodPut).Path("/set-user-status").HandlerFunc(httpTraceHdrs(adminAPI.SetUserStatus)).
|
||||
Queries("accessKey", "{accessKey:.*}").Queries("status", "{status:.*}")
|
||||
|
||||
// Remove policy IAM
|
||||
adminV1Router.Methods(http.MethodDelete).Path("/remove-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.RemoveCannedPolicy)).Queries("name", "{name:.*}")
|
||||
|
||||
// Set user or group policy
|
||||
adminV1Router.Methods(http.MethodPut).Path("/set-user-or-group-policy").
|
||||
HandlerFunc(httpTraceHdrs(adminAPI.SetPolicyForUserOrGroup)).
|
||||
Queries("policyName", "{policyName:.*}", "userOrGroup", "{userOrGroup:.*}", "isGroup", "{isGroup:true|false}")
|
||||
|
||||
// Remove user IAM
|
||||
adminV1Router.Methods(http.MethodDelete).Path("/remove-user").HandlerFunc(httpTraceHdrs(adminAPI.RemoveUser)).Queries("accessKey", "{accessKey:.*}")
|
||||
|
||||
// List users
|
||||
adminV1Router.Methods(http.MethodGet).Path("/list-users").HandlerFunc(httpTraceHdrs(adminAPI.ListUsers))
|
||||
|
||||
// User info
|
||||
adminV1Router.Methods(http.MethodGet).Path("/user-info").HandlerFunc(httpTraceHdrs(adminAPI.GetUserInfo)).Queries("accessKey", "{accessKey:.*}")
|
||||
|
||||
// Add/Remove members from group
|
||||
adminV1Router.Methods(http.MethodPut).Path("/update-group-members").HandlerFunc(httpTraceHdrs(adminAPI.UpdateGroupMembers))
|
||||
|
||||
|
@ -530,6 +530,7 @@ func (ies *IAMEtcdStore) reloadFromEvent(sys *IAMSys, event *etcd.Event) {
|
||||
policyPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPoliciesPrefix)
|
||||
policyDBUsersPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPolicyDBUsersPrefix)
|
||||
policyDBSTSUsersPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPolicyDBSTSUsersPrefix)
|
||||
policyDBGroupsPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPolicyDBGroupsPrefix)
|
||||
|
||||
switch {
|
||||
case eventCreate:
|
||||
@ -563,6 +564,11 @@ func (ies *IAMEtcdStore) reloadFromEvent(sys *IAMSys, event *etcd.Event) {
|
||||
iamConfigPolicyDBSTSUsersPrefix)
|
||||
user := strings.TrimSuffix(policyMapFile, ".json")
|
||||
ies.loadMappedPolicy(user, true, false, sys.iamUserPolicyMap)
|
||||
case policyDBGroupsPrefix:
|
||||
policyMapFile := strings.TrimPrefix(string(event.Kv.Key),
|
||||
iamConfigPolicyDBGroupsPrefix)
|
||||
user := strings.TrimSuffix(policyMapFile, ".json")
|
||||
ies.loadMappedPolicy(user, false, true, sys.iamGroupPolicyMap)
|
||||
}
|
||||
case eventDelete:
|
||||
switch {
|
||||
@ -594,6 +600,11 @@ func (ies *IAMEtcdStore) reloadFromEvent(sys *IAMSys, event *etcd.Event) {
|
||||
iamConfigPolicyDBSTSUsersPrefix)
|
||||
user := strings.TrimSuffix(policyMapFile, ".json")
|
||||
delete(sys.iamUserPolicyMap, user)
|
||||
case policyDBGroupsPrefix:
|
||||
policyMapFile := strings.TrimPrefix(string(event.Kv.Key),
|
||||
iamConfigPolicyDBGroupsPrefix)
|
||||
user := strings.TrimSuffix(policyMapFile, ".json")
|
||||
delete(sys.iamGroupPolicyMap, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
130
cmd/iam.go
130
cmd/iam.go
@ -259,6 +259,33 @@ func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadPolicyMapping - loads the mapped policy for a user or group
|
||||
// from storage into server memory.
|
||||
func (sys *IAMSys) LoadPolicyMapping(objAPI ObjectLayer, userOrGroup string, isGroup bool) error {
|
||||
if objAPI == nil {
|
||||
return errInvalidArgument
|
||||
}
|
||||
|
||||
sys.Lock()
|
||||
defer sys.Unlock()
|
||||
|
||||
if globalEtcdClient == nil {
|
||||
var err error
|
||||
if isGroup {
|
||||
err = sys.store.loadMappedPolicy(userOrGroup, false, isGroup, sys.iamGroupPolicyMap)
|
||||
} else {
|
||||
err = sys.store.loadMappedPolicy(userOrGroup, false, isGroup, sys.iamUserPolicyMap)
|
||||
}
|
||||
|
||||
// Ignore policy not mapped error
|
||||
if err != nil && err != errConfigNotFound {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// When etcd is set, we use watch APIs so this code is not needed.
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadUser - reloads a specific user from backend disks or etcd.
|
||||
func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, isSTS bool) error {
|
||||
if objAPI == nil {
|
||||
@ -516,6 +543,29 @@ func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) {
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// GetUserInfo - get info on a user.
|
||||
func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) {
|
||||
objectAPI := newObjectLayerFn()
|
||||
if objectAPI == nil {
|
||||
return u, errServerNotInitialized
|
||||
}
|
||||
|
||||
sys.RLock()
|
||||
defer sys.RUnlock()
|
||||
|
||||
creds, found := sys.iamUsersMap[name]
|
||||
if !found {
|
||||
return u, errNoSuchUser
|
||||
}
|
||||
|
||||
u = madmin.UserInfo{
|
||||
PolicyName: sys.iamUserPolicyMap[name].Policy,
|
||||
Status: madmin.AccountStatus(creds.Status),
|
||||
MemberOf: sys.iamUserGroupMemberships[name].ToSlice(),
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// SetUserStatus - sets current user status, supports disabled or enabled.
|
||||
func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error {
|
||||
objectAPI := newObjectLayerFn()
|
||||
@ -776,6 +826,16 @@ func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error {
|
||||
|
||||
// GetGroupDescription - builds up group description
|
||||
func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err error) {
|
||||
ps, err := sys.PolicyDBGet(group, true)
|
||||
if err != nil {
|
||||
return gd, err
|
||||
}
|
||||
// A group may be mapped to at most one policy.
|
||||
policy := ""
|
||||
if len(ps) > 0 {
|
||||
policy = ps[0]
|
||||
}
|
||||
|
||||
sys.RLock()
|
||||
defer sys.RUnlock()
|
||||
|
||||
@ -784,17 +844,6 @@ func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err e
|
||||
return gd, errNoSuchGroup
|
||||
}
|
||||
|
||||
var p []string
|
||||
p, err = sys.policyDBGet(group, true)
|
||||
if err != nil {
|
||||
return gd, err
|
||||
}
|
||||
|
||||
policy := ""
|
||||
if len(p) > 0 {
|
||||
policy = p[0]
|
||||
}
|
||||
|
||||
return madmin.GroupDesc{
|
||||
Name: group,
|
||||
Status: gi.Status,
|
||||
@ -837,21 +886,28 @@ func (sys *IAMSys) policyDBSet(objectAPI ObjectLayer, name, policy string, isSTS
|
||||
if name == "" || policy == "" {
|
||||
return errInvalidArgument
|
||||
}
|
||||
if _, ok := sys.iamUsersMap[name]; !ok {
|
||||
return errNoSuchUser
|
||||
}
|
||||
if _, ok := sys.iamPolicyDocsMap[policy]; !ok {
|
||||
return errNoSuchPolicy
|
||||
}
|
||||
if _, ok := sys.iamUsersMap[name]; !ok {
|
||||
return errNoSuchUser
|
||||
if !isGroup {
|
||||
if _, ok := sys.iamUsersMap[name]; !ok {
|
||||
return errNoSuchUser
|
||||
}
|
||||
} else {
|
||||
if _, ok := sys.iamGroupsMap[name]; !ok {
|
||||
return errNoSuchGroup
|
||||
}
|
||||
}
|
||||
|
||||
mp := newMappedPolicy(policy)
|
||||
if err := sys.store.saveMappedPolicy(name, isSTS, isGroup, mp); err != nil {
|
||||
return err
|
||||
}
|
||||
sys.iamUserPolicyMap[name] = mp
|
||||
if !isGroup {
|
||||
sys.iamUserPolicyMap[name] = mp
|
||||
} else {
|
||||
sys.iamGroupPolicyMap[name] = mp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -991,18 +1047,42 @@ func (sys *IAMSys) IsAllowed(args iampolicy.Args) bool {
|
||||
return sys.IsAllowedSTS(args)
|
||||
}
|
||||
|
||||
// Policies don't apply to the owner.
|
||||
if args.IsOwner {
|
||||
return true
|
||||
}
|
||||
|
||||
policies, err := sys.PolicyDBGet(args.AccountName, false)
|
||||
if err != nil {
|
||||
logger.LogIf(context.Background(), err)
|
||||
return false
|
||||
}
|
||||
|
||||
if len(policies) == 0 {
|
||||
// No policy found.
|
||||
return false
|
||||
}
|
||||
|
||||
// Policies were found, evaluate all of them.
|
||||
sys.RLock()
|
||||
defer sys.RUnlock()
|
||||
|
||||
// If policy is available for given user, check the policy.
|
||||
if mp, found := sys.iamUserPolicyMap[args.AccountName]; found {
|
||||
p, ok := sys.iamPolicyDocsMap[mp.Policy]
|
||||
return ok && p.IsAllowed(args)
|
||||
var availablePolicies []iampolicy.Policy
|
||||
for _, pname := range policies {
|
||||
p, found := sys.iamPolicyDocsMap[pname]
|
||||
if found {
|
||||
availablePolicies = append(availablePolicies, p)
|
||||
}
|
||||
}
|
||||
|
||||
// As policy is not available and OPA is not configured,
|
||||
// return the owner value.
|
||||
return args.IsOwner
|
||||
if len(availablePolicies) == 0 {
|
||||
return false
|
||||
}
|
||||
combinedPolicy := availablePolicies[0]
|
||||
for i := 1; i < len(availablePolicies); i++ {
|
||||
combinedPolicy.Statements = append(combinedPolicy.Statements,
|
||||
availablePolicies[i].Statements...)
|
||||
}
|
||||
return combinedPolicy.IsAllowed(args)
|
||||
}
|
||||
|
||||
// Set default canned policies only if not already overridden by users.
|
||||
|
@ -189,6 +189,21 @@ func (sys *NotificationSys) LoadPolicy(policyName string) []NotificationPeerErr
|
||||
return ng.Wait()
|
||||
}
|
||||
|
||||
// LoadPolicyMapping - reloads a policy mapping across all peers
|
||||
func (sys *NotificationSys) LoadPolicyMapping(userOrGroup string, isGroup bool) []NotificationPeerErr {
|
||||
ng := WithNPeers(len(sys.peerClients))
|
||||
for idx, client := range sys.peerClients {
|
||||
if client == nil {
|
||||
continue
|
||||
}
|
||||
client := client
|
||||
ng.Go(context.Background(), func() error {
|
||||
return client.LoadPolicyMapping(userOrGroup, isGroup)
|
||||
}, idx, *client.host)
|
||||
}
|
||||
return ng.Wait()
|
||||
}
|
||||
|
||||
// DeleteUser - deletes a specific user across all peers
|
||||
func (sys *NotificationSys) DeleteUser(accessKey string) []NotificationPeerErr {
|
||||
ng := WithNPeers(len(sys.peerClients))
|
||||
|
@ -406,6 +406,22 @@ func (client *peerRESTClient) LoadPolicy(policyName string) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadPolicyMapping - reload a specific policy mapping
|
||||
func (client *peerRESTClient) LoadPolicyMapping(userOrGroup string, isGroup bool) error {
|
||||
values := make(url.Values)
|
||||
values.Set(peerRESTUserOrGroup, userOrGroup)
|
||||
if isGroup {
|
||||
values.Set(peerRESTIsGroup, "")
|
||||
}
|
||||
|
||||
respBody, err := client.call(peerRESTMethodLoadPolicyMapping, values, nil, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer http.DrainBody(respBody)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteUser - delete a specific user.
|
||||
func (client *peerRESTClient) DeleteUser(accessKey string) (err error) {
|
||||
values := make(url.Values)
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package cmd
|
||||
|
||||
const peerRESTVersion = "v3"
|
||||
const peerRESTVersion = "v4"
|
||||
const peerRESTPath = minioReservedBucketPath + "/peer/" + peerRESTVersion
|
||||
|
||||
const (
|
||||
@ -33,6 +33,7 @@ const (
|
||||
peerRESTMethodLoadUser = "loaduser"
|
||||
peerRESTMethodDeleteUser = "deleteuser"
|
||||
peerRESTMethodLoadPolicy = "loadpolicy"
|
||||
peerRESTMethodLoadPolicyMapping = "loadpolicymapping"
|
||||
peerRESTMethodDeletePolicy = "deletepolicy"
|
||||
peerRESTMethodLoadUsers = "loadusers"
|
||||
peerRESTMethodLoadGroup = "loadgroup"
|
||||
@ -50,14 +51,16 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
peerRESTBucket = "bucket"
|
||||
peerRESTUser = "user"
|
||||
peerRESTGroup = "group"
|
||||
peerRESTUserTemp = "user-temp"
|
||||
peerRESTPolicy = "policy"
|
||||
peerRESTSignal = "signal"
|
||||
peerRESTProfiler = "profiler"
|
||||
peerRESTDryRun = "dry-run"
|
||||
peerRESTTraceAll = "all"
|
||||
peerRESTTraceErr = "err"
|
||||
peerRESTBucket = "bucket"
|
||||
peerRESTUser = "user"
|
||||
peerRESTGroup = "group"
|
||||
peerRESTUserTemp = "user-temp"
|
||||
peerRESTPolicy = "policy"
|
||||
peerRESTUserOrGroup = "user-or-group"
|
||||
peerRESTIsGroup = "is-group"
|
||||
peerRESTSignal = "signal"
|
||||
peerRESTProfiler = "profiler"
|
||||
peerRESTDryRun = "dry-run"
|
||||
peerRESTTraceAll = "all"
|
||||
peerRESTTraceErr = "err"
|
||||
)
|
||||
|
@ -176,6 +176,35 @@ func (s *peerRESTServer) LoadPolicyHandler(w http.ResponseWriter, r *http.Reques
|
||||
w.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
// LoadPolicyMappingHandler - reloads a policy mapping on the server.
|
||||
func (s *peerRESTServer) LoadPolicyMappingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.IsValid(w, r) {
|
||||
s.writeErrorResponse(w, errors.New("Invalid request"))
|
||||
return
|
||||
}
|
||||
|
||||
objAPI := newObjectLayerFn()
|
||||
if objAPI == nil {
|
||||
s.writeErrorResponse(w, errServerNotInitialized)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
userOrGroup := vars[peerRESTUserOrGroup]
|
||||
if userOrGroup == "" {
|
||||
s.writeErrorResponse(w, errors.New("user-or-group is missing"))
|
||||
return
|
||||
}
|
||||
_, isGroup := vars[peerRESTIsGroup]
|
||||
|
||||
if err := globalIAMSys.LoadPolicyMapping(objAPI, userOrGroup, isGroup); err != nil {
|
||||
s.writeErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
// DeleteUserHandler - deletes a user on the server.
|
||||
func (s *peerRESTServer) DeleteUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.IsValid(w, r) {
|
||||
@ -831,6 +860,7 @@ func registerPeerRESTHandlers(router *mux.Router) {
|
||||
|
||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeletePolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadPolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadPolicyMapping).HandlerFunc(httpTraceAll(server.LoadPolicyMappingHandler)).Queries(restQueries(peerRESTUserOrGroup)...)
|
||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeleteUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser)...)
|
||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...)
|
||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadUsers).HandlerFunc(httpTraceAll(server.LoadUsersHandler))
|
||||
|
@ -105,3 +105,32 @@ func (adm *AdminClient) AddCannedPolicy(policyName, policy string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPolicy - sets the policy for a user or a group.
|
||||
func (adm *AdminClient) SetPolicy(policyName, entityName string, isGroup bool) error {
|
||||
queryValues := url.Values{}
|
||||
queryValues.Set("policyName", policyName)
|
||||
queryValues.Set("userOrGroup", entityName)
|
||||
groupStr := "false"
|
||||
if isGroup {
|
||||
groupStr = "true"
|
||||
}
|
||||
queryValues.Set("isGroup", groupStr)
|
||||
|
||||
reqData := requestData{
|
||||
relPath: "/v1/set-user-or-group-policy",
|
||||
queryValues: queryValues,
|
||||
}
|
||||
|
||||
// Execute PUT on /minio/admin/v1/set-user-or-group-policy to set policy.
|
||||
resp, err := adm.executeMethod("PUT", reqData)
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return httpRespToErrorResponse(resp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package madmin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
@ -39,6 +40,7 @@ type UserInfo struct {
|
||||
SecretKey string `json:"secretKey,omitempty"`
|
||||
PolicyName string `json:"policyName,omitempty"`
|
||||
Status AccountStatus `json:"status"`
|
||||
MemberOf []string `json:"memberOf,omitempty"`
|
||||
}
|
||||
|
||||
// RemoveUser - remove a user.
|
||||
@ -97,6 +99,40 @@ func (adm *AdminClient) ListUsers() (map[string]UserInfo, error) {
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// GetUserInfo - get info on a user
|
||||
func (adm *AdminClient) GetUserInfo(name string) (u UserInfo, err error) {
|
||||
queryValues := url.Values{}
|
||||
queryValues.Set("accessKey", name)
|
||||
|
||||
reqData := requestData{
|
||||
relPath: "/v1/user-info",
|
||||
queryValues: queryValues,
|
||||
}
|
||||
|
||||
// Execute GET on /minio/admin/v1/user-info
|
||||
resp, err := adm.executeMethod("GET", reqData)
|
||||
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return u, httpRespToErrorResponse(resp)
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(b, &u); err != nil {
|
||||
return u, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// SetUser - sets a user info.
|
||||
func (adm *AdminClient) SetUser(accessKey, secretKey string, status AccountStatus) error {
|
||||
|
||||
@ -149,32 +185,6 @@ func (adm *AdminClient) AddUser(accessKey, secretKey string) error {
|
||||
return adm.SetUser(accessKey, secretKey, AccountEnabled)
|
||||
}
|
||||
|
||||
// SetUserPolicy - adds a policy for a user.
|
||||
func (adm *AdminClient) SetUserPolicy(accessKey, policyName string) error {
|
||||
queryValues := url.Values{}
|
||||
queryValues.Set("accessKey", accessKey)
|
||||
queryValues.Set("name", policyName)
|
||||
|
||||
reqData := requestData{
|
||||
relPath: "/v1/set-user-policy",
|
||||
queryValues: queryValues,
|
||||
}
|
||||
|
||||
// Execute PUT on /minio/admin/v1/set-user-policy to set policy.
|
||||
resp, err := adm.executeMethod("PUT", reqData)
|
||||
|
||||
defer closeResponse(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return httpRespToErrorResponse(resp)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetUserStatus - adds a status for a user.
|
||||
func (adm *AdminClient) SetUserStatus(accessKey string, status AccountStatus) error {
|
||||
queryValues := url.Values{}
|
||||
|
Loading…
Reference in New Issue
Block a user