| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2021-03-24 08:39:20 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	"io" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2021-02-10 01:53:07 +08:00
										 |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/gorilla/mux" | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 	"github.com/minio/madmin-go" | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	"github.com/minio/minio/internal/auth" | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/config/dns" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2021-05-30 12:16:42 +08:00
										 |  |  | 	iampolicy "github.com/minio/pkg/iam/policy" | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.DeleteUserAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars["accessKey"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-26 05:49:59 +08:00
										 |  |  | 	ok, _, err := globalIAMSys.IsTempUser(accessKey) | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ok { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, errIAMActionNotAllowed), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err := globalIAMSys.DeleteUser(ctx, accessKey); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		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) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 01:15:02 +08:00
										 |  |  | // ListUsers - GET /minio/admin/v3/list-users?bucket={bucket}
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) ListBucketUsers(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListBucketUsers") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, cred := validateAdminReq(ctx, w, r, iampolicy.ListUsersAdminAction) | 
					
						
							| 
									
										
										
										
											2021-05-28 01:15:02 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bucket := mux.Vars(r)["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	password := cred.SecretKey | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	allCredentials, err := globalIAMSys.ListBucketUsers(bucket) | 
					
						
							|  |  |  | 	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
										 |  |  | // 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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, cred := validateAdminReq(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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	name := vars["accessKey"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-16 09:52:01 +08:00
										 |  |  | 	accessKey := cred.ParentUser | 
					
						
							|  |  |  | 	if accessKey == "" { | 
					
						
							|  |  |  | 		accessKey = cred.AccessKey | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// For temporary credentials always
 | 
					
						
							|  |  |  | 	// the temporary credentials to check
 | 
					
						
							|  |  |  | 	// policy without implicit permissions.
 | 
					
						
							|  |  |  | 	if cred.IsTemp() && cred.ParentUser == globalActiveCred.AccessKey { | 
					
						
							|  |  |  | 		accessKey = cred.AccessKey | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	implicitPerm := name == accessKey | 
					
						
							|  |  |  | 	if !implicitPerm { | 
					
						
							|  |  |  | 		if !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							|  |  |  | 			AccountName:     accessKey, | 
					
						
							| 
									
										
										
										
											2021-03-24 06:15:51 +08:00
										 |  |  | 			Groups:          cred.Groups, | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 			Action:          iampolicy.GetUserAdminAction, | 
					
						
							|  |  |  | 			ConditionValues: getConditionValues(r, "", accessKey, claims), | 
					
						
							|  |  |  | 			IsOwner:         owner, | 
					
						
							|  |  |  | 			Claims:          claims, | 
					
						
							|  |  |  | 		}) { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	userInfo, err := globalIAMSys.GetUserInfo(ctx, name) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.AddUserToGroupAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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 { | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 		err = globalIAMSys.RemoveUsersFromGroup(ctx, updReq.Group, updReq.Members) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 		err = globalIAMSys.AddUsersToGroup(ctx, updReq.Group, updReq.Members) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | // 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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.ListGroupsAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	groups, err := globalIAMSys.ListGroups(ctx) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(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 | 
					
						
							| 
									
										
										
										
											2021-11-17 01:28:29 +08:00
										 |  |  | 	switch status { | 
					
						
							|  |  |  | 	case statusEnabled: | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 		err = globalIAMSys.SetGroupStatus(ctx, group, true) | 
					
						
							| 
									
										
										
										
											2021-11-17 01:28:29 +08:00
										 |  |  | 	case statusDisabled: | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 		err = globalIAMSys.SetGroupStatus(ctx, group, false) | 
					
						
							| 
									
										
										
										
											2021-11-17 01:28:29 +08:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		err = errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.EnableUserAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	accessKey := vars["accessKey"] | 
					
						
							|  |  |  | 	status := vars["status"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	// This API is not allowed to lookup accessKey user status
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if accessKey == globalActiveCred.AccessKey { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err := globalIAMSys.SetUserStatus(ctx, accessKey, madmin.AccountStatus(status)); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							| 
									
										
										
										
											2021-04-16 07:32:13 +08:00
										 |  |  | 	accessKey := vars["accessKey"] | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 05:24:21 +08:00
										 |  |  | 	// Not allowed to add a user with same access key as root credential
 | 
					
						
							|  |  |  | 	if owner && accessKey == cred.AccessKey { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAddUserInvalidArgument), r.URL) | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 05:24:21 +08:00
										 |  |  | 	if (cred.IsTemp() || cred.IsServiceAccount()) && cred.ParentUser == accessKey { | 
					
						
							|  |  |  | 		// Incoming access key matches parent user then we should
 | 
					
						
							|  |  |  | 		// reject password change requests.
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAddUserInvalidArgument), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	implicitPerm := accessKey == cred.AccessKey | 
					
						
							|  |  |  | 	if !implicitPerm { | 
					
						
							| 
									
										
										
										
											2020-12-20 05:24:21 +08:00
										 |  |  | 		parentUser := cred.ParentUser | 
					
						
							|  |  |  | 		if parentUser == "" { | 
					
						
							|  |  |  | 			parentUser = cred.AccessKey | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-16 09:52:01 +08:00
										 |  |  | 		// For temporary credentials always
 | 
					
						
							|  |  |  | 		// the temporary credentials to check
 | 
					
						
							|  |  |  | 		// policy without implicit permissions.
 | 
					
						
							|  |  |  | 		if cred.IsTemp() && cred.ParentUser == globalActiveCred.AccessKey { | 
					
						
							|  |  |  | 			parentUser = cred.AccessKey | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 		if !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							| 
									
										
										
										
											2020-12-20 05:24:21 +08:00
										 |  |  | 			AccountName:     parentUser, | 
					
						
							| 
									
										
										
										
											2021-03-24 06:15:51 +08:00
										 |  |  | 			Groups:          cred.Groups, | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 			Action:          iampolicy.CreateUserAdminAction, | 
					
						
							| 
									
										
										
										
											2020-12-20 05:24:21 +08:00
										 |  |  | 			ConditionValues: getConditionValues(r, "", parentUser, claims), | 
					
						
							| 
									
										
										
										
											2021-03-03 09:02:29 +08:00
										 |  |  | 			IsOwner:         owner, | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 			Claims:          claims, | 
					
						
							|  |  |  | 		}) { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 07:35:50 +08:00
										 |  |  | 	if implicitPerm && !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							|  |  |  | 		AccountName:     accessKey, | 
					
						
							| 
									
										
										
										
											2021-03-24 06:15:51 +08:00
										 |  |  | 		Groups:          cred.Groups, | 
					
						
							| 
									
										
										
										
											2021-03-03 07:35:50 +08:00
										 |  |  | 		Action:          iampolicy.CreateUserAdminAction, | 
					
						
							|  |  |  | 		ConditionValues: getConditionValues(r, "", accessKey, claims), | 
					
						
							| 
									
										
										
										
											2021-03-03 09:02:29 +08:00
										 |  |  | 		IsOwner:         owner, | 
					
						
							| 
									
										
										
										
											2021-03-03 07:35:50 +08:00
										 |  |  | 		Claims:          claims, | 
					
						
							|  |  |  | 		DenyOnly:        true, // check if changing password is explicitly denied.
 | 
					
						
							|  |  |  | 	}) { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err = globalIAMSys.CreateUser(ctx, accessKey, uinfo); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	// Get current object layer instance.
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		targetUser   string | 
					
						
							|  |  |  | 		targetGroups []string | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 	// If the request did not set a TargetUser, the service account is
 | 
					
						
							|  |  |  | 	// created for the request sender.
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	targetUser = createReq.TargetUser | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 	if targetUser == "" { | 
					
						
							|  |  |  | 		targetUser = cred.AccessKey | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	opts := newServiceAccountOpts{ | 
					
						
							|  |  |  | 		accessKey: createReq.AccessKey, | 
					
						
							|  |  |  | 		secretKey: createReq.SecretKey, | 
					
						
							| 
									
										
										
										
											2021-10-06 02:49:33 +08:00
										 |  |  | 		claims:    make(map[string]interface{}), | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Find the user for the request sender (as it may be sent via a service
 | 
					
						
							|  |  |  | 	// account or STS account):
 | 
					
						
							|  |  |  | 	requestorUser := cred.AccessKey | 
					
						
							|  |  |  | 	requestorParentUser := cred.AccessKey | 
					
						
							|  |  |  | 	requestorGroups := cred.Groups | 
					
						
							|  |  |  | 	requestorIsDerivedCredential := false | 
					
						
							|  |  |  | 	if cred.IsServiceAccount() || cred.IsTemp() { | 
					
						
							|  |  |  | 		requestorParentUser = cred.ParentUser | 
					
						
							|  |  |  | 		requestorIsDerivedCredential = true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check if we are creating svc account for request sender.
 | 
					
						
							|  |  |  | 	isSvcAccForRequestor := false | 
					
						
							|  |  |  | 	if targetUser == requestorUser || targetUser == requestorParentUser { | 
					
						
							|  |  |  | 		isSvcAccForRequestor = true | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 	// If we are creating svc account for request sender, ensure
 | 
					
						
							|  |  |  | 	// that targetUser is a real user (i.e. not derived
 | 
					
						
							|  |  |  | 	// credentials).
 | 
					
						
							|  |  |  | 	if isSvcAccForRequestor { | 
					
						
							| 
									
										
										
										
											2021-11-15 22:57:52 +08:00
										 |  |  | 		// Check if adding service account is explicitly denied.
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// This allows turning off service accounts for request sender,
 | 
					
						
							|  |  |  | 		// if there is no deny statement this call is implicitly enabled.
 | 
					
						
							|  |  |  | 		if !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							|  |  |  | 			AccountName:     requestorUser, | 
					
						
							| 
									
										
										
										
											2021-12-07 07:55:11 +08:00
										 |  |  | 			Groups:          requestorGroups, | 
					
						
							| 
									
										
										
										
											2021-11-15 22:57:52 +08:00
										 |  |  | 			Action:          iampolicy.CreateServiceAccountAdminAction, | 
					
						
							|  |  |  | 			ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							|  |  |  | 			IsOwner:         owner, | 
					
						
							|  |  |  | 			Claims:          claims, | 
					
						
							|  |  |  | 			DenyOnly:        true, | 
					
						
							|  |  |  | 		}) { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 		if requestorIsDerivedCredential { | 
					
						
							|  |  |  | 			if requestorParentUser == "" { | 
					
						
							|  |  |  | 				writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, | 
					
						
							|  |  |  | 					errors.New("service accounts cannot be generated for temporary credentials without parent")), r.URL) | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			targetUser = requestorParentUser | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		targetGroups = requestorGroups | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-06 02:49:33 +08:00
										 |  |  | 		// In case of LDAP/OIDC we need to set `opts.claims` to ensure
 | 
					
						
							|  |  |  | 		// it is associated with the LDAP/OIDC user properly.
 | 
					
						
							|  |  |  | 		for k, v := range cred.Claims { | 
					
						
							|  |  |  | 			if k == expClaim { | 
					
						
							|  |  |  | 				continue | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-10-06 02:49:33 +08:00
										 |  |  | 			opts.claims[k] = v | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// Need permission if we are creating a service acccount for a
 | 
					
						
							|  |  |  | 		// user <> to the request sender
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 		if !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 			AccountName:     requestorUser, | 
					
						
							| 
									
										
										
										
											2021-12-07 07:55:11 +08:00
										 |  |  | 			Groups:          requestorGroups, | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 			Action:          iampolicy.CreateServiceAccountAdminAction, | 
					
						
							|  |  |  | 			ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							|  |  |  | 			IsOwner:         owner, | 
					
						
							|  |  |  | 			Claims:          claims, | 
					
						
							| 
									
										
										
										
											2021-12-07 07:55:11 +08:00
										 |  |  | 			DenyOnly:        true, | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 		}) { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 		// In case of LDAP we need to resolve the targetUser to a DN and
 | 
					
						
							|  |  |  | 		// query their groups:
 | 
					
						
							|  |  |  | 		if globalLDAPConfig.Enabled { | 
					
						
							| 
									
										
										
										
											2021-10-06 02:49:33 +08:00
										 |  |  | 			opts.claims[ldapUserN] = targetUser // simple username
 | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 			targetUser, targetGroups, err = globalLDAPConfig.LookupUserDN(targetUser) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							| 
									
										
										
										
											2021-04-30 04:01:42 +08:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-10-06 02:49:33 +08:00
										 |  |  | 			opts.claims[ldapUser] = targetUser // username DN
 | 
					
						
							| 
									
										
										
										
											2021-05-13 12:25:07 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// NOTE: if not using LDAP, then internal IDP or open ID is
 | 
					
						
							|  |  |  | 		// being used - in the former, group info is enforced when
 | 
					
						
							|  |  |  | 		// generated credentials are used to make requests, and in the
 | 
					
						
							|  |  |  | 		// latter, a group notion is not supported.
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 	var sp *iampolicy.Policy | 
					
						
							|  |  |  | 	if len(createReq.Policy) > 0 { | 
					
						
							|  |  |  | 		sp, err = iampolicy.ParseConfig(bytes.NewReader(createReq.Policy)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 05:28:19 +08:00
										 |  |  | 	opts.sessionPolicy = sp | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	newCred, err := globalIAMSys.NewServiceAccount(ctx, targetUser, targetGroups, opts) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	// Call hook for cluster-replication.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// FIXME: This wont work in an OpenID situation as the parent credential
 | 
					
						
							|  |  |  | 	// may not be present on peer clusters to provide inherited policies.
 | 
					
						
							|  |  |  | 	// Also, we should not be replicating root user's service account - as
 | 
					
						
							|  |  |  | 	// they are not authenticated by a common external IDP, so we skip when
 | 
					
						
							|  |  |  | 	// opts.ldapUser == "".
 | 
					
						
							|  |  |  | 	if _, isLDAPAccount := opts.claims[ldapUserN]; isLDAPAccount { | 
					
						
							|  |  |  | 		err = globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{ | 
					
						
							|  |  |  | 			Type: madmin.SRIAMItemSvcAcc, | 
					
						
							|  |  |  | 			SvcAccChange: &madmin.SRSvcAccChange{ | 
					
						
							|  |  |  | 				Create: &madmin.SRSvcAccCreate{ | 
					
						
							|  |  |  | 					Parent:        newCred.ParentUser, | 
					
						
							|  |  |  | 					AccessKey:     newCred.AccessKey, | 
					
						
							|  |  |  | 					SecretKey:     newCred.SecretKey, | 
					
						
							|  |  |  | 					Groups:        newCred.Groups, | 
					
						
							|  |  |  | 					Claims:        opts.claims, | 
					
						
							|  |  |  | 					SessionPolicy: createReq.Policy, | 
					
						
							|  |  |  | 					Status:        auth.AccountOn, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	var createResp = madmin.AddServiceAccountResp{ | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 		Credentials: madmin.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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | // UpdateServiceAccount - POST /minio/admin/v3/update-service-account
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) UpdateServiceAccount(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "UpdateServiceAccount") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	accessKey := mux.Vars(r)["accessKey"] | 
					
						
							|  |  |  | 	if accessKey == "" { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	svcAccount, _, err := globalIAMSys.GetServiceAccount(ctx, accessKey) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							|  |  |  | 		AccountName:     cred.AccessKey, | 
					
						
							|  |  |  | 		Action:          iampolicy.UpdateServiceAccountAdminAction, | 
					
						
							|  |  |  | 		ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							|  |  |  | 		IsOwner:         owner, | 
					
						
							|  |  |  | 		Claims:          claims, | 
					
						
							|  |  |  | 	}) { | 
					
						
							|  |  |  | 		requestUser := cred.AccessKey | 
					
						
							|  |  |  | 		if cred.ParentUser != "" { | 
					
						
							|  |  |  | 			requestUser = cred.ParentUser | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if requestUser != svcAccount.ParentUser { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	password := cred.SecretKey | 
					
						
							|  |  |  | 	reqBytes, err := madmin.DecryptData(password, io.LimitReader(r.Body, r.ContentLength)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var updateReq madmin.UpdateServiceAccountReq | 
					
						
							|  |  |  | 	if err = json.Unmarshal(reqBytes, &updateReq); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 	var sp *iampolicy.Policy | 
					
						
							|  |  |  | 	if len(updateReq.NewPolicy) > 0 { | 
					
						
							|  |  |  | 		sp, err = iampolicy.ParseConfig(bytes.NewReader(updateReq.NewPolicy)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	opts := updateServiceAccountOpts{ | 
					
						
							|  |  |  | 		secretKey:     updateReq.NewSecretKey, | 
					
						
							|  |  |  | 		status:        updateReq.NewStatus, | 
					
						
							|  |  |  | 		sessionPolicy: sp, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	err = globalIAMSys.UpdateServiceAccount(ctx, accessKey, opts) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	// Call site replication hook. Only LDAP accounts are supported for
 | 
					
						
							|  |  |  | 	// replication operations.
 | 
					
						
							|  |  |  | 	svcAccClaims, err := globalIAMSys.GetClaimsForSvcAcc(ctx, accessKey) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if _, isLDAPAccount := svcAccClaims[ldapUserN]; isLDAPAccount { | 
					
						
							|  |  |  | 		err = globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{ | 
					
						
							|  |  |  | 			Type: madmin.SRIAMItemSvcAcc, | 
					
						
							|  |  |  | 			SvcAccChange: &madmin.SRSvcAccChange{ | 
					
						
							|  |  |  | 				Update: &madmin.SRSvcAccUpdate{ | 
					
						
							|  |  |  | 					AccessKey:     accessKey, | 
					
						
							|  |  |  | 					SecretKey:     opts.secretKey, | 
					
						
							|  |  |  | 					Status:        opts.status, | 
					
						
							|  |  |  | 					SessionPolicy: updateReq.NewPolicy, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	writeSuccessNoContent(w) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // InfoServiceAccount - GET /minio/admin/v3/info-service-account
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) InfoServiceAccount(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "InfoServiceAccount") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get current object layer instance.
 | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	accessKey := mux.Vars(r)["accessKey"] | 
					
						
							|  |  |  | 	if accessKey == "" { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidRequest), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	svcAccount, policy, err := globalIAMSys.GetServiceAccount(ctx, accessKey) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							|  |  |  | 		AccountName:     cred.AccessKey, | 
					
						
							|  |  |  | 		Action:          iampolicy.ListServiceAccountsAdminAction, | 
					
						
							|  |  |  | 		ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							|  |  |  | 		IsOwner:         owner, | 
					
						
							|  |  |  | 		Claims:          claims, | 
					
						
							|  |  |  | 	}) { | 
					
						
							|  |  |  | 		requestUser := cred.AccessKey | 
					
						
							|  |  |  | 		if cred.ParentUser != "" { | 
					
						
							|  |  |  | 			requestUser = cred.ParentUser | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if requestUser != svcAccount.ParentUser { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var svcAccountPolicy iampolicy.Policy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	impliedPolicy := policy == nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If policy is empty, check for policy of the parent user
 | 
					
						
							|  |  |  | 	if !impliedPolicy { | 
					
						
							| 
									
										
										
										
											2021-04-16 05:47:58 +08:00
										 |  |  | 		svcAccountPolicy = svcAccountPolicy.Merge(*policy) | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2021-04-22 09:12:02 +08:00
										 |  |  | 		policiesNames, err := globalIAMSys.PolicyDBGet(svcAccount.ParentUser, false) | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-04-16 05:47:58 +08:00
										 |  |  | 		svcAccountPolicy = svcAccountPolicy.Merge(globalIAMSys.GetCombinedPolicy(policiesNames...)) | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 00:22:22 +08:00
										 |  |  | 	policyJSON, err := json.MarshalIndent(svcAccountPolicy, "", " ") | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var infoResp = madmin.InfoServiceAccountResp{ | 
					
						
							|  |  |  | 		ParentUser:    svcAccount.ParentUser, | 
					
						
							|  |  |  | 		AccountStatus: svcAccount.Status, | 
					
						
							|  |  |  | 		ImpliedPolicy: impliedPolicy, | 
					
						
							|  |  |  | 		Policy:        string(policyJSON), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := json.Marshal(infoResp) | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | // ListServiceAccounts - GET /minio/admin/v3/list-service-accounts
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) ListServiceAccounts(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListServiceAccounts") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	// Get current object layer instance.
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	var targetAccount string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 04:35:35 +08:00
										 |  |  | 	// If listing is requested for a specific user (who is not the request
 | 
					
						
							|  |  |  | 	// sender), check that the user has permissions.
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	user := r.Form.Get("user") | 
					
						
							| 
									
										
										
										
											2021-11-20 04:35:35 +08:00
										 |  |  | 	if user != "" && user != cred.AccessKey { | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 		if !globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							|  |  |  | 			AccountName:     cred.AccessKey, | 
					
						
							|  |  |  | 			Action:          iampolicy.ListServiceAccountsAdminAction, | 
					
						
							|  |  |  | 			ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							|  |  |  | 			IsOwner:         owner, | 
					
						
							|  |  |  | 			Claims:          claims, | 
					
						
							|  |  |  | 		}) { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		targetAccount = user | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		targetAccount = cred.AccessKey | 
					
						
							|  |  |  | 		if cred.ParentUser != "" { | 
					
						
							|  |  |  | 			targetAccount = cred.ParentUser | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-01 23:05:14 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	serviceAccounts, err := globalIAMSys.ListServiceAccounts(ctx, targetAccount) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	var serviceAccountsNames []string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, svc := range serviceAccounts { | 
					
						
							|  |  |  | 		serviceAccountsNames = append(serviceAccountsNames, svc.AccessKey) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	var listResp = madmin.ListServiceAccountsResp{ | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 		Accounts: serviceAccountsNames, | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	// Get current object layer instance.
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	serviceAccount := mux.Vars(r)["accessKey"] | 
					
						
							|  |  |  | 	if serviceAccount == "" { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminInvalidArgument), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	svcAccount, _, err := globalIAMSys.GetServiceAccount(ctx, serviceAccount) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	adminPrivilege := globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							|  |  |  | 		AccountName:     cred.AccessKey, | 
					
						
							|  |  |  | 		Action:          iampolicy.RemoveServiceAccountAdminAction, | 
					
						
							|  |  |  | 		ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							|  |  |  | 		IsOwner:         owner, | 
					
						
							|  |  |  | 		Claims:          claims, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2020-05-01 23:05:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-15 13:51:14 +08:00
										 |  |  | 	if !adminPrivilege { | 
					
						
							|  |  |  | 		parentUser := cred.AccessKey | 
					
						
							|  |  |  | 		if cred.ParentUser != "" { | 
					
						
							|  |  |  | 			parentUser = cred.ParentUser | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if parentUser != svcAccount.ParentUser { | 
					
						
							|  |  |  | 			// The service account belongs to another user but return not
 | 
					
						
							|  |  |  | 			// found error to mitigate brute force attacks. or the
 | 
					
						
							|  |  |  | 			// serviceAccount doesn't exist.
 | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminServiceAccountNotFound), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-25 07:19:33 +08:00
										 |  |  | 	// Save svc acc claims before deletion (for site replication hook).
 | 
					
						
							|  |  |  | 	svcAccClaims, err := globalIAMSys.GetClaimsForSvcAcc(ctx, serviceAccount) | 
					
						
							|  |  |  | 	if err != nil && err != errNoSuchServiceAccount { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	err = globalIAMSys.DeleteServiceAccount(ctx, serviceAccount) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-15 12:28:53 +08:00
										 |  |  | 	for _, nerr := range globalNotificationSys.DeleteServiceAccount(serviceAccount) { | 
					
						
							|  |  |  | 		if nerr.Err != nil { | 
					
						
							|  |  |  | 			logger.GetReqInfo(ctx).SetTags("peerAddress", nerr.Host.String()) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, nerr.Err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	// Call site replication hook. Only LDAP accounts are supported for
 | 
					
						
							|  |  |  | 	// replication operations.
 | 
					
						
							|  |  |  | 	if _, isLDAPAccount := svcAccClaims[ldapUserN]; isLDAPAccount { | 
					
						
							|  |  |  | 		err = globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{ | 
					
						
							|  |  |  | 			Type: madmin.SRIAMItemSvcAcc, | 
					
						
							|  |  |  | 			SvcAccChange: &madmin.SRSvcAccChange{ | 
					
						
							|  |  |  | 				Delete: &madmin.SRSvcAccDelete{ | 
					
						
							|  |  |  | 					AccessKey: serviceAccount, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	writeSuccessNoContent(w) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | // AccountInfoHandler returns usage
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) AccountInfoHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "AccountInfo") | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Get current object layer instance.
 | 
					
						
							| 
									
										
										
										
											2020-10-10 00:59:52 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if objectAPI == nil || globalNotificationSys == nil { | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, claims, owner, s3Err := validateAdminSignature(ctx, r, "") | 
					
						
							|  |  |  | 	if s3Err != ErrNone { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set prefix value for "s3:prefix" policy conditionals.
 | 
					
						
							|  |  |  | 	r.Header.Set("prefix", "") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set delimiter value for "s3:delimiter" policy conditionals.
 | 
					
						
							|  |  |  | 	r.Header.Set("delimiter", SlashSeparator) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-14 23:51:10 +08:00
										 |  |  | 	// Check if we are asked to return prefix usage
 | 
					
						
							| 
									
										
										
										
											2021-08-08 13:43:01 +08:00
										 |  |  | 	enablePrefixUsage := r.Form.Get("prefix-usage") == "true" | 
					
						
							| 
									
										
										
										
											2021-07-14 23:51:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 	isAllowedAccess := func(bucketName string) (rd, wr bool) { | 
					
						
							|  |  |  | 		if globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							| 
									
										
										
										
											2021-07-12 08:39:52 +08:00
										 |  |  | 			AccountName:     cred.AccessKey, | 
					
						
							| 
									
										
										
										
											2021-03-24 06:15:51 +08:00
										 |  |  | 			Groups:          cred.Groups, | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 			Action:          iampolicy.ListBucketAction, | 
					
						
							|  |  |  | 			BucketName:      bucketName, | 
					
						
							| 
									
										
										
										
											2021-07-12 08:39:52 +08:00
										 |  |  | 			ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 			IsOwner:         owner, | 
					
						
							|  |  |  | 			ObjectName:      "", | 
					
						
							|  |  |  | 			Claims:          claims, | 
					
						
							|  |  |  | 		}) { | 
					
						
							|  |  |  | 			rd = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if globalIAMSys.IsAllowed(iampolicy.Args{ | 
					
						
							| 
									
										
										
										
											2021-07-12 08:39:52 +08:00
										 |  |  | 			AccountName:     cred.AccessKey, | 
					
						
							| 
									
										
										
										
											2021-03-24 06:15:51 +08:00
										 |  |  | 			Groups:          cred.Groups, | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 			Action:          iampolicy.PutObjectAction, | 
					
						
							|  |  |  | 			BucketName:      bucketName, | 
					
						
							| 
									
										
										
										
											2021-07-12 08:39:52 +08:00
										 |  |  | 			ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 			IsOwner:         owner, | 
					
						
							|  |  |  | 			ObjectName:      "", | 
					
						
							|  |  |  | 			Claims:          claims, | 
					
						
							|  |  |  | 		}) { | 
					
						
							|  |  |  | 			wr = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return rd, wr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-19 04:31:35 +08:00
										 |  |  | 	var dataUsageInfo DataUsageInfo | 
					
						
							| 
									
										
										
										
											2021-07-10 01:35:09 +08:00
										 |  |  | 	var err error | 
					
						
							|  |  |  | 	if !globalIsGateway { | 
					
						
							|  |  |  | 		// Load the latest calculated data usage
 | 
					
						
							|  |  |  | 		dataUsageInfo, err = loadDataUsageFromBackend(ctx, objectAPI) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			// log the error, continue with the accounting response
 | 
					
						
							|  |  |  | 			logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 01:53:07 +08:00
										 |  |  | 	// If etcd, dns federation configured list buckets from etcd.
 | 
					
						
							|  |  |  | 	var buckets []BucketInfo | 
					
						
							|  |  |  | 	if globalDNSConfig != nil && globalBucketFederation { | 
					
						
							|  |  |  | 		dnsBuckets, err := globalDNSConfig.List() | 
					
						
							|  |  |  | 		if err != nil && !IsErrIgnored(err, | 
					
						
							|  |  |  | 			dns.ErrNoEntriesFound, | 
					
						
							|  |  |  | 			dns.ErrDomainMissing) { | 
					
						
							| 
									
										
										
										
											2021-06-16 09:52:01 +08:00
										 |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							| 
									
										
										
										
											2021-02-10 01:53:07 +08:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, dnsRecords := range dnsBuckets { | 
					
						
							|  |  |  | 			buckets = append(buckets, BucketInfo{ | 
					
						
							|  |  |  | 				Name:    dnsRecords[0].Key, | 
					
						
							|  |  |  | 				Created: dnsRecords[0].CreationDate, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		sort.Slice(buckets, func(i, j int) bool { | 
					
						
							|  |  |  | 			return buckets[i].Name < buckets[j].Name | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		buckets, err = objectAPI.ListBuckets(ctx) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 	accountName := cred.AccessKey | 
					
						
							| 
									
										
										
										
											2021-03-24 08:39:20 +08:00
										 |  |  | 	var policies []string | 
					
						
							|  |  |  | 	switch globalIAMSys.usersSysType { | 
					
						
							|  |  |  | 	case MinIOUsersSysType: | 
					
						
							|  |  |  | 		policies, err = globalIAMSys.PolicyDBGet(accountName, false) | 
					
						
							|  |  |  | 	case LDAPUsersSysType: | 
					
						
							| 
									
										
										
										
											2021-03-25 15:38:15 +08:00
										 |  |  | 		parentUser := accountName | 
					
						
							|  |  |  | 		if cred.ParentUser != "" { | 
					
						
							|  |  |  | 			parentUser = cred.ParentUser | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		policies, err = globalIAMSys.PolicyDBGet(parentUser, false, cred.Groups...) | 
					
						
							| 
									
										
										
										
											2021-03-24 08:39:20 +08:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2021-04-30 04:01:42 +08:00
										 |  |  | 		err = errors.New("should never happen") | 
					
						
							| 
									
										
										
										
											2021-03-24 08:39:20 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 00:22:22 +08:00
										 |  |  | 	buf, err := json.MarshalIndent(globalIAMSys.GetCombinedPolicy(policies...), "", " ") | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	acctInfo := madmin.AccountInfo{ | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 		AccountName: accountName, | 
					
						
							| 
									
										
										
										
											2021-07-17 05:37:06 +08:00
										 |  |  | 		Server:      objectAPI.BackendInfo(), | 
					
						
							| 
									
										
										
										
											2021-05-06 23:52:02 +08:00
										 |  |  | 		Policy:      buf, | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, bucket := range buckets { | 
					
						
							|  |  |  | 		rd, wr := isAllowedAccess(bucket.Name) | 
					
						
							|  |  |  | 		if rd || wr { | 
					
						
							|  |  |  | 			// Fetch the data usage of the current bucket
 | 
					
						
							| 
									
										
										
										
											2021-07-14 23:51:10 +08:00
										 |  |  | 			var size uint64 | 
					
						
							| 
									
										
										
										
											2021-09-18 06:02:21 +08:00
										 |  |  | 			var objectsCount uint64 | 
					
						
							|  |  |  | 			var objectsHist map[string]uint64 | 
					
						
							| 
									
										
										
										
											2020-05-27 21:45:43 +08:00
										 |  |  | 			if !dataUsageInfo.LastUpdate.IsZero() { | 
					
						
							|  |  |  | 				size = dataUsageInfo.BucketsUsage[bucket.Name].Size | 
					
						
							| 
									
										
										
										
											2021-09-18 06:02:21 +08:00
										 |  |  | 				objectsCount = dataUsageInfo.BucketsUsage[bucket.Name].ObjectsCount | 
					
						
							|  |  |  | 				objectsHist = dataUsageInfo.BucketsUsage[bucket.Name].ObjectSizesHistogram | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-07-14 23:51:10 +08:00
										 |  |  | 			// Fetch the prefix usage of the current bucket
 | 
					
						
							|  |  |  | 			var prefixUsage map[string]uint64 | 
					
						
							|  |  |  | 			if enablePrefixUsage { | 
					
						
							|  |  |  | 				if pu, err := loadPrefixUsageFromBackend(ctx, objectAPI, bucket.Name); err == nil { | 
					
						
							|  |  |  | 					prefixUsage = pu | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-09-18 06:02:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			lcfg, _ := globalBucketObjectLockSys.Get(bucket.Name) | 
					
						
							|  |  |  | 			quota, _ := globalBucketQuotaSys.Get(bucket.Name) | 
					
						
							|  |  |  | 			rcfg, _ := globalBucketMetadataSys.GetReplicationConfig(ctx, bucket.Name) | 
					
						
							|  |  |  | 			tcfg, _ := globalBucketMetadataSys.GetTaggingConfig(bucket.Name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-04 00:03:42 +08:00
										 |  |  | 			acctInfo.Buckets = append(acctInfo.Buckets, madmin.BucketAccessInfo{ | 
					
						
							| 
									
										
										
										
											2021-09-18 06:02:21 +08:00
										 |  |  | 				Name:                 bucket.Name, | 
					
						
							|  |  |  | 				Created:              bucket.Created, | 
					
						
							|  |  |  | 				Size:                 size, | 
					
						
							|  |  |  | 				Objects:              objectsCount, | 
					
						
							|  |  |  | 				ObjectSizesHistogram: objectsHist, | 
					
						
							|  |  |  | 				PrefixUsage:          prefixUsage, | 
					
						
							|  |  |  | 				Details: &madmin.BucketDetails{ | 
					
						
							|  |  |  | 					Versioning:          globalBucketVersioningSys.Enabled(bucket.Name), | 
					
						
							|  |  |  | 					VersioningSuspended: globalBucketVersioningSys.Suspended(bucket.Name), | 
					
						
							|  |  |  | 					Replication:         rcfg != nil, | 
					
						
							|  |  |  | 					Locking:             lcfg.LockEnabled, | 
					
						
							|  |  |  | 					Quota:               quota, | 
					
						
							|  |  |  | 					Tagging:             tcfg, | 
					
						
							|  |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2020-05-16 09:16:45 +08:00
										 |  |  | 				Access: madmin.AccountAccess{ | 
					
						
							|  |  |  | 					Read:  rd, | 
					
						
							|  |  |  | 					Write: wr, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	usageInfoJSON, err := json.Marshal(acctInfo) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessResponseJSON(w, usageInfoJSON) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | // 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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 00:22:22 +08:00
										 |  |  | 	buf, err := json.MarshalIndent(policy, "", " ") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-09-28 01:24:04 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-30 00:22:22 +08:00
										 |  |  | 	w.Write(buf) | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 01:15:02 +08:00
										 |  |  | // ListBucketPolicies - GET /minio/admin/v3/list-canned-policies?bucket={bucket}
 | 
					
						
							|  |  |  | func (a adminAPIHandlers) ListBucketPolicies(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 	ctx := newContext(r, w, "ListBucketPolicies") | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.ListUserPoliciesAdminAction) | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 01:15:02 +08:00
										 |  |  | 	bucket := mux.Vars(r)["bucket"] | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	policies, err := globalIAMSys.ListPolicies(ctx, bucket) | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-28 01:15:02 +08:00
										 |  |  | 	var newPolicies = make(map[string]iampolicy.Policy) | 
					
						
							|  |  |  | 	for name, p := range policies { | 
					
						
							|  |  |  | 		_, err = json.Marshal(p) | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-05-28 01:15:02 +08:00
										 |  |  | 		newPolicies[name] = p | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-28 01:15:02 +08:00
										 |  |  | 	if err = json.NewEncoder(w).Encode(newPolicies); err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.ListUserPoliciesAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	policies, err := globalIAMSys.ListPolicies(ctx, "") | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.DeletePolicyAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	policyName := vars["name"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-30 06:38:57 +08:00
										 |  |  | 	if err := globalIAMSys.DeletePolicy(ctx, policyName, true); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	// Call cluster-replication policy creation hook to replicate policy deletion to
 | 
					
						
							|  |  |  | 	// other minio clusters.
 | 
					
						
							|  |  |  | 	if err := globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{ | 
					
						
							|  |  |  | 		Type: madmin.SRIAMItemPolicy, | 
					
						
							|  |  |  | 		Name: policyName, | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(ctx, w, r, iampolicy.CreatePolicyAdminAction) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	policyName := vars["name"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	iamPolicyBytes, err := ioutil.ReadAll(io.LimitReader(r.Body, r.ContentLength)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iamPolicy, err := iampolicy.ParseConfig(bytes.NewReader(iamPolicyBytes)) | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 	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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err = globalIAMSys.SetPolicy(ctx, policyName, *iamPolicy); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	// Call cluster-replication policy creation hook to replicate policy to
 | 
					
						
							|  |  |  | 	// other minio clusters.
 | 
					
						
							|  |  |  | 	if err := globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{ | 
					
						
							|  |  |  | 		Type:   madmin.SRIAMItemPolicy, | 
					
						
							|  |  |  | 		Name:   policyName, | 
					
						
							|  |  |  | 		Policy: iamPolicyBytes, | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 05:21:51 +08:00
										 |  |  | 	defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r)) | 
					
						
							| 
									
										
										
										
											2020-05-12 01:34:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:14:38 +08:00
										 |  |  | 	objectAPI, _ := validateAdminReq(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" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 	if !isGroup { | 
					
						
							| 
									
										
										
										
											2021-02-26 05:49:59 +08:00
										 |  |  | 		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 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 06:14:22 +08:00
										 |  |  | 	if err := globalIAMSys.PolicyDBSet(ctx, entityName, policyName, isGroup); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-07 07:36:31 +08:00
										 |  |  | 	if err := globalSiteReplicationSys.IAMChangeHook(ctx, madmin.SRIAMItem{ | 
					
						
							|  |  |  | 		Type: madmin.SRIAMItemPolicyMapping, | 
					
						
							|  |  |  | 		PolicyMapping: &madmin.SRPolicyMapping{ | 
					
						
							|  |  |  | 			UserOrGroup: entityName, | 
					
						
							|  |  |  | 			IsGroup:     isGroup, | 
					
						
							|  |  |  | 			Policy:      policyName, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							|  |  |  | 		writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | } |