From 4347776ac6ef9ae86fb016862f4a6b2376f8319a Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Tue, 15 Mar 2016 09:16:06 +0100 Subject: [PATCH] CLOUDSTACK-8562: DB-Backed Dynamic Role Based API Access Checker This feature allows root administrators to define new roles and associate API permissions to them. A limited form of role-based access control for the CloudStack management server API is provided through a properties file, commands.properties, embedded in the WAR distribution. Therefore, customizing API permissions requires unpacking the distribution and modifying this file consistently on all servers. The old system also does not permit the specification of additional roles. FS: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Dynamic+Role+Based+API+Access+Checker+for+CloudStack DB-Backed Dynamic Role Based API Access Checker for CloudStack brings following changes, features and use-cases: - Moves the API access definitions from commands.properties to the mgmt server DB - Allows defining custom roles (such as a read-only ROOT admin) beyond the current set of four (4) roles - All roles will resolve to one of the four known roles types (Admin, Resource Admin, Domain Admin and User) which maintains this association by requiring all new defined roles to specify a role type. - Allows changes to roles and API permissions per role at runtime including additions or removal of roles and/or modifications of permissions, without the need of restarting management server(s) Upgrade/installation notes: - The feature will be enabled by default for new installations, existing deployments will continue to use the older static role based api access checker with an option to enable this feature - During fresh installation or upgrade, the upgrade paths will add four default roles based on the four default role types - For ease of migration, at the time of upgrade commands.properties will be used to add existing set of permissions to the default roles. cloud.account will have a new role_id column which will be populated based on default roles as well Dynamic-roles migration tool: scripts/util/migrate-dynamicroles.py - Allows admins to migrate to the dynamic role based checker at a future date - Performs a harder one-way migrate and update - Migrates rules from existing commands.properties file into db and deprecates it - Enables an internal hidden switch to enable dynamic role based checker feature Signed-off-by: Rohit Yadav --- .travis.yml | 4 +- api/src/com/cloud/event/EventTypes.java | 18 + api/src/com/cloud/user/Account.java | 2 + api/src/com/cloud/user/AccountService.java | 4 +- api/src/org/apache/cloudstack/acl/Role.java | 27 + .../apache/cloudstack/acl/RolePermission.java | 31 + .../apache/cloudstack/acl/RoleService.java | 52 + .../org/apache/cloudstack/acl/RoleType.java | 80 +- api/src/org/apache/cloudstack/acl/Rule.java | 54 ++ .../apache/cloudstack/api/ApiConstants.java | 7 + .../org/apache/cloudstack/api/BaseCmd.java | 7 +- .../admin/account/CreateAccountCmd.java | 17 +- .../api/command/admin/acl/CreateRoleCmd.java | 105 ++ .../admin/acl/CreateRolePermissionCmd.java | 124 +++ .../api/command/admin/acl/DeleteRoleCmd.java | 83 ++ .../admin/acl/DeleteRolePermissionCmd.java | 83 ++ .../admin/acl/ListRolePermissionsCmd.java | 106 ++ .../api/command/admin/acl/ListRolesCmd.java | 128 +++ .../api/command/admin/acl/UpdateRoleCmd.java | 108 +++ .../admin/acl/UpdateRolePermissionCmd.java | 104 ++ .../command/admin/config/UpdateCfgCmd.java | 12 + .../user/config/ListCapabilitiesCmd.java | 1 + .../api/response/AccountResponse.java | 27 + .../api/response/CapabilitiesResponse.java | 8 + .../api/response/RolePermissionResponse.java | 101 ++ .../cloudstack/api/response/RoleResponse.java | 63 ++ .../cloudstack/api/response/UserResponse.java | 27 + .../apache/cloudstack/acl/RoleTypeTest.java | 100 ++ .../org/apache/cloudstack/acl/RuleTest.java | 98 ++ .../admin/account/CreateAccountCmdTest.java | 10 +- .../api/command/test/UpdateCfgCmdTest.java | 28 +- .../classes/resources/messages.properties | 8 + client/pom.xml | 5 + debian/cloudstack-management.install | 1 - debian/control | 2 +- developer/developer-prefill.sql | 5 + ...spring-engine-schema-core-daos-context.xml | 2 + .../cloud/upgrade/dao/Upgrade481to490.java | 75 +- .../schema/src/com/cloud/user/AccountVO.java | 31 +- .../src/com/cloud/user/dao/AccountDao.java | 2 + .../com/cloud/user/dao/AccountDaoImpl.java | 19 +- .../cloudstack/acl/RolePermissionVO.java | 120 +++ .../src/org/apache/cloudstack/acl/RoleVO.java | 106 ++ .../apache/cloudstack/acl/dao/RoleDao.java | 29 + .../cloudstack/acl/dao/RoleDaoImpl.java | 61 ++ .../acl/dao/RolePermissionsDao.java | 49 + .../acl/dao/RolePermissionsDaoImpl.java | 166 ++++ plugins/acl/dynamic-role-based/pom.xml | 32 + .../acl-dynamic-role-based/module.properties | 18 + .../spring-acl-dynamic-role-based-context.xml | 33 + .../acl/DynamicRoleBasedAPIAccessChecker.java | 144 +++ .../DynamicRoleBasedAPIAccessCheckerTest.java | 164 ++++ .../acl/StaticRoleBasedAPIAccessChecker.java | 48 +- .../command/user/discovery/ListApisCmd.java | 3 +- .../manager/BaremetalVlanManagerImpl.java | 27 +- .../management/MockAccountManager.java | 8 +- plugins/pom.xml | 1 + .../api/command/LdapCreateAccountCmd.java | 41 +- .../api/command/LdapImportUsersCmd.java | 20 +- .../api/command/LinkDomainToLdapCmd.java | 3 +- .../cloudstack/ldap/LdapAuthenticator.java | 4 +- .../ldap/LdapImportUsersCmdSpec.groovy | 2 +- scripts/util/migrate-dynamicroles.py | 136 +++ .../spring-server-core-managers-context.xml | 2 + server/src/com/cloud/api/ApiDBUtils.java | 27 +- .../com/cloud/api/ApiResponseGsonHelper.java | 2 +- server/src/com/cloud/api/ApiServer.java | 8 +- .../com/cloud/api/query/vo/AccountJoinVO.java | 7 + .../cloud/api/query/vo/UserAccountJoinVO.java | 7 + .../api/response/ApiResponseSerializer.java | 2 +- .../cloud/projects/ProjectManagerImpl.java | 2 +- .../cloud/server/ConfigurationServerImpl.java | 6 +- server/src/com/cloud/user/AccountManager.java | 2 +- .../com/cloud/user/AccountManagerImpl.java | 37 +- .../cloudstack/acl/RoleManagerImpl.java | 264 +++++ .../cloud/user/MockAccountManagerImpl.java | 6 +- .../iam/RoleBasedAPIAccessChecker.java | 2 +- .../db/create-default-role-api-mappings.sql | 902 ++++++++++++++++++ setup/db/db/schema-481to490-cleanup.sql | 188 ++++ setup/db/db/schema-481to490.sql | 35 + setup/db/server-setup.sql | 3 +- setup/db/server-setup.xml | 7 + test/integration/smoke/test_dynamicroles.py | 537 +++++++++++ test/integration/smoke/test_staticroles.py | 134 +++ tools/apidoc/gen_toc.py | 1 + tools/marvin/marvin/cloudstackConnection.py | 2 +- tools/marvin/marvin/lib/base.py | 89 +- ui/css/cloudstack3.css | 16 + ui/dictionary.jsp | 7 + ui/dictionary2.jsp | 1 + ui/images/icons.png | Bin 61164 -> 48358 bytes ui/index.jsp | 1 + ui/plugins/quota/quota.js | 16 +- ui/scripts/accounts.js | 31 +- ui/scripts/accountsWizard.js | 38 +- ui/scripts/cloudStack.js | 3 +- ui/scripts/roles.js | 388 ++++++++ ui/scripts/sharedFunctions.js | 11 + .../main/java/com/cloud/utils/ListUtils.java | 31 + .../java/com/cloud/utils/PropertiesUtil.java | 4 + 100 files changed, 5633 insertions(+), 170 deletions(-) create mode 100644 api/src/org/apache/cloudstack/acl/Role.java create mode 100644 api/src/org/apache/cloudstack/acl/RolePermission.java create mode 100644 api/src/org/apache/cloudstack/acl/RoleService.java create mode 100644 api/src/org/apache/cloudstack/acl/Rule.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/CreateRolePermissionCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRoleCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRolePermissionCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/ListRolePermissionsCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRoleCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java create mode 100644 api/src/org/apache/cloudstack/api/response/RolePermissionResponse.java create mode 100644 api/src/org/apache/cloudstack/api/response/RoleResponse.java create mode 100644 api/test/org/apache/cloudstack/acl/RoleTypeTest.java create mode 100644 api/test/org/apache/cloudstack/acl/RuleTest.java create mode 100644 engine/schema/src/org/apache/cloudstack/acl/RolePermissionVO.java create mode 100644 engine/schema/src/org/apache/cloudstack/acl/RoleVO.java create mode 100644 engine/schema/src/org/apache/cloudstack/acl/dao/RoleDao.java create mode 100644 engine/schema/src/org/apache/cloudstack/acl/dao/RoleDaoImpl.java create mode 100644 engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java create mode 100644 engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java create mode 100644 plugins/acl/dynamic-role-based/pom.xml create mode 100644 plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/module.properties create mode 100644 plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/spring-acl-dynamic-role-based-context.xml create mode 100644 plugins/acl/dynamic-role-based/src/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java create mode 100644 plugins/acl/dynamic-role-based/test/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessCheckerTest.java create mode 100755 scripts/util/migrate-dynamicroles.py create mode 100644 server/src/org/apache/cloudstack/acl/RoleManagerImpl.java create mode 100644 setup/db/db/create-default-role-api-mappings.sql create mode 100644 test/integration/smoke/test_dynamicroles.py create mode 100644 test/integration/smoke/test_staticroles.py create mode 100644 ui/scripts/roles.js create mode 100644 utils/src/main/java/com/cloud/utils/ListUtils.java diff --git a/.travis.yml b/.travis.yml index d160e487aa1..9d9822ce119 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,10 +36,10 @@ env: - REGRESSION_INDEX=6 - PATH=$HOME/.local/bin:$PATH matrix: - - TESTS="smoke/test_affinity_groups smoke/test_affinity_groups_projects smoke/test_deploy_vgpu_enabled_vm smoke/test_deploy_vm_iso smoke/test_deploy_vm_root_resize smoke/test_deploy_vm_with_userdata smoke/test_deploy_vms_with_varied_deploymentplanners smoke/test_disk_offerings smoke/test_global_settings smoke/test_guest_vlan_range" + - TESTS="smoke/test_affinity_groups smoke/test_affinity_groups_projects smoke/test_dynamicroles smoke/test_deploy_vgpu_enabled_vm smoke/test_deploy_vm_iso smoke/test_deploy_vm_root_resize smoke/test_deploy_vm_with_userdata smoke/test_deploy_vms_with_varied_deploymentplanners smoke/test_disk_offerings smoke/test_global_settings smoke/test_guest_vlan_range" - TESTS="smoke/test_hosts smoke/test_internal_lb smoke/test_iso smoke/test_list_ids_parameter smoke/test_loadbalance smoke/test_multipleips_per_nic smoke/test_network smoke/test_network_acl smoke/test_nic smoke/test_nic_adapter_type smoke/test_non_contigiousvlan" - TESTS="smoke/test_over_provisioning smoke/test_password_server smoke/test_portable_publicip smoke/test_primary_storage smoke/test_privategw_acl smoke/test_public_ip_range smoke/test_pvlan smoke/test_regions smoke/test_reset_vm_on_reboot smoke/test_resource_detail" - - TESTS="smoke/test_router_dhcphosts smoke/test_routers smoke/test_routers_iptables_default_policy smoke/test_routers_network_ops smoke/test_scale_vm smoke/test_secondary_storage smoke/test_service_offerings smoke/test_snapshots smoke/test_ssvm smoke/test_templates" + - TESTS="smoke/test_router_dhcphosts smoke/test_routers smoke/test_routers_iptables_default_policy smoke/test_routers_network_ops smoke/test_staticroles smoke/test_scale_vm smoke/test_secondary_storage smoke/test_service_offerings smoke/test_snapshots smoke/test_ssvm smoke/test_templates" - TESTS="smoke/test_usage_events smoke/test_vm_life_cycle smoke/test_vm_snapshots smoke/test_volumes smoke/test_vpc_redundant smoke/test_vpc_router_nics smoke/test_vpc_vpn smoke/misc/test_deploy_vm smoke/misc/test_vm_ha smoke/misc/test_escalations_templates smoke/misc/test_vm_sync" - TESTS="component/test_mm_max_limits component/test_acl_isolatednetwork_delete" diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 7349c1f5413..23de15295ea 100644 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -66,6 +66,8 @@ import com.cloud.user.User; import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; import org.apache.cloudstack.config.Configuration; import org.apache.cloudstack.usage.Usage; @@ -166,6 +168,14 @@ public class EventTypes { public static final String EVENT_GLOBAL_LOAD_BALANCER_DELETE = "GLOBAL.LB.DELETE"; public static final String EVENT_GLOBAL_LOAD_BALANCER_UPDATE = "GLOBAL.LB.UPDATE"; + // Role events + public static final String EVENT_ROLE_CREATE = "ROLE.CREATE"; + public static final String EVENT_ROLE_UPDATE = "ROLE.UPDATE"; + public static final String EVENT_ROLE_DELETE = "ROLE.DELETE"; + public static final String EVENT_ROLE_PERMISSION_CREATE = "ROLE.PERMISSION.CREATE"; + public static final String EVENT_ROLE_PERMISSION_UPDATE = "ROLE.PERMISSION.UPDATE"; + public static final String EVENT_ROLE_PERMISSION_DELETE = "ROLE.PERMISSION.DELETE"; + // Account events public static final String EVENT_ACCOUNT_ENABLE = "ACCOUNT.ENABLE"; public static final String EVENT_ACCOUNT_DISABLE = "ACCOUNT.DISABLE"; @@ -605,6 +615,14 @@ public class EventTypes { entityEventDetails.put(EVENT_LB_CERT_ASSIGN, LoadBalancer.class); entityEventDetails.put(EVENT_LB_CERT_REMOVE, LoadBalancer.class); + // Role events + entityEventDetails.put(EVENT_ROLE_CREATE, Role.class); + entityEventDetails.put(EVENT_ROLE_UPDATE, Role.class); + entityEventDetails.put(EVENT_ROLE_DELETE, Role.class); + entityEventDetails.put(EVENT_ROLE_PERMISSION_CREATE, RolePermission.class); + entityEventDetails.put(EVENT_ROLE_PERMISSION_UPDATE, RolePermission.class); + entityEventDetails.put(EVENT_ROLE_PERMISSION_DELETE, RolePermission.class); + // Account events entityEventDetails.put(EVENT_ACCOUNT_ENABLE, Account.class); entityEventDetails.put(EVENT_ACCOUNT_DISABLE, Account.class); diff --git a/api/src/com/cloud/user/Account.java b/api/src/com/cloud/user/Account.java index b912e515bf3..58cedcd5746 100644 --- a/api/src/com/cloud/user/Account.java +++ b/api/src/com/cloud/user/Account.java @@ -46,6 +46,8 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity { public short getType(); + public Long getRoleId(); + public State getState(); public Date getRemoved(); diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java index 7cc1e3089ca..959a710d6d9 100644 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -57,9 +57,9 @@ public interface AccountService { * @return the user if created successfully, null otherwise */ UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, - short accountType, Long domainId, String networkDomain, Map details, String accountUUID, String userUUID); + short accountType, Long roleId, Long domainId, String networkDomain, Map details, String accountUUID, String userUUID); - UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long domainId, String networkDomain, + UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long roleId, Long domainId, String networkDomain, Map details, String accountUUID, String userUUID, User.Source source); /** diff --git a/api/src/org/apache/cloudstack/acl/Role.java b/api/src/org/apache/cloudstack/acl/Role.java new file mode 100644 index 00000000000..b05d886fdbf --- /dev/null +++ b/api/src/org/apache/cloudstack/acl/Role.java @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface Role extends InternalIdentity, Identity { + String getName(); + RoleType getRoleType(); + String getDescription(); +} diff --git a/api/src/org/apache/cloudstack/acl/RolePermission.java b/api/src/org/apache/cloudstack/acl/RolePermission.java new file mode 100644 index 00000000000..0157a668256 --- /dev/null +++ b/api/src/org/apache/cloudstack/acl/RolePermission.java @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface RolePermission extends InternalIdentity, Identity { + enum Permission {ALLOW, DENY} + + long getRoleId(); + Rule getRule(); + Permission getPermission(); + String getDescription(); + long getSortOrder(); +} diff --git a/api/src/org/apache/cloudstack/acl/RoleService.java b/api/src/org/apache/cloudstack/acl/RoleService.java new file mode 100644 index 00000000000..59eef51e782 --- /dev/null +++ b/api/src/org/apache/cloudstack/acl/RoleService.java @@ -0,0 +1,52 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl; + +import org.apache.cloudstack.framework.config.ConfigKey; + +import java.util.List; + +public interface RoleService { + + ConfigKey EnableDynamicApiChecker = new ConfigKey<>("Advanced", Boolean.class, "dynamic.apichecker.enabled", "false", + "If set to true, this enables the dynamic role-based api access checker and disables the default static role-based api access checker.", + true); + + boolean isEnabled(); + Role findRole(final Long id); + Role createRole(final String name, final RoleType roleType, final String description); + boolean updateRole(final Role role, final String name, final RoleType roleType, final String description); + boolean deleteRole(final Role role); + + RolePermission findRolePermission(final Long id); + RolePermission findRolePermissionByUuid(final String uuid); + + RolePermission createRolePermission(final Role role, final Rule rule, final RolePermission.Permission permission, final String description); + /** + * updateRolePermission updates the order/position of an role permission + * @param role The role whose permissions needs to be re-ordered + * @param newOrder The new list of ordered role permissions + */ + boolean updateRolePermission(final Role role, final List newOrder); + boolean deleteRolePermission(final RolePermission rolePermission); + + List listRoles(); + List findRolesByName(final String name); + List findRolesByType(final RoleType roleType); + List findAllPermissionsBy(final Long roleId); +} diff --git a/api/src/org/apache/cloudstack/acl/RoleType.java b/api/src/org/apache/cloudstack/acl/RoleType.java index 90e3d1ef604..a8a64a58df5 100644 --- a/api/src/org/apache/cloudstack/acl/RoleType.java +++ b/api/src/org/apache/cloudstack/acl/RoleType.java @@ -16,18 +16,90 @@ // under the License. package org.apache.cloudstack.acl; +import com.cloud.user.Account; +import com.google.common.base.Enums; +import com.google.common.base.Strings; + // Enum for default roles in CloudStack public enum RoleType { - Admin(1), ResourceAdmin(2), DomainAdmin(4), User(8), Unknown(0); + Admin(1L, Account.ACCOUNT_TYPE_ADMIN, 1), + ResourceAdmin(2L, Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN, 2), + DomainAdmin(3L, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, 4), + User(4L, Account.ACCOUNT_TYPE_NORMAL, 8), + Unknown(-1L, (short) -1, 0); + private long id; + private short accountType; private int mask; - private RoleType(int mask) { + RoleType(final long id, final short accountType, final int mask) { + this.id = id; + this.accountType = accountType; this.mask = mask; } - public int getValue() { + public long getId() { + return id; + } + + public short getAccountType() { + return accountType; + } + + public int getMask() { return mask; } -} + public static RoleType fromString(final String name) { + if (!Strings.isNullOrEmpty(name) + && Enums.getIfPresent(RoleType.class, name).isPresent()) { + return RoleType.valueOf(name); + } + throw new IllegalStateException("Illegal RoleType name provided"); + } + + public static RoleType fromMask(int mask) { + for (RoleType roleType : RoleType.values()) { + if (roleType.getMask() == mask) { + return roleType; + } + } + return Unknown; + } + + public static RoleType getByAccountType(final short accountType) { + RoleType roleType = RoleType.Unknown; + switch (accountType) { + case Account.ACCOUNT_TYPE_ADMIN: + roleType = RoleType.Admin; + break; + case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: + roleType = RoleType.DomainAdmin; + break; + case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: + roleType = RoleType.ResourceAdmin; + break; + case Account.ACCOUNT_TYPE_NORMAL: + roleType = RoleType.User; + break; + } + return roleType; + } + + public static Long getRoleByAccountType(final Long roleId, final Short accountType) { + if (roleId == null && accountType != null) { + RoleType defaultRoleType = RoleType.getByAccountType(accountType); + if (defaultRoleType != null && defaultRoleType != RoleType.Unknown) { + return defaultRoleType.getId(); + } + } + return roleId; + } + + public static Short getAccountTypeByRole(final Role role, final Short accountType) { + if (role != null && role.getId() > 0L) { + return role.getRoleType().getAccountType(); + } + return accountType; + } +} diff --git a/api/src/org/apache/cloudstack/acl/Rule.java b/api/src/org/apache/cloudstack/acl/Rule.java new file mode 100644 index 00000000000..27920107fdc --- /dev/null +++ b/api/src/org/apache/cloudstack/acl/Rule.java @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl; + +import com.cloud.exception.InvalidParameterValueException; +import com.google.common.base.Strings; + +import java.util.regex.Pattern; + +public final class Rule { + private final String rule; + private final static Pattern ALLOWED_PATTERN = Pattern.compile("^[a-zA-Z0-9*]+$"); + + public Rule(final String rule) { + validate(rule); + this.rule = rule; + } + + public boolean matches(final String commandName) { + return !Strings.isNullOrEmpty(commandName) + && commandName.toLowerCase().matches(rule.toLowerCase().replace("*", "\\w*")); + } + + public String getRuleString() { + return rule; + } + + @Override + public String toString() { + return rule; + } + + private static boolean validate(final String rule) { + if (Strings.isNullOrEmpty(rule) || !ALLOWED_PATTERN.matcher(rule).matches()) { + throw new InvalidParameterValueException("Only API names and wildcards are allowed, invalid rule provided: " + rule); + } + return true; + } +} diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 6f3152b75a7..490492533be 100644 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -193,6 +193,7 @@ public class ApiConstants { public static final String PORTABLE_IP_ADDRESS = "portableipaddress"; public static final String PORT_FORWARDING_SERVICE_ID = "portforwardingserviceid"; public static final String POST_URL = "postURL"; + public static final String PARENT = "parent"; public static final String PRIVATE_INTERFACE = "privateinterface"; public static final String PRIVATE_IP = "privateip"; public static final String PRIVATE_PORT = "privateport"; @@ -358,6 +359,12 @@ public class ApiConstants { public static final String PROJECT_IDS = "projectids"; public static final String PROJECT = "project"; public static final String ROLE = "role"; + public static final String ROLE_ID = "roleid"; + public static final String ROLE_TYPE = "roletype"; + public static final String ROLE_NAME = "rolename"; + public static final String PERMISSION = "permission"; + public static final String RULE = "rule"; + public static final String RULE_ORDER = "ruleorder"; public static final String USER = "user"; public static final String ACTIVE_ONLY = "activeonly"; public static final String TOKEN = "token"; diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 360b277d897..5be75196d39 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -30,6 +30,7 @@ import java.util.regex.Pattern; import javax.inject.Inject; import com.cloud.utils.HttpUtils; +import org.apache.cloudstack.acl.RoleService; import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; @@ -85,6 +86,7 @@ import com.cloud.vm.snapshot.VMSnapshotService; public abstract class BaseCmd { private static final Logger s_logger = Logger.getLogger(BaseCmd.class.getName()); + public static final String RESPONSE_SUFFIX = "response"; public static final String RESPONSE_TYPE_XML = HttpUtils.RESPONSE_TYPE_XML; public static final String RESPONSE_TYPE_JSON = HttpUtils.RESPONSE_TYPE_JSON; public static final String USER_ERROR_MESSAGE = "Internal error executing command, please contact your system administrator"; @@ -104,12 +106,13 @@ public abstract class BaseCmd { @Parameter(name = "response", type = CommandType.STRING) private String responseType; - @Inject public ConfigurationService _configService; @Inject public AccountService _accountService; @Inject + public RoleService roleService; + @Inject public UserVmService _userVmService; @Inject public ManagementService _mgr; @@ -323,7 +326,7 @@ public abstract class BaseCmd { if (allowedRoles.length > 0) { roleIsAllowed = false; for (final RoleType allowedRole : allowedRoles) { - if (allowedRole.getValue() == caller.getType()) { + if (allowedRole.getAccountType() == caller.getType()) { roleIsAllowed = true; break; } diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java index b55ce714988..2e1fbd6f861 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java @@ -22,6 +22,7 @@ import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,6 +32,7 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.RoleResponse; import org.apache.cloudstack.context.CallContext; import com.cloud.user.Account; @@ -55,10 +57,12 @@ public class CreateAccountCmd extends BaseCmd { @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, - required = true, description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin") private Short accountType; + @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class, description = "Creates the account under the specified role.") + private Long roleId; + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "Creates the user under the specified domain.") private Long domainId; @@ -106,7 +110,11 @@ public class CreateAccountCmd extends BaseCmd { } public Short getAccountType() { - return accountType; + return RoleType.getAccountTypeByRole(roleService.findRole(roleId), accountType); + } + + public Long getRoleId() { + return RoleType.getRoleByAccountType(roleId, accountType); } public Long getDomainId() { @@ -178,7 +186,7 @@ public class CreateAccountCmd extends BaseCmd { validateParams(); CallContext.current().setEventDetails("Account Name: " + getAccountName() + ", Domain Id:" + getDomainId()); UserAccount userAccount = - _accountService.createUserAccount(getUsername(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimeZone(), getAccountName(), getAccountType(), + _accountService.createUserAccount(getUsername(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimeZone(), getAccountName(), getAccountType(), getRoleId(), getDomainId(), getNetworkDomain(), getDetails(), getAccountUUID(), getUserUUID()); if (userAccount != null) { AccountResponse response = _responseGenerator.createUserAccountResponse(ResponseView.Full, userAccount); @@ -196,5 +204,8 @@ public class CreateAccountCmd extends BaseCmd { if(StringUtils.isEmpty(getPassword())) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Empty passwords are not allowed"); } + if (getAccountType() == null && (getRoleId() == null || getRoleId() < 1L)) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Neither account type and role ID are not provided"); + } } } diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java new file mode 100644 index 00000000000..994573d1796 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java @@ -0,0 +1,105 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.user.Account; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.response.RoleResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = CreateRoleCmd.APINAME, description = "Creates a role", responseObject = RoleResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin}) +public class CreateRoleCmd extends BaseCmd { + public static final String APINAME = "createRole"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, + description = "creates a role with this unique name", validations = {ApiArgValidator.NotNullOrEmpty}) + private String roleName; + + @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, + description = "The type of the role, valid options are: Admin, ResourceAdmin, DomainAdmin, User", + validations = {ApiArgValidator.NotNullOrEmpty}) + private String roleType; + + @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the role") + private String roleDescription; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getRoleName() { + return roleName; + } + + public RoleType getRoleType() { + return RoleType.fromString(roleType); + } + + public String getRoleDescription() { + return roleDescription; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + private void setupResponse(final Role role) { + final RoleResponse response = new RoleResponse(); + response.setId(role.getUuid()); + response.setRoleName(role.getName()); + response.setRoleType(role.getRoleType()); + response.setResponseName(getCommandName()); + response.setObjectName("role"); + setResponseObject(response); + } + + @Override + public void execute() { + CallContext.current().setEventDetails("Role: " + getRoleName() + ", type:" + getRoleType() + ", description: " + getRoleDescription()); + final Role role = roleService.createRole(getRoleName(), getRoleType(), getRoleDescription()); + if (role == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create role"); + } + setupResponse(role); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRolePermissionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRolePermissionCmd.java new file mode 100644 index 00000000000..aeb3f4ee11a --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRolePermissionCmd.java @@ -0,0 +1,124 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.user.Account; +import com.google.common.base.Strings; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.Rule; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.response.RolePermissionResponse; +import org.apache.cloudstack.api.response.RoleResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = CreateRolePermissionCmd.APINAME, description = "Adds a API permission to a role", responseObject = RolePermissionResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin}) +public class CreateRolePermissionCmd extends BaseCmd { + public static final String APINAME = "createRolePermission"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, required = true, entityType = RoleResponse.class, + description = "ID of the role", validations = {ApiArgValidator.PositiveNumber}) + private Long roleId; + + @Parameter(name = ApiConstants.RULE, type = CommandType.STRING, required = true, description = "The API name or wildcard rule such as list*", + validations = {ApiArgValidator.NotNullOrEmpty}) + private String rule; + + @Parameter(name = ApiConstants.PERMISSION, type = CommandType.STRING, required = true, description = "The rule permission, allow or deny. Default: deny.") + private String permission; + + @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "The description of the role permission") + private String description; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getRoleId() { + return roleId; + } + + public Rule getRule() { + return new Rule(rule); + } + + public RolePermission.Permission getPermission() { + if (Strings.isNullOrEmpty(permission)) { + return null; + } + return RolePermission.Permission.valueOf(permission.toUpperCase()); + } + + public String getDescription() { + return description; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + private void setupResponse(final RolePermission rolePermission, final Role role) { + final RolePermissionResponse response = new RolePermissionResponse(); + response.setId(rolePermission.getUuid()); + response.setRoleId(role.getUuid()); + response.setRule(rolePermission.getRule()); + response.setRulePermission(rolePermission.getPermission()); + response.setDescription(rolePermission.getDescription()); + response.setResponseName(getCommandName()); + response.setObjectName("rolepermission"); + setResponseObject(response); + } + + @Override + public void execute() { + final Role role = roleService.findRole(getRoleId()); + if (role == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid role id provided"); + } + CallContext.current().setEventDetails("Role id: " + role.getId() + ", rule:" + getRule() + ", permission: " + getPermission() + ", description: " + getDescription()); + final RolePermission rolePermission = roleService.createRolePermission(role, getRule(), getPermission(), getDescription()); + if (rolePermission == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create role permission"); + } + setupResponse(rolePermission, role); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRoleCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRoleCmd.java new file mode 100644 index 00000000000..bd4a7cdacb7 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRoleCmd.java @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.user.Account; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.response.RoleResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = DeleteRoleCmd.APINAME, description = "Deletes a role", responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin}) +public class DeleteRoleCmd extends BaseCmd { + public static final String APINAME = "deleteRole"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, required = true, entityType = RoleResponse.class, + description = "ID of the role", validations = {ApiArgValidator.PositiveNumber}) + private Long roleId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getRoleId() { + return roleId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + Role role = roleService.findRole(getRoleId()); + if (role == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Cannot find the role with provided id"); + } + CallContext.current().setEventDetails("Role id: " + role.getId()); + boolean result = roleService.deleteRole(role); + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setSuccess(result); + setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRolePermissionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRolePermissionCmd.java new file mode 100644 index 00000000000..9c7dc7c9861 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRolePermissionCmd.java @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.response.RolePermissionResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = DeleteRolePermissionCmd.APINAME, description = "Deletes a role permission", responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin}) +public class DeleteRolePermissionCmd extends BaseCmd { + public static final String APINAME = "deleteRolePermission"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, required = true, entityType = RolePermissionResponse.class, + description = "ID of the role permission", validations = {ApiArgValidator.PositiveNumber}) + private Long rolePermissionId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getRolePermissionId() { + return rolePermissionId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + RolePermission rolePermission = roleService.findRolePermission(getRolePermissionId()); + if (rolePermission == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid role permission id provided"); + } + CallContext.current().setEventDetails("Role permission id: " + rolePermission.getId()); + boolean result = roleService.deleteRolePermission(rolePermission); + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setSuccess(result); + setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolePermissionsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolePermissionsCmd.java new file mode 100644 index 00000000000..f20abf40146 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolePermissionsCmd.java @@ -0,0 +1,106 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.RolePermissionResponse; +import org.apache.cloudstack.api.response.RoleResponse; + +import java.util.ArrayList; +import java.util.List; + + +@APICommand(name = ListRolePermissionsCmd.APINAME, description = "Lists role permissions", responseObject = RolePermissionResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin}) +public class ListRolePermissionsCmd extends BaseCmd { + public static final String APINAME = "listRolePermissions"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class, + description = "ID of the role", validations = {ApiArgValidator.PositiveNumber}) + private Long roleId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getRoleId() { + return roleId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + private void setupResponse(final List rolePermissions, final Long roleId) { + final Role roleProvided = roleService.findRole(roleId); + final ListResponse response = new ListResponse<>(); + final List rolePermissionResponses = new ArrayList<>(); + for (final RolePermission rolePermission : rolePermissions) { + final RolePermissionResponse rolePermissionResponse = new RolePermissionResponse(); + Role role = roleProvided; + if (role == null) { + role = roleService.findRole(rolePermission.getRoleId()); + } + rolePermissionResponse.setRoleId(role.getUuid()); + rolePermissionResponse.setRoleName(role.getName()); + rolePermissionResponse.setId(rolePermission.getUuid()); + rolePermissionResponse.setRule(rolePermission.getRule()); + rolePermissionResponse.setRulePermission(rolePermission.getPermission()); + rolePermissionResponse.setDescription(rolePermission.getDescription()); + rolePermissionResponse.setObjectName("rolepermission"); + rolePermissionResponses.add(rolePermissionResponse); + } + response.setResponses(rolePermissionResponses); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException { + final List rolePermissions = roleService.findAllPermissionsBy(getRoleId()); + setupResponse(rolePermissions, getRoleId()); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java new file mode 100644 index 00000000000..5cf870bfc06 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java @@ -0,0 +1,128 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; +import com.google.common.base.Strings; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.RoleResponse; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@APICommand(name = ListRolesCmd.APINAME, description = "Lists dynamic roles in CloudStack", responseObject = RoleResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin}) +public class ListRolesCmd extends BaseCmd { + public static final String APINAME = "listRoles"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = RoleResponse.class, description = "List role by role ID.") + private Long id; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "List role by role name.") + private String roleName; + + @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = "List role by role type, valid options are: Admin, ResourceAdmin, DomainAdmin, User.") + private String roleType; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public String getName() { + return roleName; + } + + public RoleType getRoleType() { + if (!Strings.isNullOrEmpty(roleType)) { + return RoleType.valueOf(roleType); + } + return null; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + private void setupResponse(final List roles) { + final ListResponse response = new ListResponse<>(); + final List roleResponses = new ArrayList<>(); + for (final Role role : roles) { + if (role == null) { + continue; + } + final RoleResponse roleResponse = new RoleResponse(); + roleResponse.setId(role.getUuid()); + roleResponse.setRoleName(role.getName()); + roleResponse.setRoleType(role.getRoleType()); + roleResponse.setDescription(role.getDescription()); + roleResponse.setObjectName("role"); + roleResponses.add(roleResponse); + } + response.setResponses(roleResponses); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + final List roles; + if (getId() != null && getId() > 0L) { + roles = Collections.singletonList(roleService.findRole(getId())); + } else if (!Strings.isNullOrEmpty(getName())) { + roles = roleService.findRolesByName(getName()); + } else if (getRoleType() != null){ + roles = roleService.findRolesByType(getRoleType()); + } else { + roles = roleService.listRoles(); + } + setupResponse(roles); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRoleCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRoleCmd.java new file mode 100644 index 00000000000..e17fc6f5714 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRoleCmd.java @@ -0,0 +1,108 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.user.Account; +import com.google.common.base.Strings; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.response.RoleResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = UpdateRoleCmd.APINAME, description = "Updates a role", responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin}) +public class UpdateRoleCmd extends BaseCmd { + public static final String APINAME = "updateRole"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, required = true, entityType = RoleResponse.class, + description = "ID of the role", validations = {ApiArgValidator.PositiveNumber}) + private Long roleId; + + @Parameter(name = ApiConstants.NAME, type = BaseCmd.CommandType.STRING, description = "creates a role with this unique name") + private String roleName; + + @Parameter(name = ApiConstants.TYPE, type = BaseCmd.CommandType.STRING, description = "The type of the role, valid options are: Admin, ResourceAdmin, DomainAdmin, User") + private String roleType; + + @Parameter(name = ApiConstants.DESCRIPTION, type = BaseCmd.CommandType.STRING, description = "The description of the role") + private String roleDescription; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getRoleId() { + return roleId; + } + + public String getRoleName() { + return roleName; + } + + public RoleType getRoleType() { + if (!Strings.isNullOrEmpty(roleType)) { + return RoleType.fromString(roleType); + } + return null; + } + + public String getRoleDescription() { + return roleDescription; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + Role role = roleService.findRole(getRoleId()); + if (role == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid role id provided"); + } + CallContext.current().setEventDetails("Role: " + getRoleName() + ", type:" + getRoleType() + ", description: " + getRoleDescription()); + boolean result = roleService.updateRole(role, getRoleName(), getRoleType(), getRoleDescription()); + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setSuccess(result); + setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java new file mode 100644 index 00000000000..055265c5ccc --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java @@ -0,0 +1,104 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.acl; + +import com.cloud.user.Account; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.RolePermissionResponse; +import org.apache.cloudstack.api.response.RoleResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; + +import java.util.ArrayList; +import java.util.List; + +@APICommand(name = UpdateRolePermissionCmd.APINAME, description = "Updates a role permission order", responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.9.0", + authorized = {RoleType.Admin}) +public class UpdateRolePermissionCmd extends BaseCmd { + public static final String APINAME = "updateRolePermission"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, required = true, entityType = RoleResponse.class, + description = "ID of the role", validations = {ApiArgValidator.PositiveNumber}) + private Long roleId; + + @Parameter(name = ApiConstants.RULE_ORDER, type = CommandType.LIST, collectionType = CommandType.UUID, required = true, entityType = RolePermissionResponse.class, + description = "The parent role permission uuid, use 0 to move this rule at the top of the list") + private List rulePermissionOrder; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getRoleId() { + return roleId; + } + + public List getRulePermissionOrder() { + return rulePermissionOrder; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + final Role role = roleService.findRole(getRoleId()); + if (role == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid role id provided"); + } + CallContext.current().setEventDetails("Reordering permissions for role id: " + role.getId()); + final List rolePermissionsOrder = new ArrayList<>(); + for (Long rolePermissionId : getRulePermissionOrder()) { + final RolePermission rolePermission = roleService.findRolePermission(rolePermissionId); + if (rolePermission == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Provided role permission(s) do not exist"); + } + rolePermissionsOrder.add(rolePermission); + } + boolean result = roleService.updateRolePermission(role, rolePermissionsOrder); + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setSuccess(result); + setResponseObject(response); + } +} \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java index 0124d5997b3..45f790fb70b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java @@ -16,6 +16,8 @@ // under the License. package org.apache.cloudstack.api.command.admin.config; +import com.google.common.base.Strings; +import org.apache.cloudstack.acl.RoleService; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -81,6 +83,10 @@ public class UpdateCfgCmd extends BaseCmd { return cfgName; } + public void setCfgName(final String cfgName) { + this.cfgName = cfgName; + } + public String getValue() { return value; } @@ -117,6 +123,12 @@ public class UpdateCfgCmd extends BaseCmd { @Override public void execute() { + if (Strings.isNullOrEmpty(getCfgName())) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Empty configuration name provided"); + } + if (getCfgName().equalsIgnoreCase(RoleService.EnableDynamicApiChecker.key())) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Restricted configuration update not allowed"); + } Configuration cfg = _configService.updateConfiguration(this); if (cfg != null) { ConfigurationResponse response = _responseGenerator.createConfigurationResponse(cfg); diff --git a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java index 24486a3c79b..9c526563d44 100644 --- a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java @@ -47,6 +47,7 @@ public class ListCapabilitiesCmd extends BaseCmd { Map capabilities = _mgr.listCapabilities(this); CapabilitiesResponse response = new CapabilitiesResponse(); response.setSecurityGroupsEnabled((Boolean)capabilities.get("securityGroupsEnabled")); + response.setDynamicRolesEnabled(roleService.isEnabled()); response.setCloudStackVersion((String)capabilities.get("cloudStackVersion")); response.setUserPublicTemplateEnabled((Boolean)capabilities.get("userPublicTemplateEnabled")); response.setSupportELB((String)capabilities.get("supportELB")); diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java index 2e50c51858a..7b48a1ea8a1 100644 --- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java @@ -21,6 +21,7 @@ import java.util.Map; import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; @@ -43,6 +44,18 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou @Param(description = "account type (admin, domain-admin, user)") private Short accountType; + @SerializedName(ApiConstants.ROLE_ID) + @Param(description = "the ID of the role") + private String roleId; + + @SerializedName(ApiConstants.ROLE_TYPE) + @Param(description = "the type of the role (Admin, ResourceAdmin, DomainAdmin, User)") + private String roleType; + + @SerializedName(ApiConstants.ROLE_NAME) + @Param(description = "the name of the role") + private String roleName; + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description = "id of the Domain the account belongs too") private String domainId; @@ -260,6 +273,20 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou this.accountType = accountType; } + public void setRoleId(String roleId) { + this.roleId = roleId; + } + + public void setRoleType(RoleType roleType) { + if (roleType != null) { + this.roleType = roleType.name(); + } + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + public void setDomainId(String domainId) { this.domainId = domainId; } diff --git a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java index 623a0a231f7..bcdad468fac 100644 --- a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java +++ b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java @@ -28,6 +28,10 @@ public class CapabilitiesResponse extends BaseResponse { @Param(description = "true if security groups support is enabled, false otherwise") private boolean securityGroupsEnabled; + @SerializedName("dynamicrolesenabled") + @Param(description = "true if dynamic role-based api checker is enabled, false otherwise") + private boolean dynamicRolesEnabled; + @SerializedName("cloudstackversion") @Param(description = "version of the cloud stack") private String cloudStackVersion; @@ -84,6 +88,10 @@ public class CapabilitiesResponse extends BaseResponse { this.securityGroupsEnabled = securityGroupsEnabled; } + public void setDynamicRolesEnabled(boolean dynamicRolesEnabled) { + this.dynamicRolesEnabled = dynamicRolesEnabled; + } + public void setCloudStackVersion(String cloudStackVersion) { this.cloudStackVersion = cloudStackVersion; } diff --git a/api/src/org/apache/cloudstack/api/response/RolePermissionResponse.java b/api/src/org/apache/cloudstack/api/response/RolePermissionResponse.java new file mode 100644 index 00000000000..ac1c5298c1e --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/RolePermissionResponse.java @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.acl.Rule; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +@EntityReference(value = RolePermission.class) +public class RolePermissionResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) + @Param(description = "the ID of the role permission") + private String id; + + @SerializedName(ApiConstants.ROLE_ID) + @Param(description = "the ID of the role to which the role permission belongs") + private String roleId; + + @SerializedName(ApiConstants.ROLE_NAME) + @Param(description = "the name of the role to which the role permission belongs") + private String roleName; + + @SerializedName(ApiConstants.RULE) + @Param(description = "the api name or wildcard rule") + private String rule; + + @SerializedName(ApiConstants.PERMISSION) + @Param(description = "the permission type of the api name or wildcard rule, allow/deny") + private String rulePermission; + + @SerializedName(ApiConstants.DESCRIPTION) + @Param(description = "the description of the role permission") + private String ruleDescription; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getRoleId() { + return roleId; + } + + public void setRoleId(String roleId) { + this.roleId = roleId; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public String getRule() { + return rule; + } + + public void setRule(Rule rule) { + if (rule != null) { + this.rule = rule.getRuleString(); + } + } + + public String getRulePermission() { + return rulePermission; + } + + public void setRulePermission(RolePermission.Permission rulePermission) { + if (rulePermission != null) { + this.rulePermission = rulePermission.name().toLowerCase(); + } + } + + public void setDescription(String description) { + this.ruleDescription = description; + } +} \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/api/response/RoleResponse.java b/api/src/org/apache/cloudstack/api/response/RoleResponse.java new file mode 100644 index 00000000000..fd4bf28e618 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/RoleResponse.java @@ -0,0 +1,63 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +@EntityReference(value = Role.class) +public class RoleResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) + @Param(description = "the ID of the role") + private String id; + + @SerializedName(ApiConstants.NAME) + @Param(description = "the name of the role") + private String roleName; + + @SerializedName(ApiConstants.TYPE) + @Param(description = "the type of the role") + private String roleType; + + @SerializedName(ApiConstants.DESCRIPTION) + @Param(description = "the description of the role") + private String roleDescription; + + public void setId(String id) { + this.id = id; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public void setRoleType(RoleType roleType) { + if (roleType != null) { + this.roleType = roleType.name(); + } + } + + public void setDescription(String description) { + this.roleDescription = description; + } +} diff --git a/api/src/org/apache/cloudstack/api/response/UserResponse.java b/api/src/org/apache/cloudstack/api/response/UserResponse.java index 36611ae7385..cc986b38a1c 100644 --- a/api/src/org/apache/cloudstack/api/response/UserResponse.java +++ b/api/src/org/apache/cloudstack/api/response/UserResponse.java @@ -20,6 +20,7 @@ import java.util.Date; import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; @@ -65,6 +66,18 @@ public class UserResponse extends BaseResponse { @Param(description = "the account type of the user") private Short accountType; + @SerializedName(ApiConstants.ROLE_ID) + @Param(description = "the ID of the role") + private String roleId; + + @SerializedName(ApiConstants.ROLE_TYPE) + @Param(description = "the type of the role") + private String roleType; + + @SerializedName(ApiConstants.ROLE_NAME) + @Param(description = "the name of the role") + private String roleName; + @SerializedName("domainid") @Param(description = "the domain ID of the user") private String domainId; @@ -174,6 +187,20 @@ public class UserResponse extends BaseResponse { this.accountType = accountType; } + public void setRoleId(String roleId) { + this.roleId = roleId; + } + + public void setRoleType(RoleType roleType) { + if (roleType != null) { + this.roleType = roleType.name(); + } + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + public String getDomainId() { return domainId; } diff --git a/api/test/org/apache/cloudstack/acl/RoleTypeTest.java b/api/test/org/apache/cloudstack/acl/RoleTypeTest.java new file mode 100644 index 00000000000..611b761014f --- /dev/null +++ b/api/test/org/apache/cloudstack/acl/RoleTypeTest.java @@ -0,0 +1,100 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.acl; + +import com.cloud.user.Account; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.Arrays; + +public class RoleTypeTest { + + @Test + public void testValidRoleTypeFromString() { + for (RoleType roleType : RoleType.values()) { + Assert.assertEquals(RoleType.fromString(roleType.name()), roleType); + } + } + + @Test + public void testInvalidRoleTypeFromString() { + for (String roleType : Arrays.asList(null, "", "admin", "12345%&^*")) { + try { + RoleType.fromString(roleType); + Assert.fail("Invalid roletype provided, exception was expected"); + } catch (IllegalStateException e) { + Assert.assertEquals(e.getMessage(), "Illegal RoleType name provided"); + } + } + } + + @Test + public void testDefaultRoleMaskByValue() { + Assert.assertEquals(RoleType.fromMask(1), RoleType.Admin); + Assert.assertEquals(RoleType.fromMask(2), RoleType.ResourceAdmin); + Assert.assertEquals(RoleType.fromMask(4), RoleType.DomainAdmin); + Assert.assertEquals(RoleType.fromMask(8), RoleType.User); + Assert.assertEquals(RoleType.fromMask(0), RoleType.Unknown); + } + + @Test + public void testGetByAccountType() { + Assert.assertEquals(RoleType.getByAccountType(Account.ACCOUNT_TYPE_NORMAL), RoleType.User); + Assert.assertEquals(RoleType.getByAccountType(Account.ACCOUNT_TYPE_ADMIN), RoleType.Admin); + Assert.assertEquals(RoleType.getByAccountType(Account.ACCOUNT_TYPE_DOMAIN_ADMIN), RoleType.DomainAdmin); + Assert.assertEquals(RoleType.getByAccountType(Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN), RoleType.ResourceAdmin); + Assert.assertEquals(RoleType.getByAccountType(Account.ACCOUNT_TYPE_PROJECT), RoleType.Unknown); + } + + @Test + public void testGetRoleByAccountTypeWhenRoleIdIsProvided() { + Assert.assertEquals(RoleType.getRoleByAccountType(123L, Account.ACCOUNT_TYPE_ADMIN), Long.valueOf(123L)); + Assert.assertEquals(RoleType.getRoleByAccountType(1234L, null), Long.valueOf(1234L)); + } + + @Test + public void testGetRoleByAccountTypeForDefaultAccountTypes() { + Assert.assertEquals(RoleType.getRoleByAccountType(null, Account.ACCOUNT_TYPE_ADMIN), (Long) RoleType.Admin.getId()); + Assert.assertEquals(RoleType.getRoleByAccountType(null, Account.ACCOUNT_TYPE_NORMAL), (Long) RoleType.User.getId()); + Assert.assertEquals(RoleType.getRoleByAccountType(null, Account.ACCOUNT_TYPE_DOMAIN_ADMIN), (Long) RoleType.DomainAdmin.getId()); + Assert.assertEquals(RoleType.getRoleByAccountType(null, Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN), (Long) RoleType.ResourceAdmin.getId()); + Assert.assertEquals(RoleType.getRoleByAccountType(null, Account.ACCOUNT_TYPE_PROJECT), null); + } + + @Test + public void testGetAccountTypeByRoleWhenRoleIsNull() { + for (Short accountType: Arrays.asList( + Account.ACCOUNT_TYPE_NORMAL, + Account.ACCOUNT_TYPE_ADMIN, + Account.ACCOUNT_TYPE_DOMAIN_ADMIN, + Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN, + Account.ACCOUNT_TYPE_PROJECT, + (short) 12345)) { + Assert.assertEquals(RoleType.getAccountTypeByRole(null, accountType), accountType); + } + } + + @Test + public void testGetAccountTypeByRole() { + Role role = Mockito.mock(Role.class); + Mockito.when(role.getRoleType()).thenReturn(RoleType.Admin); + Mockito.when(role.getId()).thenReturn(100L); + Assert.assertEquals(RoleType.getAccountTypeByRole(role, null), (Short) RoleType.Admin.getAccountType()); + } +} \ No newline at end of file diff --git a/api/test/org/apache/cloudstack/acl/RuleTest.java b/api/test/org/apache/cloudstack/acl/RuleTest.java new file mode 100644 index 00000000000..08bd775bd08 --- /dev/null +++ b/api/test/org/apache/cloudstack/acl/RuleTest.java @@ -0,0 +1,98 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.acl; + +import com.cloud.exception.InvalidParameterValueException; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; + +public class RuleTest { + + @Test + public void testToString() throws Exception { + Rule rule = new Rule("someString"); + Assert.assertEquals(rule.toString(), "someString"); + } + + @Test + public void testMatchesEmpty() throws Exception { + Rule rule = new Rule("someString"); + Assert.assertFalse(rule.matches("")); + } + + @Test + public void testMatchesNull() throws Exception { + Rule rule = new Rule("someString"); + Assert.assertFalse(rule.matches(null)); + } + + @Test + public void testMatchesSpace() throws Exception { + Rule rule = new Rule("someString"); + Assert.assertFalse(rule.matches(" ")); + } + + @Test + public void testMatchesAPI() throws Exception { + Rule rule = new Rule("someApi"); + Assert.assertTrue(rule.matches("someApi")); + } + + @Test + public void testMatchesWildcardSuffix() throws Exception { + Rule rule = new Rule("list*"); + Assert.assertTrue(rule.matches("listHosts")); + } + + @Test + public void testMatchesWildcardPrefix() throws Exception { + Rule rule = new Rule("*User"); + Assert.assertTrue(rule.matches("createUser")); + } + + @Test + public void testMatchesWildcardMiddle() throws Exception { + Rule rule = new Rule("list*s"); + Assert.assertTrue(rule.matches("listClusters")); + } + + @Test + public void testValidateRuleWithValidData() throws Exception { + for (String rule : Arrays.asList("a", "1", "someApi", "someApi321", "123SomeApi", + "prefix*", "*middle*", "*Suffix", + "*", "**", "f***", "m0nk3yMa**g1c*")) { + Assert.assertEquals(new Rule(rule).toString(), rule); + } + } + + @Test + public void testValidateRuleWithInvalidData() throws Exception { + for (String rule : Arrays.asList(null, "", " ", " ", "\n", "\t", "\r", "\"", "\'", + "^someApi$", "^someApi", "some$", "some-Api;", "some,Api", + "^", "$", "^$", ".*", "\\w+", "r**l3rd0@Kr3", "j@s1n|+|0È·", + "[a-z0-9-]+", "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$")) { + try { + new Rule(rule); + Assert.fail("Invalid rule, exception was expected"); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().startsWith("Only API names and wildcards are allowed")); + } + } + } +} \ No newline at end of file diff --git a/api/test/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java b/api/test/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java index c0a046de435..b50b2269c17 100644 --- a/api/test/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java +++ b/api/test/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java @@ -18,6 +18,7 @@ */ package org.apache.cloudstack.api.command.admin.account; +import org.apache.cloudstack.acl.RoleService; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.context.CallContext; @@ -41,10 +42,13 @@ public class CreateAccountCmdTest { @Mock private AccountService accountService; + @Mock + private RoleService roleService; @InjectMocks private CreateAccountCmd createAccountCmd = new CreateAccountCmd(); + private long roleId = 1L; private short accountType = 1; private Long domainId = 1L; @@ -69,7 +73,7 @@ public class CreateAccountCmdTest { } catch (ServerApiException e) { Assert.assertTrue("Received exception as the mock accountService createUserAccount returns null user", true); } - Mockito.verify(accountService, Mockito.times(1)).createUserAccount(null, "Test", null, null, null, null, null, accountType, domainId, null, null, null, null); + Mockito.verify(accountService, Mockito.times(1)).createUserAccount(null, "Test", null, null, null, null, null, accountType, roleId, domainId, null, null, null, null); } @Test @@ -82,7 +86,7 @@ public class CreateAccountCmdTest { Assert.assertEquals(ApiErrorCode.PARAM_ERROR, e.getErrorCode()); Assert.assertEquals("Empty passwords are not allowed", e.getMessage()); } - Mockito.verify(accountService, Mockito.never()).createUserAccount(null, null, null, null, null, null, null, accountType, domainId, null, null, null, null); + Mockito.verify(accountService, Mockito.never()).createUserAccount(null, null, null, null, null, null, null, accountType, roleId, domainId, null, null, null, null); } @Test @@ -95,6 +99,6 @@ public class CreateAccountCmdTest { Assert.assertEquals(ApiErrorCode.PARAM_ERROR, e.getErrorCode()); Assert.assertEquals("Empty passwords are not allowed", e.getMessage()); } - Mockito.verify(accountService, Mockito.never()).createUserAccount(null, null, null, null, null, null, null, accountType, domainId, null, null, null, null); + Mockito.verify(accountService, Mockito.never()).createUserAccount(null, null, null, null, null, null, null, accountType, roleId, domainId, null, null, null, null); } } diff --git a/api/test/org/apache/cloudstack/api/command/test/UpdateCfgCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/UpdateCfgCmdTest.java index 63c4a032435..65b93306648 100644 --- a/api/test/org/apache/cloudstack/api/command/test/UpdateCfgCmdTest.java +++ b/api/test/org/apache/cloudstack/api/command/test/UpdateCfgCmdTest.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.test; import junit.framework.Assert; import junit.framework.TestCase; +import org.apache.cloudstack.acl.RoleService; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -48,22 +49,46 @@ public class UpdateCfgCmdTest extends TestCase { updateCfgCmd = new UpdateCfgCmd(); } + @Test + public void testExecuteForEmptyCfgName() { + updateCfgCmd._configService = configService; + + try { + updateCfgCmd.execute(); + } catch (ServerApiException exception) { + Assert.assertEquals("Empty configuration name provided", exception.getDescription()); + } + } + + @Test + public void testExecuteForRestrictedCfg() { + updateCfgCmd._configService = configService; + updateCfgCmd.setCfgName(RoleService.EnableDynamicApiChecker.key()); + + try { + updateCfgCmd.execute(); + } catch (ServerApiException exception) { + Assert.assertEquals("Restricted configuration update not allowed", exception.getDescription()); + } + } + @Test public void testExecuteForEmptyResult() { updateCfgCmd._configService = configService; + updateCfgCmd.setCfgName("some.cfg"); try { updateCfgCmd.execute(); } catch (ServerApiException exception) { Assert.assertEquals("Failed to update config", exception.getDescription()); } - } @Test public void testExecuteForNullResult() { updateCfgCmd._configService = configService; + updateCfgCmd.setCfgName("some.cfg"); try { Mockito.when(configService.updateConfiguration(updateCfgCmd)).thenReturn(null); @@ -88,6 +113,7 @@ public class UpdateCfgCmdTest extends TestCase { Configuration cfg = Mockito.mock(Configuration.class); updateCfgCmd._configService = configService; updateCfgCmd._responseGenerator = responseGenerator; + updateCfgCmd.setCfgName("some.cfg"); try { Mockito.when(configService.updateConfiguration(updateCfgCmd)).thenReturn(cfg); diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index fbdedda5c2d..5e979074b6a 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -1095,9 +1095,17 @@ label.retry.interval=Retry Interval label.review=Review label.revoke.project.invite=Revoke invitation label.role=Role +label.roles=Roles +label.roletype=Role Type +label.add.role=Add Role +label.edit.role=Edit Role +label.delete.role=Delete Role +message.role.ordering.fail=Reordering of rule permissions aborted as the list has changed while you were making changes. Please try again. label.root.certificate=Root certificate label.root.disk.controller=Root disk controller label.root.disk.offering=Root Disk Offering +label.permission=Permission +label.rule=Rule label.rules=Rules label.running.vms=Running VMs label.s3.access_key=Access Key diff --git a/client/pom.xml b/client/pom.xml index a1e4f609f4c..9bd80b722cf 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -50,6 +50,11 @@ cloud-plugin-acl-static-role-based ${project.version} + + org.apache.cloudstack + cloud-plugin-acl-dynamic-role-based + ${project.version} + org.apache.cloudstack cloud-plugin-dedicated-resources diff --git a/debian/cloudstack-management.install b/debian/cloudstack-management.install index 4e016dfe292..c66938263e8 100644 --- a/debian/cloudstack-management.install +++ b/debian/cloudstack-management.install @@ -18,7 +18,6 @@ /etc/cloudstack/management/catalina.policy /etc/cloudstack/management/catalina.properties /etc/cloudstack/management/logging.properties -/etc/cloudstack/management/commands.properties /etc/cloudstack/management/ehcache.xml /etc/cloudstack/management/server-ssl.xml /etc/cloudstack/management/server-nonssl.xml diff --git a/debian/control b/debian/control index 05058a8dcff..6e7881b1bcf 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: ${misc:Depends}, ${python:Depends}, cloudstack-common (= ${source:Version}), tomcat6, sudo, jsvc, python-mysql.connector, libmysql-java, augeas-tools, mysql-client, adduser, bzip2 +Depends: ${misc:Depends}, ${python:Depends}, cloudstack-common (= ${source:Version}), tomcat6 | tomcat7, sudo, jsvc, python-mysql.connector, libmysql-java, augeas-tools, mysql-client, adduser, bzip2 Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server diff --git a/developer/developer-prefill.sql b/developer/developer-prefill.sql index f874118e19d..0dbe1803b9b 100644 --- a/developer/developer-prefill.sql +++ b/developer/developer-prefill.sql @@ -106,6 +106,11 @@ INSERT INTO `cloud`.`configuration` (category, instance, component, name, value) VALUES ('Advanced', 'DEFAULT', 'management-server', 'direct.agent.load.size', '1000'); +-- Enable dynamic RBAC by default for fresh deployments +INSERT INTO `cloud`.`configuration` (category, instance, component, name, value) + VALUES ('Advanced', 'DEFAULT', 'RoleService', + 'dynamic.apichecker.enabled', 'true'); + -- Add developer configuration entry; allows management server to be run as a user other than "cloud" INSERT INTO `cloud`.`configuration` (category, instance, component, name, value) VALUES ('Advanced', 'DEFAULT', 'management-server', diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 67ed2a7d255..a3d58fc539b 100644 --- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -113,6 +113,8 @@ + + diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade481to490.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade481to490.java index 9e5213478eb..d1240ecf2cb 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade481to490.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade481to490.java @@ -17,12 +17,21 @@ package com.cloud.upgrade.dao; +import com.cloud.utils.PropertiesUtil; +import com.cloud.utils.db.ScriptRunner; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; +import org.apache.cloudstack.acl.RoleType; import org.apache.log4j.Logger; import java.io.File; +import java.io.FileReader; +import java.io.IOException; import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; public class Upgrade481to490 implements DbUpgrade { final static Logger s_logger = Logger.getLogger(Upgrade481to490.class); @@ -53,6 +62,71 @@ public class Upgrade481to490 implements DbUpgrade { @Override public void performDataMigration(Connection conn) { + setupRolesAndPermissionsForDynamicChecker(conn); + } + + private void migrateAccountsToDefaultRoles(final Connection conn) { + try (final PreparedStatement selectStatement = conn.prepareStatement("SELECT `id`, `type` FROM `cloud`.`account`;"); + final ResultSet selectResultSet = selectStatement.executeQuery()) { + while (selectResultSet.next()) { + final Long accountId = selectResultSet.getLong(1); + final Short accountType = selectResultSet.getShort(2); + final Long roleId = RoleType.getByAccountType(accountType).getId(); + if (roleId < 1L || roleId > 4L) { + s_logger.warn("Skipping role ID migration due to invalid role_id resolved for account id=" + accountId); + continue; + } + try (final PreparedStatement updateStatement = conn.prepareStatement("UPDATE `cloud`.`account` SET account.role_id = ? WHERE account.id = ? ;")) { + updateStatement.setLong(1, roleId); + updateStatement.setLong(2, accountId); + updateStatement.executeUpdate(); + } catch (SQLException e) { + s_logger.error("Failed to update cloud.account role_id for account id:" + accountId + " with exception: " + e.getMessage()); + throw new CloudRuntimeException("Exception while updating cloud.account role_id", e); + } + } + } catch (SQLException e) { + throw new CloudRuntimeException("Exception while migrating existing account table's role_id column to a role based on account type", e); + } + s_logger.debug("Done migrating existing accounts to use one of default roles based on account type"); + } + + private void setupRolesAndPermissionsForDynamicChecker(final Connection conn) { + final String alterTableSql = "ALTER TABLE `cloud`.`account` " + + "ADD COLUMN `role_id` bigint(20) unsigned COMMENT 'role id for this account' AFTER `type`, " + + "ADD KEY `fk_account__role_id` (`role_id`), " + + "ADD CONSTRAINT `fk_account__role_id` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`);"; + try (final PreparedStatement pstmt = conn.prepareStatement(alterTableSql)) { + pstmt.executeUpdate(); + } catch (SQLException e) { + if (e.getMessage().contains("role_id")) { + s_logger.warn("cloud.account table already has the role_id column, skipping altering table and migration of accounts"); + return; + } else { + throw new CloudRuntimeException("Unable to create column quota_calculated in table cloud_usage.cloud_usage", e); + } + } + + migrateAccountsToDefaultRoles(conn); + + final Map apiMap = PropertiesUtil.processConfigFile(new String[] { PropertiesUtil.getDefaultApiCommandsFileName() }); + if (apiMap == null || apiMap.isEmpty()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("The commands.properties file and default role permissions were not found. " + + "Assuming new installation, configuring default role-api mappings."); + } + String script = Script.findScript("", "db/create-default-role-api-mappings.sql"); + if (script == null) { + s_logger.error("Unable to find default role-api mapping sql file, please configure api per role manually"); + return; + } + try(final FileReader reader = new FileReader(new File(script))) { + ScriptRunner runner = new ScriptRunner(conn, false, true); + runner.runScript(reader); + } catch (SQLException | IOException e) { + s_logger.error("Unable to insert default api-role mappings from file: " + script + ". Please configure api per role manually, giving up!", e); + } + } } @Override @@ -61,7 +135,6 @@ public class Upgrade481to490 implements DbUpgrade { if (script == null) { throw new CloudRuntimeException("Unable to find db/schema-481to490-cleanup.sql"); } - return new File[] {new File(script)}; } } diff --git a/engine/schema/src/com/cloud/user/AccountVO.java b/engine/schema/src/com/cloud/user/AccountVO.java index 0f5a0446e93..a504d2fdaec 100644 --- a/engine/schema/src/com/cloud/user/AccountVO.java +++ b/engine/schema/src/com/cloud/user/AccountVO.java @@ -16,8 +16,8 @@ // under the License. package com.cloud.user; -import java.util.Date; -import java.util.UUID; +import com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.acl.RoleType; import javax.persistence.Column; import javax.persistence.Entity; @@ -27,8 +27,8 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; - -import com.cloud.utils.db.GenericDao; +import java.util.Date; +import java.util.UUID; @Entity @Table(name = "account") @@ -44,6 +44,9 @@ public class AccountVO implements Account { @Column(name = "type") private short type = ACCOUNT_TYPE_NORMAL; + @Column(name = "role_id") + private Long roleId; + @Column(name = "domain_id") private long domainId; @@ -78,13 +81,21 @@ public class AccountVO implements Account { uuid = UUID.randomUUID().toString(); } - public AccountVO(String accountName, long domainId, String networkDomain, short type, String uuid) { + public AccountVO(final String accountName, final long domainId, final String networkDomain, final short type, final String uuid) { this.accountName = accountName; this.domainId = domainId; this.networkDomain = networkDomain; this.type = type; - state = State.enabled; + this.state = State.enabled; this.uuid = uuid; + this.roleId = RoleType.getRoleByAccountType(null, type); + } + + public AccountVO(final String accountName, final long domainId, final String networkDomain, final short type, final Long roleId, final String uuid) { + this(accountName, domainId, networkDomain, type, uuid); + if (roleId != null) { + this.roleId = roleId; + } } public void setNeedsCleanup(boolean value) { @@ -122,6 +133,14 @@ public class AccountVO implements Account { this.type = type; } + public Long getRoleId() { + return roleId; + } + + public void setRoleId(long roleId) { + this.roleId = roleId; + } + @Override public long getDomainId() { return domainId; diff --git a/engine/schema/src/com/cloud/user/dao/AccountDao.java b/engine/schema/src/com/cloud/user/dao/AccountDao.java index 4c7ce8e31b7..374c9cc43d6 100644 --- a/engine/schema/src/com/cloud/user/dao/AccountDao.java +++ b/engine/schema/src/com/cloud/user/dao/AccountDao.java @@ -41,6 +41,8 @@ public interface AccountDao extends GenericDao { List findActiveAccountsForDomain(Long domain); + List findAccountsByRole(Long roleId); + void markForCleanup(long accountId); List listAccounts(String accountName, Long domainId, Filter filter); diff --git a/engine/schema/src/com/cloud/user/dao/AccountDaoImpl.java b/engine/schema/src/com/cloud/user/dao/AccountDaoImpl.java index bff6213c10b..27891503dc8 100644 --- a/engine/schema/src/com/cloud/user/dao/AccountDaoImpl.java +++ b/engine/schema/src/com/cloud/user/dao/AccountDaoImpl.java @@ -44,7 +44,7 @@ import com.cloud.utils.db.TransactionLegacy; public class AccountDaoImpl extends GenericDaoBase implements AccountDao { private static final Logger s_logger = Logger.getLogger(AccountDaoImpl.class); private static final String FIND_USER_ACCOUNT_BY_API_KEY = "SELECT u.id, u.username, u.account_id, u.secret_key, u.state, " - + "a.id, a.account_name, a.type, a.domain_id, a.state " + "FROM `cloud`.`user` u, `cloud`.`account` a " + + "a.id, a.account_name, a.type, a.role_id, a.domain_id, a.state " + "FROM `cloud`.`user` u, `cloud`.`account` a " + "WHERE u.account_id = a.id AND u.api_key = ? and u.removed IS NULL"; protected final SearchBuilder AllFieldsSearch; @@ -53,6 +53,7 @@ public class AccountDaoImpl extends GenericDaoBase implements A protected final SearchBuilder CleanupForRemovedAccountsSearch; protected final SearchBuilder CleanupForDisabledAccountsSearch; protected final SearchBuilder NonProjectAccountSearch; + protected final SearchBuilder AccountByRoleSearch; protected final GenericSearchBuilder AccountIdsSearch; public AccountDaoImpl() { @@ -96,6 +97,10 @@ public class AccountDaoImpl extends GenericDaoBase implements A AccountIdsSearch.selectFields(AccountIdsSearch.entity().getId()); AccountIdsSearch.and("ids", AccountIdsSearch.entity().getDomainId(), Op.IN); AccountIdsSearch.done(); + + AccountByRoleSearch = createSearchBuilder(); + AccountByRoleSearch.and("roleId", AccountByRoleSearch.entity().getRoleId(), SearchCriteria.Op.EQ); + AccountByRoleSearch.done(); } @Override @@ -140,8 +145,9 @@ public class AccountDaoImpl extends GenericDaoBase implements A AccountVO a = new AccountVO(rs.getLong(6)); a.setAccountName(rs.getString(7)); a.setType(rs.getShort(8)); - a.setDomainId(rs.getLong(9)); - a.setState(State.valueOf(rs.getString(10))); + a.setRoleId(rs.getLong(9)); + a.setDomainId(rs.getLong(10)); + a.setState(State.valueOf(rs.getString(11))); userAcctPair = new Pair(u, a); } @@ -258,6 +264,13 @@ public class AccountDaoImpl extends GenericDaoBase implements A return listBy(sc); } + @Override + public List findAccountsByRole(Long roleId) { + SearchCriteria sc = AccountByRoleSearch.create(); + sc.setParameters("roleId", roleId); + return listBy(sc); + } + @Override public void markForCleanup(long accountId) { AccountVO account = findByIdIncludingRemoved(accountId); diff --git a/engine/schema/src/org/apache/cloudstack/acl/RolePermissionVO.java b/engine/schema/src/org/apache/cloudstack/acl/RolePermissionVO.java new file mode 100644 index 00000000000..a81cebb70d7 --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/acl/RolePermissionVO.java @@ -0,0 +1,120 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.UUID; + +@Entity +@Table(name = "role_permissions") +public class RolePermissionVO implements RolePermission { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "uuid") + private String uuid; + + @Column(name = "role_id") + private long roleId; + + @Column(name = "rule") + private String rule; + + @Column(name = "permission", nullable = false) + @Enumerated(value = EnumType.STRING) + private Permission permission = RolePermission.Permission.DENY; + + @Column(name = "description") + private String description; + + @Column(name = "sort_order") + private long sortOrder = 0; + + public RolePermissionVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public RolePermissionVO(final long roleId, final String rule, final Permission permission, final String description) { + this(); + this.roleId = roleId; + this.rule = rule; + this.permission = permission; + this.description = description; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getUuid() { + return uuid; + } + + public long getRoleId() { + return roleId; + } + + public void setRoleId(long roleId) { + this.roleId = roleId; + } + + @Override + public Rule getRule() { + return new Rule(rule); + } + + public void setRule(String rule) { + this.rule = rule; + } + + @Override + public Permission getPermission() { + return permission; + } + + public void setPermission(Permission permission) { + this.permission = permission; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public long getSortOrder() { + return sortOrder; + } + + public void setSortOrder(long sortOrder) { + this.sortOrder = sortOrder; + } +} \ No newline at end of file diff --git a/engine/schema/src/org/apache/cloudstack/acl/RoleVO.java b/engine/schema/src/org/apache/cloudstack/acl/RoleVO.java new file mode 100644 index 00000000000..f3404ab6d79 --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/acl/RoleVO.java @@ -0,0 +1,106 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl; + +import com.cloud.utils.db.GenericDao; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Date; +import java.util.UUID; + +@Entity +@Table(name = "roles") +public class RoleVO implements Role { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "uuid") + private String uuid; + + @Column(name = "name") + private String name; + + @Column(name = "role_type", nullable = false) + @Enumerated(value = EnumType.STRING) + private RoleType roleType = RoleType.User; + + @Column(name = "description") + private String description; + + @Column(name = GenericDao.REMOVED_COLUMN) + private Date removed; + + public RoleVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public RoleVO(final String name, final RoleType roleType, final String description) { + this(); + this.name = name; + this.roleType = roleType; + this.description = description; + } + + public RoleVO(final long id, final String name, final RoleType roleType, final String description) { + this(name, roleType, description); + this.id = id; + } + + @Override + public String getUuid() { + return uuid; + } + + @Override + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public RoleType getRoleType() { + return roleType; + } + + public void setRoleType(RoleType roleType) { + this.roleType = roleType; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/RoleDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/RoleDao.java new file mode 100644 index 00000000000..e53654d998e --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/RoleDao.java @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl.dao; + +import com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.RoleVO; + +import java.util.List; + +public interface RoleDao extends GenericDao { + List findAllByName(String roleName); + List findAllByRoleType(RoleType type); +} diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/RoleDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/RoleDaoImpl.java new file mode 100644 index 00000000000..c7eb496213e --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/RoleDaoImpl.java @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl.dao; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.acl.RoleVO; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import java.util.List; + +@Component +@Local(value = {RoleDao.class}) +public class RoleDaoImpl extends GenericDaoBase implements RoleDao { + private final SearchBuilder RoleByNameSearch; + private final SearchBuilder RoleByTypeSearch; + + public RoleDaoImpl() { + super(); + + RoleByNameSearch = createSearchBuilder(); + RoleByNameSearch.and("roleName", RoleByNameSearch.entity().getName(), SearchCriteria.Op.LIKE); + RoleByNameSearch.done(); + + RoleByTypeSearch = createSearchBuilder(); + RoleByTypeSearch.and("roleType", RoleByTypeSearch.entity().getRoleType(), SearchCriteria.Op.EQ); + RoleByTypeSearch.done(); + } + + @Override + public List findAllByName(final String roleName) { + SearchCriteria sc = RoleByNameSearch.create(); + sc.setParameters("roleName", "%" + roleName + "%"); + return listBy(sc); + } + + @Override + public List findAllByRoleType(final RoleType type) { + SearchCriteria sc = RoleByTypeSearch.create(); + sc.setParameters("roleType", type); + return listBy(sc); + } +} diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java new file mode 100644 index 00000000000..37544919657 --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl.dao; + +import com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.acl.RolePermissionVO; + +import java.util.List; + +public interface RolePermissionsDao extends GenericDao { + /** + * Adds a new role permission at the end of the list of role permissions + * @param item the new role permission + * @return returns persisted role permission + */ + RolePermissionVO persist(final RolePermissionVO item); + + /** + * Moves an existing role permission under a given parent role permission + * @param role the existing role + * @param newOrder the new role permissions order + * @return returns true on success + */ + boolean update(final Role role, final List newOrder); + + /** + * Returns ordered linked-list of role permission for a given role + * @param roleId the ID of the role + * @return returns list of role permissions + */ + List findAllByRoleIdSorted(Long roleId); +} diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java new file mode 100644 index 00000000000..960b652a3b4 --- /dev/null +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java @@ -0,0 +1,166 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.acl.dao; + +import com.cloud.utils.db.Attribute; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionCallback; +import com.cloud.utils.db.TransactionStatus; +import com.cloud.utils.db.UpdateBuilder; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RolePermission; +import org.apache.cloudstack.acl.RolePermissionVO; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Component +@Local(value = {RolePermissionsDao.class}) +public class RolePermissionsDaoImpl extends GenericDaoBase implements RolePermissionsDao { + protected static final Logger LOGGER = Logger.getLogger(RolePermissionsDaoImpl.class); + + private final SearchBuilder RolePermissionsSearch; + private Attribute sortOrderAttribute; + + public RolePermissionsDaoImpl() { + super(); + + RolePermissionsSearch = createSearchBuilder(); + RolePermissionsSearch.and("uuid", RolePermissionsSearch.entity().getUuid(), SearchCriteria.Op.EQ); + RolePermissionsSearch.and("roleId", RolePermissionsSearch.entity().getRoleId(), SearchCriteria.Op.EQ); + RolePermissionsSearch.and("sortOrder", RolePermissionsSearch.entity().getSortOrder(), SearchCriteria.Op.EQ); + RolePermissionsSearch.done(); + + sortOrderAttribute = _allAttributes.get("sortOrder"); + + assert (sortOrderAttribute != null) : "Couldn't find one of these attributes"; + } + + private boolean updateSortOrder(final RolePermissionVO permissionBeingMoved, final RolePermissionVO parentPermission) { + if (parentPermission != null && permissionBeingMoved.getId() == parentPermission.getId()) { + return true; + } + final List newOrderedPermissionsList = new ArrayList<>(); + // Null parent implies item needs to move to the top + if (parentPermission == null) { + newOrderedPermissionsList.add(permissionBeingMoved); + } + for (final RolePermissionVO permission : findAllByRoleIdSorted(permissionBeingMoved.getRoleId())) { + if (permission.getId() == permissionBeingMoved.getId()) { + continue; + } + newOrderedPermissionsList.add(permission); + if (parentPermission != null && permission.getId() == parentPermission.getId()) { + newOrderedPermissionsList.add(permissionBeingMoved); + } + } + long sortOrder = 0L; + for (final RolePermissionVO permission : newOrderedPermissionsList) { + permission.setSortOrder(sortOrder++); + if (!update(permission.getId(), permission)) { + LOGGER.warn("Failed to update item's sort order with id:" + permission.getId() + " while moving permission with id:" + permissionBeingMoved.getId() + " to a new position"); + return false; + } + } + return true; + } + + @Override + public RolePermissionVO persist(final RolePermissionVO item) { + item.setSortOrder(0); + final List permissionsList = findAllByRoleIdSorted(item.getRoleId()); + if (permissionsList != null && permissionsList.size() > 0) { + RolePermission lastRule = permissionsList.get(permissionsList.size() - 1); + item.setSortOrder(lastRule.getSortOrder() + 1); + } + return super.persist(item); + } + + @Override + public boolean update(final Role role, final List newOrder) { + if (role == null || newOrder == null || newOrder.isEmpty()) { + return false; + } + return Transaction.execute(new TransactionCallback() { + @Override + public Boolean doInTransaction(TransactionStatus status) { + final String failMessage = "The role's rule permissions list has changed while you were making updates, aborted re-ordering of rules. Please try again."; + final List currentOrder = findAllByRoleIdSorted(role.getId()); + if (role.getId() < 1L || newOrder.size() != currentOrder.size()) { + throw new CloudRuntimeException(failMessage); + } + final Set newOrderSet = new HashSet<>(); + for (final RolePermission permission : newOrder) { + if (permission == null) { + continue; + } + newOrderSet.add(permission.getId()); + } + final Set currentOrderSet = new HashSet<>(); + for (final RolePermission permission : currentOrder) { + currentOrderSet.add(permission.getId()); + } + if (!newOrderSet.equals(currentOrderSet)) { + throw new CloudRuntimeException(failMessage); + } + long sortOrder = 0L; + for (RolePermission rolePermission : newOrder) { + final SearchCriteria sc = RolePermissionsSearch.create(); + sc.setParameters("uuid", rolePermission.getUuid()); + sc.setParameters("roleId", role.getId()); + sc.setParameters("sortOrder", rolePermission.getSortOrder()); + + final UpdateBuilder ub = getUpdateBuilder(rolePermission); + ub.set(rolePermission, sortOrderAttribute, sortOrder); + final int result = update(ub, sc, null); + if (result < 1) { + throw new CloudRuntimeException(failMessage); + } + sortOrder++; + } + return true; + } + }); + } + + @Override + public List findAllByRoleIdSorted(final Long roleId) { + final SearchCriteria sc = RolePermissionsSearch.create(); + if (roleId != null && roleId > 0L) { + sc.setParameters("roleId", roleId); + } + final Filter searchBySorted = new Filter(RolePermissionVO.class, "sortOrder", true, null, null); + searchBySorted.addOrderBy(RolePermissionVO.class, "id", true); + final List rolePermissionList = listBy(sc, searchBySorted); + if (rolePermissionList == null) { + return Collections.emptyList(); + } + return rolePermissionList; + } +} diff --git a/plugins/acl/dynamic-role-based/pom.xml b/plugins/acl/dynamic-role-based/pom.xml new file mode 100644 index 00000000000..96d7e53d1ce --- /dev/null +++ b/plugins/acl/dynamic-role-based/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + cloud-plugin-acl-dynamic-role-based + Apache CloudStack Plugin - ACL Dynamic Role Based + + org.apache.cloudstack + cloudstack-plugins + 4.9.0-SNAPSHOT + ../../pom.xml + + diff --git a/plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/module.properties b/plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/module.properties new file mode 100644 index 00000000000..dda9998224f --- /dev/null +++ b/plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/module.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +name=acl-dynamic-role-based +parent=api diff --git a/plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/spring-acl-dynamic-role-based-context.xml b/plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/spring-acl-dynamic-role-based-context.xml new file mode 100644 index 00000000000..9ffe465a9aa --- /dev/null +++ b/plugins/acl/dynamic-role-based/resources/META-INF/cloudstack/acl-dynamic-role-based/spring-acl-dynamic-role-based-context.xml @@ -0,0 +1,33 @@ + + + + + + + diff --git a/plugins/acl/dynamic-role-based/src/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java b/plugins/acl/dynamic-role-based/src/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java new file mode 100644 index 00000000000..754d4cc86a5 --- /dev/null +++ b/plugins/acl/dynamic-role-based/src/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessChecker.java @@ -0,0 +1,144 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.acl; + +import com.cloud.exception.PermissionDeniedException; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.User; +import com.cloud.utils.component.AdapterBase; +import com.cloud.utils.component.PluggableService; +import com.google.common.base.Strings; +import org.apache.cloudstack.api.APICommand; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Local(value = APIChecker.class) +public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements APIChecker { + + @Inject + private AccountService accountService; + @Inject + private RoleService roleService; + + private List services; + private Map> annotationRoleBasedApisMap = new HashMap<>(); + + protected DynamicRoleBasedAPIAccessChecker() { + super(); + for (RoleType roleType : RoleType.values()) { + annotationRoleBasedApisMap.put(roleType, new HashSet()); + } + } + + private void denyApiAccess(final String commandName) throws PermissionDeniedException { + throw new PermissionDeniedException("The API does not exist or is blacklisted for the account's role. " + + "The account with is not allowed to request the api: " + commandName); + } + + public boolean isDisabled() { + return !roleService.isEnabled(); + } + + @Override + public boolean checkAccess(User user, String commandName) throws PermissionDeniedException { + if (isDisabled()) { + return true; + } + Account account = accountService.getAccount(user.getAccountId()); + if (account == null) { + throw new PermissionDeniedException("The account id=" + user.getAccountId() + "for user id=" + user.getId() + "is null"); + } + + final Role accountRole = roleService.findRole(account.getRoleId()); + if (accountRole == null || accountRole.getId() < 1L) { + denyApiAccess(commandName); + } + + // Allow all APIs for root admins + if (accountRole.getRoleType() == RoleType.Admin && accountRole.getId() == RoleType.Admin.getId()) { + return true; + } + + // Check against current list of permissions + for (final RolePermission permission : roleService.findAllPermissionsBy(accountRole.getId())) { + if (permission.getRule().matches(commandName)) { + if (RolePermission.Permission.ALLOW.equals(permission.getPermission())) { + return true; + } else { + denyApiAccess(commandName); + } + } + } + + // Check annotations + if (annotationRoleBasedApisMap.get(accountRole.getRoleType()) != null + && annotationRoleBasedApisMap.get(accountRole.getRoleType()).contains(commandName)) { + return true; + } + + // Default deny all + denyApiAccess(commandName); + return false; + } + + public void addApiToRoleBasedAnnotationsMap(final RoleType roleType, final String commandName) { + if (roleType == null || Strings.isNullOrEmpty(commandName)) { + return; + } + final Set commands = annotationRoleBasedApisMap.get(roleType); + if (commands != null && !commands.contains(commandName)) { + commands.add(commandName); + } + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + super.configure(name, params); + return true; + } + + @Override + public boolean start() { + for (PluggableService service : services) { + for (Class clz : service.getCommands()) { + APICommand command = clz.getAnnotation(APICommand.class); + for (RoleType role : command.authorized()) { + addApiToRoleBasedAnnotationsMap(role, command.name()); + } + } + } + return super.start(); + } + + public List getServices() { + return services; + } + + @Inject + public void setServices(List services) { + this.services = services; + } + +} diff --git a/plugins/acl/dynamic-role-based/test/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessCheckerTest.java b/plugins/acl/dynamic-role-based/test/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessCheckerTest.java new file mode 100644 index 00000000000..12ebbe56f5f --- /dev/null +++ b/plugins/acl/dynamic-role-based/test/org/apache/cloudstack/acl/DynamicRoleBasedAPIAccessCheckerTest.java @@ -0,0 +1,164 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.acl; + +import com.cloud.exception.PermissionDeniedException; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.AccountVO; +import com.cloud.user.User; +import com.cloud.user.UserVO; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +import java.lang.reflect.Field; +import java.util.Collections; + +@RunWith(MockitoJUnitRunner.class) +public class DynamicRoleBasedAPIAccessCheckerTest extends TestCase { + + @Mock + private AccountService accountService; + @Mock + private RoleService roleService; + + private DynamicRoleBasedAPIAccessChecker apiAccessChecker; + + private User getTestUser() { + return new UserVO(12L, "some user", "password", "firstName", "lastName", + "email@gmail.com", "GMT", "uuid", User.Source.UNKNOWN); + } + + private Account getTestAccount() { + return new AccountVO("some name", 1L, "network-domain", (short)0, "some-uuid"); + } + + private Role getTestRole() { + return new RoleVO(4L, "SomeRole", RoleType.User, "some description"); + } + + private void setupMockField(final Object obj, final String fieldName, final Object mock) throws NoSuchFieldException, IllegalAccessException { + Field roleDaoField = DynamicRoleBasedAPIAccessChecker.class.getDeclaredField(fieldName); + roleDaoField.setAccessible(true); + roleDaoField.set(obj, mock); + } + + @Override + @Before + public void setUp() throws NoSuchFieldException, IllegalAccessException { + apiAccessChecker = Mockito.spy(new DynamicRoleBasedAPIAccessChecker()); + setupMockField(apiAccessChecker, "accountService", accountService); + setupMockField(apiAccessChecker, "roleService", roleService); + + Mockito.when(accountService.getAccount(Mockito.anyLong())).thenReturn(getTestAccount()); + Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn((RoleVO) getTestRole()); + + // Enabled plugin + Mockito.doReturn(false).when(apiAccessChecker).isDisabled(); + Mockito.doCallRealMethod().when(apiAccessChecker).checkAccess(Mockito.any(User.class), Mockito.anyString()); + } + + @Test + public void testInvalidAccountCheckAccess() { + Mockito.when(accountService.getAccount(Mockito.anyLong())).thenReturn(null); + try { + apiAccessChecker.checkAccess(getTestUser(), "someApi"); + fail("Exception was expected"); + } catch (PermissionDeniedException ignored) { + } + } + + @Test + public void testInvalidAccountRoleCheckAccess() { + Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(null); + try { + apiAccessChecker.checkAccess(getTestUser(), "someApi"); + fail("Exception was expected"); + } catch (PermissionDeniedException ignored) { + } + } + + @Test + public void testDefaultRootAdminAccess() { + Mockito.when(accountService.getAccount(Mockito.anyLong())).thenReturn(new AccountVO("root admin", 1L, null, (short)1, "some-uuid")); + Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO(1L, "SomeRole", RoleType.Admin, "default root admin role")); + assertTrue(apiAccessChecker.checkAccess(getTestUser(), "anyApi")); + } + + @Test + public void testInvalidRolePermissionsCheckAccess() { + Mockito.when(roleService.findAllPermissionsBy(Mockito.anyLong())).thenReturn(Collections.emptyList()); + try { + apiAccessChecker.checkAccess(getTestUser(), "someApi"); + fail("Exception was expected"); + } catch (PermissionDeniedException ignored) { + } + } + + @Test + public void testValidAllowRolePermissionApiCheckAccess() { + final String allowedApiName = "someAllowedApi"; + final RolePermission permission = new RolePermissionVO(1L, allowedApiName, RolePermission.Permission.ALLOW, null); + Mockito.when(roleService.findAllPermissionsBy(Mockito.anyLong())).thenReturn(Collections.singletonList(permission)); + assertTrue(apiAccessChecker.checkAccess(getTestUser(), allowedApiName)); + } + + @Test + public void testValidAllowRolePermissionWildcardCheckAccess() { + final String allowedApiName = "someAllowedApi"; + final RolePermission permission = new RolePermissionVO(1L, "some*", RolePermission.Permission.ALLOW, null); + Mockito.when(roleService.findAllPermissionsBy(Mockito.anyLong())).thenReturn(Collections.singletonList(permission)); + assertTrue(apiAccessChecker.checkAccess(getTestUser(), allowedApiName)); + } + + @Test + public void testValidDenyRolePermissionApiCheckAccess() { + final String denyApiName = "someDeniedApi"; + final RolePermission permission = new RolePermissionVO(1L, denyApiName, RolePermission.Permission.DENY, null); + Mockito.when(roleService.findAllPermissionsBy(Mockito.anyLong())).thenReturn(Collections.singletonList(permission)); + try { + apiAccessChecker.checkAccess(getTestUser(), denyApiName); + fail("Exception was expected"); + } catch (PermissionDeniedException ignored) { + } + } + + @Test + public void testValidDenyRolePermissionWildcardCheckAccess() { + final String denyApiName = "someDenyApi"; + final RolePermission permission = new RolePermissionVO(1L, "*Deny*", RolePermission.Permission.DENY, null); + Mockito.when(roleService.findAllPermissionsBy(Mockito.anyLong())).thenReturn(Collections.singletonList(permission)); + try { + apiAccessChecker.checkAccess(getTestUser(), denyApiName); + fail("Exception was expected"); + } catch (PermissionDeniedException ignored) { + } + } + + @Test + public void testAnnotationFallbackCheckAccess() { + final String allowedApiName = "someApiWithAnnotations"; + apiAccessChecker.addApiToRoleBasedAnnotationsMap(getTestRole().getRoleType(), allowedApiName); + assertTrue(apiAccessChecker.checkAccess(getTestUser(), allowedApiName)); + } + +} \ No newline at end of file diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index 9221ea4c786..fc78268fc62 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -41,18 +41,20 @@ import com.cloud.utils.component.PluggableService; // based on the account type, access is granted public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIChecker { - protected static final Logger s_logger = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); + protected static final Logger LOGGER = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); - Set commandPropertyFiles = new HashSet(); - Set commandsPropertiesOverrides = new HashSet(); - Map> commandsPropertiesRoleBasedApisMap = new HashMap>(); - Map> annotationRoleBasedApisMap = new HashMap>(); + private Set commandPropertyFiles = new HashSet(); + private Set commandsPropertiesOverrides = new HashSet(); + private Map> commandsPropertiesRoleBasedApisMap = new HashMap>(); + private Map> annotationRoleBasedApisMap = new HashMap>(); + private List services; - List _services; @Inject - AccountService _accountService; + private AccountService accountService; + @Inject + private RoleService roleService; - protected StaticRoleBasedAPIAccessChecker() { + public StaticRoleBasedAPIAccessChecker() { super(); for (RoleType roleType : RoleType.values()) { commandsPropertiesRoleBasedApisMap.put(roleType, new HashSet()); @@ -60,23 +62,31 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC } } + public boolean isDisabled() { + return roleService.isEnabled(); + } + @Override public boolean checkAccess(User user, String commandName) throws PermissionDeniedException { - Account account = _accountService.getAccount(user.getAccountId()); + if (isDisabled()) { + return true; + } + + Account account = accountService.getAccount(user.getAccountId()); if (account == null) { throw new PermissionDeniedException("The account id=" + user.getAccountId() + "for user id=" + user.getId() + "is null"); } - RoleType roleType = _accountService.getRoleType(account); + RoleType roleType = accountService.getRoleType(account); boolean isAllowed = commandsPropertiesOverrides.contains(commandName) ? commandsPropertiesRoleBasedApisMap.get(roleType).contains(commandName) : annotationRoleBasedApisMap.get( roleType).contains(commandName); - if (!isAllowed) { - throw new PermissionDeniedException("The API does not exist or is blacklisted. Role type=" + roleType.toString() + " is not allowed to request the api: " + - commandName); + if (isAllowed) { + return true; } - return isAllowed; + + throw new PermissionDeniedException("The API does not exist or is blacklisted. Role type=" + roleType.toString() + " is not allowed to request the api: " + commandName); } @Override @@ -91,7 +101,7 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC @Override public boolean start() { - for (PluggableService service : _services) { + for (PluggableService service : services) { for (Class clz : service.getCommands()) { APICommand command = clz.getAnnotation(APICommand.class); for (RoleType role : command.authorized()) { @@ -112,22 +122,22 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC try { short cmdPermissions = Short.parseShort(roleMask); for (RoleType roleType : RoleType.values()) { - if ((cmdPermissions & roleType.getValue()) != 0) + if ((cmdPermissions & roleType.getMask()) != 0) commandsPropertiesRoleBasedApisMap.get(roleType).add(apiName); } } catch (NumberFormatException nfe) { - s_logger.info("Malformed key=value pair for entry: " + entry.toString()); + LOGGER.info("Malformed key=value pair for entry: " + entry.toString()); } } } public List getServices() { - return _services; + return services; } @Inject public void setServices(List services) { - this._services = services; + this.services = services; } public Set getCommandPropertyFiles() { diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java index be0d5d53260..66d8c5d64e3 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java @@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.discovery; import javax.inject.Inject; +import org.apache.cloudstack.acl.RoleType; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -38,7 +39,7 @@ import com.cloud.user.User; description = "lists all available apis on the server, provided by the Api Discovery plugin", since = "4.1.0", requestHasSensitiveInfo = false, - responseHasSensitiveInfo = false) + responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListApisCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(ListApisCmd.class.getName()); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java index 2451b561bcb..aca756502e8 100644 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java @@ -37,12 +37,13 @@ import com.cloud.user.dao.UserDao; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.vm.VirtualMachineProfile; -import com.google.gson.Gson; -import org.apache.cloudstack.api.AddBaremetalRctCmd; -import org.apache.cloudstack.api.DeleteBaremetalRctCmd; -import org.apache.cloudstack.api.ListBaremetalRctCmd; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachineProfile; +import com.google.gson.Gson; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.AddBaremetalRctCmd; +import org.apache.cloudstack.api.DeleteBaremetalRctCmd; +import org.apache.cloudstack.api.ListBaremetalRctCmd; import org.apache.cloudstack.utils.baremetal.BaremetalUtils; import org.springframework.web.client.RestTemplate; @@ -244,12 +245,14 @@ public class BaremetalVlanManagerImpl extends ManagerBase implements BaremetalVl acnt = new AccountVO(); acnt.setAccountName(BaremetalUtils.BAREMETAL_SYSTEM_ACCOUNT_NAME); - acnt.setUuid(UUID.randomUUID().toString()); - acnt.setState(Account.State.enabled); - acnt.setDomainId(1); - acnt = acntDao.persist(acnt); - - UserVO user = new UserVO(); + acnt.setUuid(UUID.randomUUID().toString()); + acnt.setState(Account.State.enabled); + acnt.setDomainId(1); + acnt.setType(RoleType.User.getAccountType()); + acnt.setRoleId(RoleType.User.getId()); + acnt = acntDao.persist(acnt); + + UserVO user = new UserVO(); user.setState(Account.State.enabled); user.setUuid(UUID.randomUUID().toString()); user.setAccountId(acnt.getAccountId()); diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java index b5da6043352..e56766aaf46 100644 --- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java +++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java @@ -134,14 +134,14 @@ public class MockAccountManager extends ManagerBase implements AccountManager { } @Override - public UserAccount createUserAccount(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5, String arg6, short arg7, Long arg8, String arg9, + public UserAccount createUserAccount(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5, String arg6, short arg7, Long roleId, Long arg8, String arg9, Map arg10, String arg11, String arg12) { // TODO Auto-generated method stub return null; } @Override - public UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, + public UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long roleId, Long domainId, String networkDomain, Map details, String accountUUID, String userUUID, User.Source source) { // TODO Auto-generated method stub return null; @@ -392,8 +392,8 @@ public class MockAccountManager extends ManagerBase implements AccountManager { } @Override - public Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid) { - final AccountVO account = new AccountVO(accountName, domainId, networkDomain, accountType, uuid); + public Account createAccount(String accountName, short accountType, Long roleId, Long domainId, String networkDomain, Map details, String uuid) { + final AccountVO account = new AccountVO(accountName, domainId, networkDomain, accountType, roleId, uuid); Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { diff --git a/plugins/pom.xml b/plugins/pom.xml index bafe299da9c..1a2581972a4 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -50,6 +50,7 @@ api/solidfire-intg-test api/discovery acl/static-role-based + acl/dynamic-role-based affinity-group-processors/host-anti-affinity affinity-group-processors/explicit-dedication deployment-planners/user-concentrated-pod diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java index 1968f85b040..d845857925d 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapCreateAccountCmd.java @@ -16,12 +16,12 @@ // under the License. package org.apache.cloudstack.api.command; -import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.Map; - -import javax.inject.Inject; +import com.cloud.domain.DomainVO; +import com.cloud.user.Account; +import com.cloud.user.AccountService; +import com.cloud.user.User; +import com.cloud.user.UserAccount; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,6 +31,7 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.RoleResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.ldap.LdapManager; import org.apache.cloudstack.ldap.LdapUser; @@ -38,11 +39,11 @@ import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException; import org.apache.log4j.Logger; import org.bouncycastle.util.encoders.Base64; -import com.cloud.domain.DomainVO; -import com.cloud.user.Account; -import com.cloud.user.AccountService; -import com.cloud.user.User; -import com.cloud.user.UserAccount; +import javax.inject.Inject; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Map; @APICommand(name = "ldapCreateAccount", description = "Creates an account from an LDAP user", responseObject = AccountResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class LdapCreateAccountCmd extends BaseCmd { @@ -55,9 +56,12 @@ public class LdapCreateAccountCmd extends BaseCmd { @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.") private String accountName; - @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, required = true, description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin") + @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin") private Short accountType; + @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class, description = "Creates the account under the specified role.") + private Long roleId; + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "Creates the user under the specified domain.") private Long domainId; @@ -92,7 +96,7 @@ public class LdapCreateAccountCmd extends BaseCmd { UserAccount createCloudstackUserAccount(final LdapUser user, String accountName, Long domainId) { Account account = _accountService.getActiveAccountByName(accountName, domainId); if (account == null) { - return _accountService.createUserAccount(username, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, accountType, + return _accountService.createUserAccount(username, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, getAccountType(), getRoleId(), domainId, networkDomain, details, accountUUID, userUUID, User.Source.LDAP); } else { User newUser = _accountService.createUser(username, generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, domainId, @@ -101,6 +105,14 @@ public class LdapCreateAccountCmd extends BaseCmd { } } + public Short getAccountType() { + return RoleType.getAccountTypeByRole(roleService.findRole(roleId), accountType); + } + + public Long getRoleId() { + return RoleType.getRoleByAccountType(roleId, accountType); + } + private String getAccountName() { String name = accountName; if (accountName == null) { @@ -119,6 +131,9 @@ public class LdapCreateAccountCmd extends BaseCmd { @Override public void execute() throws ServerApiException { + if (getAccountType() == null && getRoleId() == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Both account type and role ID are not provided"); + } final CallContext callContext = getCurrentContext(); String finalAccountName = getAccountName(); Long finalDomainId = getDomainId(); diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java index 63549f1111f..9fdd700638c 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LdapImportUsersCmd.java @@ -29,6 +29,7 @@ import javax.inject.Inject; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.user.UserAccount; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -38,6 +39,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.LdapUserResponse; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.RoleResponse; import org.apache.cloudstack.ldap.LdapManager; import org.apache.cloudstack.ldap.LdapUser; import org.apache.cloudstack.ldap.NoLdapUserMatchingQueryException; @@ -70,10 +72,12 @@ public class LdapImportUsersCmd extends BaseListCmd { @Parameter(name = ApiConstants.ACCOUNT_TYPE, type = CommandType.SHORT, - required = true, description = "Type of the account. Specify 0 for user, 1 for root admin, and 2 for domain admin") private Short accountType; + @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class, description = "Creates the account under the specified role.") + private Long roleId; + @Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters") private Map details; @@ -112,7 +116,7 @@ public class LdapImportUsersCmd extends BaseListCmd { Account account = _accountService.getActiveAccountByName(accountName, domain.getId()); if (account == null) { s_logger.debug("No account exists with name: " + accountName + " creating the account and an user with name: " + user.getUsername() + " in the account"); - _accountService.createUserAccount(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, accountType, + _accountService.createUserAccount(user.getUsername(), generatePassword(), user.getFirstname(), user.getLastname(), user.getEmail(), timezone, accountName, getAccountType(), getRoleId(), domain.getId(), domain.getNetworkDomain(), details, UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP); } else { // check if the user exists. if yes, call update @@ -131,7 +135,9 @@ public class LdapImportUsersCmd extends BaseListCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - + if (getAccountType() == null && getRoleId() == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Both account type and role ID are not provided"); + } List users; try { if (StringUtils.isNotBlank(groupName)) { @@ -161,6 +167,14 @@ public class LdapImportUsersCmd extends BaseListCmd { setResponseObject(response); } + public Short getAccountType() { + return RoleType.getAccountTypeByRole(roleService.findRole(roleId), accountType); + } + + public Long getRoleId() { + return RoleType.getRoleByAccountType(roleId, accountType); + } + private String getAccountName(LdapUser user) { String finalAccountName = accountName; if(finalAccountName == null ) { diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java index ae3e7065134..477e80f2556 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/api/command/LinkDomainToLdapCmd.java @@ -23,6 +23,7 @@ import javax.inject.Inject; import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.User; import com.cloud.user.UserAccount; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -82,7 +83,7 @@ public class LinkDomainToLdapCmd extends BaseCmd { if (account == null) { try { UserAccount userAccount = _accountService.createUserAccount(admin, "", ldapUser.getFirstname(), ldapUser.getLastname(), ldapUser.getEmail(), null, - admin, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, domainId, null, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP); + admin, Account.ACCOUNT_TYPE_DOMAIN_ADMIN, RoleType.DomainAdmin.getId(), domainId, null, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP); response.setAdminId(String.valueOf(userAccount.getAccountId())); s_logger.info("created an account with name " + admin + " in the given domain " + domainId); } catch (Exception e) { diff --git a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java index 5683b50a47d..add39c5b13d 100644 --- a/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java +++ b/plugins/user-authenticators/ldap/src/org/apache/cloudstack/ldap/LdapAuthenticator.java @@ -21,6 +21,7 @@ import java.util.UUID; import javax.inject.Inject; +import org.apache.cloudstack.acl.RoleType; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; @@ -119,7 +120,8 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator private void createCloudStackUserAccount(LdapUser user, long domainId, short accountType) { String username = user.getUsername(); - _accountManager.createUserAccount(username, "", user.getFirstname(), user.getLastname(), user.getEmail(), null, username, accountType, domainId, null, null, + _accountManager.createUserAccount(username, "", user.getFirstname(), user.getLastname(), user.getEmail(), null, username, + accountType, RoleType.getByAccountType(accountType).getId(), domainId, null, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), User.Source.LDAP); } diff --git a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy index 514caeb17da..434151ae234 100644 --- a/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy +++ b/plugins/user-authenticators/ldap/test/groovy/org/apache/cloudstack/ldap/LdapImportUsersCmdSpec.groovy @@ -246,7 +246,7 @@ class LdapImportUsersCmdSpec extends spock.lang.Specification { 1 * accountService.getActiveAccountByName('ACCOUNT', 0) >> Mock(AccountVO) 1 * accountService.getActiveUserAccount('rmurphy',0) >> Mock(UserAccountVO) 0 * accountService.createUser('rmurphy', _ , 'Ryan', 'Murphy', 'rmurphy@test.com', null, 'ACCOUNT', 0, _) >> Mock(UserVO) - 0 * accountService.createUserAccount('rmurphy', _, 'Ryan', 'Murphy', 'rmurphy@test.com', null, 'ACCOUNT', 2, 0, 'DOMAIN', null, _, _) + 0 * accountService.createUserAccount('rmurphy', _, 'Ryan', 'Murphy', 'rmurphy@test.com', null, 'ACCOUNT', 2, null, 0, 'DOMAIN', null, _, _) 1 * accountService.updateUser(_,'Ryan', 'Murphy', 'rmurphy@test.com', null, null, null, null, null); def ldapImportUsersCmd = new LdapImportUsersCmd(ldapManager, domainService, accountService) diff --git a/scripts/util/migrate-dynamicroles.py b/scripts/util/migrate-dynamicroles.py new file mode 100755 index 00000000000..e97e94cb252 --- /dev/null +++ b/scripts/util/migrate-dynamicroles.py @@ -0,0 +1,136 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import os +import sys +import uuid + +from contextlib import closing +from optparse import OptionParser + +try: + import MySQLdb +except ImportError: + print("MySQLdb cannot be imported, please install python-mysqldb(apt) or mysql-python(yum)") + sys.exit(1) + +dryrun = False + + +def runSql(conn, query): + if dryrun: + print("Running SQL query: " + query) + return + with closing(conn.cursor()) as cursor: + cursor.execute(query) + + +def migrateApiRolePermissions(apis, conn): + # All allow for root admin role Admin(id:1) + runSql(conn, "INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 1, '*', 'ALLOW', 0);") + # Migrate rules based on commands.properties rule for ResourceAdmin(id:2), DomainAdmin(id:3), User(id:4) + octetKey = {2:2, 3:4, 4:8} + for role in [2, 3, 4]: + sortOrder = 0 + for api in sorted(apis.keys()): + # Ignore auth commands + if api in ['login', 'logout', 'samlSso', 'samlSlo', 'listIdps', 'listAndSwitchSamlAccount', 'getSPMetadata']: + continue + if (octetKey[role] & int(apis[api])) > 0: + runSql(conn, "INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), %d, '%s', 'ALLOW', %d);" % (role, api, sortOrder)) + sortOrder += 1 + + +def main(): + parser = OptionParser() + parser.add_option("-b", "--db", action="store", type="string", dest="db", default="cloud", + help="The name of the database, default: cloud") + parser.add_option("-u", "--user", action="store", type="string", dest="user", default="cloud", + help="User name a MySQL user with privileges on cloud database") + parser.add_option("-p", "--password", action="store", type="string", dest="password", default="cloud", + help="Password of a MySQL user with privileges on cloud database") + parser.add_option("-H", "--host", action="store", type="string", dest="host", default="127.0.0.1", + help="Host or IP of the MySQL server") + parser.add_option("-P", "--port", action="store", type="int", dest="port", default=3306, + help="Host or IP of the MySQL server") + parser.add_option("-f", "--properties-file", action="store", type="string", dest="commandsfile", default="/etc/cloudstack/management/commands.properties", + help="The commands.properties file") + parser.add_option("-d", "--dryrun", action="store_true", dest="dryrun", default=False, + help="Dry run and debug operations this tool will perform") + (options, args) = parser.parse_args() + + print("Apache CloudStack Role Permission Migration Tool") + print("(c) Apache CloudStack Authors and the ASF, under the Apache License, Version 2.0\n") + + global dryrun + if options.dryrun: + dryrun = True + + conn = MySQLdb.connect( + host=options.host, + user=options.user, + passwd=options.password, + port=int(options.port), + db=options.db) + + if not os.path.isfile(options.commandsfile): + print("Provided commands.properties cannot be accessed or does not exist, please check check permissions") + sys.exit(1) + + while True: + choice = raw_input("Running this migration tool will remove any " + + "default-role permissions from cloud.role_permissions. " + + "Do you want to continue? [y/N]").lower() + if choice == 'y': + break + else: + print("Aborting!") + sys.exit(1) + + # Generate API to permission octet map + apiMap = {} + with open(options.commandsfile) as f: + for line in f.readlines(): + if not line or line == '' or line == '\n' or line.startswith('#'): + continue + name, value = line.split('=') + apiMap[name.strip()] = value.strip() + + # Rename and deprecate old commands.properties file + if not dryrun: + os.rename(options.commandsfile, options.commandsfile + '.deprecated') + print("The commands.properties file has been deprecated and moved at: " + options.commandsfile + '.deprecated') + + # Truncate any rules in cloud.role_permissions table + runSql(conn, "DELETE FROM `cloud`.`role_permissions` WHERE `role_id` in (1,2,3,4);") + + # Migrate rules from commands.properties to cloud.role_permissions + migrateApiRolePermissions(apiMap, conn) + print("Static role permissions from commands.properties have been migrated into the db") + + # Enable dynamic role based API checker + runSql(conn, "UPDATE `cloud`.`configuration` SET value='true' where name='dynamic.apichecker.enabled'") + conn.commit() + conn.close() + + print("Dynamic role based API checker has been enabled!") + + +if __name__ == '__main__': + main() diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml index e39d918c9d8..6618e3ee5c8 100644 --- a/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml +++ b/server/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml @@ -37,6 +37,8 @@ value="#{pluggableAPIAuthenticatorsRegistry.registered}" /> + + diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 1c55c674e64..d6b529fa2f0 100644 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -27,6 +27,8 @@ import java.util.Set; import javax.annotation.PostConstruct; import javax.inject.Inject; +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RoleService; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; @@ -423,6 +425,7 @@ public class ApiDBUtils { static AffinityGroupJoinDao s_affinityGroupJoinDao; static GlobalLoadBalancingRulesService s_gslbService; static NetworkACLDao s_networkACLDao; + static RoleService s_roleService; static AccountService s_accountService; static ResourceMetaDataService s_resourceDetailsService; static HostGpuGroupsDao s_hostGpuGroupsDao; @@ -646,6 +649,8 @@ public class ApiDBUtils { @Inject private NetworkACLDao networkACLDao; @Inject + private RoleService roleService; + @Inject private AccountService accountService; @Inject private ConfigurationManager configMgr; @@ -768,6 +773,7 @@ public class ApiDBUtils { // Note: stats collector should already have been initialized by this time, otherwise a null instance is returned s_statsCollector = StatsCollector.getInstance(); s_networkACLDao = networkACLDao; + s_roleService = roleService; s_accountService = accountService; s_resourceDetailsService = resourceDetailsService; s_hostGpuGroupsDao = hostGpuGroupsDao; @@ -1695,6 +1701,15 @@ public class ApiDBUtils { public static UserResponse newUserResponse(UserAccountJoinVO usr, Long domainId) { UserResponse response = s_userAccountJoinDao.newUserResponse(usr); + // Populate user account role information + if (usr.getAccountRoleId() != null) { + Role role = s_roleService.findRole( usr.getAccountRoleId()); + if (role != null) { + response.setRoleId(role.getUuid()); + response.setRoleType(role.getRoleType()); + response.setRoleName(role.getName()); + } + } if (domainId != null && usr.getDomainId() != domainId) response.setIsCallerChildDomain(true); else @@ -1820,7 +1835,17 @@ public class ApiDBUtils { } public static AccountResponse newAccountResponse(ResponseView view, AccountJoinVO ve) { - return s_accountJoinDao.newAccountResponse(view, ve); + AccountResponse response = s_accountJoinDao.newAccountResponse(view, ve); + // Populate account role information + if (ve.getRoleId() != null) { + Role role = s_roleService.findRole(ve.getRoleId()); + if (role != null) { + response.setRoleId(role.getUuid()); + response.setRoleType(role.getRoleType()); + response.setRoleName(role.getName()); + } + } + return response; } public static AccountJoinVO newAccountView(Account e) { diff --git a/server/src/com/cloud/api/ApiResponseGsonHelper.java b/server/src/com/cloud/api/ApiResponseGsonHelper.java index 1708fa764d7..19db96ae36c 100644 --- a/server/src/com/cloud/api/ApiResponseGsonHelper.java +++ b/server/src/com/cloud/api/ApiResponseGsonHelper.java @@ -68,7 +68,7 @@ public class ApiResponseGsonHelper { boolean permittedParameter = false; Account caller = CallContext.current().getCallingAccount(); for (RoleType allowedRole : allowedRoles) { - if (allowedRole.getValue() == caller.getType()) { + if (allowedRole.getAccountType() == caller.getType()) { permittedParameter = true; break; } diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 6ec2f18e774..d7da425b7ab 100644 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -797,15 +797,15 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer s_logger.debug(ex.getMessage()); throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage()); } catch (final PermissionDeniedException ex) { - s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); - throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user"); + s_logger.debug("The user with id:" + userId + " is not allowed to request the API command or the API command does not exist: " + commandName); + throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The user is not allowed to request the API command or the API command does not exist"); } return true; } else { // check against every available command to see if the command exists or not if (!s_apiNameCmdClassMap.containsKey(commandName) && !commandName.equals("login") && !commandName.equals("logout")) { - s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user with id:" + userId); - throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The given command does not exist or it is not available for user"); + s_logger.debug("The user with id:" + userId + " is not allowed to request the API command or the API command does not exist: " + commandName); + throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The user is not allowed to request the API command or the API command does not exist"); } } diff --git a/server/src/com/cloud/api/query/vo/AccountJoinVO.java b/server/src/com/cloud/api/query/vo/AccountJoinVO.java index 8d642edd7cf..f251abc4726 100644 --- a/server/src/com/cloud/api/query/vo/AccountJoinVO.java +++ b/server/src/com/cloud/api/query/vo/AccountJoinVO.java @@ -48,6 +48,9 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident @Column(name = "type") private short type; + @Column(name = "role_id") + private Long roleId; + @Column(name = "state") @Enumerated(value = EnumType.STRING) private State state; @@ -202,6 +205,10 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident return type; } + public Long getRoleId() { + return roleId; + } + public State getState() { return state; } diff --git a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java index 0e66ca022c5..e6b1ace0966 100644 --- a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java +++ b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java @@ -96,6 +96,9 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I @Column(name = "account_type") private short accountType; + @Column(name = "account_role_id") + private Long accountRoleId; + @Column(name = "domain_id") private long domainId; @@ -149,6 +152,10 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I return accountType; } + public Long getAccountRoleId() { + return accountRoleId; + } + public long getDomainId() { return domainId; } diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java b/server/src/com/cloud/api/response/ApiResponseSerializer.java index 59426e65742..2b9717de1e2 100644 --- a/server/src/com/cloud/api/response/ApiResponseSerializer.java +++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java @@ -251,7 +251,7 @@ public class ApiResponseSerializer { boolean permittedParameter = false; Account caller = CallContext.current().getCallingAccount(); for (RoleType allowedRole : allowedRoles) { - if (allowedRole.getValue() == caller.getType()) { + if (allowedRole.getAccountType() == caller.getType()) { permittedParameter = true; break; } diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index ee6650698c3..a8dd225c54c 100644 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -211,7 +211,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { StringBuilder acctNm = new StringBuilder("PrjAcct-"); acctNm.append(name).append("-").append(ownerFinal.getDomainId()); - Account projectAccount = _accountMgr.createAccount(acctNm.toString(), Account.ACCOUNT_TYPE_PROJECT, domainId, null, null, UUID.randomUUID().toString()); + Account projectAccount = _accountMgr.createAccount(acctNm.toString(), Account.ACCOUNT_TYPE_PROJECT, null, domainId, null, null, UUID.randomUUID().toString()); Project project = _projectDao.persist(new ProjectVO(name, displayText, ownerFinal.getDomainId(), projectAccount.getId())); diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 16e4ff05902..13f98a2f488 100644 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -449,7 +449,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio public void doInTransactionWithoutResult(TransactionStatus status) { TransactionLegacy txn = TransactionLegacy.currentTxn(); // insert system account - String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (1, UUID(), 'system', '1', '1', 1)"; + String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, role_id, domain_id, account.default) VALUES (1, UUID(), 'system', '1', '1', '1', 1)"; try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); @@ -476,8 +476,8 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio String lastname = "cloud"; // create an account for the admin user first - insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (" + id + ", UUID(), '" + username - + "', '1', '1', 1)"; + insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, role_id, domain_id, account.default) VALUES (" + id + ", UUID(), '" + username + + "', '1', '1', '1', 1)"; try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); stmt.executeUpdate(); diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java index 7b9e0936bb9..9789a223296 100644 --- a/server/src/com/cloud/user/AccountManager.java +++ b/server/src/com/cloud/user/AccountManager.java @@ -50,7 +50,7 @@ public interface AccountManager extends AccountService { Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId); - Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid); + Account createAccount(String accountName, short accountType, Long roleId, Long domainId, String networkDomain, Map details, String uuid); /** * Logs out a user diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index d3eb40c7db6..7e80681caa2 100644 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -994,9 +994,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User") }) public UserAccount createUserAccount(final String userName, final String password, final String firstName, final String lastName, final String email, final String timezone, - String accountName, final short accountType, Long domainId, final String networkDomain, final Map details, String accountUUID, final String userUUID) { + String accountName, final short accountType, final Long roleId, Long domainId, final String networkDomain, final Map details, String accountUUID, final String userUUID) { - return createUserAccount(userName, password, firstName, lastName, email, timezone, accountName, accountType, domainId, networkDomain, details, accountUUID, userUUID, + return createUserAccount(userName, password, firstName, lastName, email, timezone, accountName, accountType, roleId, domainId, networkDomain, details, accountUUID, userUUID, User.Source.UNKNOWN); } @@ -1011,7 +1011,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User") }) public UserAccount createUserAccount(final String userName, final String password, final String firstName, final String lastName, final String email, - final String timezone, String accountName, final short accountType, Long domainId, final String networkDomain, final Map details, + final String timezone, String accountName, final short accountType, final Long roleId, Long domainId, final String networkDomain, final Map details, String accountUUID, final String userUUID, final User.Source source) { if (accountName == null) { @@ -1065,7 +1065,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M if (accountUUID == null) { accountUUID = UUID.randomUUID().toString(); } - AccountVO account = createAccount(accountNameFinal, accountType, domainIdFinal, networkDomain, details, accountUUID); + AccountVO account = createAccount(accountNameFinal, accountType, roleId, domainIdFinal, networkDomain, details, accountUUID); long accountId = account.getId(); // create the first user for the account @@ -1869,27 +1869,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Override public RoleType getRoleType(Account account) { - RoleType roleType = RoleType.Unknown; - if (account == null) - return roleType; - short accountType = account.getType(); - - // Account type to role type translation - switch (accountType) { - case Account.ACCOUNT_TYPE_ADMIN: - roleType = RoleType.Admin; - break; - case Account.ACCOUNT_TYPE_DOMAIN_ADMIN: - roleType = RoleType.DomainAdmin; - break; - case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN: - roleType = RoleType.ResourceAdmin; - break; - case Account.ACCOUNT_TYPE_NORMAL: - roleType = RoleType.User; - break; + if (account == null) { + return RoleType.Unknown; } - return roleType; + return RoleType.getByAccountType(account.getType()); } @Override @@ -1916,7 +1899,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Override @DB - public AccountVO createAccount(final String accountName, final short accountType, final Long domainId, final String networkDomain, final Map details, + public AccountVO createAccount(final String accountName, final short accountType, final Long roleId, final Long domainId, final String networkDomain, final Map details, final String uuid) { // Validate domain Domain domain = _domainMgr.getDomain(domainId); @@ -1929,7 +1912,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } if ((domainId != Domain.ROOT_DOMAIN) && (accountType == Account.ACCOUNT_TYPE_ADMIN)) { - throw new InvalidParameterValueException("Invalid account type " + accountType + " given for an account in domain " + domainId + "; unable to create user."); + throw new InvalidParameterValueException("Invalid account type " + accountType + " given for an account in domain " + domainId + "; unable to create user of admin role type in non-ROOT domain."); } // Validate account/user/domain settings @@ -1961,7 +1944,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return Transaction.execute(new TransactionCallback() { @Override public AccountVO doInTransaction(TransactionStatus status) { - AccountVO account = _accountDao.persist(new AccountVO(accountName, domainId, networkDomain, accountType, uuid)); + AccountVO account = _accountDao.persist(new AccountVO(accountName, domainId, networkDomain, accountType, roleId, uuid)); if (account == null) { throw new CloudRuntimeException("Failed to create account name " + accountName + " in domain id=" + domainId); diff --git a/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java new file mode 100644 index 00000000000..7363b13b35a --- /dev/null +++ b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java @@ -0,0 +1,264 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.acl; + +import com.cloud.event.ActionEvent; +import com.cloud.event.EventTypes; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.user.Account; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.ListUtils; +import com.cloud.utils.PropertiesUtil; +import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.component.PluggableService; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionCallback; +import com.cloud.utils.db.TransactionStatus; +import com.google.common.base.Strings; +import org.apache.cloudstack.acl.dao.RoleDao; +import org.apache.cloudstack.acl.dao.RolePermissionsDao; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.acl.CreateRoleCmd; +import org.apache.cloudstack.api.command.admin.acl.CreateRolePermissionCmd; +import org.apache.cloudstack.api.command.admin.acl.DeleteRoleCmd; +import org.apache.cloudstack.api.command.admin.acl.DeleteRolePermissionCmd; +import org.apache.cloudstack.api.command.admin.acl.ListRolePermissionsCmd; +import org.apache.cloudstack.api.command.admin.acl.ListRolesCmd; +import org.apache.cloudstack.api.command.admin.acl.UpdateRoleCmd; +import org.apache.cloudstack.api.command.admin.acl.UpdateRolePermissionCmd; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Local(value = {RoleService.class}) +public class RoleManagerImpl extends ManagerBase implements RoleService, Configurable, PluggableService { + @Inject + private AccountDao accountDao; + @Inject + private RoleDao roleDao; + @Inject + private RolePermissionsDao rolePermissionsDao; + + private void checkCallerAccess() { + if (!isEnabled()) { + throw new PermissionDeniedException("Dynamic api checker is not enabled, aborting role operation"); + } + Account caller = CallContext.current().getCallingAccount(); + if (caller == null || caller.getRoleId() == null) { + throw new PermissionDeniedException("Restricted API called by an invalid user account"); + } + Role callerRole = findRole(caller.getRoleId()); + if (callerRole == null || callerRole.getRoleType() != RoleType.Admin) { + throw new PermissionDeniedException("Restricted API called by an user account of non-Admin role type"); + } + } + + @Override + public boolean isEnabled() { + File apiCmdFile = PropertiesUtil.findConfigFile(PropertiesUtil.getDefaultApiCommandsFileName()); + return RoleService.EnableDynamicApiChecker.value() && (apiCmdFile == null || !apiCmdFile.exists()); + } + + @Override + public Role findRole(final Long id) { + if (id == null || id < 1L) { + return null; + } + return roleDao.findById(id); + } + + @Override + public RolePermission findRolePermission(final Long id) { + if (id == null) { + return null; + } + return rolePermissionsDao.findById(id); + } + + @Override + public RolePermission findRolePermissionByUuid(final String uuid) { + if (Strings.isNullOrEmpty(uuid)) { + return null; + } + return rolePermissionsDao.findByUuid(uuid); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_ROLE_CREATE, eventDescription = "creating Role") + public Role createRole(final String name, final RoleType roleType, final String description) { + checkCallerAccess(); + if (roleType == null || roleType == RoleType.Unknown) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid role type provided"); + } + return Transaction.execute(new TransactionCallback() { + @Override + public RoleVO doInTransaction(TransactionStatus status) { + return roleDao.persist(new RoleVO(name, roleType, description)); + } + }); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_ROLE_UPDATE, eventDescription = "updating Role") + public boolean updateRole(final Role role, final String name, final RoleType roleType, final String description) { + checkCallerAccess(); + if (role == null) { + return false; + } + if (roleType != null && roleType == RoleType.Unknown) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unknown is not a valid role type"); + } + RoleVO roleVO = (RoleVO) role; + if (!Strings.isNullOrEmpty(name)) { + roleVO.setName(name); + } + if (roleType != null) { + if (role.getId() <= RoleType.User.getId()) { + throw new PermissionDeniedException("The role type of default roles cannot be changed"); + } + List accounts = accountDao.findAccountsByRole(role.getId()); + if (accounts == null || accounts.isEmpty()) { + roleVO.setRoleType(roleType); + } else { + throw new PermissionDeniedException("Found accounts that have role in use, won't allow to change role type"); + } + } + if (!Strings.isNullOrEmpty(description)) { + roleVO.setDescription(description); + } + return roleDao.update(role.getId(), roleVO); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_ROLE_DELETE, eventDescription = "deleting Role") + public boolean deleteRole(final Role role) { + checkCallerAccess(); + if (role == null) { + return false; + } + if (role.getId() <= RoleType.User.getId()) { + throw new PermissionDeniedException("Default roles cannot be deleted"); + } + List accounts = accountDao.findAccountsByRole(role.getId()); + if (accounts == null || accounts.size() == 0) { + return Transaction.execute(new TransactionCallback() { + @Override + public Boolean doInTransaction(TransactionStatus status) { + List rolePermissions = rolePermissionsDao.findAllByRoleIdSorted(role.getId()); + if (rolePermissions != null && !rolePermissions.isEmpty()) { + for (RolePermission rolePermission : rolePermissions) { + rolePermissionsDao.remove(rolePermission.getId()); + } + } + return roleDao.remove(role.getId()); + } + }); + } + throw new PermissionDeniedException("Found accounts that have role in use, won't allow to delete role"); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_CREATE, eventDescription = "creating Role Permission") + public RolePermission createRolePermission(final Role role, final Rule rule, final RolePermission.Permission permission, final String description) { + checkCallerAccess(); + return Transaction.execute(new TransactionCallback() { + @Override + public RolePermissionVO doInTransaction(TransactionStatus status) { + return rolePermissionsDao.persist(new RolePermissionVO(role.getId(), rule.toString(), permission, description)); + } + }); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_UPDATE, eventDescription = "updating Role Permission order") + public boolean updateRolePermission(final Role role, final List newOrder) { + checkCallerAccess(); + return role != null && newOrder != null && rolePermissionsDao.update(role, newOrder); + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_DELETE, eventDescription = "deleting Role Permission") + public boolean deleteRolePermission(final RolePermission rolePermission) { + checkCallerAccess(); + return rolePermission != null && rolePermissionsDao.remove(rolePermission.getId()); + } + + @Override + public List findRolesByName(final String name) { + List roles = null; + if (!Strings.isNullOrEmpty(name)) { + roles = roleDao.findAllByName(name); + } + return ListUtils.toListOfInterface(roles); + } + + @Override + public List findRolesByType(final RoleType roleType) { + List roles = null; + if (roleType != null) { + roles = roleDao.findAllByRoleType(roleType); + } + return ListUtils.toListOfInterface(roles); + } + + @Override + public List listRoles() { + List roles = roleDao.listAll(); + return ListUtils.toListOfInterface(roles); + } + + @Override + public List findAllPermissionsBy(final Long roleId) { + List permissions = rolePermissionsDao.findAllByRoleIdSorted(roleId); + if (permissions != null) { + return new ArrayList<>(permissions); + } + return Collections.emptyList(); + } + + @Override + public String getConfigComponentName() { + return RoleService.class.getSimpleName(); + } + + @Override + public ConfigKey[] getConfigKeys() { + return new ConfigKey[]{RoleService.EnableDynamicApiChecker}; + } + + @Override + public List> getCommands() { + final List> cmdList = new ArrayList<>(); + cmdList.add(CreateRoleCmd.class); + cmdList.add(ListRolesCmd.class); + cmdList.add(UpdateRoleCmd.class); + cmdList.add(DeleteRoleCmd.class); + cmdList.add(CreateRolePermissionCmd.class); + cmdList.add(ListRolePermissionsCmd.class); + cmdList.add(UpdateRolePermissionCmd.class); + cmdList.add(DeleteRolePermissionCmd.class); + return cmdList; + } + } diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index 3971fd6b4fc..fd851672255 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -328,13 +328,13 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco @Override public UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, - short accountType, Long domainId, String networkDomain, Map details, String accountUUID, String userUUID) { + short accountType, Long roleId, Long domainId, String networkDomain, Map details, String accountUUID, String userUUID) { // TODO Auto-generated method stub return null; } @Override - public UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, + public UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long roleId, Long domainId, String networkDomain, Map details, String accountUUID, String userUUID, User.Source source) { // TODO Auto-generated method stub return null; @@ -366,7 +366,7 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco } @Override - public Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid) { + public Account createAccount(String accountName, short accountType, Long roleId, Long domainId, String networkDomain, Map details, String uuid) { // TODO Auto-generated method stub return null; } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java index 634ce0a2e02..3072b77a5cd 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java @@ -196,7 +196,7 @@ public class RoleBasedAPIAccessChecker extends AdapterBase implements APIChecker try { short cmdPermissions = Short.parseShort(roleMask); for (RoleType roleType : RoleType.values()) { - if ((cmdPermissions & roleType.getValue()) != 0) + if ((cmdPermissions & roleType.getMask()) != 0) commandsPropertiesRoleBasedApisMap.get(roleType).add(apiName); } } catch (NumberFormatException nfe) { diff --git a/setup/db/db/create-default-role-api-mappings.sql b/setup/db/db/create-default-role-api-mappings.sql new file mode 100644 index 00000000000..57601fbde17 --- /dev/null +++ b/setup/db/db/create-default-role-api-mappings.sql @@ -0,0 +1,902 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + +-- The default admin role (id:1) will be allowed all APIs so need to insert rules for admin role + +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 1, '*', 'ALLOW', 0) ON DUPLICATE KEY UPDATE rule=rule; + +-- Insert default role-api mappings for rest of the default roles: resourceadmin(id:2), domainadmin(id:3), user(id:4) +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'activateProject', 'ALLOW', 0) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'addAccountToProject', 'ALLOW', 1) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'addHost', 'ALLOW', 2) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'addIpToNic', 'ALLOW', 3) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'addLdapConfiguration', 'ALLOW', 4) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'addNicToVirtualMachine', 'ALLOW', 5) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'addVpnUser', 'ALLOW', 6) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'archiveEvents', 'ALLOW', 7) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'assignCertToLoadBalancer', 'ALLOW', 8) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'assignToGlobalLoadBalancerRule', 'ALLOW', 9) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'assignToLoadBalancerRule', 'ALLOW', 10) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'assignVirtualMachine', 'ALLOW', 11) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'associateIpAddress', 'ALLOW', 12) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'associateLun', 'ALLOW', 13) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'attachIso', 'ALLOW', 14) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'attachVolume', 'ALLOW', 15) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'authorizeSamlSso', 'ALLOW', 16) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'authorizeSecurityGroupEgress', 'ALLOW', 17) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'authorizeSecurityGroupIngress', 'ALLOW', 18) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'changeServiceForRouter', 'ALLOW', 19) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'changeServiceForVirtualMachine', 'ALLOW', 20) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'configureInternalLoadBalancerElement', 'ALLOW', 21) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'configureOvsElement', 'ALLOW', 22) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'configureVirtualRouterElement', 'ALLOW', 23) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'copyIso', 'ALLOW', 24) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'copyTemplate', 'ALLOW', 25) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createAccount', 'ALLOW', 26) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createAffinityGroup', 'ALLOW', 27) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createAutoScalePolicy', 'ALLOW', 28) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createAutoScaleVmGroup', 'ALLOW', 29) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createAutoScaleVmProfile', 'ALLOW', 30) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createCondition', 'ALLOW', 31) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createDiskOffering', 'ALLOW', 32) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createEgressFirewallRule', 'ALLOW', 33) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createFirewallRule', 'ALLOW', 34) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createGlobalLoadBalancerRule', 'ALLOW', 35) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createInstanceGroup', 'ALLOW', 36) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createInternalLoadBalancerElement', 'ALLOW', 37) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createIpForwardingRule', 'ALLOW', 38) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createLBHealthCheckPolicy', 'ALLOW', 39) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createLBStickinessPolicy', 'ALLOW', 40) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createLoadBalancer', 'ALLOW', 41) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createLoadBalancerRule', 'ALLOW', 42) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createLunOnFiler', 'ALLOW', 43) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createNetwork', 'ALLOW', 44) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createNetworkACL', 'ALLOW', 45) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createNetworkACLList', 'ALLOW', 46) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createOvsElement', 'ALLOW', 47) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createPool', 'ALLOW', 48) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createPortForwardingRule', 'ALLOW', 49) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createProject', 'ALLOW', 50) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createRemoteAccessVpn', 'ALLOW', 51) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createSSHKeyPair', 'ALLOW', 52) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createSecurityGroup', 'ALLOW', 53) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createServiceOffering', 'ALLOW', 54) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createSnapshot', 'ALLOW', 55) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createSnapshotPolicy', 'ALLOW', 56) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createStaticRoute', 'ALLOW', 57) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createTags', 'ALLOW', 58) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createTemplate', 'ALLOW', 59) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createUser', 'ALLOW', 60) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVMSnapshot', 'ALLOW', 61) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVPC', 'ALLOW', 62) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVirtualRouterElement', 'ALLOW', 63) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVolume', 'ALLOW', 64) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVolumeOnFiler', 'ALLOW', 65) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVpnConnection', 'ALLOW', 66) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVpnCustomerGateway', 'ALLOW', 67) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'createVpnGateway', 'ALLOW', 68) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteAccount', 'ALLOW', 69) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteAccountFromProject', 'ALLOW', 70) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteAffinityGroup', 'ALLOW', 71) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteAutoScalePolicy', 'ALLOW', 72) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteAutoScaleVmGroup', 'ALLOW', 73) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteAutoScaleVmProfile', 'ALLOW', 74) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteCondition', 'ALLOW', 75) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteDiskOffering', 'ALLOW', 76) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteEgressFirewallRule', 'ALLOW', 77) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteEvents', 'ALLOW', 78) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteFirewallRule', 'ALLOW', 79) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteGlobalLoadBalancerRule', 'ALLOW', 80) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteHost', 'ALLOW', 81) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteInstanceGroup', 'ALLOW', 82) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteIpForwardingRule', 'ALLOW', 83) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteIso', 'ALLOW', 84) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteLBHealthCheckPolicy', 'ALLOW', 85) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteLBStickinessPolicy', 'ALLOW', 86) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteLdapConfiguration', 'ALLOW', 87) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteLoadBalancer', 'ALLOW', 88) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteLoadBalancerRule', 'ALLOW', 89) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteNetwork', 'ALLOW', 90) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteNetworkACL', 'ALLOW', 91) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteNetworkACLList', 'ALLOW', 92) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deletePool', 'ALLOW', 93) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deletePortForwardingRule', 'ALLOW', 94) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteProject', 'ALLOW', 95) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteProjectInvitation', 'ALLOW', 96) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteRemoteAccessVpn', 'ALLOW', 97) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteSSHKeyPair', 'ALLOW', 98) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteSecurityGroup', 'ALLOW', 99) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteServiceOffering', 'ALLOW', 100) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteSnapshot', 'ALLOW', 101) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteSnapshotPolicies', 'ALLOW', 102) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteSslCert', 'ALLOW', 103) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteStaticRoute', 'ALLOW', 104) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteTags', 'ALLOW', 105) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteTemplate', 'ALLOW', 106) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteUser', 'ALLOW', 107) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteVMSnapshot', 'ALLOW', 108) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteVPC', 'ALLOW', 109) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteVolume', 'ALLOW', 110) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteVpnConnection', 'ALLOW', 111) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteVpnCustomerGateway', 'ALLOW', 112) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deleteVpnGateway', 'ALLOW', 113) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'deployVirtualMachine', 'ALLOW', 114) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'destroyLunOnFiler', 'ALLOW', 115) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'destroyRouter', 'ALLOW', 116) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'destroyVirtualMachine', 'ALLOW', 117) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'destroyVolumeOnFiler', 'ALLOW', 118) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'detachIso', 'ALLOW', 119) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'detachVolume', 'ALLOW', 120) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'disableAccount', 'ALLOW', 121) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'disableAutoScaleVmGroup', 'ALLOW', 122) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'disableStaticNat', 'ALLOW', 123) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'disableUser', 'ALLOW', 124) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'disassociateIpAddress', 'ALLOW', 125) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'dissociateLun', 'ALLOW', 126) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'enableAccount', 'ALLOW', 127) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'enableAutoScaleVmGroup', 'ALLOW', 128) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'enableStaticNat', 'ALLOW', 129) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'enableUser', 'ALLOW', 130) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'expungeVirtualMachine', 'ALLOW', 131) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'extractIso', 'ALLOW', 132) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'extractTemplate', 'ALLOW', 133) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'extractVolume', 'ALLOW', 134) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getApiLimit', 'ALLOW', 135) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getCloudIdentifier', 'ALLOW', 136) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getSolidFireAccountId', 'ALLOW', 137) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getSolidFireVolumeAccessGroupId', 'ALLOW', 138) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getSolidFireVolumeIscsiName', 'ALLOW', 139) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getSolidFireVolumeSize', 'ALLOW', 140) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getUploadParamsForTemplate', 'ALLOW', 141) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getUploadParamsForVolume', 'ALLOW', 142) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getVMPassword', 'ALLOW', 143) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'getVirtualMachineUserData', 'ALLOW', 144) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'importLdapUsers', 'ALLOW', 145) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'issueNuageVspResourceRequest', 'ALLOW', 146) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'ldapCreateAccount', 'ALLOW', 147) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'linkDomainToLdap', 'ALLOW', 148) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAccounts', 'ALLOW', 149) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAffinityGroupTypes', 'ALLOW', 150) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAffinityGroups', 'ALLOW', 151) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAlerts', 'ALLOW', 152) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listApis', 'ALLOW', 153) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAsyncJobs', 'ALLOW', 154) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAutoScalePolicies', 'ALLOW', 155) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAutoScaleVmGroups', 'ALLOW', 156) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listAutoScaleVmProfiles', 'ALLOW', 157) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listCapabilities', 'ALLOW', 158) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listCapacity', 'ALLOW', 159) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listClusters', 'ALLOW', 160) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listConditions', 'ALLOW', 161) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listCounters', 'ALLOW', 162) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listDiskOfferings', 'ALLOW', 163) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listDomainChildren', 'ALLOW', 164) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listDomains', 'ALLOW', 165) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listEgressFirewallRules', 'ALLOW', 166) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listEventTypes', 'ALLOW', 167) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listEvents', 'ALLOW', 168) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listFirewallRules', 'ALLOW', 169) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listGlobalLoadBalancerRules', 'ALLOW', 170) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listHostTags', 'ALLOW', 171) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listHosts', 'ALLOW', 172) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listHypervisors', 'ALLOW', 173) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listInstanceGroups', 'ALLOW', 174) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listInternalLoadBalancerElements', 'ALLOW', 175) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listIpForwardingRules', 'ALLOW', 176) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listIsoPermissions', 'ALLOW', 177) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listIsos', 'ALLOW', 178) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLBHealthCheckPolicies', 'ALLOW', 179) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLBStickinessPolicies', 'ALLOW', 180) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLdapConfigurations', 'ALLOW', 181) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLdapUsers', 'ALLOW', 182) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLoadBalancerRuleInstances', 'ALLOW', 183) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLoadBalancerRules', 'ALLOW', 184) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLoadBalancers', 'ALLOW', 185) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listLunsOnFiler', 'ALLOW', 186) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listNetworkACLLists', 'ALLOW', 187) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listNetworkACLs', 'ALLOW', 188) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listNetworkOfferings', 'ALLOW', 189) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listNetworks', 'ALLOW', 190) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listNics', 'ALLOW', 191) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listOsCategories', 'ALLOW', 192) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listOsTypes', 'ALLOW', 193) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listOvsElements', 'ALLOW', 194) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listPods', 'ALLOW', 195) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listPools', 'ALLOW', 196) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listPortForwardingRules', 'ALLOW', 197) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listPrivateGateways', 'ALLOW', 198) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listProjectAccounts', 'ALLOW', 199) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listProjectInvitations', 'ALLOW', 200) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listProjects', 'ALLOW', 201) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listPublicIpAddresses', 'ALLOW', 202) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listRegions', 'ALLOW', 203) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listRemoteAccessVpns', 'ALLOW', 204) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listResourceDetails', 'ALLOW', 205) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listResourceLimits', 'ALLOW', 206) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listRouters', 'ALLOW', 207) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listSSHKeyPairs', 'ALLOW', 208) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listSamlAuthorization', 'ALLOW', 209) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listSecurityGroups', 'ALLOW', 210) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listServiceOfferings', 'ALLOW', 211) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listSnapshotPolicies', 'ALLOW', 212) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listSnapshots', 'ALLOW', 213) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listSslCerts', 'ALLOW', 214) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listStaticRoutes', 'ALLOW', 215) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listStoragePools', 'ALLOW', 216) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listStorageProviders', 'ALLOW', 217) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listStorageTags', 'ALLOW', 218) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listSystemVms', 'ALLOW', 219) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listTags', 'ALLOW', 220) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listTemplatePermissions', 'ALLOW', 221) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listTemplates', 'ALLOW', 222) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listUsageRecords', 'ALLOW', 223) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listUsers', 'ALLOW', 224) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVMSnapshot', 'ALLOW', 225) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVPCOfferings', 'ALLOW', 226) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVPCs', 'ALLOW', 227) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVirtualMachines', 'ALLOW', 228) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVirtualRouterElements', 'ALLOW', 229) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVolumes', 'ALLOW', 230) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVolumesOnFiler', 'ALLOW', 231) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVpnConnections', 'ALLOW', 232) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVpnCustomerGateways', 'ALLOW', 233) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVpnGateways', 'ALLOW', 234) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listVpnUsers', 'ALLOW', 235) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'listZones', 'ALLOW', 236) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'lockAccount', 'ALLOW', 237) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'lockUser', 'ALLOW', 238) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'migrateVolume', 'ALLOW', 239) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'modifyPool', 'ALLOW', 240) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'queryAsyncJobResult', 'ALLOW', 241) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'quotaBalance', 'ALLOW', 242) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'quotaIsEnabled', 'ALLOW', 243) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'quotaStatement', 'ALLOW', 244) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'quotaSummary', 'ALLOW', 245) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'quotaTariffList', 'ALLOW', 246) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'rebootRouter', 'ALLOW', 247) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'rebootVirtualMachine', 'ALLOW', 248) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'recoverVirtualMachine', 'ALLOW', 249) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'registerIso', 'ALLOW', 250) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'registerSSHKeyPair', 'ALLOW', 251) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'registerTemplate', 'ALLOW', 252) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'registerUserKeys', 'ALLOW', 253) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'removeCertFromLoadBalancer', 'ALLOW', 254) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'removeFromGlobalLoadBalancerRule', 'ALLOW', 255) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'removeFromLoadBalancerRule', 'ALLOW', 256) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'removeIpFromNic', 'ALLOW', 257) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'removeNicFromVirtualMachine', 'ALLOW', 258) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'removeVpnUser', 'ALLOW', 259) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'replaceNetworkACLList', 'ALLOW', 260) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'resetPasswordForVirtualMachine', 'ALLOW', 261) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'resetSSHKeyForVirtualMachine', 'ALLOW', 262) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'resetVpnConnection', 'ALLOW', 263) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'resizeVolume', 'ALLOW', 264) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'restartNetwork', 'ALLOW', 265) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'restartVPC', 'ALLOW', 266) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'restoreVirtualMachine', 'ALLOW', 267) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'revertSnapshot', 'ALLOW', 268) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'revertToVMSnapshot', 'ALLOW', 269) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'revokeSecurityGroupEgress', 'ALLOW', 270) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'revokeSecurityGroupIngress', 'ALLOW', 271) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'scaleVirtualMachine', 'ALLOW', 272) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'startRouter', 'ALLOW', 273) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'startVirtualMachine', 'ALLOW', 274) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'stopRouter', 'ALLOW', 275) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'stopVirtualMachine', 'ALLOW', 276) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'suspendProject', 'ALLOW', 277) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateAccount', 'ALLOW', 278) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateAutoScalePolicy', 'ALLOW', 279) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateAutoScaleVmGroup', 'ALLOW', 280) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateAutoScaleVmProfile', 'ALLOW', 281) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateDefaultNicForVirtualMachine', 'ALLOW', 282) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateDiskOffering', 'ALLOW', 283) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateEgressFirewallRule', 'ALLOW', 284) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateFirewallRule', 'ALLOW', 285) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateGlobalLoadBalancerRule', 'ALLOW', 286) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateInstanceGroup', 'ALLOW', 287) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateIpAddress', 'ALLOW', 288) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateIso', 'ALLOW', 289) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateIsoPermissions', 'ALLOW', 290) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateLBHealthCheckPolicy', 'ALLOW', 291) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateLBStickinessPolicy', 'ALLOW', 292) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateLoadBalancer', 'ALLOW', 293) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateLoadBalancerRule', 'ALLOW', 294) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateNetwork', 'ALLOW', 295) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateNetworkACLItem', 'ALLOW', 296) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateNetworkACLList', 'ALLOW', 297) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updatePortForwardingRule', 'ALLOW', 298) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateProject', 'ALLOW', 299) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateProjectInvitation', 'ALLOW', 300) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateRemoteAccessVpn', 'ALLOW', 301) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateResourceCount', 'ALLOW', 302) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateResourceLimit', 'ALLOW', 303) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateServiceOffering', 'ALLOW', 304) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateSnapshotPolicy', 'ALLOW', 305) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateTemplate', 'ALLOW', 306) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateTemplatePermissions', 'ALLOW', 307) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateUser', 'ALLOW', 308) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateVMAffinityGroup', 'ALLOW', 309) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateVPC', 'ALLOW', 310) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateVirtualMachine', 'ALLOW', 311) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateVmNicIp', 'ALLOW', 312) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateVpnConnection', 'ALLOW', 313) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateVpnCustomerGateway', 'ALLOW', 314) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'updateVpnGateway', 'ALLOW', 315) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'uploadSslCert', 'ALLOW', 316) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 2, 'uploadVolume', 'ALLOW', 317) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'activateProject', 'ALLOW', 0) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'addAccountToProject', 'ALLOW', 1) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'addIpToNic', 'ALLOW', 2) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'addNicToVirtualMachine', 'ALLOW', 3) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'addVpnUser', 'ALLOW', 4) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'archiveEvents', 'ALLOW', 5) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'assignCertToLoadBalancer', 'ALLOW', 6) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'assignToGlobalLoadBalancerRule', 'ALLOW', 7) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'assignToLoadBalancerRule', 'ALLOW', 8) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'assignVirtualMachine', 'ALLOW', 9) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'associateIpAddress', 'ALLOW', 10) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'associateLun', 'ALLOW', 11) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'attachIso', 'ALLOW', 12) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'attachVolume', 'ALLOW', 13) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'authorizeSamlSso', 'ALLOW', 14) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'authorizeSecurityGroupEgress', 'ALLOW', 15) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'authorizeSecurityGroupIngress', 'ALLOW', 16) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'changeServiceForRouter', 'ALLOW', 17) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'changeServiceForVirtualMachine', 'ALLOW', 18) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'configureInternalLoadBalancerElement', 'ALLOW', 19) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'configureOvsElement', 'ALLOW', 20) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'configureVirtualRouterElement', 'ALLOW', 21) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'copyIso', 'ALLOW', 22) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'copyTemplate', 'ALLOW', 23) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createAccount', 'ALLOW', 24) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createAffinityGroup', 'ALLOW', 25) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createAutoScalePolicy', 'ALLOW', 26) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createAutoScaleVmGroup', 'ALLOW', 27) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createAutoScaleVmProfile', 'ALLOW', 28) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createCondition', 'ALLOW', 29) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createDiskOffering', 'ALLOW', 30) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createEgressFirewallRule', 'ALLOW', 31) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createFirewallRule', 'ALLOW', 32) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createGlobalLoadBalancerRule', 'ALLOW', 33) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createInstanceGroup', 'ALLOW', 34) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createInternalLoadBalancerElement', 'ALLOW', 35) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createIpForwardingRule', 'ALLOW', 36) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createLBHealthCheckPolicy', 'ALLOW', 37) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createLBStickinessPolicy', 'ALLOW', 38) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createLoadBalancer', 'ALLOW', 39) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createLoadBalancerRule', 'ALLOW', 40) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createLunOnFiler', 'ALLOW', 41) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createNetwork', 'ALLOW', 42) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createNetworkACL', 'ALLOW', 43) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createNetworkACLList', 'ALLOW', 44) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createOvsElement', 'ALLOW', 45) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createPool', 'ALLOW', 46) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createPortForwardingRule', 'ALLOW', 47) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createProject', 'ALLOW', 48) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createRemoteAccessVpn', 'ALLOW', 49) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createSSHKeyPair', 'ALLOW', 50) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createSecurityGroup', 'ALLOW', 51) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createServiceOffering', 'ALLOW', 52) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createSnapshot', 'ALLOW', 53) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createSnapshotPolicy', 'ALLOW', 54) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createStaticRoute', 'ALLOW', 55) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createTags', 'ALLOW', 56) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createTemplate', 'ALLOW', 57) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createUser', 'ALLOW', 58) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVMSnapshot', 'ALLOW', 59) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVPC', 'ALLOW', 60) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVirtualRouterElement', 'ALLOW', 61) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVolume', 'ALLOW', 62) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVolumeOnFiler', 'ALLOW', 63) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVpnConnection', 'ALLOW', 64) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVpnCustomerGateway', 'ALLOW', 65) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'createVpnGateway', 'ALLOW', 66) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteAccount', 'ALLOW', 67) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteAccountFromProject', 'ALLOW', 68) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteAffinityGroup', 'ALLOW', 69) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteAutoScalePolicy', 'ALLOW', 70) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteAutoScaleVmGroup', 'ALLOW', 71) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteAutoScaleVmProfile', 'ALLOW', 72) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteCondition', 'ALLOW', 73) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteDiskOffering', 'ALLOW', 74) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteEgressFirewallRule', 'ALLOW', 75) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteEvents', 'ALLOW', 76) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteFirewallRule', 'ALLOW', 77) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteGlobalLoadBalancerRule', 'ALLOW', 78) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteInstanceGroup', 'ALLOW', 79) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteIpForwardingRule', 'ALLOW', 80) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteIso', 'ALLOW', 81) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteLBHealthCheckPolicy', 'ALLOW', 82) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteLBStickinessPolicy', 'ALLOW', 83) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteLoadBalancer', 'ALLOW', 84) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteLoadBalancerRule', 'ALLOW', 85) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteNetwork', 'ALLOW', 86) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteNetworkACL', 'ALLOW', 87) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteNetworkACLList', 'ALLOW', 88) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deletePool', 'ALLOW', 89) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deletePortForwardingRule', 'ALLOW', 90) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteProject', 'ALLOW', 91) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteProjectInvitation', 'ALLOW', 92) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteRemoteAccessVpn', 'ALLOW', 93) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteSSHKeyPair', 'ALLOW', 94) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteSecurityGroup', 'ALLOW', 95) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteServiceOffering', 'ALLOW', 96) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteSnapshot', 'ALLOW', 97) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteSnapshotPolicies', 'ALLOW', 98) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteSslCert', 'ALLOW', 99) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteStaticRoute', 'ALLOW', 100) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteTags', 'ALLOW', 101) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteTemplate', 'ALLOW', 102) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteUser', 'ALLOW', 103) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteVMSnapshot', 'ALLOW', 104) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteVPC', 'ALLOW', 105) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteVolume', 'ALLOW', 106) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteVpnConnection', 'ALLOW', 107) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteVpnCustomerGateway', 'ALLOW', 108) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deleteVpnGateway', 'ALLOW', 109) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'deployVirtualMachine', 'ALLOW', 110) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'destroyLunOnFiler', 'ALLOW', 111) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'destroyRouter', 'ALLOW', 112) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'destroyVirtualMachine', 'ALLOW', 113) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'destroyVolumeOnFiler', 'ALLOW', 114) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'detachIso', 'ALLOW', 115) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'detachVolume', 'ALLOW', 116) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'disableAccount', 'ALLOW', 117) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'disableAutoScaleVmGroup', 'ALLOW', 118) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'disableStaticNat', 'ALLOW', 119) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'disableUser', 'ALLOW', 120) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'disassociateIpAddress', 'ALLOW', 121) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'dissociateLun', 'ALLOW', 122) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'enableAccount', 'ALLOW', 123) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'enableAutoScaleVmGroup', 'ALLOW', 124) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'enableStaticNat', 'ALLOW', 125) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'enableUser', 'ALLOW', 126) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'expungeVirtualMachine', 'ALLOW', 127) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'extractIso', 'ALLOW', 128) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'extractTemplate', 'ALLOW', 129) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'extractVolume', 'ALLOW', 130) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getApiLimit', 'ALLOW', 131) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getCloudIdentifier', 'ALLOW', 132) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getSolidFireAccountId', 'ALLOW', 133) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getSolidFireVolumeAccessGroupId', 'ALLOW', 134) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getSolidFireVolumeIscsiName', 'ALLOW', 135) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getSolidFireVolumeSize', 'ALLOW', 136) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getUploadParamsForTemplate', 'ALLOW', 137) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getUploadParamsForVolume', 'ALLOW', 138) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getVMPassword', 'ALLOW', 139) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'getVirtualMachineUserData', 'ALLOW', 140) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'issueNuageVspResourceRequest', 'ALLOW', 141) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listAccounts', 'ALLOW', 142) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listAffinityGroupTypes', 'ALLOW', 143) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listAffinityGroups', 'ALLOW', 144) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listApis', 'ALLOW', 145) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listAsyncJobs', 'ALLOW', 146) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listAutoScalePolicies', 'ALLOW', 147) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listAutoScaleVmGroups', 'ALLOW', 148) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listAutoScaleVmProfiles', 'ALLOW', 149) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listCapabilities', 'ALLOW', 150) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listConditions', 'ALLOW', 151) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listCounters', 'ALLOW', 152) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listDiskOfferings', 'ALLOW', 153) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listDomainChildren', 'ALLOW', 154) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listDomains', 'ALLOW', 155) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listEgressFirewallRules', 'ALLOW', 156) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listEventTypes', 'ALLOW', 157) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listEvents', 'ALLOW', 158) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listFirewallRules', 'ALLOW', 159) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listGlobalLoadBalancerRules', 'ALLOW', 160) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listHostTags', 'ALLOW', 161) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listHypervisors', 'ALLOW', 162) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listInstanceGroups', 'ALLOW', 163) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listInternalLoadBalancerElements', 'ALLOW', 164) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listIpForwardingRules', 'ALLOW', 165) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listIsoPermissions', 'ALLOW', 166) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listIsos', 'ALLOW', 167) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listLBHealthCheckPolicies', 'ALLOW', 168) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listLBStickinessPolicies', 'ALLOW', 169) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listLdapConfigurations', 'ALLOW', 170) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listLoadBalancerRuleInstances', 'ALLOW', 171) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listLoadBalancerRules', 'ALLOW', 172) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listLoadBalancers', 'ALLOW', 173) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listLunsOnFiler', 'ALLOW', 174) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listNetworkACLLists', 'ALLOW', 175) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listNetworkACLs', 'ALLOW', 176) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listNetworkOfferings', 'ALLOW', 177) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listNetworks', 'ALLOW', 178) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listNics', 'ALLOW', 179) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listOsCategories', 'ALLOW', 180) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listOsTypes', 'ALLOW', 181) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listOvsElements', 'ALLOW', 182) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listPools', 'ALLOW', 183) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listPortForwardingRules', 'ALLOW', 184) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listPrivateGateways', 'ALLOW', 185) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listProjectAccounts', 'ALLOW', 186) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listProjectInvitations', 'ALLOW', 187) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listProjects', 'ALLOW', 188) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listPublicIpAddresses', 'ALLOW', 189) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listRegions', 'ALLOW', 190) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listRemoteAccessVpns', 'ALLOW', 191) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listResourceDetails', 'ALLOW', 192) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listResourceLimits', 'ALLOW', 193) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listRouters', 'ALLOW', 194) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listSSHKeyPairs', 'ALLOW', 195) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listSamlAuthorization', 'ALLOW', 196) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listSecurityGroups', 'ALLOW', 197) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listServiceOfferings', 'ALLOW', 198) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listSnapshotPolicies', 'ALLOW', 199) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listSnapshots', 'ALLOW', 200) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listSslCerts', 'ALLOW', 201) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listStaticRoutes', 'ALLOW', 202) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listStorageTags', 'ALLOW', 203) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listTags', 'ALLOW', 204) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listTemplatePermissions', 'ALLOW', 205) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listTemplates', 'ALLOW', 206) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listUsageRecords', 'ALLOW', 207) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listUsers', 'ALLOW', 208) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVMSnapshot', 'ALLOW', 209) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVPCOfferings', 'ALLOW', 210) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVPCs', 'ALLOW', 211) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVirtualMachines', 'ALLOW', 212) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVirtualRouterElements', 'ALLOW', 213) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVolumes', 'ALLOW', 214) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVolumesOnFiler', 'ALLOW', 215) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVpnConnections', 'ALLOW', 216) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVpnCustomerGateways', 'ALLOW', 217) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVpnGateways', 'ALLOW', 218) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listVpnUsers', 'ALLOW', 219) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'listZones', 'ALLOW', 220) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'lockAccount', 'ALLOW', 221) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'lockUser', 'ALLOW', 222) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'migrateVolume', 'ALLOW', 223) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'modifyPool', 'ALLOW', 224) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'queryAsyncJobResult', 'ALLOW', 225) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'quotaBalance', 'ALLOW', 226) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'quotaIsEnabled', 'ALLOW', 227) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'quotaStatement', 'ALLOW', 228) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'quotaSummary', 'ALLOW', 229) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'quotaTariffList', 'ALLOW', 230) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'rebootRouter', 'ALLOW', 231) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'rebootVirtualMachine', 'ALLOW', 232) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'recoverVirtualMachine', 'ALLOW', 233) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'registerIso', 'ALLOW', 234) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'registerSSHKeyPair', 'ALLOW', 235) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'registerTemplate', 'ALLOW', 236) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'registerUserKeys', 'ALLOW', 237) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'removeCertFromLoadBalancer', 'ALLOW', 238) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'removeFromGlobalLoadBalancerRule', 'ALLOW', 239) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'removeFromLoadBalancerRule', 'ALLOW', 240) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'removeIpFromNic', 'ALLOW', 241) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'removeNicFromVirtualMachine', 'ALLOW', 242) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'removeVpnUser', 'ALLOW', 243) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'replaceNetworkACLList', 'ALLOW', 244) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'resetPasswordForVirtualMachine', 'ALLOW', 245) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'resetSSHKeyForVirtualMachine', 'ALLOW', 246) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'resetVpnConnection', 'ALLOW', 247) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'resizeVolume', 'ALLOW', 248) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'restartNetwork', 'ALLOW', 249) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'restartVPC', 'ALLOW', 250) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'restoreVirtualMachine', 'ALLOW', 251) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'revertSnapshot', 'ALLOW', 252) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'revertToVMSnapshot', 'ALLOW', 253) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'revokeSecurityGroupEgress', 'ALLOW', 254) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'revokeSecurityGroupIngress', 'ALLOW', 255) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'scaleVirtualMachine', 'ALLOW', 256) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'startRouter', 'ALLOW', 257) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'startVirtualMachine', 'ALLOW', 258) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'stopRouter', 'ALLOW', 259) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'stopVirtualMachine', 'ALLOW', 260) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'suspendProject', 'ALLOW', 261) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateAccount', 'ALLOW', 262) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateAutoScalePolicy', 'ALLOW', 263) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateAutoScaleVmGroup', 'ALLOW', 264) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateAutoScaleVmProfile', 'ALLOW', 265) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateDefaultNicForVirtualMachine', 'ALLOW', 266) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateDiskOffering', 'ALLOW', 267) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateEgressFirewallRule', 'ALLOW', 268) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateFirewallRule', 'ALLOW', 269) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateGlobalLoadBalancerRule', 'ALLOW', 270) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateInstanceGroup', 'ALLOW', 271) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateIpAddress', 'ALLOW', 272) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateIso', 'ALLOW', 273) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateIsoPermissions', 'ALLOW', 274) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateLBHealthCheckPolicy', 'ALLOW', 275) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateLBStickinessPolicy', 'ALLOW', 276) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateLoadBalancer', 'ALLOW', 277) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateLoadBalancerRule', 'ALLOW', 278) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateNetwork', 'ALLOW', 279) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateNetworkACLItem', 'ALLOW', 280) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateNetworkACLList', 'ALLOW', 281) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updatePortForwardingRule', 'ALLOW', 282) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateProject', 'ALLOW', 283) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateProjectInvitation', 'ALLOW', 284) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateRemoteAccessVpn', 'ALLOW', 285) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateResourceCount', 'ALLOW', 286) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateResourceLimit', 'ALLOW', 287) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateServiceOffering', 'ALLOW', 288) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateSnapshotPolicy', 'ALLOW', 289) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateTemplate', 'ALLOW', 290) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateTemplatePermissions', 'ALLOW', 291) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateUser', 'ALLOW', 292) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateVMAffinityGroup', 'ALLOW', 293) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateVPC', 'ALLOW', 294) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateVirtualMachine', 'ALLOW', 295) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateVmNicIp', 'ALLOW', 296) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateVpnConnection', 'ALLOW', 297) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateVpnCustomerGateway', 'ALLOW', 298) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'updateVpnGateway', 'ALLOW', 299) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'uploadSslCert', 'ALLOW', 300) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 3, 'uploadVolume', 'ALLOW', 301) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'activateProject', 'ALLOW', 0) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'addAccountToProject', 'ALLOW', 1) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'addIpToNic', 'ALLOW', 2) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'addNicToVirtualMachine', 'ALLOW', 3) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'addVpnUser', 'ALLOW', 4) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'archiveEvents', 'ALLOW', 5) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'assignCertToLoadBalancer', 'ALLOW', 6) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'assignToGlobalLoadBalancerRule', 'ALLOW', 7) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'assignToLoadBalancerRule', 'ALLOW', 8) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'associateIpAddress', 'ALLOW', 9) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'associateLun', 'ALLOW', 10) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'attachIso', 'ALLOW', 11) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'attachVolume', 'ALLOW', 12) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'authorizeSecurityGroupEgress', 'ALLOW', 13) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'authorizeSecurityGroupIngress', 'ALLOW', 14) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'changeServiceForVirtualMachine', 'ALLOW', 15) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'copyIso', 'ALLOW', 16) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'copyTemplate', 'ALLOW', 17) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createAffinityGroup', 'ALLOW', 18) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createAutoScalePolicy', 'ALLOW', 19) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createAutoScaleVmGroup', 'ALLOW', 20) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createAutoScaleVmProfile', 'ALLOW', 21) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createCondition', 'ALLOW', 22) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createEgressFirewallRule', 'ALLOW', 23) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createFirewallRule', 'ALLOW', 24) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createGlobalLoadBalancerRule', 'ALLOW', 25) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createInstanceGroup', 'ALLOW', 26) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createIpForwardingRule', 'ALLOW', 27) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createLBHealthCheckPolicy', 'ALLOW', 28) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createLBStickinessPolicy', 'ALLOW', 29) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createLoadBalancer', 'ALLOW', 30) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createLoadBalancerRule', 'ALLOW', 31) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createLunOnFiler', 'ALLOW', 32) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createNetwork', 'ALLOW', 33) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createNetworkACL', 'ALLOW', 34) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createNetworkACLList', 'ALLOW', 35) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createPool', 'ALLOW', 36) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createPortForwardingRule', 'ALLOW', 37) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createProject', 'ALLOW', 38) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createRemoteAccessVpn', 'ALLOW', 39) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createSSHKeyPair', 'ALLOW', 40) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createSecurityGroup', 'ALLOW', 41) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createSnapshot', 'ALLOW', 42) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createSnapshotPolicy', 'ALLOW', 43) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createStaticRoute', 'ALLOW', 44) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createTags', 'ALLOW', 45) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createTemplate', 'ALLOW', 46) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createVMSnapshot', 'ALLOW', 47) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createVPC', 'ALLOW', 48) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createVolume', 'ALLOW', 49) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createVolumeOnFiler', 'ALLOW', 50) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createVpnConnection', 'ALLOW', 51) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createVpnCustomerGateway', 'ALLOW', 52) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'createVpnGateway', 'ALLOW', 53) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteAccountFromProject', 'ALLOW', 54) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteAffinityGroup', 'ALLOW', 55) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteAutoScalePolicy', 'ALLOW', 56) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteAutoScaleVmGroup', 'ALLOW', 57) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteAutoScaleVmProfile', 'ALLOW', 58) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteCondition', 'ALLOW', 59) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteEgressFirewallRule', 'ALLOW', 60) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteEvents', 'ALLOW', 61) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteFirewallRule', 'ALLOW', 62) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteGlobalLoadBalancerRule', 'ALLOW', 63) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteInstanceGroup', 'ALLOW', 64) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteIpForwardingRule', 'ALLOW', 65) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteIso', 'ALLOW', 66) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteLBHealthCheckPolicy', 'ALLOW', 67) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteLBStickinessPolicy', 'ALLOW', 68) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteLoadBalancer', 'ALLOW', 69) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteLoadBalancerRule', 'ALLOW', 70) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteNetwork', 'ALLOW', 71) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteNetworkACL', 'ALLOW', 72) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteNetworkACLList', 'ALLOW', 73) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deletePool', 'ALLOW', 74) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deletePortForwardingRule', 'ALLOW', 75) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteProject', 'ALLOW', 76) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteProjectInvitation', 'ALLOW', 77) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteRemoteAccessVpn', 'ALLOW', 78) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteSSHKeyPair', 'ALLOW', 79) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteSecurityGroup', 'ALLOW', 80) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteSnapshot', 'ALLOW', 81) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteSnapshotPolicies', 'ALLOW', 82) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteSslCert', 'ALLOW', 83) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteStaticRoute', 'ALLOW', 84) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteTags', 'ALLOW', 85) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteTemplate', 'ALLOW', 86) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteVMSnapshot', 'ALLOW', 87) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteVPC', 'ALLOW', 88) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteVolume', 'ALLOW', 89) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteVpnConnection', 'ALLOW', 90) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteVpnCustomerGateway', 'ALLOW', 91) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deleteVpnGateway', 'ALLOW', 92) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'deployVirtualMachine', 'ALLOW', 93) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'destroyLunOnFiler', 'ALLOW', 94) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'destroyVirtualMachine', 'ALLOW', 95) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'destroyVolumeOnFiler', 'ALLOW', 96) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'detachIso', 'ALLOW', 97) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'detachVolume', 'ALLOW', 98) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'disableAutoScaleVmGroup', 'ALLOW', 99) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'disableStaticNat', 'ALLOW', 100) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'disassociateIpAddress', 'ALLOW', 101) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'dissociateLun', 'ALLOW', 102) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'enableAutoScaleVmGroup', 'ALLOW', 103) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'enableStaticNat', 'ALLOW', 104) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'expungeVirtualMachine', 'ALLOW', 105) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'extractIso', 'ALLOW', 106) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'extractTemplate', 'ALLOW', 107) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'extractVolume', 'ALLOW', 108) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getApiLimit', 'ALLOW', 109) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getCloudIdentifier', 'ALLOW', 110) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getSolidFireAccountId', 'ALLOW', 111) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getSolidFireVolumeAccessGroupId', 'ALLOW', 112) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getSolidFireVolumeIscsiName', 'ALLOW', 113) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getSolidFireVolumeSize', 'ALLOW', 114) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getUploadParamsForTemplate', 'ALLOW', 115) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getUploadParamsForVolume', 'ALLOW', 116) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getVMPassword', 'ALLOW', 117) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'getVirtualMachineUserData', 'ALLOW', 118) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'issueNuageVspResourceRequest', 'ALLOW', 119) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listAccounts', 'ALLOW', 120) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listAffinityGroupTypes', 'ALLOW', 121) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listAffinityGroups', 'ALLOW', 122) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listApis', 'ALLOW', 123) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listAsyncJobs', 'ALLOW', 124) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listAutoScalePolicies', 'ALLOW', 125) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listAutoScaleVmGroups', 'ALLOW', 126) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listAutoScaleVmProfiles', 'ALLOW', 127) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listCapabilities', 'ALLOW', 128) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listConditions', 'ALLOW', 129) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listCounters', 'ALLOW', 130) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listDiskOfferings', 'ALLOW', 131) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listEgressFirewallRules', 'ALLOW', 132) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listEventTypes', 'ALLOW', 133) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listEvents', 'ALLOW', 134) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listFirewallRules', 'ALLOW', 135) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listGlobalLoadBalancerRules', 'ALLOW', 136) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listHypervisors', 'ALLOW', 137) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listInstanceGroups', 'ALLOW', 138) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listIpForwardingRules', 'ALLOW', 139) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listIsoPermissions', 'ALLOW', 140) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listIsos', 'ALLOW', 141) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listLBHealthCheckPolicies', 'ALLOW', 142) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listLBStickinessPolicies', 'ALLOW', 143) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listLdapConfigurations', 'ALLOW', 144) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listLoadBalancerRuleInstances', 'ALLOW', 145) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listLoadBalancerRules', 'ALLOW', 146) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listLoadBalancers', 'ALLOW', 147) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listLunsOnFiler', 'ALLOW', 148) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listNetworkACLLists', 'ALLOW', 149) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listNetworkACLs', 'ALLOW', 150) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listNetworkOfferings', 'ALLOW', 151) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listNetworks', 'ALLOW', 152) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listNics', 'ALLOW', 153) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listOsCategories', 'ALLOW', 154) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listOsTypes', 'ALLOW', 155) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listPools', 'ALLOW', 156) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listPortForwardingRules', 'ALLOW', 157) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listPrivateGateways', 'ALLOW', 158) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listProjectAccounts', 'ALLOW', 159) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listProjectInvitations', 'ALLOW', 160) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listProjects', 'ALLOW', 161) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listPublicIpAddresses', 'ALLOW', 162) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listRegions', 'ALLOW', 163) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listRemoteAccessVpns', 'ALLOW', 164) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listResourceDetails', 'ALLOW', 165) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listResourceLimits', 'ALLOW', 166) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listSSHKeyPairs', 'ALLOW', 167) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listSecurityGroups', 'ALLOW', 168) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listServiceOfferings', 'ALLOW', 169) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listSnapshotPolicies', 'ALLOW', 170) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listSnapshots', 'ALLOW', 171) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listSslCerts', 'ALLOW', 172) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listStaticRoutes', 'ALLOW', 173) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listTags', 'ALLOW', 174) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listTemplatePermissions', 'ALLOW', 175) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listTemplates', 'ALLOW', 176) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listUsers', 'ALLOW', 177) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVMSnapshot', 'ALLOW', 178) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVPCOfferings', 'ALLOW', 179) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVPCs', 'ALLOW', 180) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVirtualMachines', 'ALLOW', 181) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVolumes', 'ALLOW', 182) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVolumesOnFiler', 'ALLOW', 183) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVpnConnections', 'ALLOW', 184) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVpnCustomerGateways', 'ALLOW', 185) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVpnGateways', 'ALLOW', 186) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listVpnUsers', 'ALLOW', 187) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'listZones', 'ALLOW', 188) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'migrateVolume', 'ALLOW', 189) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'modifyPool', 'ALLOW', 190) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'queryAsyncJobResult', 'ALLOW', 191) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'quotaBalance', 'ALLOW', 192) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'quotaIsEnabled', 'ALLOW', 193) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'quotaStatement', 'ALLOW', 194) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'quotaSummary', 'ALLOW', 195) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'quotaTariffList', 'ALLOW', 196) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'rebootVirtualMachine', 'ALLOW', 197) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'recoverVirtualMachine', 'ALLOW', 198) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'registerIso', 'ALLOW', 199) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'registerSSHKeyPair', 'ALLOW', 200) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'registerTemplate', 'ALLOW', 201) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'registerUserKeys', 'ALLOW', 202) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'removeCertFromLoadBalancer', 'ALLOW', 203) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'removeFromGlobalLoadBalancerRule', 'ALLOW', 204) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'removeFromLoadBalancerRule', 'ALLOW', 205) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'removeIpFromNic', 'ALLOW', 206) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'removeNicFromVirtualMachine', 'ALLOW', 207) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'removeVpnUser', 'ALLOW', 208) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'replaceNetworkACLList', 'ALLOW', 209) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'resetPasswordForVirtualMachine', 'ALLOW', 210) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'resetSSHKeyForVirtualMachine', 'ALLOW', 211) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'resetVpnConnection', 'ALLOW', 212) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'resizeVolume', 'ALLOW', 213) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'restartNetwork', 'ALLOW', 214) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'restartVPC', 'ALLOW', 215) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'restoreVirtualMachine', 'ALLOW', 216) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'revertSnapshot', 'ALLOW', 217) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'revertToVMSnapshot', 'ALLOW', 218) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'revokeSecurityGroupEgress', 'ALLOW', 219) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'revokeSecurityGroupIngress', 'ALLOW', 220) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'scaleVirtualMachine', 'ALLOW', 221) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'startVirtualMachine', 'ALLOW', 222) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'stopVirtualMachine', 'ALLOW', 223) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'suspendProject', 'ALLOW', 224) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateAutoScalePolicy', 'ALLOW', 225) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateAutoScaleVmGroup', 'ALLOW', 226) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateAutoScaleVmProfile', 'ALLOW', 227) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateDefaultNicForVirtualMachine', 'ALLOW', 228) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateEgressFirewallRule', 'ALLOW', 229) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateFirewallRule', 'ALLOW', 230) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateGlobalLoadBalancerRule', 'ALLOW', 231) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateInstanceGroup', 'ALLOW', 232) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateIpAddress', 'ALLOW', 233) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateIso', 'ALLOW', 234) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateIsoPermissions', 'ALLOW', 235) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateLBHealthCheckPolicy', 'ALLOW', 236) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateLBStickinessPolicy', 'ALLOW', 237) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateLoadBalancer', 'ALLOW', 238) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateLoadBalancerRule', 'ALLOW', 239) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateNetwork', 'ALLOW', 240) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateNetworkACLItem', 'ALLOW', 241) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateNetworkACLList', 'ALLOW', 242) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updatePortForwardingRule', 'ALLOW', 243) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateProject', 'ALLOW', 244) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateProjectInvitation', 'ALLOW', 245) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateRemoteAccessVpn', 'ALLOW', 246) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateSnapshotPolicy', 'ALLOW', 247) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateTemplate', 'ALLOW', 248) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateTemplatePermissions', 'ALLOW', 249) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateUser', 'ALLOW', 250) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateVMAffinityGroup', 'ALLOW', 251) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateVPC', 'ALLOW', 252) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateVirtualMachine', 'ALLOW', 253) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateVmNicIp', 'ALLOW', 254) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateVpnConnection', 'ALLOW', 255) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateVpnCustomerGateway', 'ALLOW', 256) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'updateVpnGateway', 'ALLOW', 257) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'uploadSslCert', 'ALLOW', 258) ON DUPLICATE KEY UPDATE rule=rule; +INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) values (UUID(), 4, 'uploadVolume', 'ALLOW', 259) ON DUPLICATE KEY UPDATE rule=rule; diff --git a/setup/db/db/schema-481to490-cleanup.sql b/setup/db/db/schema-481to490-cleanup.sql index b1bb702727e..ba206459f28 100644 --- a/setup/db/db/schema-481to490-cleanup.sql +++ b/setup/db/db/schema-481to490-cleanup.sql @@ -82,4 +82,192 @@ ALTER TABLE `cloud`.`vm_work_job` DROP INDEX `id` ; ALTER TABLE `cloud`.`vpc_gateways` DROP INDEX `id` ; ALTER TABLE `cloud`.`vpn_users` DROP INDEX `id` ; +-- Dynamic roles changes +DROP VIEW IF EXISTS `cloud`.`account_view`; +CREATE VIEW `cloud`.`account_view` AS + select + account.id, + account.uuid, + account.account_name, + account.type, + account.role_id, + account.state, + account.removed, + account.cleanup_needed, + account.network_domain, + account.default, + domain.id domain_id, + domain.uuid domain_uuid, + domain.name domain_name, + domain.path domain_path, + data_center.id data_center_id, + data_center.uuid data_center_uuid, + data_center.name data_center_name, + account_netstats_view.bytesReceived, + account_netstats_view.bytesSent, + vmlimit.max vmLimit, + vmcount.count vmTotal, + runningvm.vmcount runningVms, + stoppedvm.vmcount stoppedVms, + iplimit.max ipLimit, + ipcount.count ipTotal, + free_ip_view.free_ip ipFree, + volumelimit.max volumeLimit, + volumecount.count volumeTotal, + snapshotlimit.max snapshotLimit, + snapshotcount.count snapshotTotal, + templatelimit.max templateLimit, + templatecount.count templateTotal, + vpclimit.max vpcLimit, + vpccount.count vpcTotal, + projectlimit.max projectLimit, + projectcount.count projectTotal, + networklimit.max networkLimit, + networkcount.count networkTotal, + cpulimit.max cpuLimit, + cpucount.count cpuTotal, + memorylimit.max memoryLimit, + memorycount.count memoryTotal, + primary_storage_limit.max primaryStorageLimit, + primary_storage_count.count primaryStorageTotal, + secondary_storage_limit.max secondaryStorageLimit, + secondary_storage_count.count secondaryStorageTotal, + async_job.id job_id, + async_job.uuid job_uuid, + async_job.job_status job_status, + async_job.account_id job_account_id + from + `cloud`.`free_ip_view`, + `cloud`.`account` + inner join + `cloud`.`domain` ON account.domain_id = domain.id + left join + `cloud`.`data_center` ON account.default_zone_id = data_center.id + left join + `cloud`.`account_netstats_view` ON account.id = account_netstats_view.account_id + left join + `cloud`.`resource_limit` vmlimit ON account.id = vmlimit.account_id + and vmlimit.type = 'user_vm' + left join + `cloud`.`resource_count` vmcount ON account.id = vmcount.account_id + and vmcount.type = 'user_vm' + left join + `cloud`.`account_vmstats_view` runningvm ON account.id = runningvm.account_id + and runningvm.state = 'Running' + left join + `cloud`.`account_vmstats_view` stoppedvm ON account.id = stoppedvm.account_id + and stoppedvm.state = 'Stopped' + left join + `cloud`.`resource_limit` iplimit ON account.id = iplimit.account_id + and iplimit.type = 'public_ip' + left join + `cloud`.`resource_count` ipcount ON account.id = ipcount.account_id + and ipcount.type = 'public_ip' + left join + `cloud`.`resource_limit` volumelimit ON account.id = volumelimit.account_id + and volumelimit.type = 'volume' + left join + `cloud`.`resource_count` volumecount ON account.id = volumecount.account_id + and volumecount.type = 'volume' + left join + `cloud`.`resource_limit` snapshotlimit ON account.id = snapshotlimit.account_id + and snapshotlimit.type = 'snapshot' + left join + `cloud`.`resource_count` snapshotcount ON account.id = snapshotcount.account_id + and snapshotcount.type = 'snapshot' + left join + `cloud`.`resource_limit` templatelimit ON account.id = templatelimit.account_id + and templatelimit.type = 'template' + left join + `cloud`.`resource_count` templatecount ON account.id = templatecount.account_id + and templatecount.type = 'template' + left join + `cloud`.`resource_limit` vpclimit ON account.id = vpclimit.account_id + and vpclimit.type = 'vpc' + left join + `cloud`.`resource_count` vpccount ON account.id = vpccount.account_id + and vpccount.type = 'vpc' + left join + `cloud`.`resource_limit` projectlimit ON account.id = projectlimit.account_id + and projectlimit.type = 'project' + left join + `cloud`.`resource_count` projectcount ON account.id = projectcount.account_id + and projectcount.type = 'project' + left join + `cloud`.`resource_limit` networklimit ON account.id = networklimit.account_id + and networklimit.type = 'network' + left join + `cloud`.`resource_count` networkcount ON account.id = networkcount.account_id + and networkcount.type = 'network' + left join + `cloud`.`resource_limit` cpulimit ON account.id = cpulimit.account_id + and cpulimit.type = 'cpu' + left join + `cloud`.`resource_count` cpucount ON account.id = cpucount.account_id + and cpucount.type = 'cpu' + left join + `cloud`.`resource_limit` memorylimit ON account.id = memorylimit.account_id + and memorylimit.type = 'memory' + left join + `cloud`.`resource_count` memorycount ON account.id = memorycount.account_id + and memorycount.type = 'memory' + left join + `cloud`.`resource_limit` primary_storage_limit ON account.id = primary_storage_limit.account_id + and primary_storage_limit.type = 'primary_storage' + left join + `cloud`.`resource_count` primary_storage_count ON account.id = primary_storage_count.account_id + and primary_storage_count.type = 'primary_storage' + left join + `cloud`.`resource_limit` secondary_storage_limit ON account.id = secondary_storage_limit.account_id + and secondary_storage_limit.type = 'secondary_storage' + left join + `cloud`.`resource_count` secondary_storage_count ON account.id = secondary_storage_count.account_id + and secondary_storage_count.type = 'secondary_storage' + left join + `cloud`.`async_job` ON async_job.instance_id = account.id + and async_job.instance_type = 'Account' + and async_job.job_status = 0; +DROP VIEW IF EXISTS `cloud`.`user_view`; +CREATE VIEW `cloud`.`user_view` AS + select + user.id, + user.uuid, + user.username, + user.password, + user.firstname, + user.lastname, + user.email, + user.state, + user.api_key, + user.secret_key, + user.created, + user.removed, + user.timezone, + user.registration_token, + user.is_registered, + user.incorrect_login_attempts, + user.default, + account.id account_id, + account.uuid account_uuid, + account.account_name account_name, + account.type account_type, + account.role_id account_role_id, + domain.id domain_id, + domain.uuid domain_uuid, + domain.name domain_name, + domain.path domain_path, + async_job.id job_id, + async_job.uuid job_uuid, + async_job.job_status job_status, + async_job.account_id job_account_id + from + `cloud`.`user` + inner join + `cloud`.`account` ON user.account_id = account.id + inner join + `cloud`.`domain` ON account.domain_id = domain.id + left join + `cloud`.`async_job` ON async_job.instance_id = user.id + and async_job.instance_type = 'User' + and async_job.job_status = 0; diff --git a/setup/db/db/schema-481to490.sql b/setup/db/db/schema-481to490.sql index a02615ffa75..a2622ed536d 100644 --- a/setup/db/db/schema-481to490.sql +++ b/setup/db/db/schema-481to490.sql @@ -436,3 +436,38 @@ VIEW `account_vmstats_view` AS (`vm_instance`.`vm_type` = 'User' and `vm_instance`.`removed` is NULL) GROUP BY `vm_instance`.`account_id` , `vm_instance`.`state`; -- End CLOUDSTACK-9340 + +-- Dynamic roles +CREATE TABLE IF NOT EXISTS `cloud`.`roles` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `uuid` varchar(255) UNIQUE, + `name` varchar(255) COMMENT 'unique name of the dynamic role', + `role_type` varchar(255) NOT NULL COMMENT 'the type of the role', + `removed` datetime COMMENT 'date removed', + `description` text COMMENT 'description of the role', + PRIMARY KEY (`id`), + KEY `i_roles__name` (`name`), + KEY `i_roles__role_type` (`role_type`), + UNIQUE KEY (`name`, `role_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `cloud`.`role_permissions` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `uuid` varchar(255) UNIQUE, + `role_id` bigint(20) unsigned NOT NULL COMMENT 'id of the role', + `rule` varchar(255) NOT NULL COMMENT 'rule for the role, api name or wildcard', + `permission` varchar(255) NOT NULL COMMENT 'access authority, allow or deny', + `description` text COMMENT 'description of the rule', + `sort_order` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT 'permission sort order', + PRIMARY KEY (`id`), + KEY `fk_role_permissions__role_id` (`role_id`), + KEY `i_role_permissions__sort_order` (`sort_order`), + UNIQUE KEY (`role_id`, `rule`), + CONSTRAINT `fk_role_permissions__role_id` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- Default CloudStack roles +INSERT INTO `cloud`.`roles` (`id`, `uuid`, `name`, `role_type`, `description`) values (1, UUID(), 'Root Admin', 'Admin', 'Default root admin role') ON DUPLICATE KEY UPDATE name=name; +INSERT INTO `cloud`.`roles` (`id`, `uuid`, `name`, `role_type`, `description`) values (2, UUID(), 'Resource Admin', 'ResourceAdmin', 'Default resource admin role') ON DUPLICATE KEY UPDATE name=name; +INSERT INTO `cloud`.`roles` (`id`, `uuid`, `name`, `role_type`, `description`) values (3, UUID(), 'Domain Admin', 'DomainAdmin', 'Default domain admin role') ON DUPLICATE KEY UPDATE name=name; +INSERT INTO `cloud`.`roles` (`id`, `uuid`, `name`, `role_type`, `description`) values (4, UUID(), 'User', 'User', 'Default Root Admin role') ON DUPLICATE KEY UPDATE name=name; diff --git a/setup/db/server-setup.sql b/setup/db/server-setup.sql index b7f5c3fc302..df2c9248552 100644 --- a/setup/db/server-setup.sql +++ b/setup/db/server-setup.sql @@ -25,4 +25,5 @@ INSERT INTO `cloud`.`domain` (id, uuid, name, parent, path, owner) VALUES (1, UU INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) VALUES ('Hidden', 'DEFAULT', 'none', 'init', null, null); -- INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xenserver.public.network.device', 'public-network', "[OPTIONAL]The name of the XenServer network containing the physical network interface that is connected to the public network "); - +-- Enable dynamic RBAC by default for fresh deployments +INSERT INTO `cloud`.`configuration` (category, instance, component, name, value) VALUES ('Advanced', 'DEFAULT', 'RoleService', 'dynamic.apichecker.enabled', 'true'); diff --git a/setup/db/server-setup.xml b/setup/db/server-setup.xml index bb8878f8d37..178f29aea35 100755 --- a/setup/db/server-setup.xml +++ b/setup/db/server-setup.xml @@ -239,6 +239,13 @@ under the License. qatest-vmops.com + + dynamic.apichecker.enabled + true + +