| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2019-04-10 02:39:42 +08:00
										 |  |  |  * MinIO Cloud Storage, (C) 2018 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" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"path" | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	etcd "github.com/coreos/etcd/clientv3" | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	"github.com/coreos/etcd/mvcc/mvccpb" | 
					
						
							| 
									
										
										
										
											2019-05-30 07:35:12 +08:00
										 |  |  | 	"github.com/minio/minio-go/v6/pkg/set" | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	// IAM configuration directory.
 | 
					
						
							|  |  |  | 	iamConfigPrefix = minioConfigPrefix + "/iam" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// IAM users directory.
 | 
					
						
							|  |  |  | 	iamConfigUsersPrefix = iamConfigPrefix + "/users/" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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/" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// IAM identity file which captures identity credentials.
 | 
					
						
							|  |  |  | 	iamIdentityFile = "identity.json" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// IAM policy file which provides policies for each users.
 | 
					
						
							|  |  |  | 	iamPolicyFile = "policy.json" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IAMSys - config system.
 | 
					
						
							|  |  |  | type IAMSys struct { | 
					
						
							|  |  |  | 	sync.RWMutex | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	iamUsersMap        map[string]auth.Credentials | 
					
						
							|  |  |  | 	iamPolicyMap       map[string]string | 
					
						
							|  |  |  | 	iamCannedPolicyMap map[string]iampolicy.Policy | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prefix := iamConfigPoliciesPrefix | 
					
						
							|  |  |  | 	if globalEtcdClient == nil { | 
					
						
							|  |  |  | 		return reloadPolicy(context.Background(), objAPI, prefix, policyName, sys.iamCannedPolicyMap) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// When etcd is set, we use watch APIs so this code is not needed.
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LoadUser - reloads a specific user from backend disks or etcd.
 | 
					
						
							|  |  |  | func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, temp bool) error { | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prefix := iamConfigUsersPrefix | 
					
						
							|  |  |  | 	if temp { | 
					
						
							|  |  |  | 		prefix = iamConfigSTSPrefix | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if globalEtcdClient == nil { | 
					
						
							|  |  |  | 		return reloadUser(context.Background(), objAPI, prefix, accessKey, sys.iamUsersMap, sys.iamPolicyMap) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// When etcd is set, we use watch APIs so this code is not needed.
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 06:39:21 +08:00
										 |  |  | // Load - loads iam subsystem
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | func (sys *IAMSys) Load(objAPI ObjectLayer) error { | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							|  |  |  | 		return sys.refreshEtcd() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-12-19 06:39:21 +08:00
										 |  |  | 	return sys.refresh(objAPI) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | func (sys *IAMSys) reloadFromEvent(event *etcd.Event) { | 
					
						
							|  |  |  | 	eventCreate := event.IsModify() || event.IsCreate() | 
					
						
							|  |  |  | 	eventDelete := event.Type == etcd.EventTypeDelete | 
					
						
							|  |  |  | 	usersPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigUsersPrefix) | 
					
						
							|  |  |  | 	stsPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigSTSPrefix) | 
					
						
							|  |  |  | 	policyPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPoliciesPrefix) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), | 
					
						
							|  |  |  | 		defaultContextTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case eventCreate: | 
					
						
							|  |  |  | 		switch { | 
					
						
							|  |  |  | 		case usersPrefix: | 
					
						
							|  |  |  | 			accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key), | 
					
						
							|  |  |  | 				iamConfigUsersPrefix)) | 
					
						
							|  |  |  | 			reloadEtcdUser(ctx, iamConfigUsersPrefix, accessKey, | 
					
						
							|  |  |  | 				sys.iamUsersMap, sys.iamPolicyMap) | 
					
						
							|  |  |  | 		case stsPrefix: | 
					
						
							|  |  |  | 			accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key), | 
					
						
							|  |  |  | 				iamConfigSTSPrefix)) | 
					
						
							|  |  |  | 			reloadEtcdUser(ctx, iamConfigSTSPrefix, accessKey, | 
					
						
							|  |  |  | 				sys.iamUsersMap, sys.iamPolicyMap) | 
					
						
							|  |  |  | 		case policyPrefix: | 
					
						
							|  |  |  | 			policyName := path.Dir(strings.TrimPrefix(string(event.Kv.Key), | 
					
						
							|  |  |  | 				iamConfigPoliciesPrefix)) | 
					
						
							|  |  |  | 			reloadEtcdPolicy(ctx, iamConfigPoliciesPrefix, | 
					
						
							|  |  |  | 				policyName, sys.iamCannedPolicyMap) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case eventDelete: | 
					
						
							|  |  |  | 		switch { | 
					
						
							|  |  |  | 		case usersPrefix: | 
					
						
							|  |  |  | 			accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key), | 
					
						
							|  |  |  | 				iamConfigUsersPrefix)) | 
					
						
							|  |  |  | 			delete(sys.iamUsersMap, accessKey) | 
					
						
							|  |  |  | 			delete(sys.iamPolicyMap, accessKey) | 
					
						
							|  |  |  | 		case stsPrefix: | 
					
						
							|  |  |  | 			accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key), | 
					
						
							|  |  |  | 				iamConfigSTSPrefix)) | 
					
						
							|  |  |  | 			delete(sys.iamUsersMap, accessKey) | 
					
						
							|  |  |  | 			delete(sys.iamPolicyMap, accessKey) | 
					
						
							|  |  |  | 		case policyPrefix: | 
					
						
							|  |  |  | 			policyName := path.Dir(strings.TrimPrefix(string(event.Kv.Key), | 
					
						
							|  |  |  | 				iamConfigPoliciesPrefix)) | 
					
						
							|  |  |  | 			delete(sys.iamCannedPolicyMap, policyName) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Watch etcd entries for IAM
 | 
					
						
							|  |  |  | func (sys *IAMSys) watchIAMEtcd() { | 
					
						
							|  |  |  | 	watchEtcd := func() { | 
					
						
							|  |  |  | 		// Refresh IAMSys with etcd watch.
 | 
					
						
							|  |  |  | 		for { | 
					
						
							|  |  |  | 			watchCh := globalEtcdClient.Watch(context.Background(), | 
					
						
							|  |  |  | 				iamConfigPrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) | 
					
						
							|  |  |  | 			select { | 
					
						
							|  |  |  | 			case <-GlobalServiceDoneCh: | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			case watchResp, ok := <-watchCh: | 
					
						
							|  |  |  | 				if !ok { | 
					
						
							|  |  |  | 					time.Sleep(1 * time.Second) | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if err := watchResp.Err(); err != nil { | 
					
						
							|  |  |  | 					logger.LogIf(context.Background(), err) | 
					
						
							|  |  |  | 					// log and retry.
 | 
					
						
							|  |  |  | 					time.Sleep(1 * time.Second) | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				for _, event := range watchResp.Events { | 
					
						
							|  |  |  | 					sys.Lock() | 
					
						
							|  |  |  | 					sys.reloadFromEvent(event) | 
					
						
							|  |  |  | 					sys.Unlock() | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	go watchEtcd() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (sys *IAMSys) watchIAMDisk(objAPI ObjectLayer) { | 
					
						
							|  |  |  | 	watchDisk := func() { | 
					
						
							|  |  |  | 		ticker := time.NewTicker(globalRefreshIAMInterval) | 
					
						
							|  |  |  | 		defer ticker.Stop() | 
					
						
							|  |  |  | 		for { | 
					
						
							|  |  |  | 			select { | 
					
						
							|  |  |  | 			case <-GlobalServiceDoneCh: | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			case <-ticker.C: | 
					
						
							|  |  |  | 				sys.refresh(objAPI) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Refresh IAMSys in background.
 | 
					
						
							|  |  |  | 	go watchDisk() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // Init - initializes config system from iam.json
 | 
					
						
							|  |  |  | func (sys *IAMSys) Init(objAPI ObjectLayer) error { | 
					
						
							|  |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		defer sys.watchIAMEtcd() | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		defer sys.watchIAMDisk(objAPI) | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	doneCh := make(chan struct{}) | 
					
						
							|  |  |  | 	defer close(doneCh) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Initializing IAM needs a retry mechanism for
 | 
					
						
							|  |  |  | 	// the following reasons:
 | 
					
						
							|  |  |  | 	//  - Read quorum is lost just after the initialization
 | 
					
						
							|  |  |  | 	//    of the object layer.
 | 
					
						
							| 
									
										
										
										
											2019-02-13 20:59:36 +08:00
										 |  |  | 	for range newRetryTimerSimple(doneCh) { | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | 		if globalEtcdClient != nil { | 
					
						
							|  |  |  | 			return sys.refreshEtcd() | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-13 20:59:36 +08:00
										 |  |  | 		// Load IAMSys once during boot.
 | 
					
						
							|  |  |  | 		if err := sys.refresh(objAPI); err != nil { | 
					
						
							|  |  |  | 			if err == errDiskNotFound || | 
					
						
							|  |  |  | 				strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) || | 
					
						
							|  |  |  | 				strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) { | 
					
						
							|  |  |  | 				logger.Info("Waiting for IAM subsystem to be initialized..") | 
					
						
							|  |  |  | 				continue | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-02-13 20:59:36 +08:00
										 |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-02-13 20:59:36 +08:00
										 |  |  | 		break | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-13 20:59:36 +08:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	if policyName == "" { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	pFile := pathJoin(iamConfigPoliciesPrefix, policyName, iamPolicyFile) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		err = deleteConfigEtcd(context.Background(), globalEtcdClient, pFile) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		err = deleteConfig(context.Background(), objectAPI, pFile) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch err.(type) { | 
					
						
							|  |  |  | 	case ObjectNotFound: | 
					
						
							|  |  |  | 		// Ignore error if policy is already deleted.
 | 
					
						
							|  |  |  | 		err = nil | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	delete(sys.iamCannedPolicyMap, policyName) | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // ListPolicies - lists all canned policies.
 | 
					
						
							|  |  |  | func (sys *IAMSys) ListPolicies() (map[string][]byte, error) { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return nil, errServerNotInitialized | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	var cannedPolicyMap = make(map[string][]byte) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.RLock() | 
					
						
							|  |  |  | 	defer sys.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for k, v := range sys.iamCannedPolicyMap { | 
					
						
							|  |  |  | 		data, err := json.Marshal(v) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cannedPolicyMap[k] = data | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cannedPolicyMap, nil | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | // SetPolicy - sets a new canned policy.
 | 
					
						
							|  |  |  | func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	if p.IsEmpty() || policyName == "" { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	configFile := pathJoin(iamConfigPoliciesPrefix, policyName, iamPolicyFile) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	data, err := json.Marshal(p) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfig(context.Background(), objectAPI, configFile, data) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	sys.iamCannedPolicyMap[policyName] = p | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | // SetUserPolicy - sets policy to given user name.
 | 
					
						
							|  |  |  | func (sys *IAMSys) SetUserPolicy(accessKey, policyName string) error { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if _, ok := sys.iamUsersMap[accessKey]; !ok { | 
					
						
							|  |  |  | 		return errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if _, ok := sys.iamCannedPolicyMap[policyName]; !ok { | 
					
						
							|  |  |  | 		return errNoSuchPolicy | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data, err := json.Marshal(policyName) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	configFile := pathJoin(iamConfigUsersPrefix, accessKey, iamPolicyFile) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfig(context.Background(), objectAPI, configFile, data) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	sys.iamPolicyMap[accessKey] = policyName | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DeleteUser - set user credentials.
 | 
					
						
							|  |  |  | func (sys *IAMSys) DeleteUser(accessKey string) error { | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	pFile := pathJoin(iamConfigUsersPrefix, accessKey, iamPolicyFile) | 
					
						
							|  |  |  | 	iFile := pathJoin(iamConfigUsersPrefix, accessKey, iamIdentityFile) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		// It is okay to ignore errors when deleting policy.json for the user.
 | 
					
						
							|  |  |  | 		deleteConfigEtcd(context.Background(), globalEtcdClient, pFile) | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = deleteConfigEtcd(context.Background(), globalEtcdClient, iFile) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		// It is okay to ignore errors when deleting policy.json for the user.
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		_ = deleteConfig(context.Background(), objectAPI, pFile) | 
					
						
							|  |  |  | 		err = deleteConfig(context.Background(), objectAPI, iFile) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	switch err.(type) { | 
					
						
							|  |  |  | 	case ObjectNotFound: | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	delete(sys.iamUsersMap, accessKey) | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	delete(sys.iamPolicyMap, accessKey) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-30 02:08:59 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 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 != "" { | 
					
						
							|  |  |  | 		p, ok := sys.iamCannedPolicyMap[policyName] | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			return errInvalidArgument | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if p.IsEmpty() { | 
					
						
							|  |  |  | 			delete(sys.iamPolicyMap, accessKey) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		data, err := json.Marshal(policyName) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		configFile := pathJoin(iamConfigSTSPrefix, accessKey, iamPolicyFile) | 
					
						
							|  |  |  | 		if globalEtcdClient != nil { | 
					
						
							|  |  |  | 			err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			err = saveConfig(context.Background(), objectAPI, configFile, data) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sys.iamPolicyMap[accessKey] = policyName | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	configFile := pathJoin(iamConfigSTSPrefix, accessKey, iamIdentityFile) | 
					
						
							|  |  |  | 	data, err := json.Marshal(cred) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfig(context.Background(), objectAPI, configFile, data) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap[accessKey] = cred | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-28 09:46:55 +08:00
										 |  |  | // GetUserPolicy - returns canned policy name associated with a user.
 | 
					
						
							|  |  |  | func (sys *IAMSys) GetUserPolicy(accessKey string) (policyName string, err error) { | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return "", errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.RLock() | 
					
						
							|  |  |  | 	defer sys.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if _, ok := sys.iamUsersMap[accessKey]; !ok { | 
					
						
							|  |  |  | 		return "", errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if _, ok := sys.iamPolicyMap[accessKey]; !ok { | 
					
						
							|  |  |  | 		return "", errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sys.iamPolicyMap[accessKey], nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 15:18:43 +08:00
										 |  |  | // ListUsers - list all users.
 | 
					
						
							|  |  |  | func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return nil, errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var users = make(map[string]madmin.UserInfo) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.RLock() | 
					
						
							|  |  |  | 	defer sys.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for k, v := range sys.iamUsersMap { | 
					
						
							|  |  |  | 		users[k] = madmin.UserInfo{ | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 			PolicyName: sys.iamPolicyMap[k], | 
					
						
							|  |  |  | 			Status:     madmin.AccountStatus(v.Status), | 
					
						
							| 
									
										
										
										
											2018-10-13 15:18:43 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return users, 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 { | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if status != madmin.AccountEnabled && status != madmin.AccountDisabled { | 
					
						
							|  |  |  | 		return errInvalidArgument | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, ok := sys.iamUsersMap[accessKey] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uinfo := madmin.UserInfo{ | 
					
						
							|  |  |  | 		SecretKey: cred.SecretKey, | 
					
						
							|  |  |  | 		Status:    status, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	configFile := pathJoin(iamConfigUsersPrefix, accessKey, iamIdentityFile) | 
					
						
							|  |  |  | 	data, err := json.Marshal(uinfo) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if globalEtcdClient != nil { | 
					
						
							|  |  |  | 		err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = saveConfig(context.Background(), objectAPI, configFile, data) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap[accessKey] = auth.Credentials{ | 
					
						
							|  |  |  | 		AccessKey: accessKey, | 
					
						
							|  |  |  | 		SecretKey: uinfo.SecretKey, | 
					
						
							|  |  |  | 		Status:    string(uinfo.Status), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // SetUser - set user credentials.
 | 
					
						
							|  |  |  | func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	configFile := pathJoin(iamConfigUsersPrefix, accessKey, iamIdentityFile) | 
					
						
							|  |  |  | 	data, err := json.Marshal(uinfo) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	if globalEtcdClient != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		err = saveConfig(context.Background(), objectAPI, configFile, data) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap[accessKey] = auth.Credentials{ | 
					
						
							|  |  |  | 		AccessKey: accessKey, | 
					
						
							|  |  |  | 		SecretKey: uinfo.SecretKey, | 
					
						
							|  |  |  | 		Status:    string(uinfo.Status), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-30 04:18:46 +08:00
										 |  |  | // SetUserSecretKey - sets user secret key
 | 
					
						
							|  |  |  | func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { | 
					
						
							|  |  |  | 	objectAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, ok := sys.iamUsersMap[accessKey] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uinfo := madmin.UserInfo{ | 
					
						
							|  |  |  | 		SecretKey: secretKey, | 
					
						
							|  |  |  | 		Status:    madmin.AccountStatus(cred.Status), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	configFile := pathJoin(iamConfigUsersPrefix, accessKey, iamIdentityFile) | 
					
						
							|  |  |  | 	data, err := json.Marshal(uinfo) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if globalEtcdClient != nil { | 
					
						
							|  |  |  | 		err = saveConfigEtcd(context.Background(), globalEtcdClient, configFile, data) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		err = saveConfig(context.Background(), objectAPI, configFile, data) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap[accessKey] = auth.Credentials{ | 
					
						
							|  |  |  | 		AccessKey: accessKey, | 
					
						
							|  |  |  | 		SecretKey: secretKey, | 
					
						
							|  |  |  | 		Status:    string(uinfo.Status), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) { | 
					
						
							|  |  |  | 	sys.RLock() | 
					
						
							|  |  |  | 	defer sys.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cred, ok = sys.iamUsersMap[accessKey] | 
					
						
							|  |  |  | 	return cred, ok && cred.IsValid() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | // 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 { | 
					
						
							|  |  |  | 	pname, ok := args.Claims[iampolicy.PolicyName] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// When claims are set, it should have a "policy" field.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pnameStr, ok := pname.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// When claims has "policy" field, it should be string.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	sys.RLock() | 
					
						
							|  |  |  | 	defer sys.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	// If policy is available for given user, check the policy.
 | 
					
						
							|  |  |  | 	name, ok := sys.iamPolicyMap[args.AccountName] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// No policy available reject.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if pnameStr != name { | 
					
						
							|  |  |  | 		// When claims has a policy, it should match the
 | 
					
						
							|  |  |  | 		// policy of args.AccountName which server remembers.
 | 
					
						
							|  |  |  | 		// if not reject such requests.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Now check if we have a sessionPolicy.
 | 
					
						
							|  |  |  | 	spolicy, ok := args.Claims[iampolicy.SessionPolicyName] | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// Sub policy not set, this is most common since subPolicy
 | 
					
						
							|  |  |  | 		// is optional, use the top level policy only.
 | 
					
						
							|  |  |  | 		p, ok := sys.iamCannedPolicyMap[pnameStr] | 
					
						
							|  |  |  | 		return ok && p.IsAllowed(args) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spolicyStr, ok := spolicy.(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		// Sub policy if set, should be a string reject
 | 
					
						
							|  |  |  | 		// malformed/malicious requests.
 | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check if policy is parseable.
 | 
					
						
							|  |  |  | 	subPolicy, err := iampolicy.ParseConfig(bytes.NewReader([]byte(spolicyStr))) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		// Log any error in input session policy config.
 | 
					
						
							|  |  |  | 		logger.LogIf(context.Background(), err) | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Policy without Version string value reject it.
 | 
					
						
							|  |  |  | 	if subPolicy.Version == "" { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Sub policy is set and valid.
 | 
					
						
							|  |  |  | 	p, ok := sys.iamCannedPolicyMap[pnameStr] | 
					
						
							|  |  |  | 	return ok && p.IsAllowed(args) && subPolicy.IsAllowed(args) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 { | 
					
						
							|  |  |  | 		return globalPolicyOPA.IsAllowed(args) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 06:28:33 +08:00
										 |  |  | 	// With claims set, we should do STS related checks and validation.
 | 
					
						
							|  |  |  | 	if len(args.Claims) > 0 { | 
					
						
							|  |  |  | 		return sys.IsAllowedSTS(args) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.RLock() | 
					
						
							|  |  |  | 	defer sys.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	// If policy is available for given user, check the policy.
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	if name, found := sys.iamPolicyMap[args.AccountName]; found { | 
					
						
							|  |  |  | 		p, ok := sys.iamCannedPolicyMap[name] | 
					
						
							|  |  |  | 		return ok && p.IsAllowed(args) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// As policy is not available and OPA is not configured, return the owner value.
 | 
					
						
							|  |  |  | 	return args.IsOwner | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-19 01:36:45 +08:00
										 |  |  | var defaultContextTimeout = 30 * time.Second | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | func etcdKvsToSet(prefix string, kvs []*mvccpb.KeyValue) set.StringSet { | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 	users := set.NewStringSet() | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	for _, kv := range kvs { | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 		// Extract user by stripping off the `prefix` value as suffix,
 | 
					
						
							|  |  |  | 		// then strip off the remaining basename to obtain the prefix
 | 
					
						
							|  |  |  | 		// value, usually in the following form.
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		//  key := "config/iam/users/newuser/identity.json"
 | 
					
						
							|  |  |  | 		//  prefix := "config/iam/users/"
 | 
					
						
							|  |  |  | 		//  v := trim(trim(key, prefix), base(key)) == "newuser"
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2018-10-25 08:40:06 +08:00
										 |  |  | 		user := path.Clean(strings.TrimSuffix(strings.TrimPrefix(string(kv.Key), prefix), path.Base(string(kv.Key)))) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 		if !users.Contains(user) { | 
					
						
							|  |  |  | 			users.Add(user) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	return users | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Similar to reloadUsers but updates users, policies maps from etcd server,
 | 
					
						
							|  |  |  | func reloadEtcdUsers(prefix string, usersMap map[string]auth.Credentials, policyMap map[string]string) error { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 	r, err := globalEtcdClient.Get(ctx, prefix, etcd.WithPrefix(), etcd.WithKeysOnly()) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// No users are created yet.
 | 
					
						
							|  |  |  | 	if r.Count == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	users := etcdKvsToSet(prefix, r.Kvs) | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Reload config and policies for all users.
 | 
					
						
							|  |  |  | 	for _, user := range users.ToSlice() { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		if err = reloadEtcdUser(ctx, prefix, user, usersMap, policyMap); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | func reloadEtcdPolicy(ctx context.Context, prefix string, policyName string, | 
					
						
							|  |  |  | 	cannedPolicyMap map[string]iampolicy.Policy) error { | 
					
						
							|  |  |  | 	pFile := pathJoin(prefix, policyName, iamPolicyFile) | 
					
						
							|  |  |  | 	pdata, err := readConfigEtcd(ctx, globalEtcdClient, pFile) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var p iampolicy.Policy | 
					
						
							|  |  |  | 	if err = json.Unmarshal(pdata, &p); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cannedPolicyMap[policyName] = p | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | func reloadEtcdPolicies(prefix string, cannedPolicyMap map[string]iampolicy.Policy) error { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2019-01-19 01:36:45 +08:00
										 |  |  | 	r, err := globalEtcdClient.Get(ctx, prefix, etcd.WithPrefix(), etcd.WithKeysOnly()) | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// No users are created yet.
 | 
					
						
							|  |  |  | 	if r.Count == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	policies := etcdKvsToSet(prefix, r.Kvs) | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Reload config and policies for all policys.
 | 
					
						
							|  |  |  | 	for _, policyName := range policies.ToSlice() { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 		if err = reloadEtcdPolicy(ctx, prefix, policyName, cannedPolicyMap); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | func reloadPolicy(ctx context.Context, objectAPI ObjectLayer, prefix string, | 
					
						
							|  |  |  | 	policyName string, cannedPolicyMap map[string]iampolicy.Policy) error { | 
					
						
							|  |  |  | 	pFile := pathJoin(prefix, policyName, iamPolicyFile) | 
					
						
							|  |  |  | 	pdata, err := readConfig(context.Background(), objectAPI, pFile) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var p iampolicy.Policy | 
					
						
							|  |  |  | 	if err = json.Unmarshal(pdata, &p); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-13 05:49:45 +08:00
										 |  |  | 	cannedPolicyMap[policyName] = p | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | func reloadPolicies(objectAPI ObjectLayer, prefix string, cannedPolicyMap map[string]iampolicy.Policy) error { | 
					
						
							|  |  |  | 	marker := "" | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		var lo ListObjectsInfo | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		lo, err = objectAPI.ListObjects(context.Background(), minioMetaBucket, prefix, marker, "/", 1000) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		marker = lo.NextMarker | 
					
						
							|  |  |  | 		for _, prefix := range lo.Prefixes { | 
					
						
							| 
									
										
										
										
											2019-06-13 05:49:45 +08:00
										 |  |  | 			if err = reloadPolicy(context.Background(), objectAPI, iamConfigPoliciesPrefix, | 
					
						
							|  |  |  | 				path.Base(prefix), cannedPolicyMap); err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if !lo.IsTruncated { | 
					
						
							|  |  |  | 			break | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 02:32:18 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | func reloadEtcdUser(ctx context.Context, prefix string, accessKey string, | 
					
						
							|  |  |  | 	usersMap map[string]auth.Credentials, policyMap map[string]string) error { | 
					
						
							|  |  |  | 	idFile := pathJoin(prefix, accessKey, iamIdentityFile) | 
					
						
							|  |  |  | 	pFile := pathJoin(prefix, accessKey, iamPolicyFile) | 
					
						
							|  |  |  | 	cdata, cerr := readConfigEtcd(ctx, globalEtcdClient, idFile) | 
					
						
							|  |  |  | 	pdata, perr := readConfigEtcd(ctx, globalEtcdClient, pFile) | 
					
						
							|  |  |  | 	if cerr != nil && cerr != errConfigNotFound { | 
					
						
							|  |  |  | 		return cerr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if perr != nil && perr != errConfigNotFound { | 
					
						
							|  |  |  | 		return perr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if cerr == errConfigNotFound && perr == errConfigNotFound { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if cerr == nil { | 
					
						
							|  |  |  | 		var cred auth.Credentials | 
					
						
							|  |  |  | 		if err := json.Unmarshal(cdata, &cred); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cred.AccessKey = path.Base(accessKey) | 
					
						
							|  |  |  | 		if cred.IsExpired() { | 
					
						
							|  |  |  | 			// Delete expired identity.
 | 
					
						
							|  |  |  | 			deleteConfigEtcd(ctx, globalEtcdClient, idFile) | 
					
						
							|  |  |  | 			// Delete expired identity policy.
 | 
					
						
							|  |  |  | 			deleteConfigEtcd(ctx, globalEtcdClient, pFile) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		usersMap[cred.AccessKey] = cred | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if perr == nil { | 
					
						
							|  |  |  | 		var policyName string | 
					
						
							|  |  |  | 		if err := json.Unmarshal(pdata, &policyName); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		policyMap[path.Base(accessKey)] = policyName | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func reloadUser(ctx context.Context, objectAPI ObjectLayer, prefix string, accessKey string, | 
					
						
							|  |  |  | 	usersMap map[string]auth.Credentials, policyMap map[string]string) error { | 
					
						
							|  |  |  | 	idFile := pathJoin(prefix, accessKey, iamIdentityFile) | 
					
						
							|  |  |  | 	pFile := pathJoin(prefix, accessKey, iamPolicyFile) | 
					
						
							|  |  |  | 	cdata, cerr := readConfig(ctx, objectAPI, idFile) | 
					
						
							|  |  |  | 	pdata, perr := readConfig(ctx, objectAPI, pFile) | 
					
						
							|  |  |  | 	if cerr != nil && cerr != errConfigNotFound { | 
					
						
							|  |  |  | 		return cerr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if perr != nil && perr != errConfigNotFound { | 
					
						
							|  |  |  | 		return perr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if cerr == errConfigNotFound && perr == errConfigNotFound { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if cerr == nil { | 
					
						
							|  |  |  | 		var cred auth.Credentials | 
					
						
							|  |  |  | 		if err := json.Unmarshal(cdata, &cred); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cred.AccessKey = path.Base(accessKey) | 
					
						
							|  |  |  | 		if cred.IsExpired() { | 
					
						
							|  |  |  | 			// Delete expired identity.
 | 
					
						
							|  |  |  | 			objectAPI.DeleteObject(context.Background(), minioMetaBucket, idFile) | 
					
						
							|  |  |  | 			// Delete expired identity policy.
 | 
					
						
							|  |  |  | 			objectAPI.DeleteObject(context.Background(), minioMetaBucket, pFile) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		usersMap[cred.AccessKey] = cred | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if perr == nil { | 
					
						
							|  |  |  | 		var policyName string | 
					
						
							|  |  |  | 		if err := json.Unmarshal(pdata, &policyName); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		policyMap[path.Base(accessKey)] = policyName | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // reloadUsers reads an updates users, policies from object layer into user and policy maps.
 | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | func reloadUsers(objectAPI ObjectLayer, prefix string, usersMap map[string]auth.Credentials, policyMap map[string]string) error { | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	marker := "" | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		var lo ListObjectsInfo | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		lo, err = objectAPI.ListObjects(context.Background(), minioMetaBucket, prefix, marker, "/", 1000) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		marker = lo.NextMarker | 
					
						
							|  |  |  | 		for _, prefix := range lo.Prefixes { | 
					
						
							| 
									
										
										
										
											2019-06-07 08:46:22 +08:00
										 |  |  | 			// Prefix is empty because prefix is already part of the List output.
 | 
					
						
							|  |  |  | 			if err = reloadUser(context.Background(), objectAPI, "", prefix, usersMap, policyMap); err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !lo.IsTruncated { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | func (sys *IAMSys) refreshEtcd() error { | 
					
						
							|  |  |  | 	iamUsersMap := make(map[string]auth.Credentials) | 
					
						
							|  |  |  | 	iamPolicyMap := make(map[string]string) | 
					
						
							|  |  |  | 	iamCannedPolicyMap := make(map[string]iampolicy.Policy) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := reloadEtcdPolicies(iamConfigPoliciesPrefix, iamCannedPolicyMap); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := reloadEtcdUsers(iamConfigUsersPrefix, iamUsersMap, iamPolicyMap); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := reloadEtcdUsers(iamConfigSTSPrefix, iamUsersMap, iamPolicyMap); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Sets default canned policies, if none are set.
 | 
					
						
							|  |  |  | 	setDefaultCannedPolicies(iamCannedPolicyMap) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap = iamUsersMap | 
					
						
							|  |  |  | 	sys.iamPolicyMap = iamPolicyMap | 
					
						
							|  |  |  | 	sys.iamCannedPolicyMap = iamCannedPolicyMap | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | // Refresh IAMSys.
 | 
					
						
							|  |  |  | func (sys *IAMSys) refresh(objAPI ObjectLayer) error { | 
					
						
							|  |  |  | 	iamUsersMap := make(map[string]auth.Credentials) | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	iamPolicyMap := make(map[string]string) | 
					
						
							|  |  |  | 	iamCannedPolicyMap := make(map[string]iampolicy.Policy) | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | 	if err := reloadPolicies(objAPI, iamConfigPoliciesPrefix, iamCannedPolicyMap); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := reloadUsers(objAPI, iamConfigUsersPrefix, iamUsersMap, iamPolicyMap); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := reloadUsers(objAPI, iamConfigSTSPrefix, iamUsersMap, iamPolicyMap); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 21:18:50 +08:00
										 |  |  | 	// Sets default canned policies, if none are set.
 | 
					
						
							| 
									
										
										
										
											2018-10-25 08:14:27 +08:00
										 |  |  | 	setDefaultCannedPolicies(iamCannedPolicyMap) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.iamUsersMap = iamUsersMap | 
					
						
							|  |  |  | 	sys.iamPolicyMap = iamPolicyMap | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 	sys.iamCannedPolicyMap = iamCannedPolicyMap | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewIAMSys - creates new config system object.
 | 
					
						
							|  |  |  | func NewIAMSys() *IAMSys { | 
					
						
							|  |  |  | 	return &IAMSys{ | 
					
						
							| 
									
										
										
										
											2018-10-17 03:48:19 +08:00
										 |  |  | 		iamUsersMap:        make(map[string]auth.Credentials), | 
					
						
							|  |  |  | 		iamPolicyMap:       make(map[string]string), | 
					
						
							|  |  |  | 		iamCannedPolicyMap: make(map[string]iampolicy.Policy), | 
					
						
							| 
									
										
										
										
											2018-10-10 05:00:01 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } |