From 2a1a012a4d17f0aadf9ad79917204c79eeb0c485 Mon Sep 17 00:00:00 2001 From: davidjumani Date: Mon, 21 Feb 2022 20:55:45 +0530 Subject: [PATCH] Allow domain admin to change domain and account settings (#4339) * Allow domain admin to change domain and account settings * Cleanup * Remove useless global setting * Restrict regular users with listConfig access * Address comments * Moving upgrade path --- .../META-INF/db/schema-41520to41600.sql | 18 +++++++++--------- .../META-INF/db/schema-41610to41700.sql | 3 +++ .../ConfigurationManagerImpl.java | 18 ++++++++++++++++-- .../com/cloud/server/ManagementServerImpl.java | 18 ++++++++++++++++-- ui/src/config/section/account.js | 4 +++- ui/src/config/section/config.js | 2 +- ui/src/config/section/domain.js | 4 +++- 7 files changed, 51 insertions(+), 16 deletions(-) diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41520to41600.sql b/engine/schema/src/main/resources/META-INF/db/schema-41520to41600.sql index 0f084c5b0bc..a414f244b08 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41520to41600.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41520to41600.sql @@ -741,26 +741,26 @@ CREATE PROCEDURE `cloud`.`ADD_GUEST_OS_AND_HYPERVISOR_MAPPING` ( IN guest_os_hypervisor_hypervisor_version VARCHAR(32), IN guest_os_hypervisor_guest_os_name VARCHAR(255) ) -BEGIN - INSERT INTO cloud.guest_os (uuid, category_id, display_name, created) +BEGIN + INSERT INTO cloud.guest_os (uuid, category_id, display_name, created) SELECT UUID(), guest_os_category_id, guest_os_display_name, now() FROM DUAL - WHERE not exists( SELECT 1 + WHERE not exists( SELECT 1 FROM cloud.guest_os WHERE cloud.guest_os.category_id = guest_os_category_id - AND cloud.guest_os.display_name = guest_os_display_name) - -; INSERT INTO cloud.guest_os_hypervisor (uuid, hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created) + AND cloud.guest_os.display_name = guest_os_display_name) + +; INSERT INTO cloud.guest_os_hypervisor (uuid, hypervisor_type, hypervisor_version, guest_os_name, guest_os_id, created) SELECT UUID(), guest_os_hypervisor_hypervisor_type, guest_os_hypervisor_hypervisor_version, guest_os_hypervisor_guest_os_name, guest_os.id, now() FROM cloud.guest_os WHERE guest_os.category_id = guest_os_category_id AND guest_os.display_name = guest_os_display_name - AND NOT EXISTS (SELECT 1 + AND NOT EXISTS (SELECT 1 FROM cloud.guest_os_hypervisor as hypervisor - WHERE hypervisor_type = guest_os_hypervisor_hypervisor_type + WHERE hypervisor_type = guest_os_hypervisor_hypervisor_type AND hypervisor_version = guest_os_hypervisor_hypervisor_version AND hypervisor.guest_os_id = guest_os.id - AND hypervisor.guest_os_name = guest_os_hypervisor_guest_os_name) + AND hypervisor.guest_os_name = guest_os_hypervisor_guest_os_name) ;END; -- PR#4699 Call procedure `ADD_GUEST_OS_AND_HYPERVISOR_MAPPING` to add new data to guest_os and guest_os_hypervisor. diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql b/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql index 822cf00e630..1eeb2087ceb 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41610to41700.sql @@ -643,3 +643,6 @@ CREATE VIEW `cloud`.`domain_router_view` AS `cloud`.`async_job` ON async_job.instance_id = vm_instance.id and async_job.instance_type = 'DomainRouter' and async_job.job_status = 0; + +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'listConfigurations', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'updateConfiguration', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule; diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 0b4fcf8d97b..2a5197c7b47 100755 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -810,14 +810,25 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati final Long zoneId = cmd.getZoneId(); final Long clusterId = cmd.getClusterId(); final Long storagepoolId = cmd.getStoragepoolId(); - final Long accountId = cmd.getAccountId(); final Long imageStoreId = cmd.getImageStoreId(); - final Long domainId = cmd.getDomainId(); + Long accountId = cmd.getAccountId(); + Long domainId = cmd.getDomainId(); CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : value == null ? "" : value)); // check if config value exists final ConfigurationVO config = _configDao.findByName(name); String catergory = null; + final Account caller = CallContext.current().getCallingAccount(); + if (_accountMgr.isDomainAdmin(caller.getId())) { + if (accountId == null && domainId == null) { + domainId = caller.getDomainId(); + } + } else if (_accountMgr.isNormalUser(caller.getId())) { + if (accountId == null) { + accountId = caller.getAccountId(); + } + } + // FIX ME - All configuration parameters are not moved from config.java to configKey if (config == null) { if (_configDepot.get(name) == null) { @@ -848,11 +859,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati paramCountCheck++; } if (accountId != null) { + Account account = _accountMgr.getAccount(accountId); + _accountMgr.checkAccess(caller, null, false, account); scope = ConfigKey.Scope.Account.toString(); id = accountId; paramCountCheck++; } if (domainId != null) { + _accountMgr.checkAccess(caller, _domainDao.findById(domainId)); scope = ConfigKey.Scope.Domain.toString(); id = domainId; paramCountCheck++; diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 4082b52b2f8..8a68bb4b385 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -2013,13 +2013,24 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe final Long zoneId = cmd.getZoneId(); final Long clusterId = cmd.getClusterId(); final Long storagepoolId = cmd.getStoragepoolId(); - final Long accountId = cmd.getAccountId(); - final Long domainId = cmd.getDomainId(); final Long imageStoreId = cmd.getImageStoreId(); + Long accountId = cmd.getAccountId(); + Long domainId = cmd.getDomainId(); String scope = null; Long id = null; int paramCountCheck = 0; + final Account caller = CallContext.current().getCallingAccount(); + if (_accountMgr.isDomainAdmin(caller.getId())) { + if (accountId == null && domainId == null) { + domainId = caller.getDomainId(); + } + } else if (_accountMgr.isNormalUser(caller.getId())) { + if (accountId == null) { + accountId = caller.getAccountId(); + } + } + if (zoneId != null) { scope = ConfigKey.Scope.Zone.toString(); id = zoneId; @@ -2031,11 +2042,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe paramCountCheck++; } if (accountId != null) { + Account account = _accountMgr.getAccount(accountId); + _accountMgr.checkAccess(caller, null, false, account); scope = ConfigKey.Scope.Account.toString(); id = accountId; paramCountCheck++; } if (domainId != null) { + _accountMgr.checkAccess(caller, _domainDao.findById(domainId)); scope = ConfigKey.Scope.Domain.toString(); id = domainId; paramCountCheck++; diff --git a/ui/src/config/section/account.js b/ui/src/config/section/account.js index 701553ab789..101a306e06e 100644 --- a/ui/src/config/section/account.js +++ b/ui/src/config/section/account.js @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +import store from '@/store' + export default { name: 'account', title: 'label.accounts', @@ -49,7 +51,7 @@ export default { { name: 'settings', component: () => import('@/components/view/SettingsTab.vue'), - show: (record, route, user) => { return ['Admin'].includes(user.roletype) } + show: () => { return 'listConfigurations' in store.getters.apis } } ], actions: [ diff --git a/ui/src/config/section/config.js b/ui/src/config/section/config.js index 25c4e3e3ffe..77c6d785a8a 100644 --- a/ui/src/config/section/config.js +++ b/ui/src/config/section/config.js @@ -19,7 +19,7 @@ export default { name: 'config', title: 'label.configuration', icon: 'setting', - permission: ['listConfigurations'], + permission: ['listConfigurations', 'listInfrastructure'], children: [ { name: 'globalsetting', diff --git a/ui/src/config/section/domain.js b/ui/src/config/section/domain.js index 21e023d6bb5..da3832a0dda 100644 --- a/ui/src/config/section/domain.js +++ b/ui/src/config/section/domain.js @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +import store from '@/store' + export default { name: 'domain', title: 'label.domains', @@ -53,7 +55,7 @@ export default { { name: 'settings', component: () => import('@/components/view/SettingsTab.vue'), - show: (record, route, user) => { return ['Admin'].includes(user.roletype) } + show: () => { return 'listConfigurations' in store.getters.apis } }, { name: 'comments', component: () => import('@/components/view/AnnotationsTab.vue')