IAM: Block while loading users (#11671)

While starting up a request that needs all IAM data will start another load operation if the first on startup hasn't finished. This slows down both operations.

Block these requests until initial load has completed.

Blocking calls will be ListPolicies, ListUsers, ListServiceAccounts, ListGroups - and the calls that eventually trigger these. These will wait for the initial load to complete.

Fixes issue seen in #11305
This commit is contained in:
Klaus Post 2021-03-02 17:08:25 -08:00 committed by GitHub
parent f96d4cf7d3
commit cd9e30c0f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -220,8 +220,10 @@ type IAMSys struct {
iamGroupPolicyMap map[string]MappedPolicy
// Persistence layer for IAM subsystem
store IAMStorageAPI
storeFallback bool
store IAMStorageAPI
// configLoaded will be closed and remain so after first load.
configLoaded chan struct{}
}
// IAMUserType represents a user type inside MinIO server
@ -554,7 +556,11 @@ func (sys *IAMSys) Load(ctx context.Context, store IAMStorageAPI) error {
}
sys.buildUserGroupMemberships()
sys.storeFallback = false
select {
case <-sys.configLoaded:
default:
close(sys.configLoaded)
}
return nil
}
@ -732,15 +738,7 @@ func (sys *IAMSys) ListPolicies() (map[string]iampolicy.Policy, error) {
return nil, errServerNotInitialized
}
sys.store.rlock()
fallback := sys.storeFallback
sys.store.runlock()
if fallback {
if err := sys.store.loadAll(context.Background(), sys); err != nil {
return nil, err
}
}
<-sys.configLoaded
sys.store.rlock()
defer sys.store.runlock()
@ -915,15 +913,7 @@ func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) {
return nil, errIAMActionNotAllowed
}
sys.store.rlock()
fallback := sys.storeFallback
sys.store.runlock()
if fallback {
if err := sys.store.loadAll(context.Background(), sys); err != nil {
return nil, err
}
}
<-sys.configLoaded
sys.store.rlock()
defer sys.store.runlock()
@ -995,10 +985,9 @@ func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) {
return u, errServerNotInitialized
}
sys.store.rlock()
fallback := sys.storeFallback
sys.store.runlock()
if fallback {
select {
case <-sys.configLoaded:
default:
sys.loadUserFromStore(name)
}
@ -1178,15 +1167,7 @@ func (sys *IAMSys) ListServiceAccounts(ctx context.Context, accessKey string) ([
return nil, errServerNotInitialized
}
sys.store.rlock()
fallback := sys.storeFallback
sys.store.runlock()
if fallback {
if err := sys.store.loadAll(context.Background(), sys); err != nil {
return nil, err
}
}
<-sys.configLoaded
sys.store.rlock()
defer sys.store.runlock()
@ -1355,11 +1336,12 @@ func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) {
return cred, false
}
sys.store.rlock()
fallback := sys.storeFallback
sys.store.runlock()
if fallback {
fallback := false
select {
case <-sys.configLoaded:
default:
sys.loadUserFromStore(accessKey)
fallback = true
}
sys.store.rlock()
@ -1619,15 +1601,7 @@ func (sys *IAMSys) ListGroups() (r []string, err error) {
return nil, errIAMActionNotAllowed
}
sys.store.rlock()
fallback := sys.storeFallback
sys.store.runlock()
if fallback {
if err := sys.store.loadAll(context.Background(), sys); err != nil {
return nil, err
}
}
<-sys.configLoaded
sys.store.rlock()
defer sys.store.runlock()
@ -2182,6 +2156,6 @@ func NewIAMSys() *IAMSys {
iamGroupPolicyMap: make(map[string]MappedPolicy),
iamGroupsMap: make(map[string]GroupInfo),
iamUserGroupMemberships: make(map[string]set.StringSet),
storeFallback: true,
configLoaded: make(chan struct{}),
}
}