| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 	"path" | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2020-07-18 08:41:29 +08:00
										 |  |  | 	"unicode/utf8" | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-11 17:02:32 +08:00
										 |  |  | 	jsoniter "github.com/json-iterator/go" | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/auth" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/config" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/kms" | 
					
						
							|  |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2021-05-30 12:16:42 +08:00
										 |  |  | 	iampolicy "github.com/minio/pkg/iam/policy" | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IAMObjectStore implements IAMStorageAPI
 | 
					
						
							|  |  |  | type IAMObjectStore struct { | 
					
						
							|  |  |  | 	// Protect assignment to objAPI
 | 
					
						
							|  |  |  | 	sync.RWMutex | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	objAPI ObjectLayer | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func newIAMObjectStore(objAPI ObjectLayer) *IAMObjectStore { | 
					
						
							|  |  |  | 	return &IAMObjectStore{objAPI: objAPI} | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) lock() { | 
					
						
							|  |  |  | 	iamOS.Lock() | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) unlock() { | 
					
						
							|  |  |  | 	iamOS.Unlock() | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) rlock() { | 
					
						
							|  |  |  | 	iamOS.RLock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (iamOS *IAMObjectStore) runlock() { | 
					
						
							|  |  |  | 	iamOS.RUnlock() | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Migrate users directory in a single scan.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 1. Migrate user policy from:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // `iamConfigUsersPrefix + "<username>/policy.json"`
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // to:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // `iamConfigPolicyDBUsersPrefix + "<username>.json"`.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 2. Add versioning to the policy json file in the new
 | 
					
						
							|  |  |  | // location.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 3. Migrate user identity json file to include version info.
 | 
					
						
							| 
									
										
										
										
											2021-05-20 10:25:44 +08:00
										 |  |  | func (iamOS *IAMObjectStore) migrateUsersConfigToV1(ctx context.Context) error { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	basePrefix := iamConfigUsersPrefix | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 	for item := range listIAMConfigItems(ctx, iamOS.objAPI, basePrefix) { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		if item.Err != nil { | 
					
						
							|  |  |  | 			return item.Err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 		user := path.Dir(item.Item) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			// 1. check if there is policy file in old location.
 | 
					
						
							|  |  |  | 			oldPolicyPath := pathJoin(basePrefix, user, iamPolicyFile) | 
					
						
							|  |  |  | 			var policyName string | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 			if err := iamOS.loadIAMConfig(ctx, &policyName, oldPolicyPath); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 				switch err { | 
					
						
							|  |  |  | 				case errConfigNotFound: | 
					
						
							|  |  |  | 					// This case means it is already
 | 
					
						
							|  |  |  | 					// migrated or there is no policy on
 | 
					
						
							|  |  |  | 					// user.
 | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					// File may be corrupt or network error
 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Nothing to do on the policy file,
 | 
					
						
							|  |  |  | 				// so move on to check the id file.
 | 
					
						
							|  |  |  | 				goto next | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 2. copy policy file to new location.
 | 
					
						
							|  |  |  | 			mp := newMappedPolicy(policyName) | 
					
						
							| 
									
										
										
										
											2021-07-10 02:17:21 +08:00
										 |  |  | 			userType := regUser | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 			if err := iamOS.saveMappedPolicy(ctx, user, userType, false, mp); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 3. delete policy file from old
 | 
					
						
							|  |  |  | 			// location. Ignore error.
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 			iamOS.deleteIAMConfig(ctx, oldPolicyPath) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	next: | 
					
						
							|  |  |  | 		// 4. check if user identity has old format.
 | 
					
						
							|  |  |  | 		identityPath := pathJoin(basePrefix, user, iamIdentityFile) | 
					
						
							| 
									
										
										
										
											2021-05-20 10:25:44 +08:00
										 |  |  | 		var cred = auth.Credentials{ | 
					
						
							|  |  |  | 			AccessKey: user, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := iamOS.loadIAMConfig(ctx, &cred, identityPath); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-31 01:41:02 +08:00
										 |  |  | 			switch err { | 
					
						
							|  |  |  | 			case errConfigNotFound: | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 				// This should not happen.
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				// File may be corrupt or network error
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// If the file is already in the new format,
 | 
					
						
							|  |  |  | 		// then the parsed auth.Credentials will have
 | 
					
						
							|  |  |  | 		// the zero value for the struct.
 | 
					
						
							| 
									
										
										
										
											2021-05-20 10:25:44 +08:00
										 |  |  | 		if !cred.IsValid() { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			// nothing to do
 | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		u := newUserIdentity(cred) | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := iamOS.saveIAMConfig(ctx, u, identityPath); err != nil { | 
					
						
							| 
									
										
										
										
											2020-08-14 00:16:01 +08:00
										 |  |  | 			logger.LogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Nothing to delete as identity file location
 | 
					
						
							|  |  |  | 		// has not changed.
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) migrateToV1(ctx context.Context) error { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	var iamFmt iamFormat | 
					
						
							|  |  |  | 	path := getIAMFormatFilePath() | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := iamOS.loadIAMConfig(ctx, &iamFmt, path); err != nil { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		switch err { | 
					
						
							|  |  |  | 		case errConfigNotFound: | 
					
						
							|  |  |  | 			// Need to migrate to V1.
 | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2021-05-19 06:19:20 +08:00
										 |  |  | 			// if IAM format
 | 
					
						
							| 
									
										
										
										
											2019-08-31 01:41:02 +08:00
										 |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-20 10:25:44 +08:00
										 |  |  | 	if iamFmt.Version >= iamFormatVersion1 { | 
					
						
							|  |  |  | 		// Nothing to do.
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-20 10:25:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err := iamOS.migrateUsersConfigToV1(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 		logger.LogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-20 10:25:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	// Save iam format to version 1.
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	if err := iamOS.saveIAMConfig(ctx, newIAMFormatVersion1(), path); err != nil { | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 		logger.LogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Should be called under config migration lock
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) migrateBackendFormat(ctx context.Context) error { | 
					
						
							|  |  |  | 	return iamOS.migrateToV1(ctx) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 23:45:30 +08:00
										 |  |  | func (iamOS *IAMObjectStore) saveIAMConfig(ctx context.Context, item interface{}, objPath string, opts ...options) error { | 
					
						
							| 
									
										
										
										
											2021-05-19 06:19:20 +08:00
										 |  |  | 	var json = jsoniter.ConfigCompatibleWithStandardLibrary | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	data, err := json.Marshal(item) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-22 23:45:30 +08:00
										 |  |  | 	if GlobalKMS != nil { | 
					
						
							|  |  |  | 		data, err = config.EncryptBytes(GlobalKMS, data, kms.Context{ | 
					
						
							|  |  |  | 			minioMetaBucket: path.Join(minioMetaBucket, objPath), | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-22 23:45:30 +08:00
										 |  |  | 	return saveConfig(ctx, iamOS.objAPI, objPath, data) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-22 23:45:30 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadIAMConfig(ctx context.Context, item interface{}, objPath string) error { | 
					
						
							|  |  |  | 	data, err := readConfig(ctx, iamOS.objAPI, objPath) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-19 06:19:20 +08:00
										 |  |  | 	if !utf8.Valid(data) && GlobalKMS != nil { | 
					
						
							|  |  |  | 		data, err = config.DecryptBytes(GlobalKMS, data, kms.Context{ | 
					
						
							|  |  |  | 			minioMetaBucket: path.Join(minioMetaBucket, objPath), | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2019-11-02 06:53:16 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-11 17:02:32 +08:00
										 |  |  | 	var json = jsoniter.ConfigCompatibleWithStandardLibrary | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	return json.Unmarshal(data, item) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) deleteIAMConfig(ctx context.Context, path string) error { | 
					
						
							|  |  |  | 	return deleteConfig(ctx, iamOS.objAPI, path) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	var p iampolicy.Policy | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := iamOS.loadIAMConfig(ctx, &p, getPolicyDocPath(policy)) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 		if err == errConfigNotFound { | 
					
						
							|  |  |  | 			return errNoSuchPolicy | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m[policy] = p | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error { | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 	for item := range listIAMConfigItems(ctx, iamOS.objAPI, iamConfigPoliciesPrefix) { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		if item.Err != nil { | 
					
						
							|  |  |  | 			return item.Err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 		policyName := path.Dir(item.Item) | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := iamOS.loadPolicyDoc(ctx, policyName, m); err != nil && err != errNoSuchPolicy { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadUser(ctx context.Context, user string, userType IAMUserType, m map[string]auth.Credentials) error { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	var u UserIdentity | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := iamOS.loadIAMConfig(ctx, &u, getUserIdentityPath(user, userType)) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 		if err == errConfigNotFound { | 
					
						
							|  |  |  | 			return errNoSuchUser | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if u.Credentials.IsExpired() { | 
					
						
							|  |  |  | 		// Delete expired identity - ignoring errors here.
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		iamOS.deleteIAMConfig(ctx, getUserIdentityPath(user, userType)) | 
					
						
							|  |  |  | 		iamOS.deleteIAMConfig(ctx, getMappedPolicyPath(user, userType, false)) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if u.Credentials.AccessKey == "" { | 
					
						
							|  |  |  | 		u.Credentials.AccessKey = user | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-06 04:08:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	m[user] = u.Credentials | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadUsers(ctx context.Context, userType IAMUserType, m map[string]auth.Credentials) error { | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	var basePrefix string | 
					
						
							|  |  |  | 	switch userType { | 
					
						
							| 
									
										
										
										
											2021-07-10 02:17:21 +08:00
										 |  |  | 	case svcUser: | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 		basePrefix = iamConfigServiceAccountsPrefix | 
					
						
							|  |  |  | 	case stsUser: | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		basePrefix = iamConfigSTSPrefix | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		basePrefix = iamConfigUsersPrefix | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 	for item := range listIAMConfigItems(ctx, iamOS.objAPI, basePrefix) { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		if item.Err != nil { | 
					
						
							|  |  |  | 			return item.Err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 		userName := path.Dir(item.Item) | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := iamOS.loadUser(ctx, userName, userType, m); err != nil && err != errNoSuchUser { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadGroup(ctx context.Context, group string, m map[string]GroupInfo) error { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	var g GroupInfo | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := iamOS.loadIAMConfig(ctx, &g, getGroupInfoPath(group)) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 		if err == errConfigNotFound { | 
					
						
							|  |  |  | 			return errNoSuchGroup | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m[group] = g | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadGroups(ctx context.Context, m map[string]GroupInfo) error { | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 	for item := range listIAMConfigItems(ctx, iamOS.objAPI, iamConfigGroupsPrefix) { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		if item.Err != nil { | 
					
						
							|  |  |  | 			return item.Err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 		group := path.Dir(item.Item) | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := iamOS.loadGroup(ctx, group, m); err != nil && err != errNoSuchGroup { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	m map[string]MappedPolicy) error { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var p MappedPolicy | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 	err := iamOS.loadIAMConfig(ctx, &p, getMappedPolicyPath(name, userType, isGroup)) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 		if err == errConfigNotFound { | 
					
						
							|  |  |  | 			return errNoSuchPolicy | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m[name] = p | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	var basePath string | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	if isGroup { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		basePath = iamConfigPolicyDBGroupsPrefix | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		switch userType { | 
					
						
							| 
									
										
										
										
											2021-07-10 02:17:21 +08:00
										 |  |  | 		case svcUser: | 
					
						
							| 
									
										
										
										
											2020-03-18 01:36:13 +08:00
										 |  |  | 			basePath = iamConfigPolicyDBServiceAccountsPrefix | 
					
						
							|  |  |  | 		case stsUser: | 
					
						
							|  |  |  | 			basePath = iamConfigPolicyDBSTSUsersPrefix | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			basePath = iamConfigPolicyDBUsersPrefix | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 	for item := range listIAMConfigItems(ctx, iamOS.objAPI, basePath) { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		if item.Err != nil { | 
					
						
							|  |  |  | 			return item.Err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		policyFile := item.Item | 
					
						
							|  |  |  | 		userOrGroupName := strings.TrimSuffix(policyFile, ".json") | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | 		if err := iamOS.loadMappedPolicy(ctx, userOrGroupName, userType, isGroup, m); err != nil && err != errNoSuchPolicy { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 12:01:49 +08:00
										 |  |  | // Refresh IAMSys. If an object layer is passed in use that, otherwise load from global.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) loadAll(ctx context.Context, sys *IAMSys) error { | 
					
						
							| 
									
										
										
										
											2021-01-26 12:01:49 +08:00
										 |  |  | 	return sys.Load(ctx, iamOS) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error { | 
					
						
							|  |  |  | 	return iamOS.saveIAMConfig(ctx, &p, getPolicyDocPath(policyName)) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | func (iamOS *IAMObjectStore) saveMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, mp MappedPolicy, opts ...options) error { | 
					
						
							|  |  |  | 	return iamOS.saveIAMConfig(ctx, mp, getMappedPolicyPath(name, userType, isGroup), opts...) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 05:06:05 +08:00
										 |  |  | func (iamOS *IAMObjectStore) saveUserIdentity(ctx context.Context, name string, userType IAMUserType, u UserIdentity, opts ...options) error { | 
					
						
							|  |  |  | 	return iamOS.saveIAMConfig(ctx, u, getUserIdentityPath(name, userType), opts...) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) saveGroupInfo(ctx context.Context, name string, gi GroupInfo) error { | 
					
						
							|  |  |  | 	return iamOS.saveIAMConfig(ctx, gi, getGroupInfoPath(name)) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) deletePolicyDoc(ctx context.Context, name string) error { | 
					
						
							|  |  |  | 	err := iamOS.deleteIAMConfig(ctx, getPolicyDocPath(name)) | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 	if err == errConfigNotFound { | 
					
						
							|  |  |  | 		err = errNoSuchPolicy | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) deleteMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool) error { | 
					
						
							|  |  |  | 	err := iamOS.deleteIAMConfig(ctx, getMappedPolicyPath(name, userType, isGroup)) | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 	if err == errConfigNotFound { | 
					
						
							|  |  |  | 		err = errNoSuchPolicy | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) deleteUserIdentity(ctx context.Context, name string, userType IAMUserType) error { | 
					
						
							|  |  |  | 	err := iamOS.deleteIAMConfig(ctx, getUserIdentityPath(name, userType)) | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 	if err == errConfigNotFound { | 
					
						
							|  |  |  | 		err = errNoSuchUser | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 00:54:40 +08:00
										 |  |  | func (iamOS *IAMObjectStore) deleteGroupInfo(ctx context.Context, name string) error { | 
					
						
							|  |  |  | 	err := iamOS.deleteIAMConfig(ctx, getGroupInfoPath(name)) | 
					
						
							| 
									
										
										
										
											2019-10-30 10:50:26 +08:00
										 |  |  | 	if err == errConfigNotFound { | 
					
						
							|  |  |  | 		err = errNoSuchGroup | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // helper type for listIAMConfigItems
 | 
					
						
							|  |  |  | type itemOrErr struct { | 
					
						
							|  |  |  | 	Item string | 
					
						
							|  |  |  | 	Err  error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Lists files or dirs in the minioMetaBucket at the given path
 | 
					
						
							|  |  |  | // prefix. If dirs is true, only directories are listed, otherwise
 | 
					
						
							|  |  |  | // only objects are listed. All returned items have the pathPrefix
 | 
					
						
							|  |  |  | // removed from their names.
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | func listIAMConfigItems(ctx context.Context, objAPI ObjectLayer, pathPrefix string) <-chan itemOrErr { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	ch := make(chan itemOrErr) | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	go func() { | 
					
						
							| 
									
										
										
										
											2020-02-13 22:36:23 +08:00
										 |  |  | 		defer close(ch) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 		// Allocate new results channel to receive ObjectInfo.
 | 
					
						
							|  |  |  | 		objInfoCh := make(chan ObjectInfo) | 
					
						
							| 
									
										
										
										
											2020-02-13 22:36:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 		if err := objAPI.Walk(ctx, minioMetaBucket, pathPrefix, objInfoCh, ObjectOptions{}); err != nil { | 
					
						
							|  |  |  | 			select { | 
					
						
							|  |  |  | 			case ch <- itemOrErr{Err: err}: | 
					
						
							|  |  |  | 			case <-ctx.Done(): | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-12-20 01:36:37 +08:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for obj := range objInfoCh { | 
					
						
							|  |  |  | 			item := strings.TrimPrefix(obj.Name, pathPrefix) | 
					
						
							|  |  |  | 			item = strings.TrimSuffix(item, SlashSeparator) | 
					
						
							|  |  |  | 			select { | 
					
						
							|  |  |  | 			case ch <- itemOrErr{Item: item}: | 
					
						
							|  |  |  | 			case <-ctx.Done(): | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 	return ch | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 05:26:39 +08:00
										 |  |  | func (iamOS *IAMObjectStore) watch(ctx context.Context, sys *IAMSys) { | 
					
						
							| 
									
										
										
										
											2020-04-09 10:00:39 +08:00
										 |  |  | 	// Refresh IAMSys.
 | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2020-12-04 11:23:19 +08:00
										 |  |  | 		time.Sleep(globalRefreshIAMInterval) | 
					
						
							|  |  |  | 		if err := iamOS.loadAll(ctx, sys); err != nil { | 
					
						
							|  |  |  | 			logger.LogIf(ctx, err) | 
					
						
							| 
									
										
										
										
											2019-08-09 06:10:04 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |