fix: make single locks for both IAM and object-store (#9279)

Additionally add context support for IAM sub-system
master
Harshavardhana 5 years ago committed by GitHub
parent e375341c33
commit e7276b7b9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      cmd/admin-handlers_test.go
  2. 4
      cmd/config-encrypted.go
  3. 4
      cmd/gateway-main.go
  4. 131
      cmd/iam-etcd-store.go
  5. 186
      cmd/iam-object-store.go
  6. 321
      cmd/iam.go
  7. 2
      cmd/peer-rest-server.go
  8. 4
      cmd/server-main.go
  9. 8
      cmd/test-utils_test.go

@ -70,7 +70,7 @@ func prepareAdminXLTestBed() (*adminXLTestBed, error) {
globalConfigSys = NewConfigSys() globalConfigSys = NewConfigSys()
globalIAMSys = NewIAMSys() globalIAMSys = NewIAMSys()
globalIAMSys.Init(objLayer) globalIAMSys.Init(GlobalContext, objLayer)
buckets, err := objLayer.ListBuckets(context.Background()) buckets, err := objLayer.ListBuckets(context.Background())
if err != nil { if err != nil {

@ -163,8 +163,8 @@ func decryptData(edata []byte, creds ...auth.Credentials) ([]byte, error) {
return data, err return data, err
} }
func migrateIAMConfigsEtcdToEncrypted(client *etcd.Client) error { func migrateIAMConfigsEtcdToEncrypted(ctx context.Context, client *etcd.Client) error {
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel() defer cancel()
encrypted, err := checkBackendEtcdEncrypted(ctx, client) encrypted, err := checkBackendEtcdEncrypted(ctx, client)

@ -255,13 +255,13 @@ func StartGateway(ctx *cli.Context, gw Gateway) {
// **** WARNING **** // **** WARNING ****
// Migrating to encrypted backend on etcd should happen before initialization of // Migrating to encrypted backend on etcd should happen before initialization of
// IAM sub-systems, make sure that we do not move the above codeblock elsewhere. // IAM sub-systems, make sure that we do not move the above codeblock elsewhere.
logger.FatalIf(migrateIAMConfigsEtcdToEncrypted(globalEtcdClient), logger.FatalIf(migrateIAMConfigsEtcdToEncrypted(GlobalContext, globalEtcdClient),
"Unable to handle encrypted backend for iam and policies") "Unable to handle encrypted backend for iam and policies")
} }
if enableIAMOps { if enableIAMOps {
// Initialize IAM sys. // Initialize IAM sys.
logger.FatalIf(globalIAMSys.Init(newObject), "Unable to initialize IAM system") logger.FatalIf(globalIAMSys.Init(GlobalContext, newObject), "Unable to initialize IAM system")
} }
if globalCacheConfig.Enabled { if globalCacheConfig.Enabled {

@ -74,37 +74,30 @@ func etcdKvsToSetPolicyDB(prefix string, kvs []*mvccpb.KeyValue) set.StringSet {
// IAMEtcdStore implements IAMStorageAPI // IAMEtcdStore implements IAMStorageAPI
type IAMEtcdStore struct { type IAMEtcdStore struct {
sync.RWMutex sync.RWMutex
ctx context.Context ctx context.Context
client *etcd.Client client *etcd.Client
} }
func newIAMEtcdStore() *IAMEtcdStore { func newIAMEtcdStore(ctx context.Context) *IAMEtcdStore {
return &IAMEtcdStore{client: globalEtcdClient} return &IAMEtcdStore{client: globalEtcdClient, ctx: ctx}
}
func (ies *IAMEtcdStore) getContext() context.Context {
ies.RLock()
defer ies.RUnlock()
if ies.ctx == nil {
return context.Background()
}
return ies.ctx
} }
func (ies *IAMEtcdStore) setContext(ctx context.Context) { func (ies *IAMEtcdStore) lock() {
ies.Lock() ies.Lock()
defer ies.Unlock() }
ies.ctx = ctx func (ies *IAMEtcdStore) unlock() {
ies.Unlock()
} }
func (ies *IAMEtcdStore) clearContext() { func (ies *IAMEtcdStore) rlock() {
ies.Lock() ies.RLock()
defer ies.Unlock() }
ies.ctx = nil func (ies *IAMEtcdStore) runlock() {
ies.RUnlock()
} }
func (ies *IAMEtcdStore) saveIAMConfig(item interface{}, path string) error { func (ies *IAMEtcdStore) saveIAMConfig(item interface{}, path string) error {
@ -118,11 +111,11 @@ func (ies *IAMEtcdStore) saveIAMConfig(item interface{}, path string) error {
return err return err
} }
} }
return saveKeyEtcd(ies.getContext(), ies.client, path, data) return saveKeyEtcd(ies.ctx, ies.client, path, data)
} }
func (ies *IAMEtcdStore) loadIAMConfig(item interface{}, path string) error { func (ies *IAMEtcdStore) loadIAMConfig(item interface{}, path string) error {
pdata, err := readKeyEtcd(ies.getContext(), ies.client, path) pdata, err := readKeyEtcd(ies.ctx, ies.client, path)
if err != nil { if err != nil {
return err return err
} }
@ -138,19 +131,17 @@ func (ies *IAMEtcdStore) loadIAMConfig(item interface{}, path string) error {
} }
func (ies *IAMEtcdStore) deleteIAMConfig(path string) error { func (ies *IAMEtcdStore) deleteIAMConfig(path string) error {
return deleteKeyEtcd(ies.getContext(), ies.client, path) return deleteKeyEtcd(ies.ctx, ies.client, path)
} }
func (ies *IAMEtcdStore) migrateUsersConfigToV1(isSTS bool) error { func (ies *IAMEtcdStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) error {
basePrefix := iamConfigUsersPrefix basePrefix := iamConfigUsersPrefix
if isSTS { if isSTS {
basePrefix = iamConfigSTSPrefix basePrefix = iamConfigSTSPrefix
} }
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel() defer cancel()
ies.setContext(ctx)
defer ies.clearContext()
r, err := ies.client.Get(ctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) r, err := ies.client.Get(ctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly())
if err != nil { if err != nil {
return err return err
@ -216,7 +207,7 @@ func (ies *IAMEtcdStore) migrateUsersConfigToV1(isSTS bool) error {
cred.AccessKey = user cred.AccessKey = user
u := newUserIdentity(cred) u := newUserIdentity(cred)
if err := ies.saveIAMConfig(u, identityPath); err != nil { if err := ies.saveIAMConfig(u, identityPath); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
return err return err
} }
@ -226,7 +217,7 @@ func (ies *IAMEtcdStore) migrateUsersConfigToV1(isSTS bool) error {
return nil return nil
} }
func (ies *IAMEtcdStore) migrateToV1() error { func (ies *IAMEtcdStore) migrateToV1(ctx context.Context) error {
var iamFmt iamFormat var iamFmt iamFormat
path := getIAMFormatFilePath() path := getIAMFormatFilePath()
if err := ies.loadIAMConfig(&iamFmt, path); err != nil { if err := ies.loadIAMConfig(&iamFmt, path); err != nil {
@ -248,29 +239,26 @@ func (ies *IAMEtcdStore) migrateToV1() error {
} }
// Migrate long-term users // Migrate long-term users
if err := ies.migrateUsersConfigToV1(false); err != nil { if err := ies.migrateUsersConfigToV1(ctx, false); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
return err return err
} }
// Migrate STS users // Migrate STS users
if err := ies.migrateUsersConfigToV1(true); err != nil { if err := ies.migrateUsersConfigToV1(ctx, true); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
return err return err
} }
// Save iam version file. // Save iam version file.
if err := ies.saveIAMConfig(newIAMFormatVersion1(), path); err != nil { if err := ies.saveIAMConfig(newIAMFormatVersion1(), path); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
return err return err
} }
return nil return nil
} }
// Should be called under config migration lock // Should be called under config migration lock
func (ies *IAMEtcdStore) migrateBackendFormat(objAPI ObjectLayer) error { func (ies *IAMEtcdStore) migrateBackendFormat(ctx context.Context) error {
if err := ies.migrateToV1(); err != nil { return ies.migrateToV1(ctx)
return err
}
return nil
} }
func (ies *IAMEtcdStore) loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error { func (ies *IAMEtcdStore) loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error {
@ -283,11 +271,9 @@ func (ies *IAMEtcdStore) loadPolicyDoc(policy string, m map[string]iampolicy.Pol
return nil return nil
} }
func (ies *IAMEtcdStore) loadPolicyDocs(m map[string]iampolicy.Policy) error { func (ies *IAMEtcdStore) loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error {
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel() defer cancel()
ies.setContext(ctx)
defer ies.clearContext()
r, err := ies.client.Get(ctx, iamConfigPoliciesPrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) r, err := ies.client.Get(ctx, iamConfigPoliciesPrefix, etcd.WithPrefix(), etcd.WithKeysOnly())
if err != nil { if err != nil {
return err return err
@ -317,9 +303,8 @@ func (ies *IAMEtcdStore) loadUser(user string, userType IAMUserType, m map[strin
if u.Credentials.IsExpired() { if u.Credentials.IsExpired() {
// Delete expired identity. // Delete expired identity.
ctx := ies.getContext() deleteKeyEtcd(ies.ctx, ies.client, getUserIdentityPath(user, userType))
deleteKeyEtcd(ctx, ies.client, getUserIdentityPath(user, userType)) deleteKeyEtcd(ies.ctx, ies.client, getMappedPolicyPath(user, userType, false))
deleteKeyEtcd(ctx, ies.client, getMappedPolicyPath(user, userType, false))
return nil return nil
} }
@ -351,7 +336,7 @@ func (ies *IAMEtcdStore) loadUser(user string, userType IAMUserType, m map[strin
} }
func (ies *IAMEtcdStore) loadUsers(userType IAMUserType, m map[string]auth.Credentials) error { func (ies *IAMEtcdStore) loadUsers(ctx context.Context, userType IAMUserType, m map[string]auth.Credentials) error {
var basePrefix string var basePrefix string
switch userType { switch userType {
case srvAccUser: case srvAccUser:
@ -362,10 +347,8 @@ func (ies *IAMEtcdStore) loadUsers(userType IAMUserType, m map[string]auth.Crede
basePrefix = iamConfigUsersPrefix basePrefix = iamConfigUsersPrefix
} }
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel() defer cancel()
ies.setContext(ctx)
defer ies.clearContext()
r, err := ies.client.Get(ctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) r, err := ies.client.Get(ctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly())
if err != nil { if err != nil {
return err return err
@ -396,11 +379,9 @@ func (ies *IAMEtcdStore) loadGroup(group string, m map[string]GroupInfo) error {
} }
func (ies *IAMEtcdStore) loadGroups(m map[string]GroupInfo) error { func (ies *IAMEtcdStore) loadGroups(ctx context.Context, m map[string]GroupInfo) error {
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel() defer cancel()
ies.setContext(ctx)
defer ies.clearContext()
r, err := ies.client.Get(ctx, iamConfigGroupsPrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) r, err := ies.client.Get(ctx, iamConfigGroupsPrefix, etcd.WithPrefix(), etcd.WithKeysOnly())
if err != nil { if err != nil {
return err return err
@ -432,11 +413,9 @@ func (ies *IAMEtcdStore) loadMappedPolicy(name string, userType IAMUserType, isG
} }
func (ies *IAMEtcdStore) loadMappedPolicies(userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { func (ies *IAMEtcdStore) loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error {
ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout)
defer cancel() defer cancel()
ies.setContext(ctx)
defer ies.clearContext()
var basePrefix string var basePrefix string
if isGroup { if isGroup {
basePrefix = iamConfigPolicyDBGroupsPrefix basePrefix = iamConfigPolicyDBGroupsPrefix
@ -467,7 +446,7 @@ func (ies *IAMEtcdStore) loadMappedPolicies(userType IAMUserType, isGroup bool,
} }
func (ies *IAMEtcdStore) loadAll(sys *IAMSys, objectAPI ObjectLayer) error { func (ies *IAMEtcdStore) loadAll(ctx context.Context, sys *IAMSys) error {
iamUsersMap := make(map[string]auth.Credentials) iamUsersMap := make(map[string]auth.Credentials)
iamGroupsMap := make(map[string]GroupInfo) iamGroupsMap := make(map[string]GroupInfo)
iamPolicyDocsMap := make(map[string]iampolicy.Policy) iamPolicyDocsMap := make(map[string]iampolicy.Policy)
@ -475,51 +454,51 @@ func (ies *IAMEtcdStore) loadAll(sys *IAMSys, objectAPI ObjectLayer) error {
iamGroupPolicyMap := make(map[string]MappedPolicy) iamGroupPolicyMap := make(map[string]MappedPolicy)
isMinIOUsersSys := false isMinIOUsersSys := false
sys.RLock() ies.rlock()
if sys.usersSysType == MinIOUsersSysType { if sys.usersSysType == MinIOUsersSysType {
isMinIOUsersSys = true isMinIOUsersSys = true
} }
sys.RUnlock() ies.runlock()
if err := ies.loadPolicyDocs(iamPolicyDocsMap); err != nil { if err := ies.loadPolicyDocs(ctx, iamPolicyDocsMap); err != nil {
return err return err
} }
// load STS temp users // load STS temp users
if err := ies.loadUsers(stsUser, iamUsersMap); err != nil { if err := ies.loadUsers(ctx, stsUser, iamUsersMap); err != nil {
return err return err
} }
if isMinIOUsersSys { if isMinIOUsersSys {
// load long term users // load long term users
if err := ies.loadUsers(regularUser, iamUsersMap); err != nil { if err := ies.loadUsers(ctx, regularUser, iamUsersMap); err != nil {
return err return err
} }
if err := ies.loadUsers(srvAccUser, iamUsersMap); err != nil { if err := ies.loadUsers(ctx, srvAccUser, iamUsersMap); err != nil {
return err return err
} }
if err := ies.loadGroups(iamGroupsMap); err != nil { if err := ies.loadGroups(ctx, iamGroupsMap); err != nil {
return err return err
} }
if err := ies.loadMappedPolicies(regularUser, false, iamUserPolicyMap); err != nil { if err := ies.loadMappedPolicies(ctx, regularUser, false, iamUserPolicyMap); err != nil {
return err return err
} }
} }
// load STS policy mappings into the same map // load STS policy mappings into the same map
if err := ies.loadMappedPolicies(stsUser, false, iamUserPolicyMap); err != nil { if err := ies.loadMappedPolicies(ctx, stsUser, false, iamUserPolicyMap); err != nil {
return err return err
} }
// load policies mapped to groups // load policies mapped to groups
if err := ies.loadMappedPolicies(regularUser, true, iamGroupPolicyMap); err != nil { if err := ies.loadMappedPolicies(ctx, regularUser, true, iamGroupPolicyMap); err != nil {
return err return err
} }
// Sets default canned policies, if none are set. // Sets default canned policies, if none are set.
setDefaultCannedPolicies(iamPolicyDocsMap) setDefaultCannedPolicies(iamPolicyDocsMap)
sys.Lock() ies.lock()
defer sys.Unlock() defer ies.Unlock()
sys.iamUsersMap = iamUsersMap sys.iamUsersMap = iamUsersMap
sys.iamGroupsMap = iamGroupsMap sys.iamGroupsMap = iamGroupsMap
@ -579,17 +558,17 @@ func (ies *IAMEtcdStore) deleteGroupInfo(name string) error {
return err return err
} }
func (ies *IAMEtcdStore) watch(sys *IAMSys) { func (ies *IAMEtcdStore) watch(ctx context.Context, sys *IAMSys) {
watchEtcd := func() { watchEtcd := func() {
for { for {
outerLoop: outerLoop:
// Refresh IAMSys with etcd watch. // Refresh IAMSys with etcd watch.
watchCh := ies.client.Watch(context.Background(), watchCh := ies.client.Watch(ctx,
iamConfigPrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) iamConfigPrefix, etcd.WithPrefix(), etcd.WithKeysOnly())
for { for {
select { select {
case <-GlobalServiceDoneCh: case <-ctx.Done():
return return
case watchResp, ok := <-watchCh: case watchResp, ok := <-watchCh:
if !ok { if !ok {
@ -599,7 +578,7 @@ func (ies *IAMEtcdStore) watch(sys *IAMSys) {
goto outerLoop goto outerLoop
} }
if err := watchResp.Err(); err != nil { if err := watchResp.Err(); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
// log and retry. // log and retry.
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
// Upon an error on watch channel // Upon an error on watch channel
@ -607,9 +586,9 @@ func (ies *IAMEtcdStore) watch(sys *IAMSys) {
goto outerLoop goto outerLoop
} }
for _, event := range watchResp.Events { for _, event := range watchResp.Events {
sys.Lock() ies.lock()
ies.reloadFromEvent(sys, event) ies.reloadFromEvent(sys, event)
sys.Unlock() ies.unlock()
} }
} }
} }

@ -38,32 +38,28 @@ type IAMObjectStore struct {
// Protect assignment to objAPI // Protect assignment to objAPI
sync.RWMutex sync.RWMutex
ctx context.Context
objAPI ObjectLayer objAPI ObjectLayer
} }
func newIAMObjectStore() *IAMObjectStore { func newIAMObjectStore(ctx context.Context, objAPI ObjectLayer) *IAMObjectStore {
return &IAMObjectStore{objAPI: nil} return &IAMObjectStore{ctx: ctx, objAPI: objAPI}
} }
func (iamOS *IAMObjectStore) getObjectAPI() ObjectLayer { func (iamOS *IAMObjectStore) lock() {
iamOS.RLock() iamOS.Lock()
defer iamOS.RUnlock()
if iamOS.objAPI != nil {
return iamOS.objAPI
}
return newObjectLayerWithoutSafeModeFn()
} }
func (iamOS *IAMObjectStore) setObjectAPI(objAPI ObjectLayer) { func (iamOS *IAMObjectStore) unlock() {
iamOS.Lock() iamOS.Unlock()
defer iamOS.Unlock()
iamOS.objAPI = objAPI
} }
func (iamOS *IAMObjectStore) clearObjectAPI() { func (iamOS *IAMObjectStore) rlock() {
iamOS.Lock() iamOS.RLock()
defer iamOS.Unlock() }
iamOS.objAPI = nil
func (iamOS *IAMObjectStore) runlock() {
iamOS.RUnlock()
} }
// Migrate users directory in a single scan. // Migrate users directory in a single scan.
@ -80,17 +76,13 @@ func (iamOS *IAMObjectStore) clearObjectAPI() {
// location. // location.
// //
// 3. Migrate user identity json file to include version info. // 3. Migrate user identity json file to include version info.
func (iamOS *IAMObjectStore) migrateUsersConfigToV1(isSTS bool) error { func (iamOS *IAMObjectStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) error {
basePrefix := iamConfigUsersPrefix basePrefix := iamConfigUsersPrefix
if isSTS { if isSTS {
basePrefix = iamConfigSTSPrefix basePrefix = iamConfigSTSPrefix
} }
objAPI := iamOS.getObjectAPI() for item := range listIAMConfigItems(ctx, iamOS.objAPI, basePrefix, true) {
doneCh := make(chan struct{})
defer close(doneCh)
for item := range listIAMConfigItems(objAPI, basePrefix, true, doneCh) {
if item.Err != nil { if item.Err != nil {
return item.Err return item.Err
} }
@ -169,7 +161,7 @@ func (iamOS *IAMObjectStore) migrateUsersConfigToV1(isSTS bool) error {
} }
func (iamOS *IAMObjectStore) migrateToV1() error { func (iamOS *IAMObjectStore) migrateToV1(ctx context.Context) error {
var iamFmt iamFormat var iamFmt iamFormat
path := getIAMFormatFilePath() path := getIAMFormatFilePath()
if err := iamOS.loadIAMConfig(&iamFmt, path); err != nil { if err := iamOS.loadIAMConfig(&iamFmt, path); err != nil {
@ -190,35 +182,29 @@ func (iamOS *IAMObjectStore) migrateToV1() error {
} }
// Migrate long-term users // Migrate long-term users
if err := iamOS.migrateUsersConfigToV1(false); err != nil { if err := iamOS.migrateUsersConfigToV1(ctx, false); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
return err return err
} }
// Migrate STS users // Migrate STS users
if err := iamOS.migrateUsersConfigToV1(true); err != nil { if err := iamOS.migrateUsersConfigToV1(ctx, true); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
return err return err
} }
// Save iam format to version 1. // Save iam format to version 1.
if err := iamOS.saveIAMConfig(newIAMFormatVersion1(), path); err != nil { if err := iamOS.saveIAMConfig(newIAMFormatVersion1(), path); err != nil {
logger.LogIf(context.Background(), err) logger.LogIf(ctx, err)
return err return err
} }
return nil return nil
} }
// Should be called under config migration lock // Should be called under config migration lock
func (iamOS *IAMObjectStore) migrateBackendFormat(objAPI ObjectLayer) error { func (iamOS *IAMObjectStore) migrateBackendFormat(ctx context.Context) error {
iamOS.setObjectAPI(objAPI) return iamOS.migrateToV1(ctx)
defer iamOS.clearObjectAPI()
if err := iamOS.migrateToV1(); err != nil {
return err
}
return nil
} }
func (iamOS *IAMObjectStore) saveIAMConfig(item interface{}, path string) error { func (iamOS *IAMObjectStore) saveIAMConfig(item interface{}, path string) error {
objectAPI := iamOS.getObjectAPI()
data, err := json.Marshal(item) data, err := json.Marshal(item)
if err != nil { if err != nil {
return err return err
@ -229,12 +215,11 @@ func (iamOS *IAMObjectStore) saveIAMConfig(item interface{}, path string) error
return err return err
} }
} }
return saveConfig(context.Background(), objectAPI, path, data) return saveConfig(context.Background(), iamOS.objAPI, path, data)
} }
func (iamOS *IAMObjectStore) loadIAMConfig(item interface{}, path string) error { func (iamOS *IAMObjectStore) loadIAMConfig(item interface{}, path string) error {
objectAPI := iamOS.getObjectAPI() data, err := readConfig(iamOS.ctx, iamOS.objAPI, path)
data, err := readConfig(context.Background(), objectAPI, path)
if err != nil { if err != nil {
return err return err
} }
@ -248,7 +233,7 @@ func (iamOS *IAMObjectStore) loadIAMConfig(item interface{}, path string) error
} }
func (iamOS *IAMObjectStore) deleteIAMConfig(path string) error { func (iamOS *IAMObjectStore) deleteIAMConfig(path string) error {
err := deleteConfig(context.Background(), iamOS.getObjectAPI(), path) err := deleteConfig(iamOS.ctx, iamOS.objAPI, path)
if _, ok := err.(ObjectNotFound); ok { if _, ok := err.(ObjectNotFound); ok {
return errConfigNotFound return errConfigNotFound
} }
@ -256,11 +241,6 @@ func (iamOS *IAMObjectStore) deleteIAMConfig(path string) error {
} }
func (iamOS *IAMObjectStore) loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error { func (iamOS *IAMObjectStore) loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error {
objectAPI := iamOS.getObjectAPI()
if objectAPI == nil {
return errServerNotInitialized
}
var p iampolicy.Policy var p iampolicy.Policy
err := iamOS.loadIAMConfig(&p, getPolicyDocPath(policy)) err := iamOS.loadIAMConfig(&p, getPolicyDocPath(policy))
if err != nil { if err != nil {
@ -273,15 +253,8 @@ func (iamOS *IAMObjectStore) loadPolicyDoc(policy string, m map[string]iampolicy
return nil return nil
} }
func (iamOS *IAMObjectStore) loadPolicyDocs(m map[string]iampolicy.Policy) error { func (iamOS *IAMObjectStore) loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error {
objectAPI := iamOS.getObjectAPI() for item := range listIAMConfigItems(ctx, iamOS.objAPI, iamConfigPoliciesPrefix, true) {
if objectAPI == nil {
return errServerNotInitialized
}
doneCh := make(chan struct{})
defer close(doneCh)
for item := range listIAMConfigItems(objectAPI, iamConfigPoliciesPrefix, true, doneCh) {
if item.Err != nil { if item.Err != nil {
return item.Err return item.Err
} }
@ -296,11 +269,6 @@ func (iamOS *IAMObjectStore) loadPolicyDocs(m map[string]iampolicy.Policy) error
} }
func (iamOS *IAMObjectStore) loadUser(user string, userType IAMUserType, m map[string]auth.Credentials) error { func (iamOS *IAMObjectStore) loadUser(user string, userType IAMUserType, m map[string]auth.Credentials) error {
objectAPI := iamOS.getObjectAPI()
if objectAPI == nil {
return errServerNotInitialized
}
var u UserIdentity var u UserIdentity
err := iamOS.loadIAMConfig(&u, getUserIdentityPath(user, userType)) err := iamOS.loadIAMConfig(&u, getUserIdentityPath(user, userType))
if err != nil { if err != nil {
@ -344,15 +312,7 @@ func (iamOS *IAMObjectStore) loadUser(user string, userType IAMUserType, m map[s
return nil return nil
} }
func (iamOS *IAMObjectStore) loadUsers(userType IAMUserType, m map[string]auth.Credentials) error { func (iamOS *IAMObjectStore) loadUsers(ctx context.Context, userType IAMUserType, m map[string]auth.Credentials) error {
objectAPI := iamOS.getObjectAPI()
if objectAPI == nil {
return errServerNotInitialized
}
doneCh := make(chan struct{})
defer close(doneCh)
var basePrefix string var basePrefix string
switch userType { switch userType {
case srvAccUser: case srvAccUser:
@ -363,7 +323,7 @@ func (iamOS *IAMObjectStore) loadUsers(userType IAMUserType, m map[string]auth.C
basePrefix = iamConfigUsersPrefix basePrefix = iamConfigUsersPrefix
} }
for item := range listIAMConfigItems(objectAPI, basePrefix, true, doneCh) { for item := range listIAMConfigItems(ctx, iamOS.objAPI, basePrefix, true) {
if item.Err != nil { if item.Err != nil {
return item.Err return item.Err
} }
@ -378,11 +338,6 @@ func (iamOS *IAMObjectStore) loadUsers(userType IAMUserType, m map[string]auth.C
} }
func (iamOS *IAMObjectStore) loadGroup(group string, m map[string]GroupInfo) error { func (iamOS *IAMObjectStore) loadGroup(group string, m map[string]GroupInfo) error {
objectAPI := iamOS.getObjectAPI()
if objectAPI == nil {
return errServerNotInitialized
}
var g GroupInfo var g GroupInfo
err := iamOS.loadIAMConfig(&g, getGroupInfoPath(group)) err := iamOS.loadIAMConfig(&g, getGroupInfoPath(group))
if err != nil { if err != nil {
@ -395,15 +350,8 @@ func (iamOS *IAMObjectStore) loadGroup(group string, m map[string]GroupInfo) err
return nil return nil
} }
func (iamOS *IAMObjectStore) loadGroups(m map[string]GroupInfo) error { func (iamOS *IAMObjectStore) loadGroups(ctx context.Context, m map[string]GroupInfo) error {
objectAPI := iamOS.getObjectAPI() for item := range listIAMConfigItems(ctx, iamOS.objAPI, iamConfigGroupsPrefix, true) {
if objectAPI == nil {
return errServerNotInitialized
}
doneCh := make(chan struct{})
defer close(doneCh)
for item := range listIAMConfigItems(objectAPI, iamConfigGroupsPrefix, true, doneCh) {
if item.Err != nil { if item.Err != nil {
return item.Err return item.Err
} }
@ -420,11 +368,6 @@ func (iamOS *IAMObjectStore) loadGroups(m map[string]GroupInfo) error {
func (iamOS *IAMObjectStore) loadMappedPolicy(name string, userType IAMUserType, isGroup bool, func (iamOS *IAMObjectStore) loadMappedPolicy(name string, userType IAMUserType, isGroup bool,
m map[string]MappedPolicy) error { m map[string]MappedPolicy) error {
objectAPI := iamOS.getObjectAPI()
if objectAPI == nil {
return errServerNotInitialized
}
var p MappedPolicy var p MappedPolicy
err := iamOS.loadIAMConfig(&p, getMappedPolicyPath(name, userType, isGroup)) err := iamOS.loadIAMConfig(&p, getMappedPolicyPath(name, userType, isGroup))
if err != nil { if err != nil {
@ -437,14 +380,7 @@ func (iamOS *IAMObjectStore) loadMappedPolicy(name string, userType IAMUserType,
return nil return nil
} }
func (iamOS *IAMObjectStore) loadMappedPolicies(userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { func (iamOS *IAMObjectStore) loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error {
objectAPI := iamOS.getObjectAPI()
if objectAPI == nil {
return errServerNotInitialized
}
doneCh := make(chan struct{})
defer close(doneCh)
var basePath string var basePath string
if isGroup { if isGroup {
basePath = iamConfigPolicyDBGroupsPrefix basePath = iamConfigPolicyDBGroupsPrefix
@ -458,7 +394,7 @@ func (iamOS *IAMObjectStore) loadMappedPolicies(userType IAMUserType, isGroup bo
basePath = iamConfigPolicyDBUsersPrefix basePath = iamConfigPolicyDBUsersPrefix
} }
} }
for item := range listIAMConfigItems(objectAPI, basePath, false, doneCh) { for item := range listIAMConfigItems(ctx, iamOS.objAPI, basePath, false) {
if item.Err != nil { if item.Err != nil {
return item.Err return item.Err
} }
@ -475,17 +411,7 @@ func (iamOS *IAMObjectStore) loadMappedPolicies(userType IAMUserType, isGroup bo
// Refresh IAMSys. If an object layer is passed in use that, otherwise // Refresh IAMSys. If an object layer is passed in use that, otherwise
// load from global. // load from global.
func (iamOS *IAMObjectStore) loadAll(sys *IAMSys, objectAPI ObjectLayer) error { func (iamOS *IAMObjectStore) loadAll(ctx context.Context, sys *IAMSys) error {
if objectAPI == nil {
objectAPI = iamOS.getObjectAPI()
}
if objectAPI == nil {
return errServerNotInitialized
}
// cache object layer for other load* functions
iamOS.setObjectAPI(objectAPI)
defer iamOS.clearObjectAPI()
iamUsersMap := make(map[string]auth.Credentials) iamUsersMap := make(map[string]auth.Credentials)
iamGroupsMap := make(map[string]GroupInfo) iamGroupsMap := make(map[string]GroupInfo)
iamPolicyDocsMap := make(map[string]iampolicy.Policy) iamPolicyDocsMap := make(map[string]iampolicy.Policy)
@ -493,48 +419,48 @@ func (iamOS *IAMObjectStore) loadAll(sys *IAMSys, objectAPI ObjectLayer) error {
iamGroupPolicyMap := make(map[string]MappedPolicy) iamGroupPolicyMap := make(map[string]MappedPolicy)
isMinIOUsersSys := false isMinIOUsersSys := false
sys.RLock() iamOS.rlock()
if sys.usersSysType == MinIOUsersSysType { if sys.usersSysType == MinIOUsersSysType {
isMinIOUsersSys = true isMinIOUsersSys = true
} }
sys.RUnlock() iamOS.runlock()
if err := iamOS.loadPolicyDocs(iamPolicyDocsMap); err != nil { if err := iamOS.loadPolicyDocs(ctx, iamPolicyDocsMap); err != nil {
return err return err
} }
// load STS temp users // load STS temp users
if err := iamOS.loadUsers(stsUser, iamUsersMap); err != nil { if err := iamOS.loadUsers(ctx, stsUser, iamUsersMap); err != nil {
return err return err
} }
if isMinIOUsersSys { if isMinIOUsersSys {
if err := iamOS.loadUsers(regularUser, iamUsersMap); err != nil { if err := iamOS.loadUsers(ctx, regularUser, iamUsersMap); err != nil {
return err return err
} }
if err := iamOS.loadUsers(srvAccUser, iamUsersMap); err != nil { if err := iamOS.loadUsers(ctx, srvAccUser, iamUsersMap); err != nil {
return err return err
} }
if err := iamOS.loadGroups(iamGroupsMap); err != nil { if err := iamOS.loadGroups(ctx, iamGroupsMap); err != nil {
return err return err
} }
if err := iamOS.loadMappedPolicies(regularUser, false, iamUserPolicyMap); err != nil { if err := iamOS.loadMappedPolicies(ctx, regularUser, false, iamUserPolicyMap); err != nil {
return err return err
} }
} }
// load STS policy mappings // load STS policy mappings
if err := iamOS.loadMappedPolicies(stsUser, false, iamUserPolicyMap); err != nil { if err := iamOS.loadMappedPolicies(ctx, stsUser, false, iamUserPolicyMap); err != nil {
return err return err
} }
// load policies mapped to groups // load policies mapped to groups
if err := iamOS.loadMappedPolicies(regularUser, true, iamGroupPolicyMap); err != nil { if err := iamOS.loadMappedPolicies(ctx, regularUser, true, iamGroupPolicyMap); err != nil {
return err return err
} }
// Sets default canned policies, if none are set. // Sets default canned policies, if none are set.
setDefaultCannedPolicies(iamPolicyDocsMap) setDefaultCannedPolicies(iamPolicyDocsMap)
sys.Lock() iamOS.lock()
defer sys.Unlock() defer iamOS.unlock()
sys.iamUsersMap = iamUsersMap sys.iamUsersMap = iamUsersMap
sys.iamPolicyDocsMap = iamPolicyDocsMap sys.iamPolicyDocsMap = iamPolicyDocsMap
@ -604,10 +530,9 @@ type itemOrErr struct {
// prefix. If dirs is true, only directories are listed, otherwise // prefix. If dirs is true, only directories are listed, otherwise
// only objects are listed. All returned items have the pathPrefix // only objects are listed. All returned items have the pathPrefix
// removed from their names. // removed from their names.
func listIAMConfigItems(objectAPI ObjectLayer, pathPrefix string, dirs bool, func listIAMConfigItems(ctx context.Context, objAPI ObjectLayer, pathPrefix string, dirs bool) <-chan itemOrErr {
doneCh <-chan struct{}) <-chan itemOrErr {
ch := make(chan itemOrErr) ch := make(chan itemOrErr)
dirList := func(lo ListObjectsInfo) []string { dirList := func(lo ListObjectsInfo) []string {
return lo.Prefixes return lo.Prefixes
} }
@ -623,12 +548,12 @@ func listIAMConfigItems(objectAPI ObjectLayer, pathPrefix string, dirs bool,
marker := "" marker := ""
for { for {
lo, err := objectAPI.ListObjects(context.Background(), lo, err := objAPI.ListObjects(context.Background(),
minioMetaBucket, pathPrefix, marker, SlashSeparator, maxObjectList) minioMetaBucket, pathPrefix, marker, SlashSeparator, maxObjectList)
if err != nil { if err != nil {
select { select {
case ch <- itemOrErr{Err: err}: case ch <- itemOrErr{Err: err}:
case <-doneCh: case <-ctx.Done():
} }
return return
} }
@ -651,7 +576,7 @@ func listIAMConfigItems(objectAPI ObjectLayer, pathPrefix string, dirs bool,
item = strings.TrimSuffix(item, SlashSeparator) item = strings.TrimSuffix(item, SlashSeparator)
select { select {
case ch <- itemOrErr{Item: item}: case ch <- itemOrErr{Item: item}:
case <-doneCh: case <-ctx.Done():
return return
} }
} }
@ -660,19 +585,18 @@ func listIAMConfigItems(objectAPI ObjectLayer, pathPrefix string, dirs bool,
} }
} }
}() }()
return ch return ch
} }
func (iamOS *IAMObjectStore) watch(sys *IAMSys) { func (iamOS *IAMObjectStore) watch(ctx context.Context, sys *IAMSys) {
ctx := GlobalContext
watchDisk := func() { watchDisk := func() {
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
case <-time.NewTimer(globalRefreshIAMInterval).C: case <-time.NewTimer(globalRefreshIAMInterval).C:
err := iamOS.loadAll(sys, nil) logger.LogIf(ctx, iamOS.loadAll(ctx, sys))
logger.LogIf(ctx, err)
} }
} }
} }

@ -22,7 +22,6 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"sync"
"github.com/minio/minio-go/v6/pkg/set" "github.com/minio/minio-go/v6/pkg/set"
"github.com/minio/minio/cmd/config" "github.com/minio/minio/cmd/config"
@ -173,8 +172,6 @@ func newMappedPolicy(policy string) MappedPolicy {
// IAMSys - config system. // IAMSys - config system.
type IAMSys struct { type IAMSys struct {
sync.RWMutex
usersSysType UsersSysType usersSysType UsersSysType
// map of policy names to policy definitions // map of policy names to policy definitions
@ -205,21 +202,27 @@ const (
// IAMStorageAPI defines an interface for the IAM persistence layer // IAMStorageAPI defines an interface for the IAM persistence layer
type IAMStorageAPI interface { type IAMStorageAPI interface {
migrateBackendFormat(ObjectLayer) error lock()
unlock()
rlock()
runlock()
migrateBackendFormat(context.Context) error
loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error
loadPolicyDocs(m map[string]iampolicy.Policy) error loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error
loadUser(user string, userType IAMUserType, m map[string]auth.Credentials) error loadUser(user string, userType IAMUserType, m map[string]auth.Credentials) error
loadUsers(userType IAMUserType, m map[string]auth.Credentials) error loadUsers(ctx context.Context, userType IAMUserType, m map[string]auth.Credentials) error
loadGroup(group string, m map[string]GroupInfo) error loadGroup(group string, m map[string]GroupInfo) error
loadGroups(m map[string]GroupInfo) error loadGroups(ctx context.Context, m map[string]GroupInfo) error
loadMappedPolicy(name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error loadMappedPolicy(name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error
loadMappedPolicies(userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error
loadAll(*IAMSys, ObjectLayer) error loadAll(context.Context, *IAMSys) error
saveIAMConfig(item interface{}, path string) error saveIAMConfig(item interface{}, path string) error
loadIAMConfig(item interface{}, path string) error loadIAMConfig(item interface{}, path string) error
@ -235,7 +238,7 @@ type IAMStorageAPI interface {
deleteUserIdentity(name string, userType IAMUserType) error deleteUserIdentity(name string, userType IAMUserType) error
deleteGroupInfo(name string) error deleteGroupInfo(name string) error
watch(*IAMSys) watch(context.Context, *IAMSys)
} }
// LoadGroup - loads a specific group from storage, and updates the // LoadGroup - loads a specific group from storage, and updates the
@ -244,10 +247,7 @@ type IAMStorageAPI interface {
// simplifies the implementation for group removal. This is called // simplifies the implementation for group removal. This is called
// only via IAM notifications. // only via IAM notifications.
func (sys *IAMSys) LoadGroup(objAPI ObjectLayer, group string) error { func (sys *IAMSys) LoadGroup(objAPI ObjectLayer, group string) error {
sys.Lock() if objAPI == nil || sys == nil || sys.store == nil {
defer sys.Unlock()
if objAPI == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -256,6 +256,9 @@ func (sys *IAMSys) LoadGroup(objAPI ObjectLayer, group string) error {
return nil return nil
} }
sys.store.lock()
defer sys.store.unlock()
err := sys.store.loadGroup(group, sys.iamGroupsMap) err := sys.store.loadGroup(group, sys.iamGroupsMap)
if err != nil && err != errConfigNotFound { if err != nil && err != errConfigNotFound {
return err return err
@ -285,13 +288,13 @@ func (sys *IAMSys) LoadGroup(objAPI ObjectLayer, group string) error {
// LoadPolicy - reloads a specific canned policy from backend disks or etcd. // LoadPolicy - reloads a specific canned policy from backend disks or etcd.
func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error { func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error {
sys.Lock() if objAPI == nil || sys == nil || sys.store == nil {
defer sys.Unlock()
if objAPI == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
sys.store.lock()
defer sys.store.unlock()
if globalEtcdClient == nil { if globalEtcdClient == nil {
return sys.store.loadPolicyDoc(policyName, sys.iamPolicyDocsMap) return sys.store.loadPolicyDoc(policyName, sys.iamPolicyDocsMap)
} }
@ -303,13 +306,13 @@ func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error {
// LoadPolicyMapping - loads the mapped policy for a user or group // LoadPolicyMapping - loads the mapped policy for a user or group
// from storage into server memory. // from storage into server memory.
func (sys *IAMSys) LoadPolicyMapping(objAPI ObjectLayer, userOrGroup string, isGroup bool) error { func (sys *IAMSys) LoadPolicyMapping(objAPI ObjectLayer, userOrGroup string, isGroup bool) error {
sys.Lock() if objAPI == nil || sys == nil || sys.store == nil {
defer sys.Unlock()
if objAPI == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
sys.store.lock()
defer sys.store.unlock()
if globalEtcdClient == nil { if globalEtcdClient == nil {
var err error var err error
if isGroup { if isGroup {
@ -329,13 +332,13 @@ func (sys *IAMSys) LoadPolicyMapping(objAPI ObjectLayer, userOrGroup string, isG
// LoadUser - reloads a specific user from backend disks or etcd. // LoadUser - reloads a specific user from backend disks or etcd.
func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, userType IAMUserType) error { func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, userType IAMUserType) error {
sys.Lock() if objAPI == nil || sys == nil || sys.store == nil {
defer sys.Unlock()
if objAPI == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
sys.store.lock()
defer sys.store.unlock()
if globalEtcdClient == nil { if globalEtcdClient == nil {
err := sys.store.loadUser(accessKey, userType, sys.iamUsersMap) err := sys.store.loadUser(accessKey, userType, sys.iamUsersMap)
if err != nil { if err != nil {
@ -352,42 +355,40 @@ func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, userType IAMUs
} }
// Load - loads iam subsystem // Load - loads iam subsystem
func (sys *IAMSys) Load() error { func (sys *IAMSys) Load(ctx context.Context) error {
// Pass nil objectlayer here - it will be loaded internally // Pass nil objectlayer here - it will be loaded internally
// from the IAMStorageAPI. // from the IAMStorageAPI.
return sys.store.loadAll(sys, nil) return sys.store.loadAll(ctx, sys)
} }
// Perform IAM configuration migration. // Perform IAM configuration migration.
func (sys *IAMSys) doIAMConfigMigration(objAPI ObjectLayer) error { func (sys *IAMSys) doIAMConfigMigration(ctx context.Context) error {
return sys.store.migrateBackendFormat(objAPI) return sys.store.migrateBackendFormat(ctx)
} }
// Init - initializes config system from iam.json // Init - initializes config system from iam.json
func (sys *IAMSys) Init(objAPI ObjectLayer) error { func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer) error {
if objAPI == nil { if objAPI == nil {
return errServerNotInitialized return errServerNotInitialized
} }
if globalLDAPConfig.Enabled {
sys.EnableLDAPSys()
}
sys.Lock()
if globalEtcdClient == nil { if globalEtcdClient == nil {
sys.store = newIAMObjectStore() sys.store = newIAMObjectStore(ctx, objAPI)
} else { } else {
sys.store = newIAMEtcdStore() sys.store = newIAMEtcdStore(ctx)
}
if globalLDAPConfig.Enabled {
sys.EnableLDAPSys()
} }
sys.Unlock()
// Migrate IAM configuration // Migrate IAM configuration
if err := sys.doIAMConfigMigration(objAPI); err != nil { if err := sys.doIAMConfigMigration(ctx); err != nil {
return err return err
} }
sys.store.watch(sys) sys.store.watch(ctx, sys)
err := sys.store.loadAll(sys, objAPI) err := sys.store.loadAll(ctx, sys)
// Invalidate the old cred after finishing IAM initialization // Invalidate the old cred after finishing IAM initialization
globalOldCred = auth.Credentials{} globalOldCred = auth.Credentials{}
@ -398,7 +399,7 @@ func (sys *IAMSys) Init(objAPI ObjectLayer) error {
// DeletePolicy - deletes a canned policy from backend or etcd. // DeletePolicy - deletes a canned policy from backend or etcd.
func (sys *IAMSys) DeletePolicy(policyName string) error { func (sys *IAMSys) DeletePolicy(policyName string) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -406,12 +407,8 @@ func (sys *IAMSys) DeletePolicy(policyName string) error {
return errInvalidArgument return errInvalidArgument
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.store == nil {
return errServerNotInitialized
}
err := sys.store.deletePolicyDoc(policyName) err := sys.store.deletePolicyDoc(policyName)
switch err.(type) { switch err.(type) {
@ -462,12 +459,12 @@ func (sys *IAMSys) DeletePolicy(policyName string) error {
// InfoPolicy - expands the canned policy into its JSON structure. // InfoPolicy - expands the canned policy into its JSON structure.
func (sys *IAMSys) InfoPolicy(policyName string) ([]byte, error) { func (sys *IAMSys) InfoPolicy(policyName string) ([]byte, error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return nil, errServerNotInitialized return nil, errServerNotInitialized
} }
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
v, ok := sys.iamPolicyDocsMap[policyName] v, ok := sys.iamPolicyDocsMap[policyName]
if !ok { if !ok {
@ -479,14 +476,14 @@ func (sys *IAMSys) InfoPolicy(policyName string) ([]byte, error) {
// ListPolicies - lists all canned policies. // ListPolicies - lists all canned policies.
func (sys *IAMSys) ListPolicies() (map[string][]byte, error) { func (sys *IAMSys) ListPolicies() (map[string][]byte, error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return nil, errServerNotInitialized return nil, errServerNotInitialized
} }
var policyDocsMap = make(map[string][]byte) var policyDocsMap = make(map[string][]byte)
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
for k, v := range sys.iamPolicyDocsMap { for k, v := range sys.iamPolicyDocsMap {
data, err := json.Marshal(v) data, err := json.Marshal(v)
@ -502,7 +499,7 @@ func (sys *IAMSys) ListPolicies() (map[string][]byte, error) {
// SetPolicy - sets a new name policy. // SetPolicy - sets a new name policy.
func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -510,12 +507,8 @@ func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error {
return errInvalidArgument return errInvalidArgument
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.store == nil {
return errServerNotInitialized
}
if err := sys.store.savePolicyDoc(policyName, p); err != nil { if err := sys.store.savePolicyDoc(policyName, p); err != nil {
return err return err
@ -528,7 +521,7 @@ func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error {
// DeleteUser - delete user (only for long-term users not STS users). // DeleteUser - delete user (only for long-term users not STS users).
func (sys *IAMSys) DeleteUser(accessKey string) error { func (sys *IAMSys) DeleteUser(accessKey string) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -537,6 +530,7 @@ func (sys *IAMSys) DeleteUser(accessKey string) error {
if getErr != nil { if getErr != nil {
return getErr return getErr
} }
for _, group := range userInfo.MemberOf { for _, group := range userInfo.MemberOf {
removeErr := sys.RemoveUsersFromGroup(group, []string{accessKey}) removeErr := sys.RemoveUsersFromGroup(group, []string{accessKey})
if removeErr != nil { if removeErr != nil {
@ -545,17 +539,13 @@ func (sys *IAMSys) DeleteUser(accessKey string) error {
} }
// Next we can remove the user from memory and IAM store // Next we can remove the user from memory and IAM store
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return errIAMActionNotAllowed return errIAMActionNotAllowed
} }
if sys.store == nil {
return errServerNotInitialized
}
// It is ok to ignore deletion error on the mapped policy // It is ok to ignore deletion error on the mapped policy
sys.store.deleteMappedPolicy(accessKey, regularUser, false) sys.store.deleteMappedPolicy(accessKey, regularUser, false)
err := sys.store.deleteUserIdentity(accessKey, regularUser) err := sys.store.deleteUserIdentity(accessKey, regularUser)
@ -583,12 +573,12 @@ func (sys *IAMSys) DeleteUser(accessKey string) error {
// SetTempUser - set temporary user credentials, these credentials have an expiry. // SetTempUser - set temporary user credentials, these credentials have an expiry.
func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyName string) error { func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyName string) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
// If OPA is not set we honor any policy claims for this // If OPA is not set we honor any policy claims for this
// temporary user which match with pre-configured canned // temporary user which match with pre-configured canned
@ -603,10 +593,6 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa
return nil return nil
} }
if sys.store == nil {
return errServerNotInitialized
}
mp := newMappedPolicy(policyName) mp := newMappedPolicy(policyName)
if err := sys.store.saveMappedPolicy(accessKey, stsUser, false, mp); err != nil { if err := sys.store.saveMappedPolicy(accessKey, stsUser, false, mp); err != nil {
return err return err
@ -615,10 +601,6 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa
sys.iamUserPolicyMap[accessKey] = mp sys.iamUserPolicyMap[accessKey] = mp
} }
if sys.store == nil {
return errServerNotInitialized
}
u := newUserIdentity(cred) u := newUserIdentity(cred)
if err := sys.store.saveUserIdentity(accessKey, stsUser, u); err != nil { if err := sys.store.saveUserIdentity(accessKey, stsUser, u); err != nil {
return err return err
@ -631,14 +613,14 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa
// ListUsers - list all users. // ListUsers - list all users.
func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return nil, errServerNotInitialized return nil, errServerNotInitialized
} }
var users = make(map[string]madmin.UserInfo) var users = make(map[string]madmin.UserInfo)
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return nil, errIAMActionNotAllowed return nil, errIAMActionNotAllowed
@ -664,12 +646,12 @@ func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) {
// IsTempUser - returns if given key is a temporary user. // IsTempUser - returns if given key is a temporary user.
func (sys *IAMSys) IsTempUser(name string) (bool, error) { func (sys *IAMSys) IsTempUser(name string) (bool, error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return false, errServerNotInitialized return false, errServerNotInitialized
} }
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
creds, found := sys.iamUsersMap[name] creds, found := sys.iamUsersMap[name]
if !found { if !found {
@ -682,12 +664,12 @@ func (sys *IAMSys) IsTempUser(name string) (bool, error) {
// IsServiceAccount - returns if given key is a service account // IsServiceAccount - returns if given key is a service account
func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) { func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return false, "", errServerNotInitialized return false, "", errServerNotInitialized
} }
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
creds, found := sys.iamUsersMap[name] creds, found := sys.iamUsersMap[name]
if !found { if !found {
@ -704,12 +686,12 @@ func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) {
// GetUserInfo - get info on a user. // GetUserInfo - get info on a user.
func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) { func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return u, errServerNotInitialized return u, errServerNotInitialized
} }
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return madmin.UserInfo{ return madmin.UserInfo{
@ -743,7 +725,7 @@ func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) {
// SetUserStatus - sets current user status, supports disabled or enabled. // SetUserStatus - sets current user status, supports disabled or enabled.
func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error { func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -751,8 +733,8 @@ func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus)
return errInvalidArgument return errInvalidArgument
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return errIAMActionNotAllowed return errIAMActionNotAllowed
@ -778,10 +760,6 @@ func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus)
}(), }(),
}) })
if sys.store == nil {
return errServerNotInitialized
}
if err := sys.store.saveUserIdentity(accessKey, regularUser, uinfo); err != nil { if err := sys.store.saveUserIdentity(accessKey, regularUser, uinfo); err != nil {
return err return err
} }
@ -793,7 +771,7 @@ func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus)
// NewServiceAccount - create a new service account // NewServiceAccount - create a new service account
func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPolicy string) (auth.Credentials, error) { func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPolicy string) (auth.Credentials, error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return auth.Credentials{}, errServerNotInitialized return auth.Credentials{}, errServerNotInitialized
} }
@ -812,17 +790,13 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPol
} }
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return auth.Credentials{}, errIAMActionNotAllowed return auth.Credentials{}, errIAMActionNotAllowed
} }
if sys.store == nil {
return auth.Credentials{}, errServerNotInitialized
}
if parentUser == globalActiveCred.AccessKey { if parentUser == globalActiveCred.AccessKey {
return auth.Credentials{}, errIAMActionNotAllowed return auth.Credentials{}, errIAMActionNotAllowed
} }
@ -867,21 +841,17 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser, sessionPol
// GetServiceAccount - returns the credentials of the given service account // GetServiceAccount - returns the credentials of the given service account
func (sys *IAMSys) GetServiceAccount(ctx context.Context, serviceAccountAccessKey string) (auth.Credentials, error) { func (sys *IAMSys) GetServiceAccount(ctx context.Context, serviceAccountAccessKey string) (auth.Credentials, error) {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return auth.Credentials{}, errServerNotInitialized return auth.Credentials{}, errServerNotInitialized
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return auth.Credentials{}, errIAMActionNotAllowed return auth.Credentials{}, errIAMActionNotAllowed
} }
if sys.store == nil {
return auth.Credentials{}, errServerNotInitialized
}
cr, ok := sys.iamUsersMap[serviceAccountAccessKey] cr, ok := sys.iamUsersMap[serviceAccountAccessKey]
if !ok { if !ok {
return auth.Credentials{}, errNoSuchUser return auth.Credentials{}, errNoSuchUser
@ -897,7 +867,7 @@ func (sys *IAMSys) GetServiceAccount(ctx context.Context, serviceAccountAccessKe
// SetUser - set user credentials and policy. // SetUser - set user credentials and policy.
func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -907,17 +877,13 @@ func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error {
Status: string(uinfo.Status), Status: string(uinfo.Status),
}) })
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return errIAMActionNotAllowed return errIAMActionNotAllowed
} }
if sys.store == nil {
return errServerNotInitialized
}
cr, ok := sys.iamUsersMap[accessKey] cr, ok := sys.iamUsersMap[accessKey]
if cr.IsTemp() && ok { if cr.IsTemp() && ok {
return errIAMActionNotAllowed return errIAMActionNotAllowed
@ -939,12 +905,12 @@ func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error {
// SetUserSecretKey - sets user secret key // SetUserSecretKey - sets user secret key
func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return errIAMActionNotAllowed return errIAMActionNotAllowed
@ -955,10 +921,6 @@ func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error {
return errNoSuchUser return errNoSuchUser
} }
if sys.store == nil {
return errServerNotInitialized
}
cred.SecretKey = secretKey cred.SecretKey = secretKey
u := newUserIdentity(cred) u := newUserIdentity(cred)
if err := sys.store.saveUserIdentity(accessKey, regularUser, u); err != nil { if err := sys.store.saveUserIdentity(accessKey, regularUser, u); err != nil {
@ -971,8 +933,13 @@ func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error {
// GetUser - get user credentials // GetUser - get user credentials
func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) { func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) {
sys.RLock() objectAPI := newObjectLayerWithoutSafeModeFn()
defer sys.RUnlock() if objectAPI == nil || sys == nil || sys.store == nil {
return cred, false
}
sys.store.rlock()
defer sys.store.runlock()
cred, ok = sys.iamUsersMap[accessKey] cred, ok = sys.iamUsersMap[accessKey]
return cred, ok && cred.IsValid() return cred, ok && cred.IsValid()
@ -982,7 +949,7 @@ func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) {
// needed. No error if user(s) already are in the group. // needed. No error if user(s) already are in the group.
func (sys *IAMSys) AddUsersToGroup(group string, members []string) error { func (sys *IAMSys) AddUsersToGroup(group string, members []string) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -990,8 +957,8 @@ func (sys *IAMSys) AddUsersToGroup(group string, members []string) error {
return errInvalidArgument return errInvalidArgument
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return errIAMActionNotAllowed return errIAMActionNotAllowed
@ -1019,10 +986,6 @@ func (sys *IAMSys) AddUsersToGroup(group string, members []string) error {
gi.Members = uniqMembers gi.Members = uniqMembers
} }
if sys.store == nil {
return errServerNotInitialized
}
if err := sys.store.saveGroupInfo(group, gi); err != nil { if err := sys.store.saveGroupInfo(group, gi); err != nil {
return err return err
} }
@ -1047,7 +1010,7 @@ func (sys *IAMSys) AddUsersToGroup(group string, members []string) error {
// given, and the group is empty, deletes the group as well. // given, and the group is empty, deletes the group as well.
func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
@ -1055,8 +1018,8 @@ func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error {
return errInvalidArgument return errInvalidArgument
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return errIAMActionNotAllowed return errIAMActionNotAllowed
@ -1083,10 +1046,6 @@ func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error {
return errGroupNotEmpty return errGroupNotEmpty
} }
if sys.store == nil {
return errServerNotInitialized
}
if len(members) == 0 { if len(members) == 0 {
// len(gi.Members) == 0 here. // len(gi.Members) == 0 here.
@ -1135,16 +1094,12 @@ func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error {
// SetGroupStatus - enable/disabled a group // SetGroupStatus - enable/disabled a group
func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error { func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
if sys.store == nil {
return errServerNotInitialized
}
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return errIAMActionNotAllowed return errIAMActionNotAllowed
@ -1174,6 +1129,11 @@ func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error {
// GetGroupDescription - builds up group description // GetGroupDescription - builds up group description
func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err error) { func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err error) {
objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil || sys == nil || sys.store == nil {
return gd, errServerNotInitialized
}
ps, err := sys.PolicyDBGet(group, true) ps, err := sys.PolicyDBGet(group, true)
if err != nil { if err != nil {
return gd, err return gd, err
@ -1192,8 +1152,8 @@ func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err e
}, nil }, nil
} }
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
gi, ok := sys.iamGroupsMap[group] gi, ok := sys.iamGroupsMap[group]
if !ok { if !ok {
@ -1210,8 +1170,13 @@ func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err e
// ListGroups - lists groups. // ListGroups - lists groups.
func (sys *IAMSys) ListGroups() (r []string, err error) { func (sys *IAMSys) ListGroups() (r []string, err error) {
sys.RLock() objectAPI := newObjectLayerWithoutSafeModeFn()
defer sys.RUnlock() if objectAPI == nil || sys == nil || sys.store == nil {
return r, errServerNotInitialized
}
sys.store.rlock()
defer sys.store.runlock()
if sys.usersSysType != MinIOUsersSysType { if sys.usersSysType != MinIOUsersSysType {
return nil, errIAMActionNotAllowed return nil, errIAMActionNotAllowed
@ -1228,12 +1193,12 @@ func (sys *IAMSys) ListGroups() (r []string, err error) {
// users, policy is set directly by called sys.policyDBSet(). // users, policy is set directly by called sys.policyDBSet().
func (sys *IAMSys) PolicyDBSet(name, policy string, isGroup bool) error { func (sys *IAMSys) PolicyDBSet(name, policy string, isGroup bool) error {
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return errServerNotInitialized return errServerNotInitialized
} }
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
// isSTS is always false when called via PolicyDBSet as policy // isSTS is always false when called via PolicyDBSet as policy
// is never set by an external API call for STS users. // is never set by an external API call for STS users.
@ -1243,10 +1208,6 @@ func (sys *IAMSys) PolicyDBSet(name, policy string, isGroup bool) error {
// policyDBSet - sets a policy for user in the policy db. Assumes that caller // policyDBSet - sets a policy for user in the policy db. Assumes that caller
// has sys.Lock(). If policy == "", then policy mapping is removed. // has sys.Lock(). If policy == "", then policy mapping is removed.
func (sys *IAMSys) policyDBSet(name, policy string, userType IAMUserType, isGroup bool) error { func (sys *IAMSys) policyDBSet(name, policy string, userType IAMUserType, isGroup bool) error {
if sys.store == nil {
return errServerNotInitialized
}
if name == "" { if name == "" {
return errInvalidArgument return errInvalidArgument
} }
@ -1351,8 +1312,8 @@ func (sys *IAMSys) GetAccountAccess(accountName, bucket string) (rd, wr, o bool)
} }
// Policies were found, evaluate all of them. // Policies were found, evaluate all of them.
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
var availablePolicies []iampolicy.Policy var availablePolicies []iampolicy.Policy
for _, pname := range policies { for _, pname := range policies {
@ -1401,17 +1362,17 @@ func (sys *IAMSys) GetAccountAccess(accountName, bucket string) (rd, wr, o bool)
// be a member of multiple groups, this function returns an array of // be a member of multiple groups, this function returns an array of
// applicable policies (each group is mapped to at most one policy). // applicable policies (each group is mapped to at most one policy).
func (sys *IAMSys) PolicyDBGet(name string, isGroup bool) ([]string, error) { func (sys *IAMSys) PolicyDBGet(name string, isGroup bool) ([]string, error) {
if name == "" {
return nil, errInvalidArgument
}
objectAPI := newObjectLayerWithoutSafeModeFn() objectAPI := newObjectLayerWithoutSafeModeFn()
if objectAPI == nil { if objectAPI == nil || sys == nil || sys.store == nil {
return nil, errServerNotInitialized return nil, errServerNotInitialized
} }
sys.RLock() if name == "" {
defer sys.RUnlock() return nil, errInvalidArgument
}
sys.store.rlock()
defer sys.store.runlock()
return sys.policyDBGet(name, isGroup) return sys.policyDBGet(name, isGroup)
} }
@ -1499,14 +1460,14 @@ func (sys *IAMSys) IsAllowedServiceAccount(args iampolicy.Args, parent string) b
var availablePolicies []iampolicy.Policy var availablePolicies []iampolicy.Policy
// Policies were found, evaluate all of them. // Policies were found, evaluate all of them.
sys.RLock() sys.store.rlock()
for _, pname := range parentUserPolicies { for _, pname := range parentUserPolicies {
p, found := sys.iamPolicyDocsMap[pname] p, found := sys.iamPolicyDocsMap[pname]
if found { if found {
availablePolicies = append(availablePolicies, p) availablePolicies = append(availablePolicies, p)
} }
} }
sys.RUnlock() sys.store.runlock()
if len(availablePolicies) == 0 { if len(availablePolicies) == 0 {
return false return false
@ -1595,8 +1556,8 @@ func (sys *IAMSys) IsAllowedSTS(args iampolicy.Args) bool {
return false return false
} }
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
// We look up the policy mapping directly to bypass // We look up the policy mapping directly to bypass
// users exists, group exists validations that do not // users exists, group exists validations that do not
@ -1641,8 +1602,8 @@ func (sys *IAMSys) IsAllowedSTS(args iampolicy.Args) bool {
return false return false
} }
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
// If policy is available for given user, check the policy. // If policy is available for given user, check the policy.
mp, ok := sys.iamUserPolicyMap[args.AccountName] mp, ok := sys.iamUserPolicyMap[args.AccountName]
@ -1742,8 +1703,8 @@ func (sys *IAMSys) IsAllowed(args iampolicy.Args) bool {
} }
// Policies were found, evaluate all of them. // Policies were found, evaluate all of them.
sys.RLock() sys.store.rlock()
defer sys.RUnlock() defer sys.store.runlock()
var availablePolicies []iampolicy.Policy var availablePolicies []iampolicy.Policy
for _, pname := range policies { for _, pname := range policies {
@ -1822,8 +1783,8 @@ func (sys *IAMSys) removeGroupFromMembershipsMap(group string) {
// EnableLDAPSys - enable ldap system users type. // EnableLDAPSys - enable ldap system users type.
func (sys *IAMSys) EnableLDAPSys() { func (sys *IAMSys) EnableLDAPSys() {
sys.Lock() sys.store.lock()
defer sys.Unlock() defer sys.store.unlock()
sys.usersSysType = LDAPUsersSysType sys.usersSysType = LDAPUsersSysType
} }

@ -357,7 +357,7 @@ func (s *peerRESTServer) LoadUsersHandler(w http.ResponseWriter, r *http.Request
return return
} }
err := globalIAMSys.Load() err := globalIAMSys.Load(GlobalContext)
if err != nil { if err != nil {
s.writeErrorResponse(w, err) s.writeErrorResponse(w, err)
return return

@ -250,12 +250,12 @@ func initAllSubsystems(buckets []BucketInfo, newObject ObjectLayer) (err error)
// **** WARNING **** // **** WARNING ****
// Migrating to encrypted backend on etcd should happen before initialization of // Migrating to encrypted backend on etcd should happen before initialization of
// IAM sub-systems, make sure that we do not move the above codeblock elsewhere. // IAM sub-systems, make sure that we do not move the above codeblock elsewhere.
if err = migrateIAMConfigsEtcdToEncrypted(globalEtcdClient); err != nil { if err = migrateIAMConfigsEtcdToEncrypted(GlobalContext, globalEtcdClient); err != nil {
return fmt.Errorf("Unable to handle encrypted backend for iam and policies: %w", err) return fmt.Errorf("Unable to handle encrypted backend for iam and policies: %w", err)
} }
} }
if err = globalIAMSys.Init(newObject); err != nil { if err = globalIAMSys.Init(GlobalContext, newObject); err != nil {
return fmt.Errorf("Unable to initialize IAM system: %w", err) return fmt.Errorf("Unable to initialize IAM system: %w", err)
} }

@ -358,7 +358,7 @@ func UnstartedTestServer(t TestErrHandler, instanceType string) TestServer {
globalConfigSys = NewConfigSys() globalConfigSys = NewConfigSys()
globalIAMSys = NewIAMSys() globalIAMSys = NewIAMSys()
globalIAMSys.Init(objLayer) globalIAMSys.Init(GlobalContext, objLayer)
buckets, err := objLayer.ListBuckets(context.Background()) buckets, err := objLayer.ListBuckets(context.Background())
if err != nil { if err != nil {
@ -1604,7 +1604,7 @@ func newTestObjectLayer(endpointZones EndpointZones) (newObject ObjectLayer, err
globalConfigSys = NewConfigSys() globalConfigSys = NewConfigSys()
globalIAMSys = NewIAMSys() globalIAMSys = NewIAMSys()
globalIAMSys.Init(z) globalIAMSys.Init(GlobalContext, z)
globalPolicySys = NewPolicySys() globalPolicySys = NewPolicySys()
globalPolicySys.Init(nil, z) globalPolicySys.Init(nil, z)
@ -1908,7 +1908,7 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [
newAllSubsystems() newAllSubsystems()
globalIAMSys.Init(objLayer) globalIAMSys.Init(GlobalContext, objLayer)
buckets, err := objLayer.ListBuckets(context.Background()) buckets, err := objLayer.ListBuckets(context.Background())
if err != nil { if err != nil {
@ -1964,7 +1964,7 @@ func ExecObjectLayerTest(t TestErrHandler, objTest objTestType) {
} }
globalIAMSys = NewIAMSys() globalIAMSys = NewIAMSys()
globalIAMSys.Init(objLayer) globalIAMSys.Init(GlobalContext, objLayer)
buckets, err := objLayer.ListBuckets(context.Background()) buckets, err := objLayer.ListBuckets(context.Background())
if err != nil { if err != nil {

Loading…
Cancel
Save