| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  |  * MinIO Cloud Storage, (C) 2019-2020 MinIO, Inc. | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/gorilla/mux" | 
					
						
							|  |  |  | 	"github.com/minio/minio/cmd/logger" | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/auth" | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	iampolicy "github.com/minio/minio/pkg/iam/policy" | 
					
						
							|  |  |  | 	"github.com/minio/minio/pkg/madmin" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | func validateAdminUsersReq(ctx context.Context, w http.ResponseWriter, r *http.Request, action iampolicy.AdminAction) (ObjectLayer, auth.Credentials) { | 
					
						
							|  |  |  | 	var cred auth.Credentials | 
					
						
							|  |  |  | 	var adminAPIErr APIErrorCode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerWithoutSafeModeFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 		return nil, cred | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate request signature.
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	cred, adminAPIErr = checkAdminRequestAuthType(ctx, r, action, "") | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if adminAPIErr != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(adminAPIErr), r.URL) | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 		return nil, cred | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	return objectAPI, cred | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // RemoveUser - DELETE /minio/admin/v3/remove-user?accessKey=<access_key>
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) RemoveUser(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "RemoveUser") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.DeleteUserAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars["accessKey"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 	ok, err := globalIAMSys.IsTempUser(accessKey) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ok { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, errIAMActionNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if err := globalIAMSys.DeleteUser(accessKey); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Notify all other MinIO peers to delete user.
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.DeleteUser(accessKey) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // ListUsers - GET /minio/admin/v3/list-users
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) ListUsers(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListUsers") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-24 05:06:00 +08:00
										 |  |  | 	objectAPI, cred := validateAdminUsersReq(ctx, w, r, iampolicy.ListUsersAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-24 05:06:00 +08:00
										 |  |  | 	password := cred.SecretKey | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	allCredentials, err := globalIAMSys.ListUsers() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := json.Marshal(allCredentials) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	econfigData, err := madmin.EncryptData(password, data) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessResponseJSON(w, econfigData) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // GetUserInfo - GET /minio/admin/v3/user-info
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) GetUserInfo(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "GetUserInfo") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.GetUserAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // UpdateGroupMembers - PUT /minio/admin/v3/update-group-members
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) UpdateGroupMembers(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "UpdateGroupMembers") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.AddUserToGroupAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer r.Body.Close() | 
					
						
							|  |  |  | 	data, err := ioutil.ReadAll(r.Body) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var updReq madmin.GroupAddRemove | 
					
						
							|  |  |  | 	err = json.Unmarshal(data, &updReq) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if updReq.IsRemove { | 
					
						
							|  |  |  | 		err = globalIAMSys.RemoveUsersFromGroup(updReq.Group, updReq.Members) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = globalIAMSys.AddUsersToGroup(updReq.Group, updReq.Members) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Notify all other MinIO peers to load group.
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.LoadGroup(updReq.Group) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // GetGroup - /minio/admin/v3/group?group=mygroup1
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) GetGroup(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "GetGroup") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.GetGroupAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	group := vars["group"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gdesc, err := globalIAMSys.GetGroupDescription(group) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	body, err := json.Marshal(gdesc) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessResponseJSON(w, body) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // ListGroups - GET /minio/admin/v3/groups
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) ListGroups(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListGroups") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.ListGroupsAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	groups, err := globalIAMSys.ListGroups() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	body, err := json.Marshal(groups) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessResponseJSON(w, body) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // SetGroupStatus - PUT /minio/admin/v3/set-group-status?group=mygroup1&status=enabled
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) SetGroupStatus(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "SetGroupStatus") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.EnableGroupAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	group := vars["group"] | 
					
						
							|  |  |  | 	status := vars["status"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	if status == statusEnabled { | 
					
						
							|  |  |  | 		err = globalIAMSys.SetGroupStatus(group, true) | 
					
						
							|  |  |  | 	} else if status == statusDisabled { | 
					
						
							|  |  |  | 		err = globalIAMSys.SetGroupStatus(group, false) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Notify all other MinIO peers to reload user.
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.LoadGroup(group) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // SetUserStatus - PUT /minio/admin/v3/set-user-status?accessKey=<access_key>&status=[enabled|disabled]
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) SetUserStatus(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "SetUserStatus") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.EnableUserAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars["accessKey"] | 
					
						
							|  |  |  | 	status := vars["status"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Custom IAM policies not allowed for admin user.
 | 
					
						
							|  |  |  | 	if accessKey == globalActiveCred.AccessKey { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := globalIAMSys.SetUserStatus(accessKey, madmin.AccountStatus(status)); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Notify all other MinIO peers to reload user.
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.LoadUser(accessKey, false) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // AddUser - PUT /minio/admin/v3/add-user?accessKey=<access_key>
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) AddUser(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "AddUser") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, cred := validateAdminUsersReq(ctx, w, r, iampolicy.CreateUserAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars["accessKey"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Custom IAM policies not allowed for admin user.
 | 
					
						
							|  |  |  | 	if accessKey == globalActiveCred.AccessKey { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAddUserInvalidArgument), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if r.ContentLength > maxEConfigJSONSize || r.ContentLength == -1 { | 
					
						
							|  |  |  | 		// More than maxConfigSize bytes were available
 | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminConfigTooLarge), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	password := cred.SecretKey | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	configBytes, err := madmin.DecryptData(password, io.LimitReader(r.Body, r.ContentLength)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminConfigBadJSON), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var uinfo madmin.UserInfo | 
					
						
							|  |  |  | 	if err = json.Unmarshal(configBytes, &uinfo); err != nil { | 
					
						
							|  |  |  | 		logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminConfigBadJSON), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err = globalIAMSys.SetUser(accessKey, uinfo); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Notify all other Minio peers to reload user
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.LoadUser(accessKey, false) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | // AddServiceAccount - PUT /minio/admin/v3/add-service-account
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "AddServiceAccount") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerWithoutSafeModeFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	cred, _, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	password := cred.SecretKey | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	reqBytes, err := madmin.DecryptData(password, io.LimitReader(r.Body, r.ContentLength)) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var createReq madmin.AddServiceAccountReq | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if err = json.Unmarshal(reqBytes, &createReq); err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	// Disallow creating service accounts by root user.
 | 
					
						
							|  |  |  | 	if owner { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminAccountNotEligible), r.URL) | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	newCred, err := globalIAMSys.NewServiceAccount(ctx, cred.AccessKey, createReq.Policy) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	// Notify all other Minio peers to reload user the service account
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.LoadServiceAccount(newCred.AccessKey) { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var createResp = madmin.AddServiceAccountResp{ | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 		Credentials: auth.Credentials{ | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 			AccessKey: newCred.AccessKey, | 
					
						
							|  |  |  | 			SecretKey: newCred.SecretKey, | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := json.Marshal(createResp) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	encryptedData, err := madmin.EncryptData(password, data) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	writeSuccessResponseJSON(w, encryptedData) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ListServiceAccounts - GET /minio/admin/v3/list-service-accounts
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) ListServiceAccounts(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListServiceAccounts") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerWithoutSafeModeFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, _, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Disallow creating service accounts by root user.
 | 
					
						
							|  |  |  | 	if owner { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminAccountNotEligible), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	serviceAccounts, err := globalIAMSys.ListServiceAccounts(ctx, cred.AccessKey) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var listResp = madmin.ListServiceAccountsResp{ | 
					
						
							|  |  |  | 		Accounts: serviceAccounts, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := json.Marshal(listResp) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	encryptedData, err := madmin.EncryptData(cred.SecretKey, data) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessResponseJSON(w, encryptedData) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DeleteServiceAccount - DELETE /minio/admin/v3/delete-service-account
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "DeleteServiceAccount") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerWithoutSafeModeFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, _, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Disallow creating service accounts by root user.
 | 
					
						
							|  |  |  | 	if owner { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminAccountNotEligible), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	serviceAccount := mux.Vars(r)["accessKey"] | 
					
						
							|  |  |  | 	if serviceAccount == "" { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminInvalidArgument), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	user, err := globalIAMSys.GetServiceAccountParent(ctx, serviceAccount) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if cred.AccessKey != user { | 
					
						
							|  |  |  | 		// The service account belongs to another user but return not found error to mitigate brute force attacks.
 | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServiceAccountNotFound), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = globalIAMSys.DeleteServiceAccount(ctx, serviceAccount) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessNoContent(w) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // InfoCannedPolicyV2 - GET /minio/admin/v2/info-canned-policy?name={policyName}
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) InfoCannedPolicyV2(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "InfoCannedPolicyV2") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.GetPolicyAdminAction) | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	policy, err := globalIAMSys.InfoPolicy(mux.Vars(r)["name"]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := json.Marshal(policy) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	w.Write(data) | 
					
						
							|  |  |  | 	w.(http.Flusher).Flush() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // InfoCannedPolicy - GET /minio/admin/v3/info-canned-policy?name={policyName}
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) InfoCannedPolicy(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "InfoCannedPolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.GetPolicyAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 	policy, err := globalIAMSys.InfoPolicy(mux.Vars(r)["name"]) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 	json.NewEncoder(w).Encode(policy) | 
					
						
							|  |  |  | 	w.(http.Flusher).Flush() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ListCannedPoliciesV2 - GET /minio/admin/v2/list-canned-policies
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) ListCannedPoliciesV2(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListCannedPoliciesV2") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.ListUserPoliciesAdminAction) | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	policies, err := globalIAMSys.ListPolicies() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	policyMap := make(map[string][]byte, len(policies)) | 
					
						
							|  |  |  | 	for k, p := range policies { | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		policyMap[k], err = json.Marshal(p) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err = json.NewEncoder(w).Encode(policyMap); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	w.(http.Flusher).Flush() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // ListCannedPolicies - GET /minio/admin/v3/list-canned-policies
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) ListCannedPolicies(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListCannedPolicies") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.ListUserPoliciesAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	policies, err := globalIAMSys.ListPolicies() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-16 03:16:40 +08:00
										 |  |  | 	var newPolicies = make(map[string]iampolicy.Policy) | 
					
						
							|  |  |  | 	for name, p := range policies { | 
					
						
							|  |  |  | 		_, err = json.Marshal(p) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		newPolicies[name] = p | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err = json.NewEncoder(w).Encode(newPolicies); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	w.(http.Flusher).Flush() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // RemoveCannedPolicy - DELETE /minio/admin/v3/remove-canned-policy?name=<policy_name>
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) RemoveCannedPolicy(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "RemoveCannedPolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.DeletePolicyAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	policyName := vars["name"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := globalIAMSys.DeletePolicy(policyName); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Notify all other MinIO peers to delete policy
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.DeletePolicy(policyName) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // AddCannedPolicy - PUT /minio/admin/v3/add-canned-policy?name=<policy_name>
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) AddCannedPolicy(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "AddCannedPolicy") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.CreatePolicyAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	policyName := vars["name"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Error out if Content-Length is missing.
 | 
					
						
							|  |  |  | 	if r.ContentLength <= 0 { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMissingContentLength), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Error out if Content-Length is beyond allowed size.
 | 
					
						
							|  |  |  | 	if r.ContentLength > maxBucketPolicySize { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrEntityTooLarge), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iamPolicy, err := iampolicy.ParseConfig(io.LimitReader(r.Body, r.ContentLength)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-04 03:28:52 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Version in policy must not be empty
 | 
					
						
							|  |  |  | 	if iamPolicy.Version == "" { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMalformedPolicy), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err = globalIAMSys.SetPolicy(policyName, *iamPolicy); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Notify all other MinIO peers to reload policy
 | 
					
						
							|  |  |  | 	for _, nerr := range globalNotificationSys.LoadPolicy(policyName) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // SetPolicyForUserOrGroup - PUT /minio/admin/v3/set-policy?policy=xxx&user-or-group=?[&is-group]
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | func (a adminAPIHandlers) SetPolicyForUserOrGroup(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "SetPolicyForUserOrGroup") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:03:18 +08:00
										 |  |  | 	objectAPI, _ := validateAdminUsersReq(ctx, w, r, iampolicy.AttachPolicyAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	policyName := vars["policyName"] | 
					
						
							|  |  |  | 	entityName := vars["userOrGroup"] | 
					
						
							|  |  |  | 	isGroup := vars["isGroup"] == "true" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Deny if WORM is enabled
 | 
					
						
							|  |  |  | 	if globalWORMEnabled { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 	if !isGroup { | 
					
						
							|  |  |  | 		ok, err := globalIAMSys.IsTempUser(entityName) | 
					
						
							| 
									
										
										
										
											2020-04-09 16:04:08 +08:00
										 |  |  | 		if err != nil && err != errNoSuchUser { | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, errIAMActionNotAllowed), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if err := globalIAMSys.PolicyDBSet(entityName, policyName, isGroup); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 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) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |