From cd9e30c0f48a575165f954801f74129d4225b857 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Tue, 2 Mar 2021 17:08:25 -0800 Subject: [PATCH] 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 --- cmd/iam.go | 70 +++++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/cmd/iam.go b/cmd/iam.go index e7ef3aa0b..d6020e6a3 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -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{}), } }