diff --git a/cmd/admin-handlers-users.go b/cmd/admin-handlers-users.go index cd9c9343c..5718dd758 100644 --- a/cmd/admin-handlers-users.go +++ b/cmd/admin-handlers-users.go @@ -36,7 +36,7 @@ func validateAdminUsersReq(ctx context.Context, w http.ResponseWriter, r *http.R // Get current object layer instance. objectAPI := newObjectLayerFn() - if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { + if objectAPI == nil || globalNotificationSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return nil, cred } @@ -387,7 +387,7 @@ func (a adminAPIHandlers) AddServiceAccount(w http.ResponseWriter, r *http.Reque // Get current object layer instance. objectAPI := newObjectLayerFn() - if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { + if objectAPI == nil || globalNotificationSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return } @@ -466,7 +466,7 @@ func (a adminAPIHandlers) ListServiceAccounts(w http.ResponseWriter, r *http.Req // Get current object layer instance. objectAPI := newObjectLayerFn() - if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { + if objectAPI == nil || globalNotificationSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return } @@ -521,7 +521,7 @@ func (a adminAPIHandlers) DeleteServiceAccount(w http.ResponseWriter, r *http.Re // Get current object layer instance. objectAPI := newObjectLayerFn() - if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { + if objectAPI == nil || globalNotificationSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return } @@ -580,7 +580,7 @@ func (a adminAPIHandlers) AccountUsageInfoHandler(w http.ResponseWriter, r *http // Get current object layer instance. objectAPI := newObjectLayerFn() - if objectAPI == nil || globalNotificationSys == nil || globalIAMSys == nil { + if objectAPI == nil || globalNotificationSys == nil { writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL) return } diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index 563035e3d..b336242d7 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -300,14 +300,14 @@ func StartGateway(ctx *cli.Context, gw Gateway) { } newObject = NewGatewayLayerWithLocker(newObject) + // Calls all New() for all sub-systems. + newAllSubsystems() + // Once endpoints are finalized, initialize the new object api in safe mode. globalObjLayerMutex.Lock() globalObjectAPI = newObject globalObjLayerMutex.Unlock() - // Calls all New() for all sub-systems. - newAllSubsystems() - if gatewayName == NASBackendGateway { buckets, err := newObject.ListBuckets(GlobalContext) if err != nil { @@ -326,6 +326,8 @@ func StartGateway(ctx *cli.Context, gw Gateway) { if enableIAMOps { // Initialize users credentials and policies in background. + globalIAMSys.InitStore(newObject) + go globalIAMSys.Init(GlobalContext, newObject) } diff --git a/cmd/iam-etcd-store.go b/cmd/iam-etcd-store.go index 4ba91ea68..7d4febcfe 100644 --- a/cmd/iam-etcd-store.go +++ b/cmd/iam-etcd-store.go @@ -76,13 +76,11 @@ func etcdKvsToSetPolicyDB(prefix string, kvs []*mvccpb.KeyValue) set.StringSet { type IAMEtcdStore struct { sync.RWMutex - ctx context.Context - client *etcd.Client } -func newIAMEtcdStore(ctx context.Context) *IAMEtcdStore { - return &IAMEtcdStore{client: globalEtcdClient, ctx: ctx} +func newIAMEtcdStore() *IAMEtcdStore { + return &IAMEtcdStore{client: globalEtcdClient} } func (ies *IAMEtcdStore) lock() { @@ -101,7 +99,7 @@ func (ies *IAMEtcdStore) runlock() { ies.RUnlock() } -func (ies *IAMEtcdStore) saveIAMConfig(item interface{}, path string) error { +func (ies *IAMEtcdStore) saveIAMConfig(ctx context.Context, item interface{}, path string) error { data, err := json.Marshal(item) if err != nil { return err @@ -112,11 +110,11 @@ func (ies *IAMEtcdStore) saveIAMConfig(item interface{}, path string) error { return err } } - return saveKeyEtcd(ies.ctx, ies.client, path, data) + return saveKeyEtcd(ctx, ies.client, path, data) } -func (ies *IAMEtcdStore) loadIAMConfig(item interface{}, path string) error { - pdata, err := readKeyEtcd(ies.ctx, ies.client, path) +func (ies *IAMEtcdStore) loadIAMConfig(ctx context.Context, item interface{}, path string) error { + pdata, err := readKeyEtcd(ctx, ies.client, path) if err != nil { return err } @@ -131,8 +129,8 @@ func (ies *IAMEtcdStore) loadIAMConfig(item interface{}, path string) error { return json.Unmarshal(pdata, item) } -func (ies *IAMEtcdStore) deleteIAMConfig(path string) error { - return deleteKeyEtcd(ies.ctx, ies.client, path) +func (ies *IAMEtcdStore) deleteIAMConfig(ctx context.Context, path string) error { + return deleteKeyEtcd(ctx, ies.client, path) } func (ies *IAMEtcdStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) error { @@ -154,7 +152,7 @@ func (ies *IAMEtcdStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) // 1. check if there is a policy file in the old loc. oldPolicyPath := pathJoin(basePrefix, user, iamPolicyFile) var policyName string - err := ies.loadIAMConfig(&policyName, oldPolicyPath) + err := ies.loadIAMConfig(ctx, &policyName, oldPolicyPath) if err != nil { switch err { case errConfigNotFound: @@ -172,7 +170,7 @@ func (ies *IAMEtcdStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) userType = stsUser } path := getMappedPolicyPath(user, userType, false) - if err := ies.saveIAMConfig(mp, path); err != nil { + if err := ies.saveIAMConfig(ctx, mp, path); err != nil { return err } @@ -184,7 +182,7 @@ func (ies *IAMEtcdStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) // 4. check if user identity has old format. identityPath := pathJoin(basePrefix, user, iamIdentityFile) var cred auth.Credentials - if err := ies.loadIAMConfig(&cred, identityPath); err != nil { + if err := ies.loadIAMConfig(ctx, &cred, identityPath); err != nil { switch err { case errConfigNotFound: // This case should not happen. @@ -207,7 +205,7 @@ func (ies *IAMEtcdStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) // into new format and save it. cred.AccessKey = user u := newUserIdentity(cred) - if err := ies.saveIAMConfig(u, identityPath); err != nil { + if err := ies.saveIAMConfig(ctx, u, identityPath); err != nil { logger.LogIf(ctx, err) return err } @@ -221,7 +219,7 @@ func (ies *IAMEtcdStore) migrateUsersConfigToV1(ctx context.Context, isSTS bool) func (ies *IAMEtcdStore) migrateToV1(ctx context.Context) error { var iamFmt iamFormat path := getIAMFormatFilePath() - if err := ies.loadIAMConfig(&iamFmt, path); err != nil { + if err := ies.loadIAMConfig(ctx, &iamFmt, path); err != nil { switch err { case errConfigNotFound: // Need to migrate to V1. @@ -250,7 +248,7 @@ func (ies *IAMEtcdStore) migrateToV1(ctx context.Context) error { return err } // Save iam version file. - if err := ies.saveIAMConfig(newIAMFormatVersion1(), path); err != nil { + if err := ies.saveIAMConfig(ctx, newIAMFormatVersion1(), path); err != nil { logger.LogIf(ctx, err) return err } @@ -262,9 +260,9 @@ func (ies *IAMEtcdStore) migrateBackendFormat(ctx context.Context) error { return ies.migrateToV1(ctx) } -func (ies *IAMEtcdStore) loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error { +func (ies *IAMEtcdStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error { var p iampolicy.Policy - err := ies.loadIAMConfig(&p, getPolicyDocPath(policy)) + err := ies.loadIAMConfig(ctx, &p, getPolicyDocPath(policy)) if err != nil { return err } @@ -284,7 +282,7 @@ func (ies *IAMEtcdStore) loadPolicyDocs(ctx context.Context, m map[string]iampol // Reload config and policies for all policys. for _, policyName := range policies.ToSlice() { - err = ies.loadPolicyDoc(policyName, m) + err = ies.loadPolicyDoc(ctx, policyName, m) if err != nil { return err } @@ -292,9 +290,9 @@ func (ies *IAMEtcdStore) loadPolicyDocs(ctx context.Context, m map[string]iampol return nil } -func (ies *IAMEtcdStore) loadUser(user string, userType IAMUserType, m map[string]auth.Credentials) error { +func (ies *IAMEtcdStore) loadUser(ctx context.Context, user string, userType IAMUserType, m map[string]auth.Credentials) error { var u UserIdentity - err := ies.loadIAMConfig(&u, getUserIdentityPath(user, userType)) + err := ies.loadIAMConfig(ctx, &u, getUserIdentityPath(user, userType)) if err != nil { if err == errConfigNotFound { return errNoSuchUser @@ -304,8 +302,8 @@ func (ies *IAMEtcdStore) loadUser(user string, userType IAMUserType, m map[strin if u.Credentials.IsExpired() { // Delete expired identity. - deleteKeyEtcd(ies.ctx, ies.client, getUserIdentityPath(user, userType)) - deleteKeyEtcd(ies.ctx, ies.client, getMappedPolicyPath(user, userType, false)) + deleteKeyEtcd(ctx, ies.client, getUserIdentityPath(user, userType)) + deleteKeyEtcd(ctx, ies.client, getMappedPolicyPath(user, userType, false)) return nil } @@ -320,7 +318,7 @@ func (ies *IAMEtcdStore) loadUser(user string, userType IAMUserType, m map[strin jwt := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, jwtgo.MapClaims(m)) if token, err := jwt.SignedString([]byte(globalActiveCred.SecretKey)); err == nil { u.Credentials.SessionToken = token - err := ies.saveIAMConfig(&u, getUserIdentityPath(user, userType)) + err := ies.saveIAMConfig(ctx, &u, getUserIdentityPath(user, userType)) if err != nil { return err } @@ -348,9 +346,10 @@ func (ies *IAMEtcdStore) loadUsers(ctx context.Context, userType IAMUserType, m basePrefix = iamConfigUsersPrefix } - ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout) + cctx, cancel := context.WithTimeout(ctx, defaultContextTimeout) defer cancel() - r, err := ies.client.Get(ctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) + + r, err := ies.client.Get(cctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) if err != nil { return err } @@ -359,16 +358,16 @@ func (ies *IAMEtcdStore) loadUsers(ctx context.Context, userType IAMUserType, m // Reload config for all users. for _, user := range users.ToSlice() { - if err = ies.loadUser(user, userType, m); err != nil { + if err = ies.loadUser(ctx, user, userType, m); err != nil { return err } } return nil } -func (ies *IAMEtcdStore) loadGroup(group string, m map[string]GroupInfo) error { +func (ies *IAMEtcdStore) loadGroup(ctx context.Context, group string, m map[string]GroupInfo) error { var gi GroupInfo - err := ies.loadIAMConfig(&gi, getGroupInfoPath(group)) + err := ies.loadIAMConfig(ctx, &gi, getGroupInfoPath(group)) if err != nil { if err == errConfigNotFound { return errNoSuchGroup @@ -381,9 +380,10 @@ func (ies *IAMEtcdStore) loadGroup(group string, m map[string]GroupInfo) error { } func (ies *IAMEtcdStore) loadGroups(ctx context.Context, m map[string]GroupInfo) error { - ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout) + cctx, cancel := context.WithTimeout(ctx, defaultContextTimeout) defer cancel() - r, err := ies.client.Get(ctx, iamConfigGroupsPrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) + + r, err := ies.client.Get(cctx, iamConfigGroupsPrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) if err != nil { return err } @@ -392,7 +392,7 @@ func (ies *IAMEtcdStore) loadGroups(ctx context.Context, m map[string]GroupInfo) // Reload config for all groups. for _, group := range groups.ToSlice() { - if err = ies.loadGroup(group, m); err != nil { + if err = ies.loadGroup(ctx, group, m); err != nil { return err } } @@ -400,9 +400,9 @@ func (ies *IAMEtcdStore) loadGroups(ctx context.Context, m map[string]GroupInfo) } -func (ies *IAMEtcdStore) loadMappedPolicy(name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { +func (ies *IAMEtcdStore) loadMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { var p MappedPolicy - err := ies.loadIAMConfig(&p, getMappedPolicyPath(name, userType, isGroup)) + err := ies.loadIAMConfig(ctx, &p, getMappedPolicyPath(name, userType, isGroup)) if err != nil { if err == errConfigNotFound { return errNoSuchPolicy @@ -415,7 +415,7 @@ func (ies *IAMEtcdStore) loadMappedPolicy(name string, userType IAMUserType, isG } func (ies *IAMEtcdStore) loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { - ctx, cancel := context.WithTimeout(ctx, defaultContextTimeout) + cctx, cancel := context.WithTimeout(ctx, defaultContextTimeout) defer cancel() var basePrefix string if isGroup { @@ -430,7 +430,8 @@ func (ies *IAMEtcdStore) loadMappedPolicies(ctx context.Context, userType IAMUse basePrefix = iamConfigPolicyDBUsersPrefix } } - r, err := ies.client.Get(ctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) + + r, err := ies.client.Get(cctx, basePrefix, etcd.WithPrefix(), etcd.WithKeysOnly()) if err != nil { return err } @@ -439,7 +440,7 @@ func (ies *IAMEtcdStore) loadMappedPolicies(ctx context.Context, userType IAMUse // Reload config and policies for all users. for _, user := range users.ToSlice() { - if err = ies.loadMappedPolicy(user, userType, isGroup, m); err != nil { + if err = ies.loadMappedPolicy(ctx, user, userType, isGroup, m); err != nil { return err } } @@ -531,7 +532,7 @@ func (ies *IAMEtcdStore) loadAll(ctx context.Context, sys *IAMSys) error { if v.IsServiceAccount() { for _, accessKey := range expiredEntries { if v.ParentUser == accessKey { - _ = ies.deleteUserIdentity(v.AccessKey, srvAccUser) + _ = ies.deleteUserIdentity(ctx, v.AccessKey, srvAccUser) delete(sys.iamUsersMap, v.AccessKey) } } @@ -561,48 +562,48 @@ func (ies *IAMEtcdStore) loadAll(ctx context.Context, sys *IAMSys) error { return nil } -func (ies *IAMEtcdStore) savePolicyDoc(policyName string, p iampolicy.Policy) error { - return ies.saveIAMConfig(&p, getPolicyDocPath(policyName)) +func (ies *IAMEtcdStore) savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error { + return ies.saveIAMConfig(ctx, &p, getPolicyDocPath(policyName)) } -func (ies *IAMEtcdStore) saveMappedPolicy(name string, userType IAMUserType, isGroup bool, mp MappedPolicy) error { - return ies.saveIAMConfig(mp, getMappedPolicyPath(name, userType, isGroup)) +func (ies *IAMEtcdStore) saveMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, mp MappedPolicy) error { + return ies.saveIAMConfig(ctx, mp, getMappedPolicyPath(name, userType, isGroup)) } -func (ies *IAMEtcdStore) saveUserIdentity(name string, userType IAMUserType, u UserIdentity) error { - return ies.saveIAMConfig(u, getUserIdentityPath(name, userType)) +func (ies *IAMEtcdStore) saveUserIdentity(ctx context.Context, name string, userType IAMUserType, u UserIdentity) error { + return ies.saveIAMConfig(ctx, u, getUserIdentityPath(name, userType)) } -func (ies *IAMEtcdStore) saveGroupInfo(name string, gi GroupInfo) error { - return ies.saveIAMConfig(gi, getGroupInfoPath(name)) +func (ies *IAMEtcdStore) saveGroupInfo(ctx context.Context, name string, gi GroupInfo) error { + return ies.saveIAMConfig(ctx, gi, getGroupInfoPath(name)) } -func (ies *IAMEtcdStore) deletePolicyDoc(name string) error { - err := ies.deleteIAMConfig(getPolicyDocPath(name)) +func (ies *IAMEtcdStore) deletePolicyDoc(ctx context.Context, name string) error { + err := ies.deleteIAMConfig(ctx, getPolicyDocPath(name)) if err == errConfigNotFound { err = errNoSuchPolicy } return err } -func (ies *IAMEtcdStore) deleteMappedPolicy(name string, userType IAMUserType, isGroup bool) error { - err := ies.deleteIAMConfig(getMappedPolicyPath(name, userType, isGroup)) +func (ies *IAMEtcdStore) deleteMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool) error { + err := ies.deleteIAMConfig(ctx, getMappedPolicyPath(name, userType, isGroup)) if err == errConfigNotFound { err = errNoSuchPolicy } return err } -func (ies *IAMEtcdStore) deleteUserIdentity(name string, userType IAMUserType) error { - err := ies.deleteIAMConfig(getUserIdentityPath(name, userType)) +func (ies *IAMEtcdStore) deleteUserIdentity(ctx context.Context, name string, userType IAMUserType) error { + err := ies.deleteIAMConfig(ctx, getUserIdentityPath(name, userType)) if err == errConfigNotFound { err = errNoSuchUser } return err } -func (ies *IAMEtcdStore) deleteGroupInfo(name string) error { - err := ies.deleteIAMConfig(getGroupInfoPath(name)) +func (ies *IAMEtcdStore) deleteGroupInfo(ctx context.Context, name string) error { + err := ies.deleteIAMConfig(ctx, getGroupInfoPath(name)) if err == errConfigNotFound { err = errNoSuchGroup } @@ -657,43 +658,46 @@ func (ies *IAMEtcdStore) reloadFromEvent(sys *IAMSys, event *etcd.Event) { policyDBSTSUsersPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPolicyDBSTSUsersPrefix) policyDBGroupsPrefix := strings.HasPrefix(string(event.Kv.Key), iamConfigPolicyDBGroupsPrefix) + ctx, cancel := context.WithTimeout(context.Background(), defaultContextTimeout) + defer cancel() + switch { case eventCreate: switch { case usersPrefix: accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key), iamConfigUsersPrefix)) - ies.loadUser(accessKey, regularUser, sys.iamUsersMap) + ies.loadUser(ctx, accessKey, regularUser, sys.iamUsersMap) case stsPrefix: accessKey := path.Dir(strings.TrimPrefix(string(event.Kv.Key), iamConfigSTSPrefix)) - ies.loadUser(accessKey, stsUser, sys.iamUsersMap) + ies.loadUser(ctx, accessKey, stsUser, sys.iamUsersMap) case groupsPrefix: group := path.Dir(strings.TrimPrefix(string(event.Kv.Key), iamConfigGroupsPrefix)) - ies.loadGroup(group, sys.iamGroupsMap) + ies.loadGroup(ctx, group, sys.iamGroupsMap) gi := sys.iamGroupsMap[group] sys.removeGroupFromMembershipsMap(group) sys.updateGroupMembershipsMap(group, &gi) case policyPrefix: policyName := path.Dir(strings.TrimPrefix(string(event.Kv.Key), iamConfigPoliciesPrefix)) - ies.loadPolicyDoc(policyName, sys.iamPolicyDocsMap) + ies.loadPolicyDoc(ctx, policyName, sys.iamPolicyDocsMap) case policyDBUsersPrefix: policyMapFile := strings.TrimPrefix(string(event.Kv.Key), iamConfigPolicyDBUsersPrefix) user := strings.TrimSuffix(policyMapFile, ".json") - ies.loadMappedPolicy(user, regularUser, false, sys.iamUserPolicyMap) + ies.loadMappedPolicy(ctx, user, regularUser, false, sys.iamUserPolicyMap) case policyDBSTSUsersPrefix: policyMapFile := strings.TrimPrefix(string(event.Kv.Key), iamConfigPolicyDBSTSUsersPrefix) user := strings.TrimSuffix(policyMapFile, ".json") - ies.loadMappedPolicy(user, stsUser, false, sys.iamUserPolicyMap) + ies.loadMappedPolicy(ctx, user, stsUser, false, sys.iamUserPolicyMap) case policyDBGroupsPrefix: policyMapFile := strings.TrimPrefix(string(event.Kv.Key), iamConfigPolicyDBGroupsPrefix) user := strings.TrimSuffix(policyMapFile, ".json") - ies.loadMappedPolicy(user, regularUser, true, sys.iamGroupPolicyMap) + ies.loadMappedPolicy(ctx, user, regularUser, true, sys.iamGroupPolicyMap) } case eventDelete: switch { diff --git a/cmd/iam-object-store.go b/cmd/iam-object-store.go index a5c4d55d0..985f28e4e 100644 --- a/cmd/iam-object-store.go +++ b/cmd/iam-object-store.go @@ -39,12 +39,11 @@ type IAMObjectStore struct { // Protect assignment to objAPI sync.RWMutex - ctx context.Context objAPI ObjectLayer } -func newIAMObjectStore(ctx context.Context, objAPI ObjectLayer) *IAMObjectStore { - return &IAMObjectStore{ctx: ctx, objAPI: objAPI} +func newIAMObjectStore(objAPI ObjectLayer) *IAMObjectStore { + return &IAMObjectStore{objAPI: objAPI} } func (iamOS *IAMObjectStore) lock() { @@ -94,7 +93,7 @@ func (iamOS *IAMObjectStore) migrateUsersConfigToV1(ctx context.Context, isSTS b // 1. check if there is policy file in old location. oldPolicyPath := pathJoin(basePrefix, user, iamPolicyFile) var policyName string - if err := iamOS.loadIAMConfig(&policyName, oldPolicyPath); err != nil { + if err := iamOS.loadIAMConfig(ctx, &policyName, oldPolicyPath); err != nil { switch err { case errConfigNotFound: // This case means it is already @@ -115,19 +114,19 @@ func (iamOS *IAMObjectStore) migrateUsersConfigToV1(ctx context.Context, isSTS b if isSTS { userType = stsUser } - if err := iamOS.saveMappedPolicy(user, userType, false, mp); err != nil { + if err := iamOS.saveMappedPolicy(ctx, user, userType, false, mp); err != nil { return err } // 3. delete policy file from old // location. Ignore error. - iamOS.deleteIAMConfig(oldPolicyPath) + iamOS.deleteIAMConfig(ctx, oldPolicyPath) } next: // 4. check if user identity has old format. identityPath := pathJoin(basePrefix, user, iamIdentityFile) var cred auth.Credentials - if err := iamOS.loadIAMConfig(&cred, identityPath); err != nil { + if err := iamOS.loadIAMConfig(ctx, &cred, identityPath); err != nil { switch err { case errConfigNotFound: // This should not happen. @@ -150,7 +149,7 @@ func (iamOS *IAMObjectStore) migrateUsersConfigToV1(ctx context.Context, isSTS b // into new format and save it. cred.AccessKey = user u := newUserIdentity(cred) - if err := iamOS.saveIAMConfig(u, identityPath); err != nil { + if err := iamOS.saveIAMConfig(ctx, u, identityPath); err != nil { logger.LogIf(ctx, err) return err } @@ -165,7 +164,7 @@ func (iamOS *IAMObjectStore) migrateUsersConfigToV1(ctx context.Context, isSTS b func (iamOS *IAMObjectStore) migrateToV1(ctx context.Context) error { var iamFmt iamFormat path := getIAMFormatFilePath() - if err := iamOS.loadIAMConfig(&iamFmt, path); err != nil { + if err := iamOS.loadIAMConfig(ctx, &iamFmt, path); err != nil { switch err { case errConfigNotFound: // Need to migrate to V1. @@ -193,7 +192,7 @@ func (iamOS *IAMObjectStore) migrateToV1(ctx context.Context) error { return err } // Save iam format to version 1. - if err := iamOS.saveIAMConfig(newIAMFormatVersion1(), path); err != nil { + if err := iamOS.saveIAMConfig(ctx, newIAMFormatVersion1(), path); err != nil { logger.LogIf(ctx, err) return err } @@ -205,7 +204,7 @@ func (iamOS *IAMObjectStore) migrateBackendFormat(ctx context.Context) error { return iamOS.migrateToV1(ctx) } -func (iamOS *IAMObjectStore) saveIAMConfig(item interface{}, path string) error { +func (iamOS *IAMObjectStore) saveIAMConfig(ctx context.Context, item interface{}, path string) error { data, err := json.Marshal(item) if err != nil { return err @@ -216,11 +215,11 @@ func (iamOS *IAMObjectStore) saveIAMConfig(item interface{}, path string) error return err } } - return saveConfig(GlobalContext, iamOS.objAPI, path, data) + return saveConfig(ctx, iamOS.objAPI, path, data) } -func (iamOS *IAMObjectStore) loadIAMConfig(item interface{}, path string) error { - data, err := readConfig(iamOS.ctx, iamOS.objAPI, path) +func (iamOS *IAMObjectStore) loadIAMConfig(ctx context.Context, item interface{}, path string) error { + data, err := readConfig(ctx, iamOS.objAPI, path) if err != nil { return err } @@ -233,13 +232,13 @@ func (iamOS *IAMObjectStore) loadIAMConfig(item interface{}, path string) error return json.Unmarshal(data, item) } -func (iamOS *IAMObjectStore) deleteIAMConfig(path string) error { - return deleteConfig(iamOS.ctx, iamOS.objAPI, path) +func (iamOS *IAMObjectStore) deleteIAMConfig(ctx context.Context, path string) error { + return deleteConfig(ctx, iamOS.objAPI, path) } -func (iamOS *IAMObjectStore) loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error { +func (iamOS *IAMObjectStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error { var p iampolicy.Policy - err := iamOS.loadIAMConfig(&p, getPolicyDocPath(policy)) + err := iamOS.loadIAMConfig(ctx, &p, getPolicyDocPath(policy)) if err != nil { if err == errConfigNotFound { return errNoSuchPolicy @@ -257,16 +256,16 @@ func (iamOS *IAMObjectStore) loadPolicyDocs(ctx context.Context, m map[string]ia } policyName := item.Item - if err := iamOS.loadPolicyDoc(policyName, m); err != nil && err != errNoSuchPolicy { + if err := iamOS.loadPolicyDoc(ctx, policyName, m); err != nil && err != errNoSuchPolicy { return err } } return nil } -func (iamOS *IAMObjectStore) loadUser(user string, userType IAMUserType, m map[string]auth.Credentials) error { +func (iamOS *IAMObjectStore) loadUser(ctx context.Context, user string, userType IAMUserType, m map[string]auth.Credentials) error { var u UserIdentity - err := iamOS.loadIAMConfig(&u, getUserIdentityPath(user, userType)) + err := iamOS.loadIAMConfig(ctx, &u, getUserIdentityPath(user, userType)) if err != nil { if err == errConfigNotFound { return errNoSuchUser @@ -276,8 +275,8 @@ func (iamOS *IAMObjectStore) loadUser(user string, userType IAMUserType, m map[s if u.Credentials.IsExpired() { // Delete expired identity - ignoring errors here. - iamOS.deleteIAMConfig(getUserIdentityPath(user, userType)) - iamOS.deleteIAMConfig(getMappedPolicyPath(user, userType, false)) + iamOS.deleteIAMConfig(ctx, getUserIdentityPath(user, userType)) + iamOS.deleteIAMConfig(ctx, getMappedPolicyPath(user, userType, false)) return nil } @@ -292,7 +291,7 @@ func (iamOS *IAMObjectStore) loadUser(user string, userType IAMUserType, m map[s jwt := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, jwtgo.MapClaims(m)) if token, err := jwt.SignedString([]byte(globalActiveCred.SecretKey)); err == nil { u.Credentials.SessionToken = token - err := iamOS.saveIAMConfig(&u, getUserIdentityPath(user, userType)) + err := iamOS.saveIAMConfig(ctx, &u, getUserIdentityPath(user, userType)) if err != nil { return err } @@ -326,16 +325,16 @@ func (iamOS *IAMObjectStore) loadUsers(ctx context.Context, userType IAMUserType } userName := item.Item - if err := iamOS.loadUser(userName, userType, m); err != nil && err != errNoSuchUser { + if err := iamOS.loadUser(ctx, userName, userType, m); err != nil && err != errNoSuchUser { return err } } return nil } -func (iamOS *IAMObjectStore) loadGroup(group string, m map[string]GroupInfo) error { +func (iamOS *IAMObjectStore) loadGroup(ctx context.Context, group string, m map[string]GroupInfo) error { var g GroupInfo - err := iamOS.loadIAMConfig(&g, getGroupInfoPath(group)) + err := iamOS.loadIAMConfig(ctx, &g, getGroupInfoPath(group)) if err != nil { if err == errConfigNotFound { return errNoSuchGroup @@ -353,18 +352,18 @@ func (iamOS *IAMObjectStore) loadGroups(ctx context.Context, m map[string]GroupI } group := item.Item - if err := iamOS.loadGroup(group, m); err != nil && err != errNoSuchGroup { + if err := iamOS.loadGroup(ctx, group, m); err != nil && err != errNoSuchGroup { return err } } return nil } -func (iamOS *IAMObjectStore) loadMappedPolicy(name string, userType IAMUserType, isGroup bool, +func (iamOS *IAMObjectStore) loadMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { var p MappedPolicy - err := iamOS.loadIAMConfig(&p, getMappedPolicyPath(name, userType, isGroup)) + err := iamOS.loadIAMConfig(ctx, &p, getMappedPolicyPath(name, userType, isGroup)) if err != nil { if err == errConfigNotFound { return errNoSuchPolicy @@ -396,7 +395,7 @@ func (iamOS *IAMObjectStore) loadMappedPolicies(ctx context.Context, userType IA policyFile := item.Item userOrGroupName := strings.TrimSuffix(policyFile, ".json") - if err := iamOS.loadMappedPolicy(userOrGroupName, userType, isGroup, m); err != nil && err != errNoSuchPolicy { + if err := iamOS.loadMappedPolicy(ctx, userOrGroupName, userType, isGroup, m); err != nil && err != errNoSuchPolicy { return err } } @@ -489,7 +488,7 @@ func (iamOS *IAMObjectStore) loadAll(ctx context.Context, sys *IAMSys) error { if v.IsServiceAccount() { for _, accessKey := range expiredEntries { if v.ParentUser == accessKey { - _ = iamOS.deleteUserIdentity(v.AccessKey, srvAccUser) + _ = iamOS.deleteUserIdentity(ctx, v.AccessKey, srvAccUser) delete(sys.iamUsersMap, v.AccessKey) } } @@ -510,48 +509,48 @@ func (iamOS *IAMObjectStore) loadAll(ctx context.Context, sys *IAMSys) error { return nil } -func (iamOS *IAMObjectStore) savePolicyDoc(policyName string, p iampolicy.Policy) error { - return iamOS.saveIAMConfig(&p, getPolicyDocPath(policyName)) +func (iamOS *IAMObjectStore) savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error { + return iamOS.saveIAMConfig(ctx, &p, getPolicyDocPath(policyName)) } -func (iamOS *IAMObjectStore) saveMappedPolicy(name string, userType IAMUserType, isGroup bool, mp MappedPolicy) error { - return iamOS.saveIAMConfig(mp, getMappedPolicyPath(name, userType, isGroup)) +func (iamOS *IAMObjectStore) saveMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, mp MappedPolicy) error { + return iamOS.saveIAMConfig(ctx, mp, getMappedPolicyPath(name, userType, isGroup)) } -func (iamOS *IAMObjectStore) saveUserIdentity(name string, userType IAMUserType, u UserIdentity) error { - return iamOS.saveIAMConfig(u, getUserIdentityPath(name, userType)) +func (iamOS *IAMObjectStore) saveUserIdentity(ctx context.Context, name string, userType IAMUserType, u UserIdentity) error { + return iamOS.saveIAMConfig(ctx, u, getUserIdentityPath(name, userType)) } -func (iamOS *IAMObjectStore) saveGroupInfo(name string, gi GroupInfo) error { - return iamOS.saveIAMConfig(gi, getGroupInfoPath(name)) +func (iamOS *IAMObjectStore) saveGroupInfo(ctx context.Context, name string, gi GroupInfo) error { + return iamOS.saveIAMConfig(ctx, gi, getGroupInfoPath(name)) } -func (iamOS *IAMObjectStore) deletePolicyDoc(name string) error { - err := iamOS.deleteIAMConfig(getPolicyDocPath(name)) +func (iamOS *IAMObjectStore) deletePolicyDoc(ctx context.Context, name string) error { + err := iamOS.deleteIAMConfig(ctx, getPolicyDocPath(name)) if err == errConfigNotFound { err = errNoSuchPolicy } return err } -func (iamOS *IAMObjectStore) deleteMappedPolicy(name string, userType IAMUserType, isGroup bool) error { - err := iamOS.deleteIAMConfig(getMappedPolicyPath(name, userType, isGroup)) +func (iamOS *IAMObjectStore) deleteMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool) error { + err := iamOS.deleteIAMConfig(ctx, getMappedPolicyPath(name, userType, isGroup)) if err == errConfigNotFound { err = errNoSuchPolicy } return err } -func (iamOS *IAMObjectStore) deleteUserIdentity(name string, userType IAMUserType) error { - err := iamOS.deleteIAMConfig(getUserIdentityPath(name, userType)) +func (iamOS *IAMObjectStore) deleteUserIdentity(ctx context.Context, name string, userType IAMUserType) error { + err := iamOS.deleteIAMConfig(ctx, getUserIdentityPath(name, userType)) if err == errConfigNotFound { err = errNoSuchUser } return err } -func (iamOS *IAMObjectStore) deleteGroupInfo(name string) error { - err := iamOS.deleteIAMConfig(getGroupInfoPath(name)) +func (iamOS *IAMObjectStore) deleteGroupInfo(ctx context.Context, name string) error { + err := iamOS.deleteIAMConfig(ctx, getGroupInfoPath(name)) if err == errConfigNotFound { err = errNoSuchGroup } diff --git a/cmd/iam.go b/cmd/iam.go index fa6bb8d69..109198952 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -240,33 +240,33 @@ type IAMStorageAPI interface { migrateBackendFormat(context.Context) error - loadPolicyDoc(policy string, m map[string]iampolicy.Policy) error + loadPolicyDoc(ctx context.Context, policy string, 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(ctx context.Context, user string, 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(ctx context.Context, group string, 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(ctx context.Context, name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error loadAll(context.Context, *IAMSys) error - saveIAMConfig(item interface{}, path string) error - loadIAMConfig(item interface{}, path string) error - deleteIAMConfig(path string) error + saveIAMConfig(ctx context.Context, item interface{}, path string) error + loadIAMConfig(ctx context.Context, item interface{}, path string) error + deleteIAMConfig(ctx context.Context, path string) error - savePolicyDoc(policyName string, p iampolicy.Policy) error - saveMappedPolicy(name string, userType IAMUserType, isGroup bool, mp MappedPolicy) error - saveUserIdentity(name string, userType IAMUserType, u UserIdentity) error - saveGroupInfo(group string, gi GroupInfo) error + savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error + saveMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, mp MappedPolicy) error + saveUserIdentity(ctx context.Context, name string, userType IAMUserType, u UserIdentity) error + saveGroupInfo(ctx context.Context, group string, gi GroupInfo) error - deletePolicyDoc(policyName string) error - deleteMappedPolicy(name string, userType IAMUserType, isGroup bool) error - deleteUserIdentity(name string, userType IAMUserType) error - deleteGroupInfo(name string) error + deletePolicyDoc(ctx context.Context, policyName string) error + deleteMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool) error + deleteUserIdentity(ctx context.Context, name string, userType IAMUserType) error + deleteGroupInfo(ctx context.Context, name string) error watch(context.Context, *IAMSys) } @@ -289,7 +289,7 @@ func (sys *IAMSys) LoadGroup(objAPI ObjectLayer, group string) error { sys.store.lock() defer sys.store.unlock() - err := sys.store.loadGroup(group, sys.iamGroupsMap) + err := sys.store.loadGroup(context.Background(), group, sys.iamGroupsMap) if err != nil && err != errNoSuchGroup { return err } @@ -326,7 +326,7 @@ func (sys *IAMSys) LoadPolicy(objAPI ObjectLayer, policyName string) error { defer sys.store.unlock() if globalEtcdClient == nil { - return sys.store.loadPolicyDoc(policyName, sys.iamPolicyDocsMap) + return sys.store.loadPolicyDoc(context.Background(), policyName, sys.iamPolicyDocsMap) } // When etcd is set, we use watch APIs so this code is not needed. @@ -346,9 +346,9 @@ func (sys *IAMSys) LoadPolicyMapping(objAPI ObjectLayer, userOrGroup string, isG if globalEtcdClient == nil { var err error if isGroup { - err = sys.store.loadMappedPolicy(userOrGroup, regularUser, isGroup, sys.iamGroupPolicyMap) + err = sys.store.loadMappedPolicy(context.Background(), userOrGroup, regularUser, isGroup, sys.iamGroupPolicyMap) } else { - err = sys.store.loadMappedPolicy(userOrGroup, regularUser, isGroup, sys.iamUserPolicyMap) + err = sys.store.loadMappedPolicy(context.Background(), userOrGroup, regularUser, isGroup, sys.iamUserPolicyMap) } // Ignore policy not mapped error @@ -370,11 +370,11 @@ func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, userType IAMUs defer sys.store.unlock() if globalEtcdClient == nil { - err := sys.store.loadUser(accessKey, userType, sys.iamUsersMap) + err := sys.store.loadUser(context.Background(), accessKey, userType, sys.iamUsersMap) if err != nil { return err } - err = sys.store.loadMappedPolicy(accessKey, userType, false, sys.iamUserPolicyMap) + err = sys.store.loadMappedPolicy(context.Background(), accessKey, userType, false, sys.iamUserPolicyMap) // Ignore policy not mapped error if err != nil && err != errNoSuchPolicy { return err @@ -386,7 +386,7 @@ func (sys *IAMSys) LoadUser(objAPI ObjectLayer, accessKey string, userType IAMUs // LoadServiceAccount - reloads a specific service account from backend disks or etcd. func (sys *IAMSys) LoadServiceAccount(accessKey string) error { - if sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -394,7 +394,7 @@ func (sys *IAMSys) LoadServiceAccount(accessKey string) error { defer sys.store.unlock() if globalEtcdClient == nil { - err := sys.store.loadUser(accessKey, srvAccUser, sys.iamUsersMap) + err := sys.store.loadUser(context.Background(), accessKey, srvAccUser, sys.iamUsersMap) if err != nil { return err } @@ -408,23 +408,21 @@ func (sys *IAMSys) doIAMConfigMigration(ctx context.Context) error { return sys.store.migrateBackendFormat(ctx) } -// Init - initializes config system by reading entries from config/iam -func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer) { - if objAPI == nil { - logger.LogIf(ctx, errServerNotInitialized) - return - } - +// InitStore initializes IAM stores +func (sys *IAMSys) InitStore(objAPI ObjectLayer) { if globalEtcdClient == nil { - sys.store = newIAMObjectStore(ctx, objAPI) + sys.store = newIAMObjectStore(objAPI) } else { - sys.store = newIAMEtcdStore(ctx) + sys.store = newIAMEtcdStore() } if globalLDAPConfig.Enabled { sys.EnableLDAPSys() } +} +// Init - initializes config system by reading entries from config/iam +func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer) { retryCtx, cancel := context.WithCancel(ctx) // Indicate to our routine to exit cleanly upon return. @@ -507,8 +505,7 @@ func (sys *IAMSys) Init(ctx context.Context, objAPI ObjectLayer) { // DeletePolicy - deletes a canned policy from backend or etcd. func (sys *IAMSys) DeletePolicy(policyName string) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -519,7 +516,7 @@ func (sys *IAMSys) DeletePolicy(policyName string) error { sys.store.lock() defer sys.store.unlock() - err := sys.store.deletePolicyDoc(policyName) + err := sys.store.deletePolicyDoc(context.Background(), policyName) if err == errNoSuchPolicy { // Ignore error if policy is already deleted. err = nil @@ -560,8 +557,7 @@ func (sys *IAMSys) DeletePolicy(policyName string) error { // InfoPolicy - expands the canned policy into its JSON structure. func (sys *IAMSys) InfoPolicy(policyName string) (iampolicy.Policy, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return iampolicy.Policy{}, errServerNotInitialized } @@ -578,8 +574,7 @@ func (sys *IAMSys) InfoPolicy(policyName string) (iampolicy.Policy, error) { // ListPolicies - lists all canned policies. func (sys *IAMSys) ListPolicies() (map[string]iampolicy.Policy, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return nil, errServerNotInitialized } @@ -600,8 +595,7 @@ func (sys *IAMSys) ListPolicies() (map[string]iampolicy.Policy, error) { // SetPolicy - sets a new name policy. func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -612,7 +606,7 @@ func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { sys.store.lock() defer sys.store.unlock() - if err := sys.store.savePolicyDoc(policyName, p); err != nil { + if err := sys.store.savePolicyDoc(context.Background(), policyName, p); err != nil { return err } @@ -622,8 +616,7 @@ func (sys *IAMSys) SetPolicy(policyName string, p iampolicy.Policy) error { // DeleteUser - delete user (only for long-term users not STS users). func (sys *IAMSys) DeleteUser(accessKey string) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -652,15 +645,15 @@ func (sys *IAMSys) DeleteUser(accessKey string) error { for _, u := range sys.iamUsersMap { if u.IsServiceAccount() { if u.ParentUser == accessKey { - _ = sys.store.deleteUserIdentity(u.AccessKey, srvAccUser) + _ = sys.store.deleteUserIdentity(context.Background(), u.AccessKey, srvAccUser) delete(sys.iamUsersMap, u.AccessKey) } } } // It is ok to ignore deletion error on the mapped policy - sys.store.deleteMappedPolicy(accessKey, regularUser, false) - err := sys.store.deleteUserIdentity(accessKey, regularUser) + sys.store.deleteMappedPolicy(context.Background(), accessKey, regularUser, false) + err := sys.store.deleteUserIdentity(context.Background(), accessKey, regularUser) if err == errNoSuchUser { // ignore if user is already deleted. err = nil @@ -692,8 +685,7 @@ func (sys *IAMSys) currentPolicies(policyName string) string { // SetTempUser - set temporary user credentials, these credentials have an expiry. func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyName string) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -724,7 +716,7 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa return nil } - if err := sys.store.saveMappedPolicy(accessKey, stsUser, false, mp); err != nil { + if err := sys.store.saveMappedPolicy(context.Background(), accessKey, stsUser, false, mp); err != nil { return err } @@ -732,7 +724,7 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa } u := newUserIdentity(cred) - if err := sys.store.saveUserIdentity(accessKey, stsUser, u); err != nil { + if err := sys.store.saveUserIdentity(context.Background(), accessKey, stsUser, u); err != nil { return err } @@ -742,8 +734,7 @@ func (sys *IAMSys) SetTempUser(accessKey string, cred auth.Credentials, policyNa // ListUsers - list all users. func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return nil, errServerNotInitialized } @@ -779,8 +770,7 @@ func (sys *IAMSys) ListUsers() (map[string]madmin.UserInfo, error) { // IsTempUser - returns if given key is a temporary user. func (sys *IAMSys) IsTempUser(name string) (bool, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return false, errServerNotInitialized } @@ -797,8 +787,7 @@ func (sys *IAMSys) IsTempUser(name string) (bool, error) { // IsServiceAccount - returns if given key is a service account func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return false, "", errServerNotInitialized } @@ -819,8 +808,7 @@ func (sys *IAMSys) IsServiceAccount(name string) (bool, string, error) { // GetUserInfo - get info on a user. func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return u, errServerNotInitialized } @@ -865,8 +853,8 @@ func (sys *IAMSys) GetUserInfo(name string) (u madmin.UserInfo, err error) { // SetUserStatus - sets current user status, supports disabled or enabled. func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + + if sys == nil { return errServerNotInitialized } @@ -901,7 +889,7 @@ func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) }(), }) - if err := sys.store.saveUserIdentity(accessKey, regularUser, uinfo); err != nil { + if err := sys.store.saveUserIdentity(context.Background(), accessKey, regularUser, uinfo); err != nil { return err } @@ -911,8 +899,8 @@ func (sys *IAMSys) SetUserStatus(accessKey string, status madmin.AccountStatus) // NewServiceAccount - create a new service account func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, sessionPolicy *iampolicy.Policy) (auth.Credentials, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + + if sys == nil { return auth.Credentials{}, errServerNotInitialized } @@ -967,7 +955,7 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, ses u := newUserIdentity(cred) - if err := sys.store.saveUserIdentity(u.Credentials.AccessKey, srvAccUser, u); err != nil { + if err := sys.store.saveUserIdentity(context.Background(), u.Credentials.AccessKey, srvAccUser, u); err != nil { return auth.Credentials{}, err } @@ -978,8 +966,8 @@ func (sys *IAMSys) NewServiceAccount(ctx context.Context, parentUser string, ses // ListServiceAccounts - lists all services accounts associated to a specific user func (sys *IAMSys) ListServiceAccounts(ctx context.Context, accessKey string) ([]string, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + + if sys == nil { return nil, errServerNotInitialized } @@ -1003,8 +991,8 @@ func (sys *IAMSys) ListServiceAccounts(ctx context.Context, accessKey string) ([ // GetServiceAccountParent - gets information about a service account func (sys *IAMSys) GetServiceAccountParent(ctx context.Context, accessKey string) (string, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + + if sys == nil { return "", errServerNotInitialized } @@ -1020,8 +1008,8 @@ func (sys *IAMSys) GetServiceAccountParent(ctx context.Context, accessKey string // DeleteServiceAccount - delete a service account func (sys *IAMSys) DeleteServiceAccount(ctx context.Context, accessKey string) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + + if sys == nil { return errServerNotInitialized } @@ -1034,7 +1022,7 @@ func (sys *IAMSys) DeleteServiceAccount(ctx context.Context, accessKey string) e } // It is ok to ignore deletion error on the mapped policy - err := sys.store.deleteUserIdentity(accessKey, srvAccUser) + err := sys.store.deleteUserIdentity(context.Background(), accessKey, srvAccUser) if err != nil { // ignore if user is already deleted. if err == errNoSuchUser { @@ -1049,8 +1037,8 @@ func (sys *IAMSys) DeleteServiceAccount(ctx context.Context, accessKey string) e // SetUser - set user credentials and policy. func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + + if sys == nil { return errServerNotInitialized } @@ -1072,7 +1060,7 @@ func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { return errIAMActionNotAllowed } - if err := sys.store.saveUserIdentity(accessKey, regularUser, u); err != nil { + if err := sys.store.saveUserIdentity(context.Background(), accessKey, regularUser, u); err != nil { return err } @@ -1087,8 +1075,8 @@ func (sys *IAMSys) SetUser(accessKey string, uinfo madmin.UserInfo) error { // SetUserSecretKey - sets user secret key func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + + if sys == nil { return errServerNotInitialized } @@ -1106,7 +1094,7 @@ func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { cred.SecretKey = secretKey u := newUserIdentity(cred) - if err := sys.store.saveUserIdentity(accessKey, regularUser, u); err != nil { + if err := sys.store.saveUserIdentity(context.Background(), accessKey, regularUser, u); err != nil { return err } @@ -1116,8 +1104,7 @@ func (sys *IAMSys) SetUserSecretKey(accessKey string, secretKey string) error { // GetUser - get user credentials func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return cred, false } @@ -1128,34 +1115,37 @@ func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) { sys.store.lock() // If user is already found proceed. if _, found := sys.iamUsersMap[accessKey]; !found { - sys.store.loadUser(accessKey, regularUser, sys.iamUsersMap) + sys.store.loadUser(context.Background(), accessKey, regularUser, sys.iamUsersMap) if _, found = sys.iamUsersMap[accessKey]; found { // found user, load its mapped policies - sys.store.loadMappedPolicy(accessKey, regularUser, false, sys.iamUserPolicyMap) + sys.store.loadMappedPolicy(context.Background(), accessKey, regularUser, false, sys.iamUserPolicyMap) } else { - sys.store.loadUser(accessKey, srvAccUser, sys.iamUsersMap) + sys.store.loadUser(context.Background(), accessKey, srvAccUser, sys.iamUsersMap) if svc, found := sys.iamUsersMap[accessKey]; found { // Found service account, load its parent user and its mapped policies. if sys.usersSysType == MinIOUsersSysType { - sys.store.loadUser(svc.ParentUser, regularUser, sys.iamUsersMap) + sys.store.loadUser(context.Background(), svc.ParentUser, regularUser, sys.iamUsersMap) } - sys.store.loadMappedPolicy(svc.ParentUser, regularUser, false, sys.iamUserPolicyMap) + sys.store.loadMappedPolicy(context.Background(), svc.ParentUser, regularUser, false, sys.iamUserPolicyMap) } else { // None found fall back to STS users. - sys.store.loadUser(accessKey, stsUser, sys.iamUsersMap) + sys.store.loadUser(context.Background(), accessKey, stsUser, sys.iamUsersMap) if _, found = sys.iamUsersMap[accessKey]; found { // STS user found, load its mapped policy. - sys.store.loadMappedPolicy(accessKey, stsUser, false, sys.iamUserPolicyMap) + sys.store.loadMappedPolicy(context.Background(), accessKey, stsUser, false, sys.iamUserPolicyMap) } } } } + // Load associated policies if any. for _, policy := range sys.iamUserPolicyMap[accessKey].toSlice() { if _, found := sys.iamPolicyDocsMap[policy]; !found { - sys.store.loadPolicyDoc(policy, sys.iamPolicyDocsMap) + sys.store.loadPolicyDoc(context.Background(), policy, sys.iamPolicyDocsMap) } } + + sys.buildUserGroupMemberships() sys.store.unlock() } @@ -1180,8 +1170,7 @@ func (sys *IAMSys) GetUser(accessKey string) (cred auth.Credentials, ok bool) { // AddUsersToGroup - adds users to a group, creating the group if // needed. No error if user(s) already are in the group. func (sys *IAMSys) AddUsersToGroup(group string, members []string) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -1218,7 +1207,7 @@ func (sys *IAMSys) AddUsersToGroup(group string, members []string) error { gi.Members = uniqMembers } - if err := sys.store.saveGroupInfo(group, gi); err != nil { + if err := sys.store.saveGroupInfo(context.Background(), group, gi); err != nil { return err } @@ -1241,8 +1230,7 @@ func (sys *IAMSys) AddUsersToGroup(group string, members []string) error { // RemoveUsersFromGroup - remove users from group. If no users are // given, and the group is empty, deletes the group as well. func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -1283,10 +1271,10 @@ func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { // Remove the group from storage. First delete the // mapped policy. No-mapped-policy case is ignored. - if err := sys.store.deleteMappedPolicy(group, regularUser, true); err != nil && err != errNoSuchPolicy { + if err := sys.store.deleteMappedPolicy(context.Background(), group, regularUser, true); err != nil && err != errNoSuchPolicy { return err } - if err := sys.store.deleteGroupInfo(group); err != nil && err != errNoSuchGroup { + if err := sys.store.deleteGroupInfo(context.Background(), group); err != nil && err != errNoSuchGroup { return err } @@ -1301,7 +1289,7 @@ func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { d := set.CreateStringSet(members...) gi.Members = s.Difference(d).ToSlice() - err := sys.store.saveGroupInfo(group, gi) + err := sys.store.saveGroupInfo(context.Background(), group, gi) if err != nil { return err } @@ -1322,8 +1310,7 @@ func (sys *IAMSys) RemoveUsersFromGroup(group string, members []string) error { // SetGroupStatus - enable/disabled a group func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -1349,7 +1336,7 @@ func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error { gi.Status = statusDisabled } - if err := sys.store.saveGroupInfo(group, gi); err != nil { + if err := sys.store.saveGroupInfo(context.Background(), group, gi); err != nil { return err } sys.iamGroupsMap[group] = gi @@ -1358,8 +1345,7 @@ func (sys *IAMSys) SetGroupStatus(group string, enabled bool) error { // GetGroupDescription - builds up group description func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return gd, errServerNotInitialized } @@ -1399,8 +1385,7 @@ func (sys *IAMSys) GetGroupDescription(group string) (gd madmin.GroupDesc, err e // ListGroups - lists groups. func (sys *IAMSys) ListGroups() (r []string, err error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return r, errServerNotInitialized } @@ -1423,8 +1408,7 @@ func (sys *IAMSys) ListGroups() (r []string, err error) { // PolicyDBSet - sets a policy for a user or group in the PolicyDB. func (sys *IAMSys) PolicyDBSet(name, policy string, isGroup bool) error { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return errServerNotInitialized } @@ -1455,7 +1439,7 @@ func (sys *IAMSys) policyDBSet(name, policyName string, userType IAMUserType, is // Handle policy mapping removal if policyName == "" { - if err := sys.store.deleteMappedPolicy(name, userType, isGroup); err != nil && err != errNoSuchPolicy { + if err := sys.store.deleteMappedPolicy(context.Background(), name, userType, isGroup); err != nil && err != errNoSuchPolicy { return err } if !isGroup { @@ -1475,7 +1459,7 @@ func (sys *IAMSys) policyDBSet(name, policyName string, userType IAMUserType, is } // Handle policy mapping set/update - if err := sys.store.saveMappedPolicy(name, userType, isGroup, mp); err != nil { + if err := sys.store.saveMappedPolicy(context.Background(), name, userType, isGroup, mp); err != nil { return err } if !isGroup { @@ -1490,8 +1474,7 @@ func (sys *IAMSys) policyDBSet(name, policyName string, userType IAMUserType, is // be a member of multiple groups, this function returns an array of // applicable policies (each group is mapped to at most one policy). func (sys *IAMSys) PolicyDBGet(name string, isGroup bool) ([]string, error) { - objectAPI := newObjectLayerFn() - if objectAPI == nil || sys == nil || sys.store == nil { + if sys == nil { return nil, errServerNotInitialized } diff --git a/cmd/jwt.go b/cmd/jwt.go index 63af66cc4..777da97f3 100644 --- a/cmd/jwt.go +++ b/cmd/jwt.go @@ -104,9 +104,6 @@ func webTokenCallback(claims *xjwt.MapClaims) ([]byte, error) { if claims.AccessKey == globalActiveCred.AccessKey { return []byte(globalActiveCred.SecretKey), nil } - if globalIAMSys == nil { - return nil, errInvalidAccessKeyID - } ok, err := globalIAMSys.IsTempUser(claims.AccessKey) if err != nil { if err == errNoSuchUser { diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index 3fac550b4..22141b7e3 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -71,11 +71,6 @@ func (s *peerRESTServer) DeletePolicyHandler(w http.ResponseWriter, r *http.Requ return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) policyName := vars[peerRESTPolicy] if policyName == "" { @@ -104,11 +99,6 @@ func (s *peerRESTServer) LoadPolicyHandler(w http.ResponseWriter, r *http.Reques return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) policyName := vars[peerRESTPolicy] if policyName == "" { @@ -137,11 +127,6 @@ func (s *peerRESTServer) LoadPolicyMappingHandler(w http.ResponseWriter, r *http return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) userOrGroup := vars[peerRESTUserOrGroup] if userOrGroup == "" { @@ -171,11 +156,6 @@ func (s *peerRESTServer) DeleteServiceAccountHandler(w http.ResponseWriter, r *h return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) accessKey := vars[peerRESTUser] if accessKey == "" { @@ -204,11 +184,6 @@ func (s *peerRESTServer) LoadServiceAccountHandler(w http.ResponseWriter, r *htt return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) accessKey := vars[peerRESTUser] if accessKey == "" { @@ -237,11 +212,6 @@ func (s *peerRESTServer) DeleteUserHandler(w http.ResponseWriter, r *http.Reques return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) accessKey := vars[peerRESTUser] if accessKey == "" { @@ -270,11 +240,6 @@ func (s *peerRESTServer) LoadUserHandler(w http.ResponseWriter, r *http.Request) return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) accessKey := vars[peerRESTUser] if accessKey == "" { @@ -314,11 +279,6 @@ func (s *peerRESTServer) LoadGroupHandler(w http.ResponseWriter, r *http.Request return } - if globalIAMSys == nil { - s.writeErrorResponse(w, errServerNotInitialized) - return - } - vars := mux.Vars(r) group := vars[peerRESTGroup] err := globalIAMSys.LoadGroup(objAPI, group) diff --git a/cmd/server-main.go b/cmd/server-main.go index 1d58e610f..a5e381f1c 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -327,9 +327,12 @@ func initAllSubsystems(ctx context.Context, newObject ObjectLayer) (err error) { return fmt.Errorf("Unable to initialize config system: %w", err) } // Any other config errors we simply print a message and proceed forward. - logger.LogIf(ctx, err) + logger.LogIf(ctx, fmt.Errorf("Unable to initialize config, some features may be missing %w", err)) } + // Initialize IAM store + globalIAMSys.InitStore(newObject) + // Populate existing buckets to the etcd backend if globalDNSConfig != nil { // Background this operation. @@ -385,6 +388,9 @@ func serverMain(ctx *cli.Context) { // Initialize all help initHelp() + // Initialize all sub-systems + newAllSubsystems() + var err error globalProxyEndpoints, err = GetProxyEndpoints(globalEndpoints) logger.FatalIf(err, "Invalid command line arguments") @@ -427,9 +433,6 @@ func serverMain(ctx *cli.Context) { globalReplicationState = newReplicationState() } - // Initialize all sub-systems - newAllSubsystems() - // Configure server. handler, err := configureServerHandler(globalEndpoints) if err != nil { @@ -476,11 +479,6 @@ func serverMain(ctx *cli.Context) { logger.SetDeploymentID(globalDeploymentID) - // Once endpoints are finalized, initialize the new object api in safe mode. - globalObjLayerMutex.Lock() - globalObjectAPI = newObject - globalObjLayerMutex.Unlock() - go initDataCrawler(GlobalContext, newObject) // Enable background operations for erasure coding @@ -503,6 +501,11 @@ func serverMain(ctx *cli.Context) { } } + // Once the config is fully loaded, initialize the new object layer. + globalObjLayerMutex.Lock() + globalObjectAPI = newObject + globalObjLayerMutex.Unlock() + // Initialize users credentials and policies in background right after config has initialized. go globalIAMSys.Init(GlobalContext, newObject) diff --git a/cmd/signature-v4-utils.go b/cmd/signature-v4-utils.go index 6563cdf51..8f70a55ec 100644 --- a/cmd/signature-v4-utils.go +++ b/cmd/signature-v4-utils.go @@ -124,9 +124,6 @@ func checkKeyValid(accessKey string) (auth.Credentials, bool, APIErrorCode) { var owner = true var cred = globalActiveCred if cred.AccessKey != accessKey { - if globalIAMSys == nil { - return cred, false, ErrInvalidAccessKeyID - } // Check if the access key is part of users credentials. var ok bool if cred, ok = globalIAMSys.GetUser(accessKey); !ok {