From b07df5cae1f1adc03547942064837de44eefdc52 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 19 Oct 2020 09:54:40 -0700 Subject: [PATCH] initialize IAM as soon as object layer is initialized (#10700) Allow requests to come in for users as soon as object layer and config are initialized, this allows users to be authenticated sooner and would succeed automatically on servers which are yet to fully initialize. --- cmd/admin-handlers-users.go | 10 +- cmd/gateway-main.go | 8 +- cmd/iam-etcd-store.go | 126 +++++++++++----------- cmd/iam-object-store.go | 95 +++++++++-------- cmd/iam.go | 201 +++++++++++++++++------------------- cmd/jwt.go | 3 - cmd/peer-rest-server.go | 40 ------- cmd/server-main.go | 21 ++-- cmd/signature-v4-utils.go | 3 - 9 files changed, 226 insertions(+), 281 deletions(-) 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 {