From 931f73f59ade427cca5931d63b3002e22a078c33 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 10 Jul 2021 08:32:52 -0700 Subject: [PATCH] fix: add IAM dummy store for gateway operations (#12670) with console addition users cannot login with root credentials without etcd persistent layer, allow a dummy store such that such functionalities can be supported when running as non-persistent manner, this enables all calls and operations. --- cmd/admin-handlers_test.go | 2 +- cmd/admin-router.go | 82 +++++++++++------------ cmd/gateway-main.go | 18 ++--- cmd/iam-dummy-store.go | 133 +++++++++++++++++++++++++++++++++++++ cmd/iam.go | 6 +- cmd/routers.go | 2 +- 6 files changed, 186 insertions(+), 57 deletions(-) create mode 100644 cmd/iam-dummy-store.go diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index e4b316594..9d29c9c8c 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -77,7 +77,7 @@ func prepareAdminErasureTestBed(ctx context.Context) (*adminErasureTestBed, erro // Setup admin mgmt REST API handlers. adminRouter := mux.NewRouter() - registerAdminRouter(adminRouter, true, true) + registerAdminRouter(adminRouter, true) return &adminErasureTestBed{ erasureDirs: erasureDirs, diff --git a/cmd/admin-router.go b/cmd/admin-router.go index 84a76c68e..e449a1dba 100644 --- a/cmd/admin-router.go +++ b/cmd/admin-router.go @@ -34,7 +34,7 @@ const ( type adminAPIHandlers struct{} // registerAdminRouter - Add handler functions for each service REST API routes. -func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool) { +func registerAdminRouter(router *mux.Router, enableConfigOps bool) { adminAPI := adminAPIHandlers{} // Admin router @@ -105,61 +105,59 @@ func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool) adminRouter.Methods(http.MethodPut).Path(adminVersion + "/config").HandlerFunc(httpTraceHdrs(adminAPI.SetConfigHandler)) } - if enableIAMOps { - // -- IAM APIs -- + // -- IAM APIs -- - // Add policy IAM - adminRouter.Methods(http.MethodPut).Path(adminVersion+"/add-canned-policy").HandlerFunc(httpTraceAll(adminAPI.AddCannedPolicy)).Queries("name", "{name:.*}") + // Add policy IAM + adminRouter.Methods(http.MethodPut).Path(adminVersion+"/add-canned-policy").HandlerFunc(httpTraceAll(adminAPI.AddCannedPolicy)).Queries("name", "{name:.*}") - // Add user IAM - adminRouter.Methods(http.MethodGet).Path(adminVersion + "/accountinfo").HandlerFunc(httpTraceAll(adminAPI.AccountInfoHandler)) + // Add user IAM + adminRouter.Methods(http.MethodGet).Path(adminVersion + "/accountinfo").HandlerFunc(httpTraceAll(adminAPI.AccountInfoHandler)) - adminRouter.Methods(http.MethodPut).Path(adminVersion+"/add-user").HandlerFunc(httpTraceHdrs(adminAPI.AddUser)).Queries("accessKey", "{accessKey:.*}") + adminRouter.Methods(http.MethodPut).Path(adminVersion+"/add-user").HandlerFunc(httpTraceHdrs(adminAPI.AddUser)).Queries("accessKey", "{accessKey:.*}") - adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-user-status").HandlerFunc(httpTraceHdrs(adminAPI.SetUserStatus)).Queries("accessKey", "{accessKey:.*}").Queries("status", "{status:.*}") + adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-user-status").HandlerFunc(httpTraceHdrs(adminAPI.SetUserStatus)).Queries("accessKey", "{accessKey:.*}").Queries("status", "{status:.*}") - // Service accounts ops - adminRouter.Methods(http.MethodPut).Path(adminVersion + "/add-service-account").HandlerFunc(httpTraceHdrs(adminAPI.AddServiceAccount)) - adminRouter.Methods(http.MethodPost).Path(adminVersion+"/update-service-account").HandlerFunc(httpTraceHdrs(adminAPI.UpdateServiceAccount)).Queries("accessKey", "{accessKey:.*}") - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/info-service-account").HandlerFunc(httpTraceHdrs(adminAPI.InfoServiceAccount)).Queries("accessKey", "{accessKey:.*}") - adminRouter.Methods(http.MethodGet).Path(adminVersion + "/list-service-accounts").HandlerFunc(httpTraceHdrs(adminAPI.ListServiceAccounts)) - adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/delete-service-account").HandlerFunc(httpTraceHdrs(adminAPI.DeleteServiceAccount)).Queries("accessKey", "{accessKey:.*}") + // Service accounts ops + adminRouter.Methods(http.MethodPut).Path(adminVersion + "/add-service-account").HandlerFunc(httpTraceHdrs(adminAPI.AddServiceAccount)) + adminRouter.Methods(http.MethodPost).Path(adminVersion+"/update-service-account").HandlerFunc(httpTraceHdrs(adminAPI.UpdateServiceAccount)).Queries("accessKey", "{accessKey:.*}") + adminRouter.Methods(http.MethodGet).Path(adminVersion+"/info-service-account").HandlerFunc(httpTraceHdrs(adminAPI.InfoServiceAccount)).Queries("accessKey", "{accessKey:.*}") + adminRouter.Methods(http.MethodGet).Path(adminVersion + "/list-service-accounts").HandlerFunc(httpTraceHdrs(adminAPI.ListServiceAccounts)) + adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/delete-service-account").HandlerFunc(httpTraceHdrs(adminAPI.DeleteServiceAccount)).Queries("accessKey", "{accessKey:.*}") - // Info policy IAM latest - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/info-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.InfoCannedPolicy)).Queries("name", "{name:.*}") - // List policies latest - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/list-canned-policies").HandlerFunc(httpTraceHdrs(adminAPI.ListBucketPolicies)).Queries("bucket", "{bucket:.*}") - adminRouter.Methods(http.MethodGet).Path(adminVersion + "/list-canned-policies").HandlerFunc(httpTraceHdrs(adminAPI.ListCannedPolicies)) + // Info policy IAM latest + adminRouter.Methods(http.MethodGet).Path(adminVersion+"/info-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.InfoCannedPolicy)).Queries("name", "{name:.*}") + // List policies latest + adminRouter.Methods(http.MethodGet).Path(adminVersion+"/list-canned-policies").HandlerFunc(httpTraceHdrs(adminAPI.ListBucketPolicies)).Queries("bucket", "{bucket:.*}") + adminRouter.Methods(http.MethodGet).Path(adminVersion + "/list-canned-policies").HandlerFunc(httpTraceHdrs(adminAPI.ListCannedPolicies)) - // Remove policy IAM - adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/remove-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.RemoveCannedPolicy)).Queries("name", "{name:.*}") + // Remove policy IAM + adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/remove-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.RemoveCannedPolicy)).Queries("name", "{name:.*}") - // Set user or group policy - adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-user-or-group-policy"). - HandlerFunc(httpTraceHdrs(adminAPI.SetPolicyForUserOrGroup)). - Queries("policyName", "{policyName:.*}", "userOrGroup", "{userOrGroup:.*}", "isGroup", "{isGroup:true|false}") + // Set user or group policy + adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-user-or-group-policy"). + HandlerFunc(httpTraceHdrs(adminAPI.SetPolicyForUserOrGroup)). + Queries("policyName", "{policyName:.*}", "userOrGroup", "{userOrGroup:.*}", "isGroup", "{isGroup:true|false}") - // Remove user IAM - adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/remove-user").HandlerFunc(httpTraceHdrs(adminAPI.RemoveUser)).Queries("accessKey", "{accessKey:.*}") + // Remove user IAM + adminRouter.Methods(http.MethodDelete).Path(adminVersion+"/remove-user").HandlerFunc(httpTraceHdrs(adminAPI.RemoveUser)).Queries("accessKey", "{accessKey:.*}") - // List users - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/list-users").HandlerFunc(httpTraceHdrs(adminAPI.ListBucketUsers)).Queries("bucket", "{bucket:.*}") - adminRouter.Methods(http.MethodGet).Path(adminVersion + "/list-users").HandlerFunc(httpTraceHdrs(adminAPI.ListUsers)) + // List users + adminRouter.Methods(http.MethodGet).Path(adminVersion+"/list-users").HandlerFunc(httpTraceHdrs(adminAPI.ListBucketUsers)).Queries("bucket", "{bucket:.*}") + adminRouter.Methods(http.MethodGet).Path(adminVersion + "/list-users").HandlerFunc(httpTraceHdrs(adminAPI.ListUsers)) - // User info - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/user-info").HandlerFunc(httpTraceHdrs(adminAPI.GetUserInfo)).Queries("accessKey", "{accessKey:.*}") - // Add/Remove members from group - adminRouter.Methods(http.MethodPut).Path(adminVersion + "/update-group-members").HandlerFunc(httpTraceHdrs(adminAPI.UpdateGroupMembers)) + // User info + adminRouter.Methods(http.MethodGet).Path(adminVersion+"/user-info").HandlerFunc(httpTraceHdrs(adminAPI.GetUserInfo)).Queries("accessKey", "{accessKey:.*}") + // Add/Remove members from group + adminRouter.Methods(http.MethodPut).Path(adminVersion + "/update-group-members").HandlerFunc(httpTraceHdrs(adminAPI.UpdateGroupMembers)) - // Get Group - adminRouter.Methods(http.MethodGet).Path(adminVersion+"/group").HandlerFunc(httpTraceHdrs(adminAPI.GetGroup)).Queries("group", "{group:.*}") + // Get Group + adminRouter.Methods(http.MethodGet).Path(adminVersion+"/group").HandlerFunc(httpTraceHdrs(adminAPI.GetGroup)).Queries("group", "{group:.*}") - // List Groups - adminRouter.Methods(http.MethodGet).Path(adminVersion + "/groups").HandlerFunc(httpTraceHdrs(adminAPI.ListGroups)) + // List Groups + adminRouter.Methods(http.MethodGet).Path(adminVersion + "/groups").HandlerFunc(httpTraceHdrs(adminAPI.ListGroups)) - // Set Group Status - adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-group-status").HandlerFunc(httpTraceHdrs(adminAPI.SetGroupStatus)).Queries("group", "{group:.*}").Queries("status", "{status:.*}") - } + // Set Group Status + adminRouter.Methods(http.MethodPut).Path(adminVersion+"/set-group-status").HandlerFunc(httpTraceHdrs(adminAPI.SetGroupStatus)).Queries("group", "{group:.*}").Queries("status", "{status:.*}") if globalIsDistErasure || globalIsErasure { // GetBucketQuotaConfig diff --git a/cmd/gateway-main.go b/cmd/gateway-main.go index 070ac5d3e..6e54c0860 100644 --- a/cmd/gateway-main.go +++ b/cmd/gateway-main.go @@ -248,16 +248,12 @@ func StartGateway(ctx *cli.Context, gw Gateway) { // avoid URL path encoding minio/minio#8950 router := mux.NewRouter().SkipClean(true).UseEncodedPath() - if globalEtcdClient != nil { - // Enable STS router if etcd is enabled. - registerSTSRouter(router) - } - - enableIAMOps := globalEtcdClient != nil + // Enable STS router if etcd is enabled. + registerSTSRouter(router) // Enable IAM admin APIs if etcd is enabled, if not just enable basic // operations such as profiling, server info etc. - registerAdminRouter(router, enableConfigOps, enableIAMOps) + registerAdminRouter(router, enableConfigOps) // Add healthcheck router registerHealthCheckRouter(router) @@ -315,12 +311,10 @@ func StartGateway(ctx *cli.Context, gw Gateway) { logger.FatalIf(globalNotificationSys.Init(GlobalContext, buckets, newObject), "Unable to initialize notification system") } - if enableIAMOps { - // Initialize users credentials and policies in background. - globalIAMSys.InitStore(newObject) + // Initialize users credentials and policies in background. + globalIAMSys.InitStore(newObject) - go globalIAMSys.Init(GlobalContext, newObject) - } + go globalIAMSys.Init(GlobalContext, newObject) if globalCacheConfig.Enabled { // initialize the new disk cache objects. diff --git a/cmd/iam-dummy-store.go b/cmd/iam-dummy-store.go new file mode 100644 index 000000000..02bb2cc45 --- /dev/null +++ b/cmd/iam-dummy-store.go @@ -0,0 +1,133 @@ +// Copyright (c) 2015-2021 MinIO, Inc. +// +// This file is part of MinIO Object Storage stack +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package cmd + +import ( + "context" + "sync" + + "github.com/minio/minio/internal/auth" + iampolicy "github.com/minio/pkg/iam/policy" +) + +type iamDummyStore struct { + sync.RWMutex +} + +func (ids *iamDummyStore) lock() { + ids.Lock() +} + +func (ids *iamDummyStore) unlock() { + ids.Unlock() +} + +func (ids *iamDummyStore) rlock() { + ids.RLock() +} + +func (ids *iamDummyStore) runlock() { + ids.RUnlock() +} + +func (ids *iamDummyStore) migrateBackendFormat(context.Context) error { + return nil +} + +func (ids *iamDummyStore) loadPolicyDoc(ctx context.Context, policy string, m map[string]iampolicy.Policy) error { + return nil +} + +func (ids *iamDummyStore) loadPolicyDocs(ctx context.Context, m map[string]iampolicy.Policy) error { + return nil +} + +func (ids *iamDummyStore) loadUser(ctx context.Context, user string, userType IAMUserType, m map[string]auth.Credentials) error { + return nil +} + +func (ids *iamDummyStore) loadUsers(ctx context.Context, userType IAMUserType, m map[string]auth.Credentials) error { + return nil +} + +func (ids *iamDummyStore) loadGroup(ctx context.Context, group string, m map[string]GroupInfo) error { + return nil +} + +func (ids *iamDummyStore) loadGroups(ctx context.Context, m map[string]GroupInfo) error { + return nil +} + +func (ids *iamDummyStore) loadMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { + return nil +} + +func (ids *iamDummyStore) loadMappedPolicies(ctx context.Context, userType IAMUserType, isGroup bool, m map[string]MappedPolicy) error { + return nil +} + +func (ids *iamDummyStore) loadAll(ctx context.Context, sys *IAMSys) error { + return sys.Load(ctx, ids) +} + +func (ids *iamDummyStore) saveIAMConfig(ctx context.Context, item interface{}, path string, opts ...options) error { + return nil +} + +func (ids *iamDummyStore) loadIAMConfig(ctx context.Context, item interface{}, path string) error { + return nil +} + +func (ids *iamDummyStore) deleteIAMConfig(ctx context.Context, path string) error { + return nil +} + +func (ids *iamDummyStore) savePolicyDoc(ctx context.Context, policyName string, p iampolicy.Policy) error { + return nil +} + +func (ids *iamDummyStore) saveMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool, mp MappedPolicy, opts ...options) error { + return nil +} + +func (ids *iamDummyStore) saveUserIdentity(ctx context.Context, name string, userType IAMUserType, u UserIdentity, opts ...options) error { + return nil +} + +func (ids *iamDummyStore) saveGroupInfo(ctx context.Context, group string, gi GroupInfo) error { + return nil +} + +func (ids *iamDummyStore) deletePolicyDoc(ctx context.Context, policyName string) error { + return nil +} + +func (ids *iamDummyStore) deleteMappedPolicy(ctx context.Context, name string, userType IAMUserType, isGroup bool) error { + return nil +} + +func (ids *iamDummyStore) deleteUserIdentity(ctx context.Context, name string, userType IAMUserType) error { + return nil +} + +func (ids *iamDummyStore) deleteGroupInfo(ctx context.Context, name string) error { + return nil +} + +func (ids *iamDummyStore) watch(context.Context, *IAMSys) { +} diff --git a/cmd/iam.go b/cmd/iam.go index 310cded14..001c4924a 100644 --- a/cmd/iam.go +++ b/cmd/iam.go @@ -452,7 +452,11 @@ func (sys *IAMSys) InitStore(objAPI ObjectLayer) { defer sys.Unlock() if globalEtcdClient == nil { - sys.store = newIAMObjectStore(objAPI) + if globalIsGateway { + sys.store = &iamDummyStore{} + } else { + sys.store = newIAMObjectStore(objAPI) + } } else { sys.store = newIAMEtcdStore() } diff --git a/cmd/routers.go b/cmd/routers.go index d85beb5aa..e812f0d9e 100644 --- a/cmd/routers.go +++ b/cmd/routers.go @@ -90,7 +90,7 @@ func configureServerHandler(endpointServerPools EndpointServerPools) (http.Handl } // Add Admin router, all APIs are enabled in server mode. - registerAdminRouter(router, true, true) + registerAdminRouter(router, true) // Add healthcheck router registerHealthCheckRouter(router)