diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 746c16dd5..1d111c6be 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -777,6 +777,47 @@ func (a adminAPIHandlers) ListUsers(w http.ResponseWriter, r *http.Request) { writeSuccessResponseJSON(w, econfigData) } +// SetUserStatus - PUT /minio/admin/v1/set-user-status?accessKey=&status=[enabled|disabled] +func (a adminAPIHandlers) SetUserStatus(w http.ResponseWriter, r *http.Request) { + ctx := newContext(r, w, "SetUserStatus") + + // Get current object layer instance. + objectAPI := newObjectLayerFn() + if objectAPI == nil { + writeErrorResponseJSON(w, ErrServerNotInitialized, r.URL) + return + } + + // Validate request signature. + adminAPIErr := checkAdminRequestAuthType(r, "") + if adminAPIErr != ErrNone { + writeErrorResponseJSON(w, adminAPIErr, r.URL) + return + } + + // Deny if WORM is enabled + if globalWORMEnabled { + writeErrorResponseJSON(w, ErrMethodNotAllowed, r.URL) + return + } + + vars := mux.Vars(r) + accessKey := vars["accessKey"] + status := vars["status"] + + // Custom IAM policies not allowed for admin user. + if accessKey == globalServerConfig.GetCredential().AccessKey { + writeErrorResponse(w, ErrInvalidRequest, r.URL) + return + } + + if err := globalIAMSys.SetUserStatus(accessKey, madmin.AccountStatus(status)); err != nil { + logger.LogIf(ctx, err) + writeErrorResponseJSON(w, toAdminAPIErrCode(err), r.URL) + return + } +} + // AddUser - PUT /minio/admin/v1/add-user?accessKey= func (a adminAPIHandlers) AddUser(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "AddUser") diff --git a/cmd/admin-router.go b/cmd/admin-router.go index f9cb38190..7cd505d12 100644 --- a/cmd/admin-router.go +++ b/cmd/admin-router.go @@ -88,6 +88,8 @@ func registerAdminRouter(router *mux.Router) { 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:.*}") diff --git a/cmd/iam.go b/cmd/iam.go index 066f8a868..f6a8246c9 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -320,6 +320,55 @@ func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { return users, nil } +// SetUserStatus - sets current user status, supports disabled or enabled. +func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error { + objectAPI := newObjectLayerFn() + if objectAPI == nil { + return errServerNotInitialized + } + + if status != madmin.AccountEnabled && status != madmin.AccountDisabled { + return errInvalidArgument + } + + sys.Lock() + defer sys.Unlock() + + cred, ok := sys.iamUsersMap[accessKey] + if !ok { + return errNoSuchUser + } + + uinfo := madmin.UserInfo{ + SecretKey: cred.SecretKey, + Status: status, + } + + configFile := pathJoin(iamConfigUsersPrefix, accessKey, iamIdentityFile) + data, err := json.Marshal(uinfo) + if err != nil { + return err + } + + if globalEtcdClient != nil { + err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) + } else { + err = saveConfig(context.Background(), objectAPI, configFile, data) + } + + if err != nil { + return err + } + + sys.iamUsersMap[accessKey] = auth.Credentials{ + AccessKey: accessKey, + SecretKey: uinfo.SecretKey, + Status: string(uinfo.Status), + } + + return nil +} + // SetUser - set user credentials. func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { objectAPI := newObjectLayerFn() diff --git a/pkg/madmin/user-commands.go b/pkg/madmin/user-commands.go index e0337b709..a413f7d69 100644 --- a/pkg/madmin/user-commands.go +++ b/pkg/madmin/user-commands.go @@ -163,3 +163,29 @@ func (adm *AdminClient) SetUserPolicy(accessKey, policyName string) error { return nil } + +// SetUserStatus - adds a status for a user. +func (adm *AdminClient) SetUserStatus(accessKey string, status AccountStatus) error { + queryValues := url.Values{} + queryValues.Set("accessKey", accessKey) + queryValues.Set("status", string(status)) + + reqData := requestData{ + relPath: "/v1/set-user-status", + queryValues: queryValues, + } + + // Execute PUT on /minio/admin/v1/set-user-status to set status. + resp, err := adm.executeMethod("PUT", reqData) + + defer closeResponse(resp) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + return httpRespToErrorResponse(resp) + } + + return nil +}