| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  |  * MinIO Cloud Storage, (C) 2018-2019 MinIO, Inc. | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	"encoding/base64" | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	"math/rand" | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 04:08:40 +08:00
										 |  |  | 	humanize "github.com/dustin/go-humanize" | 
					
						
							| 
									
										
										
										
											2020-07-15 00:38:05 +08:00
										 |  |  | 	"github.com/minio/minio-go/v7/pkg/set" | 
					
						
							| 
									
										
										
										
											2019-11-14 09:38:05 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/config" | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/logger" | 
					
						
							|  |  |  | 	"github.com/minio/minio/pkg/auth" | 
					
						
							| 
									
										
										
										
											2019-02-28 09:46:55 +08:00
										 |  |  | 	iampolicy "github.com/minio/minio/pkg/iam/policy" | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/madmin" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | // UsersSysType - defines the type of users and groups system that is
 | 
					
						
							|  |  |  | // active on the server.
 | 
					
						
							|  |  |  | type UsersSysType string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Types of users configured in the server.
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	// This mode uses the internal users system in MinIO.
 | 
					
						
							|  |  |  | 	MinIOUsersSysType UsersSysType = "MinIOUsersSys" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// This mode uses users and groups from a configured LDAP
 | 
					
						
							|  |  |  | 	// server.
 | 
					
						
							|  |  |  | 	LDAPUsersSysType UsersSysType = "LDAPUsersSys" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	// IAM configuration directory.
 | 
					
						
							|  |  |  | 	iamConfigPrefix = minioConfigPrefix + "/iam" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// IAM users directory.
 | 
					
						
							|  |  |  | 	iamConfigUsersPrefix = iamConfigPrefix + "/users/" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	// IAM service accounts directory.
 | 
					
						
							|  |  |  | 	iamConfigServiceAccountsPrefix = iamConfigPrefix + "/service-accounts/" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	// IAM groups directory.
 | 
					
						
							|  |  |  | 	iamConfigGroupsPrefix = iamConfigPrefix + "/groups/" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	// IAM policies directory.
 | 
					
						
							|  |  |  | 	iamConfigPoliciesPrefix = iamConfigPrefix + "/policies/" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	// IAM sts directory.
 | 
					
						
							|  |  |  | 	iamConfigSTSPrefix = iamConfigPrefix + "/sts/" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	// IAM Policy DB prefixes.
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	iamConfigPolicyDBPrefix                = iamConfigPrefix + "/policydb/" | 
					
						
							|  |  |  | 	iamConfigPolicyDBUsersPrefix           = iamConfigPolicyDBPrefix + "users/" | 
					
						
							|  |  |  | 	iamConfigPolicyDBSTSUsersPrefix        = iamConfigPolicyDBPrefix + "sts-users/" | 
					
						
							|  |  |  | 	iamConfigPolicyDBServiceAccountsPrefix = iamConfigPolicyDBPrefix + "service-accounts/" | 
					
						
							|  |  |  | 	iamConfigPolicyDBGroupsPrefix          = iamConfigPolicyDBPrefix + "groups/" | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	// IAM identity file which captures identity credentials.
 | 
					
						
							|  |  |  | 	iamIdentityFile = "identity.json" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// IAM policy file which provides policies for each users.
 | 
					
						
							|  |  |  | 	iamPolicyFile = "policy.json" | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	// IAM group members file
 | 
					
						
							|  |  |  | 	iamGroupMembersFile = "members.json" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	// IAM format file
 | 
					
						
							|  |  |  | 	iamFormatFile = "format.json" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iamFormatVersion1 = 1 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	statusEnabled  = "enabled" | 
					
						
							|  |  |  | 	statusDisabled = "disabled" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | type iamFormat struct { | 
					
						
							|  |  |  | 	Version int `json:"version"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | func newIAMFormatVersion1() iamFormat { | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	return iamFormat{Version: iamFormatVersion1} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func getIAMFormatFilePath() string { | 
					
						
							| 
									
										
										
										
											2019-08-07 03:08:58 +08:00
										 |  |  | 	return iamConfigPrefix + SlashSeparator + iamFormatFile | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | func getUserIdentityPath(user string, userType IAMUserType) string { | 
					
						
							|  |  |  | 	var basePath string | 
					
						
							|  |  |  | 	switch userType { | 
					
						
							|  |  |  | 	case srvAccUser: | 
					
						
							|  |  |  | 		basePath = iamConfigServiceAccountsPrefix | 
					
						
							|  |  |  | 	case stsUser: | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 		basePath = iamConfigSTSPrefix | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		basePath = iamConfigUsersPrefix | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return pathJoin(basePath, user, iamIdentityFile) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | func getGroupInfoPath(group string) string { | 
					
						
							|  |  |  | 	return pathJoin(iamConfigGroupsPrefix, group, iamGroupMembersFile) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | func getPolicyDocPath(name string) string { | 
					
						
							|  |  |  | 	return pathJoin(iamConfigPoliciesPrefix, name, iamPolicyFile) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | func getMappedPolicyPath(name string, userType IAMUserType, isGroup bool) string { | 
					
						
							|  |  |  | 	if isGroup { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return pathJoin(iamConfigPolicyDBGroupsPrefix, name+".json") | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	switch userType { | 
					
						
							|  |  |  | 	case srvAccUser: | 
					
						
							|  |  |  | 		return pathJoin(iamConfigPolicyDBServiceAccountsPrefix, name+".json") | 
					
						
							|  |  |  | 	case stsUser: | 
					
						
							|  |  |  | 		return pathJoin(iamConfigPolicyDBSTSUsersPrefix, name+".json") | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		return pathJoin(iamConfigPolicyDBUsersPrefix, name+".json") | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // UserIdentity represents a user's secret key and their status
 | 
					
						
							|  |  |  | type UserIdentity struct { | 
					
						
							|  |  |  | 	Version     int              `json:"version"` | 
					
						
							|  |  |  | 	Credentials auth.Credentials `json:"credentials"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | func newUserIdentity(cred auth.Credentials) UserIdentity { | 
					
						
							|  |  |  | 	return UserIdentity{Version: 1, Credentials: cred} | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | // GroupInfo contains info about a group
 | 
					
						
							|  |  |  | type GroupInfo struct { | 
					
						
							|  |  |  | 	Version int      `json:"version"` | 
					
						
							|  |  |  | 	Status  string   `json:"status"` | 
					
						
							|  |  |  | 	Members []string `json:"members"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newGroupInfo(members []string) GroupInfo { | 
					
						
							|  |  |  | 	return GroupInfo{Version: 1, Status: statusEnabled, Members: members} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MappedPolicy represents a policy name mapped to a user or group
 | 
					
						
							|  |  |  | type MappedPolicy struct { | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	Version  int    `json:"version"` | 
					
						
							|  |  |  | 	Policies string `json:"policy"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // converts a mapped policy into a slice of distinct policies
 | 
					
						
							|  |  |  | func (mp MappedPolicy) toSlice() []string { | 
					
						
							|  |  |  | 	var policies []string | 
					
						
							|  |  |  | 	for _, policy := range strings.Split(mp.Policies, ",") { | 
					
						
							|  |  |  | 		policy = strings.TrimSpace(policy) | 
					
						
							|  |  |  | 		if policy == "" { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		policies = append(policies, policy) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return policies | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | func (mp MappedPolicy) policySet() set.StringSet { | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	var policies []string | 
					
						
							|  |  |  | 	for _, policy := range strings.Split(mp.Policies, ",") { | 
					
						
							|  |  |  | 		policy = strings.TrimSpace(policy) | 
					
						
							|  |  |  | 		if policy == "" { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		policies = append(policies, policy) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return set.CreateStringSet(policies...) | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | func newMappedPolicy(policy string) MappedPolicy { | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	return MappedPolicy{Version: 1, Policies: policy} | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // IAMSys - config system.
 | 
					
						
							|  |  |  | type IAMSys struct { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	sync.Mutex | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	usersSysType UsersSysType | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	// map of policy names to policy definitions
 | 
					
						
							|  |  |  | 	iamPolicyDocsMap map[string]iampolicy.Policy | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	// map of usernames to credentials
 | 
					
						
							|  |  |  | 	iamUsersMap map[string]auth.Credentials | 
					
						
							|  |  |  | 	// map of group names to group info
 | 
					
						
							|  |  |  | 	iamGroupsMap map[string]GroupInfo | 
					
						
							|  |  |  | 	// map of user names to groups they are a member of
 | 
					
						
							|  |  |  | 	iamUserGroupMemberships map[string]set.StringSet | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	// map of usernames/temporary access keys to policy names
 | 
					
						
							|  |  |  | 	iamUserPolicyMap map[string]MappedPolicy | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	// map of group names to policy names
 | 
					
						
							|  |  |  | 	iamGroupPolicyMap map[string]MappedPolicy | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	// Persistence layer for IAM subsystem
 | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 	store         IAMStorageAPI | 
					
						
							|  |  |  | 	storeFallback bool | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | // IAMUserType represents a user type inside MinIO server
 | 
					
						
							|  |  |  | type IAMUserType int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	regularUser IAMUserType = iota | 
					
						
							|  |  |  | 	stsUser | 
					
						
							|  |  |  | 	srvAccUser | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | // key options
 | 
					
						
							|  |  |  | type options struct { | 
					
						
							|  |  |  | 	ttl int64 //expiry in seconds
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | // IAMStorageAPI defines an interface for the IAM persistence layer
 | 
					
						
							|  |  |  | type IAMStorageAPI interface { | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	lock() | 
					
						
							|  |  |  | 	unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rlock() | 
					
						
							|  |  |  | 	runlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	migrateBackendFormat(context.Context) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	loadUser(ctx context.Context, user string, userType IAMUserType, m map[string]auth.Credentials) error | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	loadUsers(ctx context.Context, userType IAMUserType, m map[string]auth.Credentials) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	loadGroup(ctx context.Context, group string, m map[string]GroupInfo) error | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	loadGroups(ctx context.Context, m map[string]GroupInfo) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	loadMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	loadAll(context.Context, *IAMSys) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | 	saveIAMConfig(ctx context.Context, item interface{}, path string, opts ...options) error | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	loadIAMConfig(ctx context.Context, item interface{}, path string) error | 
					
						
							|  |  |  | 	deleteIAMConfig(ctx context.Context, path string) error | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | 	saveMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, mp MappedPolicy, opts ...options) error | 
					
						
							|  |  |  | 	saveUserIdentity(ctx context.Context, name string, userType IAMUserType, u UserIdentity, opts ...options) error | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	saveGroupInfo(ctx context.Context, group string, gi GroupInfo) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	deletePolicyDoc(ctx context.Context, policyName string) error | 
					
						
							|  |  |  | 	deleteMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool) error | 
					
						
							|  |  |  | 	deleteUserIdentity(ctx context.Context, name string, userType IAMUserType) error | 
					
						
							|  |  |  | 	deleteGroupInfo(ctx context.Context, name string) error | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	watch(context.Context, *IAMSys) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | // LoadGroup - loads a specific group from storage, and updates the
 | 
					
						
							|  |  |  | // memberships cache. If the specified group does not exist in
 | 
					
						
							|  |  |  | // storage, it is removed from in-memory maps as well - this
 | 
					
						
							|  |  |  | // simplifies the implementation for group removal. This is called
 | 
					
						
							|  |  |  | // only via IAM notifications.
 | 
					
						
							|  |  |  | func (sys *IAMSys) LoadGroup(objAPI ObjectLayer, group string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-12-11 12:28:22 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							|  |  |  | 		// Watch APIs cover this case, so nothing to do.
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := sys.store.loadGroup(context.Background(), group, sys.iamGroupsMap) | 
					
						
							| 
									
										
										
										
											2020-05-10 04:59:12 +08:00
										 |  |  | 	if err != nil && err != errNoSuchGroup { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-10 04:59:12 +08:00
										 |  |  | 	if err == errNoSuchGroup { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		// group does not exist - so remove from memory.
 | 
					
						
							|  |  |  | 		sys.removeGroupFromMembershipsMap(group) | 
					
						
							|  |  |  | 		delete(sys.iamGroupsMap, group) | 
					
						
							|  |  |  | 		delete(sys.iamGroupPolicyMap, group) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gi := sys.iamGroupsMap[group] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Updating the group memberships cache happens in two steps:
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 1. Remove the group from each user's list of memberships.
 | 
					
						
							|  |  |  | 	// 2. Add the group to each member's list of memberships.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// This ensures that regardless of members being added or
 | 
					
						
							|  |  |  | 	// removed, the cache stays current.
 | 
					
						
							|  |  |  | 	sys.removeGroupFromMembershipsMap(group) | 
					
						
							|  |  |  | 	sys.updateGroupMembershipsMap(group, &gi) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // LoadPolicy - reloads a specific canned policy from backend disks or etcd.
 | 
					
						
							|  |  |  | func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-12-11 12:28:22 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	if globalEtcdClient == nil { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		return sys.store.loadPolicyDoc(context.Background(), policyName, sys.iamPolicyDocsMap) | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// When etcd is set, we use watch APIs so this code is not needed.
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | // LoadPolicyMapping - loads the mapped policy for a user or group
 | 
					
						
							|  |  |  | // from storage into server memory.
 | 
					
						
							|  |  |  | func (sys *IAMSys) LoadPolicyMapping(objAPI ObjectLayer, userOrGroup string, isGroup bool) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-12-11 12:28:22 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	if globalEtcdClient == nil { | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		if isGroup { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 			err = sys.store.loadMappedPolicy(context.Background(), userOrGroup, regularUser, isGroup, sys.iamGroupPolicyMap) | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 			err = sys.store.loadMappedPolicy(context.Background(), userOrGroup, regularUser, isGroup, sys.iamUserPolicyMap) | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Ignore policy not mapped error
 | 
					
						
							| 
									
										
										
										
											2020-05-10 04:59:12 +08:00
										 |  |  | 		if err != nil && err != errNoSuchPolicy { | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// When etcd is set, we use watch APIs so this code is not needed.
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // LoadUser - reloads a specific user from backend disks or etcd.
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, userType IAMUserType) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-12-11 12:28:22 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	if globalEtcdClient == nil { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		err := sys.store.loadUser(context.Background(), accessKey, userType, sys.iamUsersMap) | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		err = sys.store.loadMappedPolicy(context.Background(), accessKey, userType, false, sys.iamUserPolicyMap) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		// Ignore policy not mapped error
 | 
					
						
							| 
									
										
										
										
											2020-05-10 04:59:12 +08:00
										 |  |  | 		if err != nil && err != errNoSuchPolicy { | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// When etcd is set, we use watch APIs so this code is not needed.
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | // LoadServiceAccount - reloads a specific service account from backend disks or etcd.
 | 
					
						
							|  |  |  | func (sys *IAMSys) LoadServiceAccount(accessKey string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if globalEtcdClient == nil { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		err := sys.store.loadUser(context.Background(), accessKey, srvAccUser, sys.iamUsersMap) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// When etcd is set, we use watch APIs so this code is not needed.
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | // Perform IAM configuration migration.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (sys *IAMSys) doIAMConfigMigration(ctx context.Context) error { | 
					
						
							|  |  |  | 	return sys.store.migrateBackendFormat(ctx) | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | // InitStore initializes IAM stores
 | 
					
						
							|  |  |  | func (sys *IAMSys) InitStore(objAPI ObjectLayer) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	if globalEtcdClient == nil { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		sys.store = newIAMObjectStore(objAPI) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		sys.store = newIAMEtcdStore() | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if globalLDAPConfig.Enabled { | 
					
						
							|  |  |  | 		sys.EnableLDAPSys() | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | // Initialized check if IAM is initialized
 | 
					
						
							|  |  |  | func (sys *IAMSys) Initialized() bool { | 
					
						
							|  |  |  | 	if sys == nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 	return sys.store != nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | // Init - initializes config system by reading entries from config/iam
 | 
					
						
							|  |  |  | func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer) { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 	retryCtx, cancel := context.WithCancel(ctx) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Indicate to our routine to exit cleanly upon return.
 | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Hold the lock for migration only.
 | 
					
						
							| 
									
										
										
										
											2020-11-05 00:25:42 +08:00
										 |  |  | 	txnLk := objAPI.NewNSLock(minioMetaBucket, minioConfigPrefix+"/iam.lock") | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Initializing IAM sub-system needs a retry mechanism for
 | 
					
						
							|  |  |  | 	// the following reasons:
 | 
					
						
							|  |  |  | 	//  - Read quorum is lost just after the initialization
 | 
					
						
							|  |  |  | 	//    of the object layer.
 | 
					
						
							|  |  |  | 	//  - Write quorum not met when upgrading configuration
 | 
					
						
							|  |  |  | 	//    version is needed, migration is needed etc.
 | 
					
						
							|  |  |  | 	rquorum := InsufficientReadQuorum{} | 
					
						
							|  |  |  | 	wquorum := InsufficientWriteQuorum{} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-18 02:29:58 +08:00
										 |  |  | 	// allocate dynamic timeout once before the loop
 | 
					
						
							| 
									
										
										
										
											2020-09-19 00:18:18 +08:00
										 |  |  | 	iamLockTimeout := newDynamicTimeout(5*time.Second, 3*time.Second) | 
					
						
							| 
									
										
										
										
											2020-08-18 02:29:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	r := rand.New(rand.NewSource(time.Now().UnixNano())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 		// let one of the server acquire the lock, if not let them timeout.
 | 
					
						
							|  |  |  | 		// which shall be retried again by this loop.
 | 
					
						
							| 
									
										
										
										
											2020-12-06 05:00:44 +08:00
										 |  |  | 		if err := txnLk.GetLock(retryCtx, iamLockTimeout); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 			logger.Info("Waiting for all MinIO IAM sub-system to be initialized.. trying to acquire lock") | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 			time.Sleep(time.Duration(r.Float64() * float64(5*time.Second))) | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if globalEtcdClient != nil { | 
					
						
							|  |  |  | 			// ****  WARNING ****
 | 
					
						
							|  |  |  | 			// Migrating to encrypted backend on etcd should happen before initialization of
 | 
					
						
							|  |  |  | 			// IAM sub-system, make sure that we do not move the above codeblock elsewhere.
 | 
					
						
							| 
									
										
										
										
											2020-12-06 05:00:44 +08:00
										 |  |  | 			if err := migrateIAMConfigsEtcdToEncrypted(ctx, globalEtcdClient); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 				txnLk.Unlock() | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 				logger.LogIf(ctx, fmt.Errorf("Unable to decrypt an encrypted ETCD backend for IAM users and policies: %w", err)) | 
					
						
							|  |  |  | 				logger.LogIf(ctx, errors.New("IAM sub-system is partially initialized, some users may not be available")) | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// These messages only meant primarily for distributed setup, so only log during distributed setup.
 | 
					
						
							| 
									
										
										
										
											2020-06-13 11:04:01 +08:00
										 |  |  | 		if globalIsDistErasure { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 			logger.Info("Waiting for all MinIO IAM sub-system to be initialized.. lock acquired") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 		// Migrate IAM configuration, if necessary.
 | 
					
						
							| 
									
										
										
										
											2020-12-06 05:00:44 +08:00
										 |  |  | 		if err := sys.doIAMConfigMigration(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 			txnLk.Unlock() | 
					
						
							|  |  |  | 			if errors.Is(err, errDiskNotFound) || | 
					
						
							|  |  |  | 				errors.Is(err, errConfigNotFound) || | 
					
						
							|  |  |  | 				errors.Is(err, context.DeadlineExceeded) || | 
					
						
							|  |  |  | 				errors.As(err, &rquorum) || | 
					
						
							|  |  |  | 				errors.As(err, &wquorum) || | 
					
						
							|  |  |  | 				isErrBucketNotFound(err) { | 
					
						
							|  |  |  | 				logger.Info("Waiting for all MinIO IAM sub-system to be initialized.. possible cause (%v)", err) | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 			logger.LogIf(ctx, fmt.Errorf("Unable to migrate IAM users and policies to new format: %w", err)) | 
					
						
							|  |  |  | 			logger.LogIf(ctx, errors.New("IAM sub-system is partially initialized, some users may not be available")) | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 		// Successfully migrated, proceed to load the users.
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:19:03 +08:00
										 |  |  | 		txnLk.Unlock() | 
					
						
							|  |  |  | 		break | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-02 09:07:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 05:00:44 +08:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		if err := sys.store.loadAll(ctx, sys); err != nil { | 
					
						
							|  |  |  | 			if errors.Is(err, errDiskNotFound) || | 
					
						
							|  |  |  | 				errors.Is(err, errConfigNotFound) || | 
					
						
							|  |  |  | 				errors.Is(err, context.DeadlineExceeded) || | 
					
						
							|  |  |  | 				errors.As(err, &rquorum) || | 
					
						
							|  |  |  | 				errors.As(err, &wquorum) || | 
					
						
							|  |  |  | 				isErrBucketNotFound(err) { | 
					
						
							|  |  |  | 				logger.Info("Waiting for all MinIO IAM sub-system to be initialized.. possible cause (%v)", err) | 
					
						
							|  |  |  | 				time.Sleep(time.Duration(r.Float64() * float64(5*time.Second))) | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				logger.LogIf(ctx, fmt.Errorf("Unable to initialize IAM sub-system, some users may not be available %w", err)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 	// Invalidate the old cred always, even upon error to avoid any leakage.
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	globalOldCred = auth.Credentials{} | 
					
						
							| 
									
										
										
										
											2020-04-09 10:00:39 +08:00
										 |  |  | 	go sys.store.watch(ctx, sys) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // DeletePolicy - deletes a canned policy from backend or etcd.
 | 
					
						
							|  |  |  | func (sys *IAMSys) DeletePolicy(policyName string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	if policyName == "" { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2019-12-11 12:28:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := sys.store.deletePolicyDoc(context.Background(), policyName) | 
					
						
							| 
									
										
										
										
											2020-04-17 07:22:34 +08:00
										 |  |  | 	if err == errNoSuchPolicy { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		// Ignore error if policy is already deleted.
 | 
					
						
							|  |  |  | 		err = nil | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	delete(sys.iamPolicyDocsMap, policyName) | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Delete user-policy mappings that will no longer apply
 | 
					
						
							|  |  |  | 	for u, mp := range sys.iamUserPolicyMap { | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 		pset := mp.policySet() | 
					
						
							|  |  |  | 		if pset.Contains(policyName) { | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 			cr, ok := sys.iamUsersMap[u] | 
					
						
							|  |  |  | 			if !ok { | 
					
						
							|  |  |  | 				// This case cannot happen
 | 
					
						
							|  |  |  | 				return errNoSuchUser | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 			pset.Remove(policyName) | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 			// User is from STS if the cred are temporary
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 			if cr.IsTemp() { | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 				sys.policyDBSet(u, strings.Join(pset.ToSlice(), ","), stsUser, false) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 				sys.policyDBSet(u, strings.Join(pset.ToSlice(), ","), regularUser, false) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Delete group-policy mappings that will no longer apply
 | 
					
						
							|  |  |  | 	for g, mp := range sys.iamGroupPolicyMap { | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 		pset := mp.policySet() | 
					
						
							|  |  |  | 		if pset.Contains(policyName) { | 
					
						
							|  |  |  | 			pset.Remove(policyName) | 
					
						
							|  |  |  | 			sys.policyDBSet(g, strings.Join(pset.ToSlice(), ","), regularUser, true) | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 02:23:13 +08:00
										 |  |  | // InfoPolicy - expands the canned policy into its JSON structure.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | func (sys *IAMSys) InfoPolicy(policyName string) (iampolicy.Policy, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 		return iampolicy.Policy{}, errServerNotInitialized | 
					
						
							| 
									
										
										
										
											2019-09-27 02:23:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-09-27 02:23:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	v, ok := sys.iamPolicyDocsMap[policyName] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 		return iampolicy.Policy{}, errNoSuchPolicy | 
					
						
							| 
									
										
										
										
											2019-09-27 02:23:13 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return v, nil | 
					
						
							| 
									
										
										
										
											2019-09-27 02:23:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // ListPolicies - lists all canned policies.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | func (sys *IAMSys) ListPolicies() (map[string]iampolicy.Policy, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		return nil, errServerNotInitialized | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	fallback := sys.storeFallback | 
					
						
							|  |  |  | 	sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	if fallback { | 
					
						
							|  |  |  | 		if err := sys.store.loadAll(context.Background(), sys); err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 	policyDocsMap := make(map[string]iampolicy.Policy, len(sys.iamPolicyDocsMap)) | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	for k, v := range sys.iamPolicyDocsMap { | 
					
						
							| 
									
										
										
										
											2020-04-08 10:30:59 +08:00
										 |  |  | 		policyDocsMap[k] = v | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	return policyDocsMap, nil | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | // SetPolicy - sets a new name policy.
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	if p.IsEmpty() || policyName == "" { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2019-12-11 12:28:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.savePolicyDoc(context.Background(), policyName, p); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	sys.iamPolicyDocsMap[policyName] = p | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | // DeleteUser - delete user (only for long-term users not STS users).
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | func (sys *IAMSys) DeleteUser(accessKey string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 	// First we remove the user from their groups.
 | 
					
						
							|  |  |  | 	userInfo, getErr := sys.GetUserInfo(accessKey) | 
					
						
							|  |  |  | 	if getErr != nil { | 
					
						
							|  |  |  | 		return getErr | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 	for _, group := range userInfo.MemberOf { | 
					
						
							|  |  |  | 		removeErr := sys.RemoveUsersFromGroup(group, []string{accessKey}) | 
					
						
							|  |  |  | 		if removeErr != nil { | 
					
						
							|  |  |  | 			return removeErr | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Next we can remove the user from memory and IAM store
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	// Delete any service accounts if any first.
 | 
					
						
							|  |  |  | 	for _, u := range sys.iamUsersMap { | 
					
						
							|  |  |  | 		if u.IsServiceAccount() { | 
					
						
							|  |  |  | 			if u.ParentUser == accessKey { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 				_ = sys.store.deleteUserIdentity(context.Background(), u.AccessKey, srvAccUser) | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 				delete(sys.iamUsersMap, u.AccessKey) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	// It is ok to ignore deletion error on the mapped policy
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	sys.store.deleteMappedPolicy(context.Background(), accessKey, regularUser, false) | 
					
						
							|  |  |  | 	err := sys.store.deleteUserIdentity(context.Background(), accessKey, regularUser) | 
					
						
							| 
									
										
										
										
											2020-04-17 07:22:34 +08:00
										 |  |  | 	if err == errNoSuchUser { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		// ignore if user is already deleted.
 | 
					
						
							|  |  |  | 		err = nil | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	delete(sys.iamUsersMap, accessKey) | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	delete(sys.iamUserPolicyMap, accessKey) | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | // CurrentPolicies - returns comma separated policy string, from
 | 
					
						
							|  |  |  | // an input policy after validating if there are any current
 | 
					
						
							|  |  |  | // policies which exist on MinIO corresponding to the input.
 | 
					
						
							|  |  |  | func (sys *IAMSys) CurrentPolicies(policyName string) string { | 
					
						
							|  |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-10-21 12:28:24 +08:00
										 |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 06:34:01 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var policies []string | 
					
						
							|  |  |  | 	mp := newMappedPolicy(policyName) | 
					
						
							|  |  |  | 	for _, policy := range mp.toSlice() { | 
					
						
							|  |  |  | 		_, found := sys.iamPolicyDocsMap[policy] | 
					
						
							|  |  |  | 		if found { | 
					
						
							|  |  |  | 			policies = append(policies, policy) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return strings.Join(policies, ",") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // SetTempUser - set temporary user credentials, these credentials have an expiry.
 | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyName string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 04:24:01 +08:00
										 |  |  | 	ttl := int64(cred.Expiration.Sub(UTCNow()).Seconds()) | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | 	// If OPA is not set we honor any policy claims for this
 | 
					
						
							|  |  |  | 	// temporary user which match with pre-configured canned
 | 
					
						
							|  |  |  | 	// policies for this server.
 | 
					
						
							|  |  |  | 	if globalPolicyOPA == nil && policyName != "" { | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 		var availablePolicies []iampolicy.Policy | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 		mp := newMappedPolicy(policyName) | 
					
						
							|  |  |  | 		for _, policy := range mp.toSlice() { | 
					
						
							|  |  |  | 			p, found := sys.iamPolicyDocsMap[policy] | 
					
						
							| 
									
										
										
										
											2020-07-20 06:34:01 +08:00
										 |  |  | 			if found { | 
					
						
							|  |  |  | 				availablePolicies = append(availablePolicies, p) | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		combinedPolicy := availablePolicies[0] | 
					
						
							|  |  |  | 		for i := 1; i < len(availablePolicies); i++ { | 
					
						
							|  |  |  | 			combinedPolicy.Statements = append(combinedPolicy.Statements, | 
					
						
							|  |  |  | 				availablePolicies[i].Statements...) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if combinedPolicy.IsEmpty() { | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 			delete(sys.iamUserPolicyMap, accessKey) | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | 		if err := sys.store.saveMappedPolicy(context.Background(), accessKey, stsUser, false, mp, options{ttl: ttl}); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 		sys.iamUserPolicyMap[accessKey] = mp | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	u := newUserIdentity(cred) | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | 	if err := sys.store.saveUserIdentity(context.Background(), accessKey, stsUser, u, options{ttl: ttl}); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap[accessKey] = cred | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 15:18:43 +08:00
										 |  |  | // ListUsers - list all users.
 | 
					
						
							|  |  |  | func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-13 15:18:43 +08:00
										 |  |  | 		return nil, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return nil, errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	fallback := sys.storeFallback | 
					
						
							|  |  |  | 	sys.store.runlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if fallback { | 
					
						
							|  |  |  | 		if err := sys.store.loadAll(context.Background(), sys); err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var users = make(map[string]madmin.UserInfo) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 15:18:43 +08:00
										 |  |  | 	for k, v := range sys.iamUsersMap { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		if !v.IsTemp() && !v.IsServiceAccount() { | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 			users[k] = madmin.UserInfo{ | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 				PolicyName: sys.iamUserPolicyMap[k].Policies, | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 				Status: func() madmin.AccountStatus { | 
					
						
							|  |  |  | 					if v.IsValid() { | 
					
						
							|  |  |  | 						return madmin.AccountEnabled | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					return madmin.AccountDisabled | 
					
						
							|  |  |  | 				}(), | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-10-13 15:18:43 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return users, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | // IsTempUser - returns if given key is a temporary user.
 | 
					
						
							|  |  |  | func (sys *IAMSys) IsTempUser(name string) (bool, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 		return false, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	cred, found := sys.iamUsersMap[name] | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 	if !found { | 
					
						
							|  |  |  | 		return false, errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	return cred.IsTemp(), nil | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | // IsServiceAccount - returns if given key is a service account
 | 
					
						
							|  |  |  | func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return false, "", errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	cred, found := sys.iamUsersMap[name] | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if !found { | 
					
						
							|  |  |  | 		return false, "", errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	if cred.IsServiceAccount() { | 
					
						
							|  |  |  | 		return true, cred.ParentUser, nil | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false, "", nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | // GetUserInfo - get info on a user.
 | 
					
						
							|  |  |  | func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 		return u, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							| 
									
										
										
										
											2020-04-09 16:04:08 +08:00
										 |  |  | 		// If the user has a mapped policy or is a member of a group, we
 | 
					
						
							|  |  |  | 		// return that info. Otherwise we return error.
 | 
					
						
							|  |  |  | 		mappedPolicy, ok1 := sys.iamUserPolicyMap[name] | 
					
						
							|  |  |  | 		memberships, ok2 := sys.iamUserGroupMemberships[name] | 
					
						
							|  |  |  | 		if !ok1 && !ok2 { | 
					
						
							|  |  |  | 			return u, errNoSuchUser | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 		return madmin.UserInfo{ | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 			PolicyName: mappedPolicy.Policies, | 
					
						
							| 
									
										
										
										
											2020-04-09 16:04:08 +08:00
										 |  |  | 			MemberOf:   memberships.ToSlice(), | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 		}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	cred, found := sys.iamUsersMap[name] | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	if !found { | 
					
						
							|  |  |  | 		return u, errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	if cred.IsTemp() || cred.IsServiceAccount() { | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 		return u, errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	u = madmin.UserInfo{ | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 		PolicyName: sys.iamUserPolicyMap[name].Policies, | 
					
						
							| 
									
										
										
										
											2019-11-12 19:16:25 +08:00
										 |  |  | 		Status: func() madmin.AccountStatus { | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 			if cred.IsValid() { | 
					
						
							| 
									
										
										
										
											2019-11-12 19:16:25 +08:00
										 |  |  | 				return madmin.AccountEnabled | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return madmin.AccountDisabled | 
					
						
							|  |  |  | 		}(), | 
					
						
							|  |  |  | 		MemberOf: sys.iamUserGroupMemberships[name].ToSlice(), | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return u, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 05:55:23 +08:00
										 |  |  | // SetUserStatus - sets current user status, supports disabled or enabled.
 | 
					
						
							|  |  |  | func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-17 05:55:23 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if status != madmin.AccountEnabled && status != madmin.AccountDisabled { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2018-10-17 05:55:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 05:55:23 +08:00
										 |  |  | 	cred, ok := sys.iamUsersMap[accessKey] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	if cred.IsTemp() || cred.IsServiceAccount() { | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	uinfo := newUserIdentity(auth.Credentials{ | 
					
						
							|  |  |  | 		AccessKey: accessKey, | 
					
						
							| 
									
										
										
										
											2018-10-17 05:55:23 +08:00
										 |  |  | 		SecretKey: cred.SecretKey, | 
					
						
							| 
									
										
										
										
											2019-11-14 09:38:05 +08:00
										 |  |  | 		Status: func() string { | 
					
						
							|  |  |  | 			if status == madmin.AccountEnabled { | 
					
						
							| 
									
										
										
										
											2019-12-05 07:32:37 +08:00
										 |  |  | 				return config.EnableOn | 
					
						
							| 
									
										
										
										
											2019-11-14 09:38:05 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-12-05 07:32:37 +08:00
										 |  |  | 			return config.EnableOff | 
					
						
							| 
									
										
										
										
											2019-11-14 09:38:05 +08:00
										 |  |  | 		}(), | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-12-11 12:28:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.saveUserIdentity(context.Background(), accessKey, regularUser, uinfo); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 05:55:23 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	sys.iamUsersMap[accessKey] = uinfo.Credentials | 
					
						
							| 
									
										
										
										
											2018-10-17 05:55:23 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | // NewServiceAccount - create a new service account
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, sessionPolicy *iampolicy.Policy) (auth.Credentials, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return auth.Credentials{}, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	var policyBuf []byte | 
					
						
							|  |  |  | 	if sessionPolicy != nil { | 
					
						
							|  |  |  | 		err := sessionPolicy.Validate() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return auth.Credentials{}, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		policyBuf, err = json.Marshal(sessionPolicy) | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return auth.Credentials{}, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-08-06 04:08:40 +08:00
										 |  |  | 		if len(policyBuf) > 16*humanize.KiByte { | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 			return auth.Credentials{}, fmt.Errorf("Session policy should not exceed 16 KiB characters") | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if parentUser == globalActiveCred.AccessKey { | 
					
						
							|  |  |  | 		return auth.Credentials{}, errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cr, ok := sys.iamUsersMap[parentUser] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return auth.Credentials{}, errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	// Disallow service accounts to further create more service accounts.
 | 
					
						
							|  |  |  | 	if cr.IsServiceAccount() { | 
					
						
							|  |  |  | 		return auth.Credentials{}, errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	m := make(map[string]interface{}) | 
					
						
							|  |  |  | 	m[parentClaim] = parentUser | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	if len(policyBuf) > 0 { | 
					
						
							|  |  |  | 		m[iampolicy.SessionPolicyName] = base64.StdEncoding.EncodeToString(policyBuf) | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 		m[iamPolicyClaimNameSA()] = "embedded-policy" | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		m[iamPolicyClaimNameSA()] = "inherited-policy" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	secret := globalActiveCred.SecretKey | 
					
						
							|  |  |  | 	cred, err := auth.GetNewCredentialsWithMetadata(m, secret) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return auth.Credentials{}, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cred.ParentUser = parentUser | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	u := newUserIdentity(cred) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.saveUserIdentity(context.Background(), u.Credentials.AccessKey, srvAccUser, u); err != nil { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return auth.Credentials{}, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap[u.Credentials.AccessKey] = u.Credentials | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cred, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | // ListServiceAccounts - lists all services accounts associated to a specific user
 | 
					
						
							|  |  |  | func (sys *IAMSys) ListServiceAccounts(ctx context.Context, accessKey string) ([]string, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		return nil, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.store.rlock() | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	fallback := sys.storeFallback | 
					
						
							|  |  |  | 	sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	if fallback { | 
					
						
							|  |  |  | 		if err := sys.store.loadAll(context.Background(), sys); err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	var serviceAccounts []string | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	for k, v := range sys.iamUsersMap { | 
					
						
							|  |  |  | 		if v.IsServiceAccount() && v.ParentUser == accessKey { | 
					
						
							|  |  |  | 			serviceAccounts = append(serviceAccounts, k) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return serviceAccounts, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetServiceAccountParent - gets information about a service account
 | 
					
						
							|  |  |  | func (sys *IAMSys) GetServiceAccountParent(ctx context.Context, accessKey string) (string, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		return "", errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sa, ok := sys.iamUsersMap[accessKey] | 
					
						
							| 
									
										
										
										
											2020-05-01 23:05:14 +08:00
										 |  |  | 	if ok && sa.IsServiceAccount() { | 
					
						
							|  |  |  | 		return sa.ParentUser, nil | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-01 23:05:14 +08:00
										 |  |  | 	return "", nil | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DeleteServiceAccount - delete a service account
 | 
					
						
							|  |  |  | func (sys *IAMSys) DeleteServiceAccount(ctx context.Context, accessKey string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sa, ok := sys.iamUsersMap[accessKey] | 
					
						
							|  |  |  | 	if !ok || !sa.IsServiceAccount() { | 
					
						
							| 
									
										
										
										
											2020-05-01 23:05:14 +08:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// It is ok to ignore deletion error on the mapped policy
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := sys.store.deleteUserIdentity(context.Background(), accessKey, srvAccUser) | 
					
						
							| 
									
										
										
										
											2020-04-25 03:10:09 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		// ignore if user is already deleted.
 | 
					
						
							|  |  |  | 		if err == errNoSuchUser { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	delete(sys.iamUsersMap, accessKey) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | // SetUser - set user credentials and policy.
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	u := newUserIdentity(auth.Credentials{ | 
					
						
							|  |  |  | 		AccessKey: accessKey, | 
					
						
							|  |  |  | 		SecretKey: uinfo.SecretKey, | 
					
						
							|  |  |  | 		Status:    string(uinfo.Status), | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 	cr, ok := sys.iamUsersMap[accessKey] | 
					
						
							|  |  |  | 	if cr.IsTemp() && ok { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.saveUserIdentity(context.Background(), accessKey, regularUser, u); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	sys.iamUsersMap[accessKey] = u.Credentials | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	// Set policy if specified.
 | 
					
						
							|  |  |  | 	if uinfo.PolicyName != "" { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return sys.policyDBSet(accessKey, uinfo.PolicyName, regularUser, false) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-30 04:18:46 +08:00
										 |  |  | // SetUserSecretKey - sets user secret key
 | 
					
						
							|  |  |  | func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-05-30 04:18:46 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-30 04:18:46 +08:00
										 |  |  | 	cred, ok := sys.iamUsersMap[accessKey] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	cred.SecretKey = secretKey | 
					
						
							|  |  |  | 	u := newUserIdentity(cred) | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.saveUserIdentity(context.Background(), accessKey, regularUser, u); err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-30 04:18:46 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	sys.iamUsersMap[accessKey] = cred | 
					
						
							| 
									
										
										
										
											2019-05-30 04:18:46 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // GetUser - get user credentials
 | 
					
						
							|  |  |  | func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 		return cred, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	fallback := sys.storeFallback | 
					
						
							|  |  |  | 	sys.store.runlock() | 
					
						
							|  |  |  | 	if fallback { | 
					
						
							|  |  |  | 		sys.store.lock() | 
					
						
							|  |  |  | 		// If user is already found proceed.
 | 
					
						
							|  |  |  | 		if _, found := sys.iamUsersMap[accessKey]; !found { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 			sys.store.loadUser(context.Background(), accessKey, regularUser, sys.iamUsersMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 			if _, found = sys.iamUsersMap[accessKey]; found { | 
					
						
							|  |  |  | 				// found user, load its mapped policies
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 				sys.store.loadMappedPolicy(context.Background(), accessKey, regularUser, false, sys.iamUserPolicyMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 				sys.store.loadUser(context.Background(), accessKey, srvAccUser, sys.iamUsersMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 				if svc, found := sys.iamUsersMap[accessKey]; found { | 
					
						
							|  |  |  | 					// Found service account, load its parent user and its mapped policies.
 | 
					
						
							|  |  |  | 					if sys.usersSysType == MinIOUsersSysType { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 						sys.store.loadUser(context.Background(), svc.ParentUser, regularUser, sys.iamUsersMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 					sys.store.loadMappedPolicy(context.Background(), svc.ParentUser, regularUser, false, sys.iamUserPolicyMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 				} else { | 
					
						
							|  |  |  | 					// None found fall back to STS users.
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 					sys.store.loadUser(context.Background(), accessKey, stsUser, sys.iamUsersMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 					if _, found = sys.iamUsersMap[accessKey]; found { | 
					
						
							|  |  |  | 						// STS user found, load its mapped policy.
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 						sys.store.loadMappedPolicy(context.Background(), accessKey, stsUser, false, sys.iamUserPolicyMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 		// Load associated policies if any.
 | 
					
						
							|  |  |  | 		for _, policy := range sys.iamUserPolicyMap[accessKey].toSlice() { | 
					
						
							|  |  |  | 			if _, found := sys.iamPolicyDocsMap[policy]; !found { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 				sys.store.loadPolicyDoc(context.Background(), policy, sys.iamPolicyDocsMap) | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		sys.buildUserGroupMemberships() | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 		sys.store.unlock() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cred, ok = sys.iamUsersMap[accessKey] | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	if ok && cred.IsValid() { | 
					
						
							| 
									
										
										
										
											2020-05-13 00:21:08 +08:00
										 |  |  | 		if cred.ParentUser != "" && sys.usersSysType == MinIOUsersSysType { | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 			_, ok = sys.iamUsersMap[cred.ParentUser] | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-13 00:21:08 +08:00
										 |  |  | 		// for LDAP service accounts with ParentUser set
 | 
					
						
							|  |  |  | 		// we have no way to validate, either because user
 | 
					
						
							|  |  |  | 		// doesn't need an explicit policy as it can come
 | 
					
						
							|  |  |  | 		// automatically from a group. We are safe to ignore
 | 
					
						
							|  |  |  | 		// this and continue as policies would fail eventually
 | 
					
						
							|  |  |  | 		// the policies are missing or not configured.
 | 
					
						
							| 
									
										
										
										
											2020-04-29 03:49:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	return cred, ok && cred.IsValid() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | // AddUsersToGroup - adds users to a group, creating the group if
 | 
					
						
							|  |  |  | // needed. No error if user(s) already are in the group.
 | 
					
						
							|  |  |  | func (sys *IAMSys) AddUsersToGroup(group string, members []string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if group == "" { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	// Validate that all members exist.
 | 
					
						
							|  |  |  | 	for _, member := range members { | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 		cr, ok := sys.iamUsersMap[member] | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		if !ok { | 
					
						
							|  |  |  | 			return errNoSuchUser | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 		if cr.IsTemp() { | 
					
						
							|  |  |  | 			return errIAMActionNotAllowed | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gi, ok := sys.iamGroupsMap[group] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// Set group as enabled by default when it doesn't
 | 
					
						
							|  |  |  | 		// exist.
 | 
					
						
							|  |  |  | 		gi = newGroupInfo(members) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		mergedMembers := append(gi.Members, members...) | 
					
						
							|  |  |  | 		uniqMembers := set.CreateStringSet(mergedMembers...).ToSlice() | 
					
						
							|  |  |  | 		gi.Members = uniqMembers | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.saveGroupInfo(context.Background(), group, gi); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamGroupsMap[group] = gi | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// update user-group membership map
 | 
					
						
							|  |  |  | 	for _, member := range members { | 
					
						
							|  |  |  | 		gset := sys.iamUserGroupMemberships[member] | 
					
						
							|  |  |  | 		if gset == nil { | 
					
						
							|  |  |  | 			gset = set.CreateStringSet(group) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			gset.Add(group) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		sys.iamUserGroupMemberships[member] = gset | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RemoveUsersFromGroup - remove users from group. If no users are
 | 
					
						
							|  |  |  | // given, and the group is empty, deletes the group as well.
 | 
					
						
							|  |  |  | func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if group == "" { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	// Validate that all members exist.
 | 
					
						
							|  |  |  | 	for _, member := range members { | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 		cr, ok := sys.iamUsersMap[member] | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		if !ok { | 
					
						
							|  |  |  | 			return errNoSuchUser | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-12-20 06:21:21 +08:00
										 |  |  | 		if cr.IsTemp() { | 
					
						
							|  |  |  | 			return errIAMActionNotAllowed | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gi, ok := sys.iamGroupsMap[group] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return errNoSuchGroup | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check if attempting to delete a non-empty group.
 | 
					
						
							|  |  |  | 	if len(members) == 0 && len(gi.Members) != 0 { | 
					
						
							|  |  |  | 		return errGroupNotEmpty | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(members) == 0 { | 
					
						
							|  |  |  | 		// len(gi.Members) == 0 here.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		// Remove the group from storage. First delete the
 | 
					
						
							| 
									
										
										
										
											2020-04-17 07:22:34 +08:00
										 |  |  | 		// mapped policy. No-mapped-policy case is ignored.
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := sys.store.deleteMappedPolicy(context.Background(), group, regularUser, true); err != nil && err != errNoSuchPolicy { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := sys.store.deleteGroupInfo(context.Background(), group); err != nil && err != errNoSuchGroup { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Delete from server memory
 | 
					
						
							|  |  |  | 		delete(sys.iamGroupsMap, group) | 
					
						
							|  |  |  | 		delete(sys.iamGroupPolicyMap, group) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Only removing members.
 | 
					
						
							|  |  |  | 	s := set.CreateStringSet(gi.Members...) | 
					
						
							|  |  |  | 	d := set.CreateStringSet(members...) | 
					
						
							|  |  |  | 	gi.Members = s.Difference(d).ToSlice() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := sys.store.saveGroupInfo(context.Background(), group, gi) | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sys.iamGroupsMap[group] = gi | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// update user-group membership map
 | 
					
						
							|  |  |  | 	for _, member := range members { | 
					
						
							|  |  |  | 		gset := sys.iamUserGroupMemberships[member] | 
					
						
							|  |  |  | 		if gset == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		gset.Remove(group) | 
					
						
							|  |  |  | 		sys.iamUserGroupMemberships[member] = gset | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetGroupStatus - enable/disabled a group
 | 
					
						
							|  |  |  | func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	if group == "" { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gi, ok := sys.iamGroupsMap[group] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return errNoSuchGroup | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if enabled { | 
					
						
							|  |  |  | 		gi.Status = statusEnabled | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		gi.Status = statusDisabled | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.saveGroupInfo(context.Background(), group, gi); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sys.iamGroupsMap[group] = gi | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetGroupDescription - builds up group description
 | 
					
						
							|  |  |  | func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 		return gd, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	ps, err := sys.PolicyDBGet(group, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return gd, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	// A group may be mapped to at most one policy.
 | 
					
						
							|  |  |  | 	policy := "" | 
					
						
							|  |  |  | 	if len(ps) > 0 { | 
					
						
							|  |  |  | 		policy = ps[0] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return madmin.GroupDesc{ | 
					
						
							|  |  |  | 			Name:   group, | 
					
						
							|  |  |  | 			Policy: policy, | 
					
						
							|  |  |  | 		}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-09-27 02:23:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	gi, ok := sys.iamGroupsMap[group] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return gd, errNoSuchGroup | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return madmin.GroupDesc{ | 
					
						
							|  |  |  | 		Name:    group, | 
					
						
							|  |  |  | 		Status:  gi.Status, | 
					
						
							|  |  |  | 		Members: gi.Members, | 
					
						
							|  |  |  | 		Policy:  policy, | 
					
						
							|  |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | // ListGroups - lists groups.
 | 
					
						
							|  |  |  | func (sys *IAMSys) ListGroups() (r []string, err error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 		return r, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	if sys.usersSysType != MinIOUsersSysType { | 
					
						
							|  |  |  | 		return nil, errIAMActionNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	fallback := sys.storeFallback | 
					
						
							|  |  |  | 	sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	if fallback { | 
					
						
							|  |  |  | 		if err := sys.store.loadAll(context.Background(), sys); err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 	r = make([]string, 0, len(sys.iamGroupsMap)) | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	for k := range sys.iamGroupsMap { | 
					
						
							|  |  |  | 		r = append(r, k) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-03 09:52:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	return r, nil | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 16:04:08 +08:00
										 |  |  | // PolicyDBSet - sets a policy for a user or group in the PolicyDB.
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | func (sys *IAMSys) PolicyDBSet(name, policy string, isGroup bool) error { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.lock() | 
					
						
							|  |  |  | 	defer sys.store.unlock() | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	return sys.policyDBSet(name, policy, regularUser, isGroup) | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | // policyDBSet - sets a policy for user in the policy db. Assumes that caller
 | 
					
						
							|  |  |  | // has sys.Lock(). If policy == "", then policy mapping is removed.
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | func (sys *IAMSys) policyDBSet(name, policyName string, userType IAMUserType, isGroup bool) error { | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 	if name == "" { | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if sys.usersSysType == MinIOUsersSysType { | 
					
						
							|  |  |  | 		if !isGroup { | 
					
						
							|  |  |  | 			if _, ok := sys.iamUsersMap[name]; !ok { | 
					
						
							|  |  |  | 				return errNoSuchUser | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if _, ok := sys.iamGroupsMap[name]; !ok { | 
					
						
							|  |  |  | 				return errNoSuchGroup | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 	// Handle policy mapping removal
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 	if policyName == "" { | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := sys.store.deleteMappedPolicy(context.Background(), name, userType, isGroup); err != nil && err != errNoSuchPolicy { | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !isGroup { | 
					
						
							|  |  |  | 			delete(sys.iamUserPolicyMap, name) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			delete(sys.iamGroupPolicyMap, name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	mp := newMappedPolicy(policyName) | 
					
						
							|  |  |  | 	for _, policy := range mp.toSlice() { | 
					
						
							|  |  |  | 		if _, found := sys.iamPolicyDocsMap[policy]; !found { | 
					
						
							|  |  |  | 			logger.LogIf(GlobalContext, fmt.Errorf("%w: (%s)", errNoSuchPolicy, policy)) | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 			return errNoSuchPolicy | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 06:42:08 +08:00
										 |  |  | 	// Handle policy mapping set/update
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := sys.store.saveMappedPolicy(context.Background(), name, userType, isGroup, mp); err != nil { | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	if !isGroup { | 
					
						
							|  |  |  | 		sys.iamUserPolicyMap[name] = mp | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		sys.iamGroupPolicyMap[name] = mp | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | // PolicyDBGet - gets policy set on a user or group. Since a user may
 | 
					
						
							|  |  |  | // be a member of multiple groups, this function returns an array of
 | 
					
						
							|  |  |  | // applicable policies (each group is mapped to at most one policy).
 | 
					
						
							|  |  |  | func (sys *IAMSys) PolicyDBGet(name string, isGroup bool) ([]string, error) { | 
					
						
							| 
									
										
										
										
											2020-11-08 13:03:06 +08:00
										 |  |  | 	if !sys.Initialized() { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return nil, errServerNotInitialized | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	if name == "" { | 
					
						
							|  |  |  | 		return nil, errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	return sys.policyDBGet(name, isGroup) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This call assumes that caller has the sys.RLock()
 | 
					
						
							|  |  |  | func (sys *IAMSys) policyDBGet(name string, isGroup bool) ([]string, error) { | 
					
						
							|  |  |  | 	if isGroup { | 
					
						
							|  |  |  | 		if _, ok := sys.iamGroupsMap[name]; !ok { | 
					
						
							|  |  |  | 			return nil, errNoSuchGroup | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 		mp := sys.iamGroupPolicyMap[name] | 
					
						
							|  |  |  | 		return mp.toSlice(), nil | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-15 07:59:16 +08:00
										 |  |  | 	// When looking for a user's policies, we also check if the
 | 
					
						
							|  |  |  | 	// user and the groups they are member of are enabled.
 | 
					
						
							|  |  |  | 	if u, ok := sys.iamUsersMap[name]; !ok { | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		return nil, errNoSuchUser | 
					
						
							| 
									
										
										
										
											2019-08-15 07:59:16 +08:00
										 |  |  | 	} else if u.Status == statusDisabled { | 
					
						
							|  |  |  | 		// User is disabled, so we return no policy - this
 | 
					
						
							|  |  |  | 		// ensures the request is denied.
 | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	var policies []string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mp := sys.iamUserPolicyMap[name] | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	// returned policy could be empty
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	policies = append(policies, mp.toSlice()...) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	for _, group := range sys.iamUserGroupMemberships[name].ToSlice() { | 
					
						
							| 
									
										
										
										
											2019-08-15 07:59:16 +08:00
										 |  |  | 		// Skip missing or disabled groups
 | 
					
						
							|  |  |  | 		gi, ok := sys.iamGroupsMap[group] | 
					
						
							|  |  |  | 		if !ok || gi.Status == statusDisabled { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 		p := sys.iamGroupPolicyMap[group] | 
					
						
							|  |  |  | 		policies = append(policies, p.toSlice()...) | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	return policies, nil | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | // IsAllowedServiceAccount - checks if the given service account is allowed to perform
 | 
					
						
							|  |  |  | // actions. The permission of the parent user is checked first
 | 
					
						
							|  |  |  | func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parent string) bool { | 
					
						
							|  |  |  | 	// Now check if we have a subject claim
 | 
					
						
							|  |  |  | 	p, ok := args.Claims[parentClaim] | 
					
						
							|  |  |  | 	if ok { | 
					
						
							|  |  |  | 		parentInClaim, ok := p.(string) | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			// Reject malformed/malicious requests.
 | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// The parent claim in the session token should be equal
 | 
					
						
							|  |  |  | 		// to the parent detected in the backend
 | 
					
						
							|  |  |  | 		if parentInClaim != parent { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		// This is needed so a malicious user cannot
 | 
					
						
							|  |  |  | 		// use a leaked session key of another user
 | 
					
						
							|  |  |  | 		// to widen its privileges.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check if the parent is allowed to perform this action, reject if not
 | 
					
						
							|  |  |  | 	parentUserPolicies, err := sys.PolicyDBGet(parent, false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(parentUserPolicies) == 0 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var availablePolicies []iampolicy.Policy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Policies were found, evaluate all of them.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	for _, pname := range parentUserPolicies { | 
					
						
							|  |  |  | 		p, found := sys.iamPolicyDocsMap[pname] | 
					
						
							|  |  |  | 		if found { | 
					
						
							|  |  |  | 			availablePolicies = append(availablePolicies, p) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if len(availablePolicies) == 0 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	combinedPolicy := availablePolicies[0] | 
					
						
							|  |  |  | 	for i := 1; i < len(availablePolicies); i++ { | 
					
						
							|  |  |  | 		combinedPolicy.Statements = append(combinedPolicy.Statements, | 
					
						
							|  |  |  | 			availablePolicies[i].Statements...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 	parentArgs := args | 
					
						
							|  |  |  | 	parentArgs.AccountName = parent | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	saPolicyClaim, ok := args.Claims[iamPolicyClaimNameSA()] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	saPolicyClaimStr, ok := saPolicyClaim.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// Sub policy if set, should be a string reject
 | 
					
						
							|  |  |  | 		// malformed/malicious requests.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	if saPolicyClaimStr == "inherited-policy" { | 
					
						
							|  |  |  | 		return combinedPolicy.IsAllowed(parentArgs) | 
					
						
							| 
									
										
										
										
											2020-03-24 05:17:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Now check if we have a sessionPolicy.
 | 
					
						
							|  |  |  | 	spolicy, ok := args.Claims[iampolicy.SessionPolicyName] | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	spolicyStr, ok := spolicy.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// Sub policy if set, should be a string reject
 | 
					
						
							|  |  |  | 		// malformed/malicious requests.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	// Check if policy is parseable.
 | 
					
						
							|  |  |  | 	subPolicy, err := iampolicy.ParseConfig(bytes.NewReader([]byte(spolicyStr))) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		// Log any error in input session policy config.
 | 
					
						
							| 
									
										
										
										
											2020-08-14 00:16:01 +08:00
										 |  |  | 		logger.LogIf(GlobalContext, err) | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	// Policy without Version string value reject it.
 | 
					
						
							|  |  |  | 	if subPolicy.Version == "" { | 
					
						
							|  |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:28:56 +08:00
										 |  |  | 	return combinedPolicy.IsAllowed(parentArgs) && subPolicy.IsAllowed(parentArgs) | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | // IsAllowedLDAPSTS - checks for LDAP specific claims and values
 | 
					
						
							|  |  |  | func (sys *IAMSys) IsAllowedLDAPSTS(args iampolicy.Args) bool { | 
					
						
							|  |  |  | 	userIface, ok := args.Claims[ldapUser] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	user, ok := userIface.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	var groups []string | 
					
						
							|  |  |  | 	cred, ok := sys.iamUsersMap[args.AccountName] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	groups = cred.Groups | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// We look up the policy mapping directly to bypass
 | 
					
						
							|  |  |  | 	// users exists, group exists validations that do not
 | 
					
						
							|  |  |  | 	// apply here.
 | 
					
						
							|  |  |  | 	var policies []iampolicy.Policy | 
					
						
							|  |  |  | 	if mp, ok := sys.iamUserPolicyMap[user]; ok { | 
					
						
							|  |  |  | 		for _, pname := range mp.toSlice() { | 
					
						
							|  |  |  | 			p, found := sys.iamPolicyDocsMap[pname] | 
					
						
							|  |  |  | 			if !found { | 
					
						
							| 
									
										
										
										
											2020-07-20 06:34:01 +08:00
										 |  |  | 				logger.LogIf(GlobalContext, fmt.Errorf("expected policy (%s) missing for the LDAPUser %s, rejecting the request", pname, user)) | 
					
						
							| 
									
										
										
										
											2020-05-13 00:21:08 +08:00
										 |  |  | 				return false | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 			policies = append(policies, p) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, group := range groups { | 
					
						
							|  |  |  | 		mp, ok := sys.iamGroupPolicyMap[group] | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, pname := range mp.toSlice() { | 
					
						
							|  |  |  | 			p, found := sys.iamPolicyDocsMap[pname] | 
					
						
							|  |  |  | 			if !found { | 
					
						
							| 
									
										
										
										
											2020-07-20 06:34:01 +08:00
										 |  |  | 				logger.LogIf(GlobalContext, fmt.Errorf("expected policy (%s) missing for the LDAPGroup %s, rejecting the request", pname, group)) | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 				return false | 
					
						
							| 
									
										
										
										
											2020-05-13 00:21:08 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 			policies = append(policies, p) | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if len(policies) == 0 { | 
					
						
							| 
									
										
										
										
											2020-05-13 00:21:08 +08:00
										 |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-21 02:33:35 +08:00
										 |  |  | 	combinedPolicy := policies[0] | 
					
						
							|  |  |  | 	for i := 1; i < len(policies); i++ { | 
					
						
							|  |  |  | 		combinedPolicy.Statements = | 
					
						
							|  |  |  | 			append(combinedPolicy.Statements, | 
					
						
							|  |  |  | 				policies[i].Statements...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return combinedPolicy.IsAllowed(args) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsAllowedSTS is meant for STS based temporary credentials,
 | 
					
						
							|  |  |  | // which implements claims validation and verification other than
 | 
					
						
							|  |  |  | // applying policies.
 | 
					
						
							|  |  |  | func (sys *IAMSys) IsAllowedSTS(args iampolicy.Args) bool { | 
					
						
							|  |  |  | 	// If it is an LDAP request, check that user and group
 | 
					
						
							|  |  |  | 	// policies allow the request.
 | 
					
						
							|  |  |  | 	if sys.usersSysType == LDAPUsersSysType { | 
					
						
							|  |  |  | 		return sys.IsAllowedLDAPSTS(args) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-10 07:12:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 	policies, ok := args.GetPolicies(iamPolicyClaimNameOpenID()) | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 		// When claims are set, it should have a policy claim field.
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 	// When claims are set, it should have policies as claim.
 | 
					
						
							|  |  |  | 	if policies.IsEmpty() { | 
					
						
							|  |  |  | 		// No policy, no access!
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	// If policy is available for given user, check the policy.
 | 
					
						
							| 
									
										
										
										
											2019-07-25 08:34:23 +08:00
										 |  |  | 	mp, ok := sys.iamUserPolicyMap[args.AccountName] | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 		// No policy set for the user that we can find, no access!
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 	if !policies.Equals(mp.policySet()) { | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 		// When claims has a policy, it should match the
 | 
					
						
							|  |  |  | 		// policy of args.AccountName which server remembers.
 | 
					
						
							|  |  |  | 		// if not reject such requests.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 	var availablePolicies []iampolicy.Policy | 
					
						
							|  |  |  | 	for pname := range policies { | 
					
						
							|  |  |  | 		p, found := sys.iamPolicyDocsMap[pname] | 
					
						
							|  |  |  | 		if !found { | 
					
						
							| 
									
										
										
										
											2020-07-20 06:34:01 +08:00
										 |  |  | 			// all policies presented in the claim should exist
 | 
					
						
							|  |  |  | 			logger.LogIf(GlobalContext, fmt.Errorf("expected policy (%s) missing from the JWT claim %s, rejecting the request", pname, iamPolicyClaimNameOpenID())) | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		availablePolicies = append(availablePolicies, p) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	combinedPolicy := availablePolicies[0] | 
					
						
							|  |  |  | 	for i := 1; i < len(availablePolicies); i++ { | 
					
						
							|  |  |  | 		combinedPolicy.Statements = append(combinedPolicy.Statements, | 
					
						
							|  |  |  | 			availablePolicies[i].Statements...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	// Now check if we have a sessionPolicy.
 | 
					
						
							|  |  |  | 	spolicy, ok := args.Claims[iampolicy.SessionPolicyName] | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 	if ok { | 
					
						
							|  |  |  | 		spolicyStr, ok := spolicy.(string) | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			// Sub policy if set, should be a string reject
 | 
					
						
							|  |  |  | 			// malformed/malicious requests.
 | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 		// Check if policy is parseable.
 | 
					
						
							|  |  |  | 		subPolicy, err := iampolicy.ParseConfig(bytes.NewReader([]byte(spolicyStr))) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			// Log any error in input session policy config.
 | 
					
						
							| 
									
										
										
										
											2020-08-14 00:16:01 +08:00
										 |  |  | 			logger.LogIf(GlobalContext, err) | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 		// Policy without Version string value reject it.
 | 
					
						
							|  |  |  | 		if subPolicy.Version == "" { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 		// Sub policy is set and valid.
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 		return combinedPolicy.IsAllowed(args) && subPolicy.IsAllowed(args) | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 09:21:58 +08:00
										 |  |  | 	// Sub policy not set, this is most common since subPolicy
 | 
					
						
							| 
									
										
										
										
											2020-05-12 04:04:11 +08:00
										 |  |  | 	// is optional, use the inherited policies.
 | 
					
						
							|  |  |  | 	return combinedPolicy.IsAllowed(args) | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | // GetCombinedPolicy returns a combined policy combining all policies
 | 
					
						
							|  |  |  | func (sys *IAMSys) GetCombinedPolicy(policies ...string) iampolicy.Policy { | 
					
						
							|  |  |  | 	// Policies were found, evaluate all of them.
 | 
					
						
							|  |  |  | 	sys.store.rlock() | 
					
						
							|  |  |  | 	defer sys.store.runlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var availablePolicies []iampolicy.Policy | 
					
						
							|  |  |  | 	for _, pname := range policies { | 
					
						
							|  |  |  | 		p, found := sys.iamPolicyDocsMap[pname] | 
					
						
							|  |  |  | 		if found { | 
					
						
							|  |  |  | 			availablePolicies = append(availablePolicies, p) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(availablePolicies) == 0 { | 
					
						
							|  |  |  | 		return iampolicy.Policy{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	combinedPolicy := availablePolicies[0] | 
					
						
							|  |  |  | 	for i := 1; i < len(availablePolicies); i++ { | 
					
						
							|  |  |  | 		combinedPolicy.Statements = append(combinedPolicy.Statements, | 
					
						
							|  |  |  | 			availablePolicies[i].Statements...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return combinedPolicy | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | // IsAllowed - checks given policy args is allowed to continue the Rest API.
 | 
					
						
							|  |  |  | func (sys *IAMSys) IsAllowed(args iampolicy.Args) bool { | 
					
						
							| 
									
										
										
										
											2018-10-16 03:44:03 +08:00
										 |  |  | 	// If opa is configured, use OPA always.
 | 
					
						
							|  |  |  | 	if globalPolicyOPA != nil { | 
					
						
							| 
									
										
										
										
											2019-07-28 11:03:25 +08:00
										 |  |  | 		ok, err := globalPolicyOPA.IsAllowed(args) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2020-08-14 00:16:01 +08:00
										 |  |  | 			logger.LogIf(GlobalContext, err) | 
					
						
							| 
									
										
										
										
											2019-07-28 11:03:25 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return ok | 
					
						
							| 
									
										
										
										
											2018-10-16 03:44:03 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	// Policies don't apply to the owner.
 | 
					
						
							|  |  |  | 	if args.IsOwner { | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-22 17:39:46 +08:00
										 |  |  | 	// If the credential is temporary, perform STS related checks.
 | 
					
						
							|  |  |  | 	ok, err := sys.IsTempUser(args.AccountName) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ok { | 
					
						
							| 
									
										
										
										
											2019-10-23 13:59:13 +08:00
										 |  |  | 		return sys.IsAllowedSTS(args) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	// If the credential is for a service account, perform related check
 | 
					
						
							|  |  |  | 	ok, parentUser, err := sys.IsServiceAccount(args.AccountName) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ok { | 
					
						
							|  |  |  | 		return sys.IsAllowedServiceAccount(args, parentUser) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Continue with the assumption of a regular user
 | 
					
						
							| 
									
										
										
										
											2019-08-14 04:41:06 +08:00
										 |  |  | 	policies, err := sys.PolicyDBGet(args.AccountName, false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(policies) == 0 { | 
					
						
							|  |  |  | 		// No policy found.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Policies were found, evaluate all of them.
 | 
					
						
							| 
									
										
										
										
											2020-11-28 09:23:57 +08:00
										 |  |  | 	return sys.GetCombinedPolicy(policies...).IsAllowed(args) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 08:14:27 +08:00
										 |  |  | // Set default canned policies only if not already overridden by users.
 | 
					
						
							|  |  |  | func setDefaultCannedPolicies(policies map[string]iampolicy.Policy) { | 
					
						
							|  |  |  | 	_, ok := policies["writeonly"] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		policies["writeonly"] = iampolicy.WriteOnly | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_, ok = policies["readonly"] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		policies["readonly"] = iampolicy.ReadOnly | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	_, ok = policies["readwrite"] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		policies["readwrite"] = iampolicy.ReadWrite | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-05 09:58:38 +08:00
										 |  |  | 	_, ok = policies["diagnostics"] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		policies["diagnostics"] = iampolicy.AdminDiagnostics | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-25 08:14:27 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | // buildUserGroupMemberships - builds the memberships map. IMPORTANT:
 | 
					
						
							|  |  |  | // Assumes that sys.Lock is held by caller.
 | 
					
						
							|  |  |  | func (sys *IAMSys) buildUserGroupMemberships() { | 
					
						
							|  |  |  | 	for group, gi := range sys.iamGroupsMap { | 
					
						
							|  |  |  | 		sys.updateGroupMembershipsMap(group, &gi) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // updateGroupMembershipsMap - updates the memberships map for a
 | 
					
						
							|  |  |  | // group. IMPORTANT: Assumes sys.Lock() is held by caller.
 | 
					
						
							|  |  |  | func (sys *IAMSys) updateGroupMembershipsMap(group string, gi *GroupInfo) { | 
					
						
							|  |  |  | 	if gi == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, member := range gi.Members { | 
					
						
							|  |  |  | 		v := sys.iamUserGroupMemberships[member] | 
					
						
							|  |  |  | 		if v == nil { | 
					
						
							|  |  |  | 			v = set.CreateStringSet(group) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			v.Add(group) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		sys.iamUserGroupMemberships[member] = v | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // removeGroupFromMembershipsMap - removes the group from every member
 | 
					
						
							|  |  |  | // in the cache. IMPORTANT: Assumes sys.Lock() is held by caller.
 | 
					
						
							|  |  |  | func (sys *IAMSys) removeGroupFromMembershipsMap(group string) { | 
					
						
							|  |  |  | 	for member, groups := range sys.iamUserGroupMemberships { | 
					
						
							|  |  |  | 		if !groups.Contains(group) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		groups.Remove(group) | 
					
						
							|  |  |  | 		sys.iamUserGroupMemberships[member] = groups | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-22 13:47:26 +08:00
										 |  |  | // EnableLDAPSys - enable ldap system users type.
 | 
					
						
							|  |  |  | func (sys *IAMSys) EnableLDAPSys() { | 
					
						
							|  |  |  | 	sys.usersSysType = LDAPUsersSysType | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // NewIAMSys - creates new config system object.
 | 
					
						
							|  |  |  | func NewIAMSys() *IAMSys { | 
					
						
							|  |  |  | 	return &IAMSys{ | 
					
						
							| 
									
										
										
										
											2020-03-22 13:47:26 +08:00
										 |  |  | 		usersSysType:            MinIOUsersSysType, | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		iamUsersMap:             make(map[string]auth.Credentials), | 
					
						
							|  |  |  | 		iamPolicyDocsMap:        make(map[string]iampolicy.Policy), | 
					
						
							|  |  |  | 		iamUserPolicyMap:        make(map[string]MappedPolicy), | 
					
						
							| 
									
										
										
										
											2020-05-29 21:13:54 +08:00
										 |  |  | 		iamGroupPolicyMap:       make(map[string]MappedPolicy), | 
					
						
							| 
									
										
										
										
											2019-08-03 05:25:00 +08:00
										 |  |  | 		iamGroupsMap:            make(map[string]GroupInfo), | 
					
						
							|  |  |  | 		iamUserGroupMemberships: make(map[string]set.StringSet), | 
					
						
							| 
									
										
										
										
											2020-06-12 05:11:30 +08:00
										 |  |  | 		storeFallback:           true, | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |