diff --git a/.travis.yml b/.travis.yml index d160e487aa1e..9d9822ce119b 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 7349c1f54133..23de15295ea5 100644 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -66,6 +66,8 @@ 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 b912e515bf30..58cedcd57460 100644 --- a/api/src/com/cloud/user/Account.java +++ b/api/src/com/cloud/user/Account.java @@ -46,6 +46,8 @@ public enum State { 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 7cc1e3089ca1..959a710d6d9f 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 000000000000..b05d886fdbfc --- /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 000000000000..0157a6682560 --- /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 000000000000..59eef51e782f --- /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 90e3d1ef6048..a8a64a58df51 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 000000000000..27920107fdc1 --- /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/ApiArgValidator.java b/api/src/org/apache/cloudstack/api/ApiArgValidator.java new file mode 100644 index 000000000000..bd2294c6018f --- /dev/null +++ b/api/src/org/apache/cloudstack/api/ApiArgValidator.java @@ -0,0 +1,23 @@ +// 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; + +public enum ApiArgValidator { + NotNullOrEmpty, // does Strings.isNullOrEmpty check + PositiveNumber, // does != null and > 0 check +} diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 6f3152b75a70..490492533be6 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 360b277d8979..5be75196d39a 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -30,6 +30,7 @@ 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 @@ 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 static enum CommandType { @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 List getParamFields() { 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/Parameter.java b/api/src/org/apache/cloudstack/api/Parameter.java index 7ee6897af29c..fa6075dc9707 100644 --- a/api/src/org/apache/cloudstack/api/Parameter.java +++ b/api/src/org/apache/cloudstack/api/Parameter.java @@ -49,4 +49,6 @@ String since() default ""; RoleType[] authorized() default {}; + + ApiArgValidator[] validations() default {}; } 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 b55ce7149884..2e1fbd6f8614 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 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.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 String getAccountName() { } 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 void execute() { 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 @@ private void validateParams() { 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 000000000000..994573d17966 --- /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 000000000000..aeb3f4ee11ad --- /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 000000000000..bd4a7cdacb72 --- /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 000000000000..9c7dc7c9861d --- /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 000000000000..f20abf40146d --- /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 000000000000..5cf870bfc063 --- /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 000000000000..e17fc6f5714b --- /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 000000000000..055265c5ccc8 --- /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 0124d5997b34..45f790fb70be 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 String getCfgName() { return cfgName; } + public void setCfgName(final String cfgName) { + this.cfgName = cfgName; + } + public String getValue() { return value; } @@ -117,6 +123,12 @@ public long getEntityOwnerId() { @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 24486a3c79b8..9c526563d44d 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 void execute() { 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 2e50c51858a9..7b48a1ea8a1c 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 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 void setAccountType(Short accountType) { 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 623a0a231f78..bcdad468fac8 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 void setSecurityGroupsEnabled(boolean securityGroupsEnabled) { 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 000000000000..ac1c5298c1e8 --- /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 000000000000..fd4bf28e6184 --- /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 36611ae7385b..cc986b38a1c6 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 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 void setAccountType(Short accountType) { 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 000000000000..611b761014ff --- /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 000000000000..08bd775bd082 --- /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 c0a046de4354..b50b2269c176 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 void testExecuteWithNotBlankPassword() { } 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 void testExecuteWithNullPassword() { 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 void testExecuteWithEmptyPassword() { 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 63c4a032435f..65b93306648f 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 @@ 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 void setUp() { 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 void testCreateSuccess() { 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 fbdedda5c2db..5e979074b6ad 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 a1e4f609f4c2..9bd80b722cf4 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/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in deleted file mode 100644 index 32f33c98805b..000000000000 --- a/client/tomcatconf/commands.properties.in +++ /dev/null @@ -1,801 +0,0 @@ -# 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. - -### bitmap of permissions at the end of each classname, 1 = ADMIN, 2 = RESOURCE_DOMAIN_ADMIN, 4 = DOMAIN_ADMIN, 8 = USER -### Please standardize naming conventions to camel-case (even for acronyms). - -### CloudStack authentication commands -login=15 -logout=15 - -### SAML SSO/SLO commands -samlSso=15 -samlSlo=15 -getSPMetadata=15 -listIdps=15 -authorizeSamlSso=7 -listSamlAuthorization=7 -listAndSwitchSamlAccount=15 - -### Account commands -createAccount=7 -deleteAccount=7 -updateAccount=7 -disableAccount=7 -enableAccount=7 -lockAccount=7 -listAccounts=15 -markDefaultZoneForAccount=1 - -#### User commands -createUser=7 -deleteUser=7 -updateUser=15 -listUsers=15 -lockUser=7 -disableUser=7 -enableUser=7 -getUser=1 - -#### Domain commands -createDomain=1 -updateDomain=1 -deleteDomain=1 -listDomains=7 -listDomainChildren=7 - -####Cloud Identifier commands -getCloudIdentifier=15 - -#### Limit commands -updateResourceLimit=7 -updateResourceCount=7 -listResourceLimits=15 - -#### VM commands -deployVirtualMachine=15 -destroyVirtualMachine=15 -rebootVirtualMachine=15 -startVirtualMachine=15 -stopVirtualMachine=15 -resetPasswordForVirtualMachine=15 -resetSSHKeyForVirtualMachine=15 -updateVirtualMachine=15 -listVirtualMachines=15 -getVMPassword=15 -restoreVirtualMachine=15 -changeServiceForVirtualMachine=15 -scaleVirtualMachine=15 -assignVirtualMachine=7 -migrateVirtualMachine=1 -migrateVirtualMachineWithVolume=1 -recoverVirtualMachine=15 -expungeVirtualMachine=15 -getVirtualMachineUserData=15 - -#### snapshot commands -createSnapshot=15 -listSnapshots=15 -deleteSnapshot=15 -createSnapshotPolicy=15 -updateSnapshotPolicy=15 -deleteSnapshotPolicies=15 -listSnapshotPolicies=15 -revertSnapshot=15 - -#### template commands -createTemplate=15 -registerTemplate=15 -updateTemplate=15 -copyTemplate=15 -deleteTemplate=15 -listTemplates=15 -updateTemplatePermissions=15 -listTemplatePermissions=15 -extractTemplate=15 -prepareTemplate=1 - -#### iso commands -attachIso=15 -detachIso=15 -listIsos=15 -registerIso=15 -updateIso=15 -deleteIso=15 -copyIso=15 -updateIsoPermissions=15 -listIsoPermissions=15 -extractIso=15 - -#### guest OS commands -listOsTypes=15 -listOsCategories=15 -addGuestOs=1 -updateGuestOs=1 -removeGuestOs=1 - -#### guest OS mapping commands -listGuestOsMapping=1 -addGuestOsMapping=1 -updateGuestOsMapping=1 -removeGuestOsMapping=1 - -#### service offering commands -createServiceOffering=7 -deleteServiceOffering=7 -updateServiceOffering=7 -listServiceOfferings=15 - -#### disk offering commands -createDiskOffering=7 -updateDiskOffering=7 -deleteDiskOffering=7 -listDiskOfferings=15 - -#### vlan commands -createVlanIpRange=1 -deleteVlanIpRange=1 -listVlanIpRanges=1 -dedicatePublicIpRange=1 -releasePublicIpRange=1 -dedicateGuestVlanRange=1 -releaseDedicatedGuestVlanRange=1 -listDedicatedGuestVlanRanges=1 - -#### address commands -associateIpAddress=15 -disassociateIpAddress=15 -listPublicIpAddresses=15 -updateIpAddress=15 - -#### firewall commands -listPortForwardingRules=15 -createPortForwardingRule=15 -deletePortForwardingRule=15 -updatePortForwardingRule=15 - -#### NAT commands -enableStaticNat=15 -createIpForwardingRule=15 -deleteIpForwardingRule=15 -listIpForwardingRules=15 -disableStaticNat=15 - -#### load balancer commands -createLoadBalancerRule=15 -deleteLoadBalancerRule=15 -removeFromLoadBalancerRule=15 -assignToLoadBalancerRule=15 -createLBStickinessPolicy=15 -updateLBStickinessPolicy=15 -deleteLBStickinessPolicy=15 -listLoadBalancerRules=15 -listLBStickinessPolicies=15 -listLBHealthCheckPolicies=15 -createLBHealthCheckPolicy=15 -updateLBHealthCheckPolicy=15 -deleteLBHealthCheckPolicy=15 -listLoadBalancerRuleInstances=15 -updateLoadBalancerRule=15 - -##### SSL offload commands - -uploadSslCert=15 -deleteSslCert=15 -listSslCerts=15 -assignCertToLoadBalancer=15 -removeCertFromLoadBalancer=15 - -#### autoscale commands -createCounter=1 -createCondition=15 -createAutoScalePolicy=15 -createAutoScaleVmProfile=15 -createAutoScaleVmGroup=15 -deleteCounter=1 -deleteCondition=15 -deleteAutoScalePolicy=15 -deleteAutoScaleVmProfile=15 -deleteAutoScaleVmGroup=15 -listCounters=15 -listConditions=15 -listAutoScalePolicies=15 -listAutoScaleVmProfiles=15 -listAutoScaleVmGroups=15 -enableAutoScaleVmGroup=15 -disableAutoScaleVmGroup=15 -updateAutoScalePolicy=15 -updateAutoScaleVmProfile=15 -updateAutoScaleVmGroup=15 - -#### router commands -startRouter=7 -rebootRouter=7 -stopRouter=7 -destroyRouter=7 -changeServiceForRouter=7 -listRouters=7 -listVirtualRouterElements=7 -configureVirtualRouterElement=7 -createVirtualRouterElement=7 -upgradeRouterTemplate=1 - -#### system vm commands -startSystemVm=1 -rebootSystemVm=1 -stopSystemVm=1 -destroySystemVm=1 -listSystemVms=3 -migrateSystemVm=1 -changeServiceForSystemVm=1 -scaleSystemVm=1 - -#### configuration commands -updateConfiguration=1 -listConfigurations=1 -listCapabilities=15 -listDeploymentPlanners=1 -cleanVMReservations=1 - -#### pod commands -createPod=1 -updatePod=1 -deletePod=1 -listPods=3 - -#### zone commands -createZone=1 -updateZone=1 -deleteZone=1 -listZones=15 - -#### events commands -listEvents=15 -listEventTypes=15 -archiveEvents=15 -deleteEvents=15 - -#### alerts commands -listAlerts=3 -archiveAlerts=1 -deleteAlerts=1 -generateAlert=1 - -#### system capacity commands -listCapacity=3 - -#### swift commands -addSwift=1 -listSwifts=1 - -#### image store commands -addImageStore=1 -addImageStoreS3=1 -listImageStores=1 -deleteImageStore=1 -createSecondaryStagingStore=1 -listSecondaryStagingStores=1 -deleteSecondaryStagingStore=1 -updateCloudToUseObjectStore=1 - -#### host commands -addHost=3 -addCluster=1 -deleteCluster=1 -updateCluster=1 -reconnectHost=1 -updateHost=1 -deleteHost=3 -prepareHostForMaintenance=1 -cancelHostMaintenance=1 -listHosts=3 -listHostTags=7 -findHostsForMigration=1 -addSecondaryStorage=1 -updateHostPassword=1 -releaseHostReservation=1 - -#### VmWare DC -addVmwareDc=1 -removeVmwareDc=1 -listVmwareDcs=1 - -#### volume commands -attachVolume=15 -uploadVolume=15 -detachVolume=15 -createVolume=15 -deleteVolume=15 -listVolumes=15 -extractVolume=15 -migrateVolume=15 -resizeVolume=15 -updateVolume=1 - -#### registration command: FIXME -- this really should be something in management server that -#### generates a new key for the user and they just have to -#### use that key...the key is stored in the db associated w/ -#### the userId...every request to the developer API should be -#### checked against the key -registerUserKeys=15 - -### async-query command -queryAsyncJobResult=15 -listAsyncJobs=15 - -#### storage pools commands -listStoragePools=3 -listStorageProviders=3 -listStorageTags=7 -createStoragePool=1 -updateStoragePool=1 -deleteStoragePool=1 -listClusters=3 -enableStorageMaintenance=1 -cancelStorageMaintenance=1 -findStoragePoolsForMigration=1 - -#### security group commands -createSecurityGroup=15 -deleteSecurityGroup=15 -authorizeSecurityGroupIngress=15 -revokeSecurityGroupIngress=15 -authorizeSecurityGroupEgress=15 -revokeSecurityGroupEgress=15 -listSecurityGroups=15 - -#### vm group commands -createInstanceGroup=15 -deleteInstanceGroup=15 -updateInstanceGroup=15 -listInstanceGroups=15 - -### Certificate commands -uploadCustomCertificate=1 - -### other commands -listHypervisors=15 - -### VPN -createRemoteAccessVpn=15 -deleteRemoteAccessVpn=15 -listRemoteAccessVpns=15 -updateRemoteAccessVpn=15 - - -addVpnUser=15 -removeVpnUser=15 -listVpnUsers=15 - -#### network offering commands -createNetworkOffering=1 -updateNetworkOffering=1 -deleteNetworkOffering=1 -listNetworkOfferings=15 - -#### network commands -createNetwork=15 -deleteNetwork=15 -listNetworks=15 -restartNetwork=15 -updateNetwork=15 - -#### nic commands #### -addNicToVirtualMachine=15 -removeNicFromVirtualMachine=15 -updateDefaultNicForVirtualMachine=15 - -#### -addIpToNic=15 -removeIpFromNic=15 -updateVmNicIp=15 -listNics=15 - -#### SSH key pair commands -registerSSHKeyPair=15 -createSSHKeyPair=15 -deleteSSHKeyPair=15 -listSSHKeyPairs=15 - -#### Projects commands -createProject=15 -deleteProject=15 -updateProject=15 -activateProject=15 -suspendProject=15 -listProjects=15 -addAccountToProject=15 -deleteAccountFromProject=15 -listProjectAccounts=15 -listProjectInvitations=15 -updateProjectInvitation=15 -deleteProjectInvitation=15 - -#### -createFirewallRule=15 -deleteFirewallRule=15 -listFirewallRules=15 -updateFirewallRule=15 - -#### -createEgressFirewallRule=15 -deleteEgressFirewallRule=15 -listEgressFirewallRules=15 -updateEgressFirewallRule=15 - -#### hypervisor capabilities commands -updateHypervisorCapabilities=1 -listHypervisorCapabilities=1 - -#### Physical Network commands -createPhysicalNetwork=1 -deletePhysicalNetwork=1 -listPhysicalNetworks=1 -updatePhysicalNetwork=1 - -#### Physical Network Service Provider commands -listSupportedNetworkServices=1 -addNetworkServiceProvider=1 -deleteNetworkServiceProvider=1 -listNetworkServiceProviders=1 -updateNetworkServiceProvider=1 - -#### Physical Network Traffic Type commands -addTrafficType=1 -deleteTrafficType=1 -listTrafficTypes=1 -updateTrafficType=1 -listTrafficTypeImplementors=1 - -#### Storage Network commands -createStorageNetworkIpRange=1 -deleteStorageNetworkIpRange=1 -listStorageNetworkIpRange=1 -updateStorageNetworkIpRange=1 - -### Network Devices commands -addNetworkDevice=1 -listNetworkDevice=1 -deleteNetworkDevice=1 - -### VPC commands -createVPC=15 -listVPCs=15 -deleteVPC=15 -updateVPC=15 -restartVPC=15 - -#### VPC offering commands -createVPCOffering=1 -updateVPCOffering=1 -deleteVPCOffering=1 -listVPCOfferings=15 - -#### Private gateway commands -createPrivateGateway=1 -listPrivateGateways=15 -deletePrivateGateway=1 - -#### Network ACL commands -createNetworkACL=15 -updateNetworkACLItem=15 -deleteNetworkACL=15 -listNetworkACLs=15 -createNetworkACLList=15 -deleteNetworkACLList=15 -replaceNetworkACLList=15 -listNetworkACLLists=15 -updateNetworkACLList=15 - - -#### Static route commands -createStaticRoute=15 -deleteStaticRoute=15 -listStaticRoutes=15 - -#### Tags commands -createTags=15 -deleteTags=15 -listTags=15 - -#### Meta Data commands -addResourceDetail=1 -removeResourceDetail=1 -listResourceDetails=15 - -### Site-to-site VPN commands -createVpnCustomerGateway=15 -createVpnGateway=15 -createVpnConnection=15 -deleteVpnCustomerGateway=15 -deleteVpnGateway=15 -deleteVpnConnection=15 -updateVpnCustomerGateway=15 -resetVpnConnection=15 -listVpnCustomerGateways=15 -listVpnGateways=15 -listVpnConnections=15 -updateVpnConnection=15 -updateVpnGateway=15 - -#### router commands -createVirtualRouterElement=7 -configureVirtualRouterElement=7 -listVirtualRouterElements=7 - -#### ovs commands -createOvsElement=7 -configureOvsElement=7 -listOvsElements=7 - -#### usage commands -generateUsageRecords=1 -listUsageRecords=7 -listUsageTypes=1 -removeRawUsageRecords=1 - -#### traffic monitor commands -addTrafficMonitor=1 -deleteTrafficMonitor=1 -listTrafficMonitors=1 - -#### Cisco Nexus 1000v Virtual Supervisor Module (VSM) commands -deleteCiscoNexusVSM=1 -enableCiscoNexusVSM=1 -disableCiscoNexusVSM=1 -listCiscoNexusVSMs=1 - -#### f5 big ip load balancer commands - -#Deprecated commands -addExternalLoadBalancer=1 -deleteExternalLoadBalancer=1 -listExternalLoadBalancers=1 - -addF5LoadBalancer=1 -configureF5LoadBalancer=1 -deleteF5LoadBalancer=1 -listF5LoadBalancers=1 -listF5LoadBalancerNetworks=1 - -#### juniper srx firewall commands -addExternalFirewall=1 -deleteExternalFirewall=1 -listExternalFirewalls=1 - -addSrxFirewall=1 -deleteSrxFirewall=1 -configureSrxFirewall=1 -listSrxFirewalls=1 -listSrxFirewallNetworks=1 - -#### Palo Alto firewall commands -addPaloAltoFirewall=1 -deletePaloAltoFirewall=1 -configurePaloAltoFirewall=1 -listPaloAltoFirewalls=1 -listPaloAltoFirewallNetworks=1 - -####Netapp integration commands -createVolumeOnFiler=15 -destroyVolumeOnFiler=15 -listVolumesOnFiler=15 -createLunOnFiler=15 -destroyLunOnFiler=15 -listLunsOnFiler=15 -associateLun=15 -dissociateLun=15 -createPool=15 -deletePool=15 -modifyPool=15 -listPools=15 - -#### netscaler load balancer commands -addNetscalerLoadBalancer=1 -deleteNetscalerLoadBalancer=1 -configureNetscalerLoadBalancer=1 -listNetscalerLoadBalancers=1 -listNetscalerLoadBalancerNetworks=1 - -#### nicira nvp commands - -addNiciraNvpDevice=1 -deleteNiciraNvpDevice=1 -listNiciraNvpDevices=1 -listNiciraNvpDeviceNetworks=1 - -# Not implemented (yet) -#configureNiciraNvpDevice=1 - -#### brocade vcs commands - -addBrocadeVcsDevice=1 -deleteBrocadeVcsDevice=1 -listBrocadeVcsDevices=1 -listBrocadeVcsDeviceNetworks=1 - -#### bigswitch bcf commands - -addBigSwitchBcfDevice=1 -deleteBigSwitchBcfDevice=1 -listBigSwitchBcfDevices=1 - -#### stratosphere ssp commands - -addStratosphereSsp=1 -deleteStratoshereSsp=1 - -#### nuage vsp commands - -addNuageVspDevice=1 -updateNuageVspDevice=1 -deleteNuageVspDevice=1 -listNuageVspDevices=1 -issueNuageVspResourceRequest=15 - -#### host simulator commands - -configureSimulator=1 -querySimulatorMock=1 -cleanupSimulatorMock=1 - -#### api discovery commands - -listApis=15 - -#### API Rate Limit service command - -getApiLimit=15 -resetApiLimit=1 - -#### API SolidFire Service Command -getSolidFireAccountId=15 -getSolidFireVolumeSize=15 -getSolidFireVolumeAccessGroupId=15 -getSolidFireVolumeIscsiName=15 - -#### Region commands -addRegion=1 -updateRegion=1 -removeRegion=1 -listRegions=15 - -#### GSLB (Global Server Load Balancing) commands -createGlobalLoadBalancerRule=15 -deleteGlobalLoadBalancerRule=15 -updateGlobalLoadBalancerRule=15 -listGlobalLoadBalancerRules=15 -assignToGlobalLoadBalancerRule=15 -removeFromGlobalLoadBalancerRule=15 - -### VM Snapshot commands -listVMSnapshot=15 -createVMSnapshot=15 -deleteVMSnapshot=15 -revertToVMSnapshot=15 - -#### Baremetal commands -addBaremetalHost=1 -addBaremetalPxeKickStartServer=1 -addBaremetalPxePingServer=1 -addBaremetalDhcp=1 -listBaremetalDhcp=1 -listBaremetalPxeServers=1 -addBaremetalRct=1 -deleteBaremetalRct=1 -listBaremetalRct=1 - -#### UCS commands -addUcsManager=1 -listUcsManagers=1 -listUcsProfiles=1 -listUcsBlades=1 -associateUcsProfileToBlade=1 -removedeleteUcsManager=1 - -#### New Load Balancer commands -createLoadBalancer=15 -listLoadBalancers=15 -deleteLoadBalancer=15 -updateLoadBalancer=15 - -#Internal Load Balancer Element commands -configureInternalLoadBalancerElement=7 -createInternalLoadBalancerElement=7 -listInternalLoadBalancerElements=7 - - -#### Affinity group commands -createAffinityGroup=15 -deleteAffinityGroup=15 -listAffinityGroups=15 -updateVMAffinityGroup=15 -listAffinityGroupTypes=15 - -#### Cisco Vnmc commands -addCiscoVnmcResource=1 -deleteCiscoVnmcResource=1 -listCiscoVnmcResources=1 - -#### Cisco Asa1000v commands -addCiscoAsa1000vResource=1 -deleteCiscoAsa1000vResource=1 -listCiscoAsa1000vResources=1 - -#### portable public IP commands -createPortableIpRange=1 -deletePortableIpRange=1 -listPortableIpRanges=1 - -#### Internal LB VM commands -stopInternalLoadBalancerVM=1 -startInternalLoadBalancerVM=1 -listInternalLoadBalancerVMs=1 - -### Network Isolation methods listing -listNetworkIsolationMethods=1 - -#### Dedicated Resource commands -dedicateZone=1 -dedicatePod=1 -dedicateCluster=1 -dedicateHost=1 -releaseDedicatedZone=1 -releaseDedicatedPod=1 -releaseDedicatedCluster=1 -releaseDedicatedHost=1 -listDedicatedZones=1 -listDedicatedPods=1 -listDedicatedClusters=1 -listDedicatedHosts=1 - -### LDAP -listLdapConfigurations=15 -addLdapConfiguration=3 -deleteLdapConfiguration=3 -listLdapUsers=3 -ldapCreateAccount=3 -importLdapUsers=3 -linkDomainToLdap=3 - - -#### juniper-contrail commands -createServiceInstance=1 - -### OpenDaylight plugin commands -addOpenDaylightController=1 -deleteOpenDaylightController=1 -listOpenDaylightControllers=1 - -### GloboDNS commands -addGloboDnsHost=1 - -### volume/template post upload -getUploadParamsForVolume=15 -getUploadParamsForTemplate=15 - -### Quota Service -quotaStatement=15 -quotaBalance=15 -quotaSummary=15 -quotaUpdate=1 -quotaTariffList=15 -quotaTariffUpdate=1 -quotaCredits=1 -quotaEmailTemplateList=1 -quotaEmailTemplateUpdate=1 -quotaIsEnabled=15 diff --git a/debian/cloudstack-management.install b/debian/cloudstack-management.install index 4e016dfe292c..c66938263e85 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 05058a8dcff3..6e7881b1bcf1 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 f874118e19da..0dbe1803b9be 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 67ed2a7d255c..a3d58fc539b4 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 9e5213478eb0..d1240ecf2cbc 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 File[] getPrepareScripts() { @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 File[] getCleanupScripts() { 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 0f5a0446e937..a504d2fdaec5 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.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 AccountVO(long id) { 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 void setType(short type) { 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 4c7ce8e31b71..374c9cc43d6d 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 bff6213c10b7..27891503dc8b 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 @@ 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 AccountDaoImpl() { 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 Pair findUserAccountByApiKey(String apiKey) { 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 List findActiveAccountsForDomain(Long domain) { 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 000000000000..a81cebb70d75 --- /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 000000000000..f3404ab6d791 --- /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 000000000000..e53654d998e6 --- /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 000000000000..c7eb496213ef --- /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 000000000000..375449196575 --- /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 000000000000..960b652a3b4f --- /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 000000000000..96d7e53d1ce9 --- /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 000000000000..dda9998224f5 --- /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 000000000000..9ffe465a9aa7 --- /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 000000000000..754d4cc86a56 --- /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 000000000000..12ebbe56f5fe --- /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 9221ea4c7862..fc78268fc624 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 @@ // 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 @@ protected StaticRoleBasedAPIAccessChecker() { } } + 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 boolean configure(String name, Map params) throws Configu @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 @@ private void processMapping(Map configMap) { 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 be0d5d532609..66d8c5d64e35 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 @@ 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 @@ 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 2451b561bcbc..aca756502e84 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.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 boolean start() { 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 b5da60433529..e56766aaf469 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 User createUser(String arg0, String arg1, String arg2, String arg3, Strin } @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 Account getAccount(long accountId) { } @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 bafe299da9c1..1a2581972a4a 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 1968f85b0400..d845857925d1 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.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.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 LdapCreateAccountCmd(final LdapManager ldapManager, final AccountService 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 @@ UserAccount createCloudstackUserAccount(final LdapUser user, String accountName, } } + 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 @@ private Long getDomainId() { @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 63549f1111f9..9fdd700638c5 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 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.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 @@ private void createCloudstackUserAccount(LdapUser user, String accountName, Doma 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 @@ private void createCloudstackUserAccount(LdapUser user, String accountName, Doma @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 void execute() throws ResourceUnavailableException, InsufficientCapacityE 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 ae3e70651342..477e80f25566 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 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 void execute() throws ServerApiException { 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 5683b50a47db..add39c5b13d5 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 javax.inject.Inject; +import org.apache.cloudstack.acl.RoleType; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; @@ -119,7 +120,8 @@ private void enableUserInCloudStack(UserAccount user) { 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 514caeb17da5..434151ae234d 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/pom.xml b/pom.xml index 30e96a610743..b75afd2ed2fd 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,8 @@ 1.2.8 2.0.4 2.5 - 1.2.1 + 1.2 + 1.2.1 1.0-20081010.060147 6.0 3.2.16.RELEASE diff --git a/scripts/installer/windows/client.wxs b/scripts/installer/windows/client.wxs index 3c9121de69f1..414d81347599 100644 --- a/scripts/installer/windows/client.wxs +++ b/scripts/installer/windows/client.wxs @@ -595,9 +595,6 @@ - - - diff --git a/scripts/util/migrate-dynamicroles.py b/scripts/util/migrate-dynamicroles.py new file mode 100755 index 000000000000..e97e94cb2520 --- /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/pom.xml b/server/pom.xml index 8461d18a4f46..32695094e68d 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -69,10 +69,15 @@ javax.mail mail + + jstl + jstl + ${cs.jstl.version} + javax.servlet.jsp.jstl javax.servlet.jsp.jstl-api - ${cs.jstl.version} + ${cs.jstl-api.version} commons-codec 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 e39d918c9d82..6618e3ee5c83 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 1c55c674e64f..d6b529fa2f04 100644 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -27,6 +27,8 @@ 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 @@ void init() { // 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 static UserResponse newUserResponse(UserAccountJoinVO usr) { 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 static DomainResponse newDomainResponse(ResponseView view, DomainJoinVO v } 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 1708fa764d7f..19db96ae36c5 100644 --- a/server/src/com/cloud/api/ApiResponseGsonHelper.java +++ b/server/src/com/cloud/api/ApiResponseGsonHelper.java @@ -68,7 +68,7 @@ public boolean shouldSkipField(FieldAttributes f) { 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 6ec2f18e774f..d7da425b7abd 100644 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -797,15 +797,15 @@ public boolean verifyRequest(final Map requestParameters, fina 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/dispatch/ParamProcessWorker.java b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java index 099c0c91e667..feefaabc5510 100644 --- a/server/src/com/cloud/api/dispatch/ParamProcessWorker.java +++ b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java @@ -34,6 +34,7 @@ import javax.inject.Inject; +import com.google.common.base.Strings; import org.apache.log4j.Logger; import org.apache.cloudstack.acl.ControlledEntity; @@ -49,6 +50,7 @@ import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiArgValidator; import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd; import org.apache.cloudstack.api.command.admin.usage.GetUsageRecordsCmd; @@ -92,6 +94,55 @@ public void handle(final DispatchTask task) { processParameters(task.getCmd(), task.getParams()); } + private void validateNonEmptyString(final Object param, final String argName) { + if (param == null || Strings.isNullOrEmpty(param.toString())) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Empty or null value provided for API arg: %s", argName)); + } + } + + private void validateNaturalNumber(final Object param, final String argName) { + Long value = null; + if (param != null && param instanceof Long) { + value = (Long) param; + } else if (param != null) { + value = Long.valueOf(param.toString()); + } + if (value == null || value < 1L) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Invalid value provided for API arg: %s", argName)); + } + } + + private void validateField(final Object paramObj, final Parameter annotation) throws ServerApiException { + if (annotation == null) { + return; + } + final String argName = annotation.name(); + for (final ApiArgValidator validator : annotation.validations()) { + if (validator == null) { + continue; + } + switch (validator) { + case NotNullOrEmpty: + switch (annotation.type()) { + case UUID: + case STRING: + validateNonEmptyString(paramObj, argName); + break; + } + break; + case PositiveNumber: + switch (annotation.type()) { + case SHORT: + case INTEGER: + case LONG: + validateNaturalNumber(paramObj, argName); + break; + } + break; + } + } + } + @SuppressWarnings({"unchecked", "rawtypes"}) public void processParameters(final BaseCmd cmd, final Map params) { final Map entitiesToAccess = new HashMap(); @@ -112,6 +163,7 @@ public void processParameters(final BaseCmd cmd, final Map params) { // marshall the parameter into the correct type and set the field value try { + validateField(paramObj, parameterAnnotation); setFieldValue(field, cmd, paramObj, parameterAnnotation); } catch (final IllegalArgumentException argEx) { if (s_logger.isDebugEnabled()) { @@ -420,6 +472,7 @@ private Long translateUuidToInternalId(final String uuid, final Parameter annota for (final Class entity : entities) { CallContext.current().putContextParameter(entity, internalId); } + validateNaturalNumber(internalId, annotation.name()); return internalId; } } @@ -452,6 +505,7 @@ private Long translateUuidToInternalId(final String uuid, final Parameter annota throw new InvalidParameterValueException("Invalid parameter " + annotation.name() + " value=" + uuid + " due to incorrect long value format, or entity does not exist or due to incorrect parameter annotation for the field in api cmd class."); } + validateNaturalNumber(internalId, annotation.name()); return internalId; } } diff --git a/server/src/com/cloud/api/doc/ApiXmlDocWriter.java b/server/src/com/cloud/api/doc/ApiXmlDocWriter.java index 166af4bafd01..9246edd4adc7 100644 --- a/server/src/com/cloud/api/doc/ApiXmlDocWriter.java +++ b/server/src/com/cloud/api/doc/ApiXmlDocWriter.java @@ -41,7 +41,6 @@ import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; @@ -67,16 +66,10 @@ public class ApiXmlDocWriter { public static final Logger s_logger = Logger.getLogger(ApiXmlDocWriter.class.getName()); - private static final short DOMAIN_ADMIN_COMMAND = 4; - private static final short USER_COMMAND = 8; + private static String s_dirName = ""; private static Map> s_apiNameCmdClassMap = new HashMap>(); private static LinkedHashMap s_allApiCommands = new LinkedHashMap(); - private static LinkedHashMap s_domainAdminApiCommands = new LinkedHashMap(); - private static LinkedHashMap s_regularUserApiCommands = new LinkedHashMap(); private static TreeMap s_allApiCommandsSorted = new TreeMap(); - private static TreeMap s_domainAdminApiCommandsSorted = new TreeMap(); - private static TreeMap s_regularUserApiCommandsSorted = new TreeMap(); - private static String s_dirName = ""; private static final List AsyncResponses = setAsyncResponses(); private static List setAsyncResponses() { @@ -123,71 +116,22 @@ public static void main(String[] args) { s_apiNameCmdClassMap.put(apiName, cmdClass); } } - - LinkedProperties preProcessedCommands = new LinkedProperties(); - String[] fileNames = null; - + System.out.printf("Scanned and found %d APIs\n", s_apiNameCmdClassMap.size()); List argsList = Arrays.asList(args); Iterator iter = argsList.iterator(); while (iter.hasNext()) { String arg = iter.next(); - // populate the file names - if (arg.equals("-f")) { - fileNames = iter.next().split(","); - } if (arg.equals("-d")) { s_dirName = iter.next(); } } - if ((fileNames == null) || (fileNames.length == 0)) { - System.out.println("Please specify input file(s) separated by coma using -f option"); - System.exit(2); - } - - for (String fileName : fileNames) { - try(FileInputStream in = new FileInputStream(fileName);) { - preProcessedCommands.load(in); - } catch (FileNotFoundException ex) { - System.out.println("Can't find file " + fileName); - System.exit(2); - } catch (IOException ex1) { - System.out.println("Error reading from file " + ex1); - System.exit(2); - } - } - - Iterator propertiesIterator = preProcessedCommands.keys.iterator(); - // Get command classes and response object classes - while (propertiesIterator.hasNext()) { - String key = (String)propertiesIterator.next(); - String preProcessedCommand = preProcessedCommands.getProperty(key); - int splitIndex = preProcessedCommand.lastIndexOf(";"); - String commandRoleMask = preProcessedCommand.substring(splitIndex + 1); - Class cmdClass = s_apiNameCmdClassMap.get(key); - if (cmdClass == null) { - System.out.println("Check, is this api part of another build profile? Null value for key: " + key + " preProcessedCommand=" + preProcessedCommand); - continue; - } - String commandName = cmdClass.getName(); - s_allApiCommands.put(key, commandName); - - short cmdPermissions = 1; - if (commandRoleMask != null) { - cmdPermissions = Short.parseShort(commandRoleMask); - } - - if ((cmdPermissions & DOMAIN_ADMIN_COMMAND) != 0) { - s_domainAdminApiCommands.put(key, commandName); - } - if ((cmdPermissions & USER_COMMAND) != 0) { - s_regularUserApiCommands.put(key, commandName); - } + for (Map.Entry> entry: s_apiNameCmdClassMap.entrySet()) { + Class cls = entry.getValue(); + s_allApiCommands.put(entry.getKey(), cls.getName()); } s_allApiCommandsSorted.putAll(s_allApiCommands); - s_domainAdminApiCommandsSorted.putAll(s_domainAdminApiCommands); - s_regularUserApiCommandsSorted.putAll(s_regularUserApiCommands); try { // Create object writer @@ -195,83 +139,38 @@ public static void main(String[] args) { xs.alias("command", Command.class); xs.alias("arg", Argument.class); String xmlDocDir = s_dirName + "/xmldoc"; - String rootAdminDirName = xmlDocDir + "/root_admin"; - String domainAdminDirName = xmlDocDir + "/domain_admin"; - String regularUserDirName = xmlDocDir + "/regular_user"; + String rootAdminDirName = xmlDocDir + "/apis"; (new File(rootAdminDirName)).mkdirs(); - (new File(domainAdminDirName)).mkdirs(); - (new File(regularUserDirName)).mkdirs(); ObjectOutputStream out = xs.createObjectOutputStream(new FileWriter(s_dirName + "/commands.xml"), "commands"); - ObjectOutputStream rootAdmin = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + "rootAdminSummary.xml"), "commands"); - ObjectOutputStream rootAdminSorted = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + "rootAdminSummarySorted.xml"), "commands"); - ObjectOutputStream domainAdmin = xs.createObjectOutputStream(new FileWriter(domainAdminDirName + "/" + "domainAdminSummary.xml"), "commands"); - ObjectOutputStream outDomainAdminSorted = xs.createObjectOutputStream(new FileWriter(domainAdminDirName + "/" + "domainAdminSummarySorted.xml"), "commands"); - ObjectOutputStream regularUser = xs.createObjectOutputStream(new FileWriter(regularUserDirName + "/regularUserSummary.xml"), "commands"); - ObjectOutputStream regularUserSorted = xs.createObjectOutputStream(new FileWriter(regularUserDirName + "/regularUserSummarySorted.xml"), "commands"); - - // Write commands in the order they are represented in commands.properties.in file + ObjectOutputStream rootAdmin = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + "apiSummary.xml"), "commands"); + ObjectOutputStream rootAdminSorted = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + "apiSummarySorted.xml"), "commands"); + Iterator it = s_allApiCommands.keySet().iterator(); while (it.hasNext()) { String key = (String)it.next(); - // Write admin commands writeCommand(out, key); writeCommand(rootAdmin, key); - // Write single commands to separate xml files ObjectOutputStream singleRootAdminCommandOs = xs.createObjectOutputStream(new FileWriter(rootAdminDirName + "/" + key + ".xml"), "command"); writeCommand(singleRootAdminCommandOs, key); singleRootAdminCommandOs.close(); - - if (s_domainAdminApiCommands.containsKey(key)) { - writeCommand(domainAdmin, key); - ObjectOutputStream singleDomainAdminCommandOs = xs.createObjectOutputStream(new FileWriter(domainAdminDirName + "/" + key + ".xml"), "command"); - writeCommand(singleDomainAdminCommandOs, key); - singleDomainAdminCommandOs.close(); - } - - if (s_regularUserApiCommands.containsKey(key)) { - writeCommand(regularUser, key); - ObjectOutputStream singleRegularUserCommandOs = xs.createObjectOutputStream(new FileWriter(regularUserDirName + "/" + key + ".xml"), "command"); - writeCommand(singleRegularUserCommandOs, key); - singleRegularUserCommandOs.close(); - } } // Write sorted commands it = s_allApiCommandsSorted.keySet().iterator(); while (it.hasNext()) { String key = (String)it.next(); - writeCommand(rootAdminSorted, key); - - if (s_domainAdminApiCommands.containsKey(key)) { - writeCommand(outDomainAdminSorted, key); - } - - if (s_regularUserApiCommands.containsKey(key)) { - writeCommand(regularUserSorted, key); - } } out.close(); rootAdmin.close(); rootAdminSorted.close(); - domainAdmin.close(); - outDomainAdminSorted.close(); - regularUser.close(); - regularUserSorted.close(); // write alerttypes to xml writeAlertTypes(xmlDocDir); - - // gzip directory with xml doc - // zipDir(dirName + "xmldoc.zip", xmlDocDir); - - // Delete directory - // deleteDir(new File(xmlDocDir)); - } catch (Exception ex) { ex.printStackTrace(); System.exit(2); @@ -537,5 +436,4 @@ public Object put(Object key, Object value) { return super.put(key, value); } } - } diff --git a/server/src/com/cloud/api/query/vo/AccountJoinVO.java b/server/src/com/cloud/api/query/vo/AccountJoinVO.java index 8d642edd7cf8..f251abc47262 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 short getType() { 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 0e66ca022c58..e6b1ace09663 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 short getAccountType() { 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 59426e65742f..2b9717de1e29 100644 --- a/server/src/com/cloud/api/response/ApiResponseSerializer.java +++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java @@ -251,7 +251,7 @@ private static void serializeResponseObjFieldsXML(StringBuilder sb, StringBuilde 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 ee6650698c3a..a8dd225c54c6 100644 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -211,7 +211,7 @@ public Project doInTransaction(TransactionStatus status) { 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 16e4ff059022..13f98a2f488e 100644 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -449,7 +449,7 @@ public void saveUser() { 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 void doInTransactionWithoutResult(TransactionStatus status) { 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 7b9e0936bb95..9789a2232965 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 d3eb40c7db69..7e80681caa20 100644 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -994,9 +994,9 @@ private boolean doDisableAccount(long accountId) throws ConcurrentOperationExcep @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 UserAccount createUserAccount(final String userName, final String passwor @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 Pair doInTransaction(TransactionStatus status) { 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 Account getAccount(long accountId) { @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 void markUserRegistered(long userId) { @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 AccountVO createAccount(final String accountName, final short accountType } 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 AccountVO createAccount(final String accountName, final short accountType 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 000000000000..7363b13b35ac --- /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 3971fd6b4fcd..fd8516722556 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -328,13 +328,13 @@ public UserAccount getUserByApiKey(String apiKey) { @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 boolean deleteAccount(AccountVO account, long callerUserId, Account calle } @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 634ce0a2e02d..3072b77a5cd9 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 @@ private void processMapping(Map configMap) { 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 000000000000..57601fbde17f --- /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 b1bb702727eb..ba206459f28a 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 a02615ffa754..a2622ed536d3 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 b7f5c3fc3026..df2c9248552a 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 bb8878f8d376..178f29aea352 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 + + - - Apache CloudStack v4.6.0 Root Admin API Reference + + + Apache CloudStack v4.9.0 Root Admin API Reference

@@ -65,16 +65,16 @@ version="1.0"> - +
- +
-
-

Request parameters

- - - +
+

Request parameters

+
Parameter Name
+ + @@ -87,7 +87,7 @@ version="1.0"> - + @@ -95,16 +95,16 @@ version="1.0">
Parameter Name Description Required
- - -
-

Response Tags

- - - + + +
+

Response Tags

+
Response Name
+ + - + @@ -112,31 +112,31 @@ version="1.0"> - + - + - - + + - - - - - + + + + +
Response Name Description
- - - + + - - + + + @@ -149,10 +149,10 @@ version="1.0"> - @@ -161,4 +161,3 @@ version="1.0"> - diff --git a/tools/apidoc/generatedomainadmincommands.xsl b/tools/apidoc/generatedomainadmincommands.xsl deleted file mode 100644 index e260b4fab47c..000000000000 --- a/tools/apidoc/generatedomainadmincommands.xsl +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - -Apache CloudStack | The Power Behind Your Cloud - - - -
-
-
-
- -
-
- -
-
- -
- -
- -
-
- - -
- -
- -
-
-
-
- - - - Apache CloudStack v4.6.0 Domain Admin API Reference - -

-

-

-
-
- - -
- -
-
-
-

Request parameters

- - - - - - - - - - - - - - - - - - - - - -
Parameter NameDescriptionRequired
-
- - -
-

Response Tags

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Response NameDescription
- -
- - -
-
- - -
-
- - -
-
- - -
-
- diff --git a/tools/apidoc/generatetoc.xsl b/tools/apidoc/generatetoc.xsl index 2cd1b0059a27..687e626a5d66 100644 --- a/tools/apidoc/generatetoc.xsl +++ b/tools/apidoc/generatetoc.xsl @@ -25,7 +25,7 @@ version="1.0"> -

Cloudstack API Version 4.6.0

+

Cloudstack API Version 4.9.0


Table of Contents

diff --git a/tools/apidoc/generatetoc_header.xsl b/tools/apidoc/generatetoc_header.xsl index f760430964f1..6362ab861061 100644 --- a/tools/apidoc/generatetoc_header.xsl +++ b/tools/apidoc/generatetoc_header.xsl @@ -52,7 +52,7 @@ version="1.0">
-

Apache CloudStack API Documentation (v4.6.0)

+

Apache CloudStack API Documentation (v4.9.0)

diff --git a/tools/apidoc/generateusercommands.xsl b/tools/apidoc/generateusercommands.xsl deleted file mode 100644 index c9ec8572e3b6..000000000000 --- a/tools/apidoc/generateusercommands.xsl +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - -Apache CloudStack | The Power Behind Your Cloud - - - -
-
-
-
-
- -
-
- -
- -
- -
-
- -
- -
- -
-
-
-
- - - - Apache CloudStack v4.6.0 User API Reference - -

-

-

-
-
- - -
- -
-
-
-

Request parameters

-

Name

- - - - - - - - - - - - - - - - - - - - -
Parameter NameDescriptionRequired
- - - -
-

Response Tags

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Response NameDescription
- -
- - - - - - - - - - - - - - - - - diff --git a/tools/apidoc/pom.xml b/tools/apidoc/pom.xml index 75cb1650d17c..63af063bfc41 100644 --- a/tools/apidoc/pom.xml +++ b/tools/apidoc/pom.xml @@ -61,8 +61,6 @@ ${client.config.jars} ${client.config.jars} ./target - -f - ${client.config.conf}/commands.properties diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index aa7b18ff6c75..d044fdd0eb4e 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -143,7 +143,7 @@ def __sign(self, payload): ["=".join( [str.lower(r[0]), str.lower( - urllib.quote_plus(str(r[1])) + urllib.quote_plus(str(r[1]), safe="*") ).replace("+", "%20")] ) for r in params] ) diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index 93923ad80eaf..f5f53a5d85b7 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -87,13 +87,96 @@ def list(cls, apiclient, **kwargs): return(apiclient.listDomains(cmd)) +class Role: + """Manage Role""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, domainid=None): + """Create role""" + cmd = createRole.createRoleCmd() + cmd.name = services["name"] + cmd.type = services["type"] + if "description" in services: + cmd.description = services["description"] + + return Role(apiclient.createRole(cmd).__dict__) + + def delete(self, apiclient): + """Delete Role""" + + cmd = deleteRole.deleteRoleCmd() + cmd.id = self.id + apiclient.deleteRole(cmd) + + def update(self, apiclient, **kwargs): + """Update the role""" + + cmd = updateRole.updateRoleCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return apiclient.updateRole(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """List all Roles matching criteria""" + + cmd = listRoles.listRolesCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listRoles(cmd)) + + +class RolePermission: + """Manage Role Permission""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, domainid=None): + """Create role permission""" + cmd = createRolePermission.createRolePermissionCmd() + cmd.roleid = services["roleid"] + cmd.rule = services["rule"] + cmd.permission = services["permission"] + if "description" in services: + cmd.description = services["description"] + + return RolePermission(apiclient.createRolePermission(cmd).__dict__) + + def delete(self, apiclient): + """Delete role permission""" + + cmd = deleteRolePermission.deleteRolePermissionCmd() + cmd.id = self.id + apiclient.deleteRolePermission(cmd) + + def update(self, apiclient, **kwargs): + """Update the role permission""" + + cmd = updateRolePermission.updateRolePermissionCmd() + cmd.roleid = self.roleid + [setattr(cmd, k, v) for k, v in kwargs.items()] + return apiclient.updateRolePermission(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """List all role permissions matching criteria""" + + cmd = listRolePermissions.listRolePermissionsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listRolePermissions(cmd)) + + class Account: """ Account Life Cycle """ def __init__(self, items): self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, admin=False, domainid=None): + def create(cls, apiclient, services, admin=False, domainid=None, roleid=None): """Creates an account""" cmd = createAccount.createAccountCmd() @@ -121,6 +204,10 @@ def create(cls, apiclient, services, admin=False, domainid=None): if domainid: cmd.domainid = domainid + + if roleid: + cmd.roleid = roleid + account = apiclient.createAccount(cmd) return Account(account.__dict__) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 830a39088abd..17cab9e708b2 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -2904,6 +2904,15 @@ div.detail-group.actions td { background-position: -366px -239px; } +#navigation ul li.roles span.icon { + background-position: -460px -80px; +} + +#navigation ul li.roles.active span.icon, +#navigation ul li.roles:hover span.icon { + background-position: -469px -750px; +} + #navigation ul li.accounts span.icon { background-position: -458px -19px; } @@ -13162,3 +13171,10 @@ div.gpugroups div.list-view { background: transparent url("../images/icons.png") no-repeat -626px -209px; padding: 0 0 3px 18px; } + +ul.ui-autocomplete.ui-menu { + width: 250px; + background: #ddd; + font-size: 13px; + padding: 5px; +} diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index b97141ca3b83..ddcd1813b594 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -1120,7 +1120,14 @@ dictionary = { 'label.retry.interval': '', 'label.review': '', 'label.revoke.project.invite': '', +'label.permission': '', 'label.role': '', +'label.roles': '', +'label.roletype': '', +'label.add.role': '', +'label.edit.role': '', +'label.delete.role': '', +'message.role.ordering.fail': '', 'label.root.disk.controller': '', 'label.root.disk.offering': '', 'message.configure.firewall.rules.allow.traffic': '', diff --git a/ui/dictionary2.jsp b/ui/dictionary2.jsp index 4268104d825c..f919b156d72d 100644 --- a/ui/dictionary2.jsp +++ b/ui/dictionary2.jsp @@ -26,6 +26,7 @@ under the License. + diff --git a/ui/plugins/quota/quota.js b/ui/plugins/quota/quota.js index 4780d7169776..4505b9687e48 100644 --- a/ui/plugins/quota/quota.js +++ b/ui/plugins/quota/quota.js @@ -25,12 +25,18 @@ id: 'quota', title: 'Quota', preFilter: function(args) { - var retval = $.ajax({ - url: createURL("quotaIsEnabled"), - async: false + var pluginEnabled = false; + $.ajax({ + url: createURL("quotaIsEnabled"), + async: false, + success: function(json) { + pluginEnabled = json.quotaisenabledresponse.isenabled.isenabled; + }, + error: function(data) { + pluginEnabled = false; + } }); - var json = JSON.parse(retval.responseText); - return json.quotaisenabledresponse.isenabled.isenabled; + return pluginEnabled; }, showOnNavigation: true, sectionSelect: { diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js index 0058b6902496..913f81ff5167 100644 --- a/ui/scripts/accounts.js +++ b/ui/scripts/accounts.js @@ -17,6 +17,7 @@ (function(cloudStack) { var domainObjs; + var roleObjs; cloudStack.sections.accounts = { title: 'label.accounts', @@ -38,11 +39,11 @@ name: { label: 'label.name' }, - accounttype: { - label: 'label.role', - converter: function(args) { - return cloudStack.converters.toRole(args); - } + rolename: { + label: 'label.role' + }, + roletype: { + label: 'label.roletype' }, domain: { label: 'label.domain' @@ -678,11 +679,11 @@ id: { label: 'label.id' }, - accounttype: { - label: 'label.role', - converter: function(args) { - return cloudStack.converters.toRole(args); - } + rolename: { + label: 'label.role' + }, + roletype: { + label: 'label.roletype' }, domain: { label: 'label.domain' @@ -1570,11 +1571,11 @@ account: { label: 'label.account.name' }, - accounttype: { - label: 'label.role', - converter: function(args) { - return cloudStack.converters.toRole(args); - } + rolename: { + label: 'label.role' + }, + roletype: { + label: 'label.roletype' }, domain: { label: 'label.domain' diff --git a/ui/scripts/accountsWizard.js b/ui/scripts/accountsWizard.js index 633821edb14e..7fc4014de68b 100644 --- a/ui/scripts/accountsWizard.js +++ b/ui/scripts/accountsWizard.js @@ -110,24 +110,28 @@ required: false } }, - accounttype: { - label: 'label.type', + roleid: { + label: 'label.role', docID: 'helpAccountType', validation: { required: true }, select: function(args) { - var items = []; - items.push({ - id: 0, - description: "User" - }); //regular-user - items.push({ - id: 1, - description: "Admin" - }); //root-admin - args.response.success({ - data: items + $.ajax({ + url: createURL("listRoles"), + success: function(json) { + var items = []; + roleObjs = json.listrolesresponse.role; + $(roleObjs).each(function() { + items.push({ + id: this.id, + description: this.name + ' (' + this.type + ')' + }); + }); + args.response.success({ + data: items + }); + } }); } }, @@ -226,13 +230,9 @@ array1.push("&account=" + account); } - var accountType = args.data.accounttype; - if (accountType == "1") { //if "admin" is selected in account type dropdown - if (rootDomainId == undefined || args.data.domainid != rootDomainId ) { //but current login has no visibility to root domain object, or the selected domain is not root domain - accountType = "2"; // change accountType from root-domain("1") to domain-admin("2") - } + if (args.data.roleid) { + array1.push("&roleid=" + args.data.roleid); } - array1.push("&accounttype=" + accountType); if (args.data.timezone !== null && args.data.timezone.length > 0) { array1.push("&timezone=" + args.data.timezone); diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js index 0725bf3bef1a..b712d6cdfc2d 100644 --- a/ui/scripts/cloudStack.js +++ b/ui/scripts/cloudStack.js @@ -22,7 +22,7 @@ var sections = []; if (isAdmin()) { - sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "system", "global-settings", "configuration", "projects", "regions", "affinityGroups"]; + sections = ["dashboard", "instances", "storage", "network", "templates", "roles", "accounts", "domains", "events", "system", "global-settings", "configuration", "projects", "regions", "affinityGroups"]; } else if (isDomainAdmin()) { sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "projects", "configuration", "regions", "affinityGroups"]; } else if (g_userProjectsEnabled) { @@ -52,6 +52,7 @@ templates: {}, events: {}, projects: {}, + roles: {}, accounts: {}, domains: {}, //domain-admin and root-admin only diff --git a/ui/scripts/roles.js b/ui/scripts/roles.js new file mode 100644 index 000000000000..eae088fafa8f --- /dev/null +++ b/ui/scripts/roles.js @@ -0,0 +1,388 @@ +// 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. +(function($, cloudStack) { + var apiList = []; + var rolePermissions = []; + cloudStack.sections.roles = { + title: 'label.roles', + id: 'roles', + listView: { + id: 'roles', + fields: { + name: { + label: 'label.name' + }, + type: { + label: 'label.type' + }, + description: { + label: 'label.description' + } + }, + disableInfiniteScrolling: true, + dataProvider: function(args) { + var data = {}; + if (args.filterBy.search && args.filterBy.search.value) { + data['name'] = args.filterBy.search.value; + } + $.ajax({ + url: createURL("listRoles"), + data: data, + dataType: "json", + async: true, + success: function(json) { + var jsonObj; + jsonObj = json.listrolesresponse.role; + args.response.success({ + data: jsonObj + }); + } + }); + }, + actions: { + add: { + label: 'label.add.role', + preFilter: function(args) { + if (isAdmin()) + return true; + }, + messages: { + notification: function() { + return 'label.add.role'; + } + }, + createForm: { + title: 'label.add.role', + fields: { + name: { + label: 'label.name', + validation: { + required: true + } + }, + description: { + label: 'label.description', + }, + type: { + label: 'label.type', + validation: { + required: true + }, + select: function(args) { + var items = []; + items.push({ + id: "Admin", + description: "Admin" + }); + items.push({ + id: "DomainAdmin", + description: "Domain Admin" + }); + items.push({ + id: "User", + description: "User" + }); + args.response.success({ + data: items + }); + } + } + } + }, + action: function(args) { + $.ajax({ + url: createURL('createRole'), + data: args.data, + success: function(json) { + var item = json.createroleresponse.role; + args.response.success({ + data: item + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: function(args) { + args.complete(); + } + } + } + }, + detailView: { + tabs: { + details: { + title: 'label.details', + fields: { + id: { + label: 'label.id' + }, + name: { + label: 'label.name', + isEditable: true, + validation: { + required: true + } + }, + type: { + label: 'label.type' + }, + description: { + label: 'label.description', + isEditable: true + } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL("listRoles&id=" + args.context.roles[0].id), + dataType: "json", + async: true, + success: function(json) { + var response = json.listrolesresponse.role[0]; + args.response.success({ + data: response + }); + } + }); + } + }, + rules: { + title: 'label.rules', + custom: function(args) { + var context = args.context; + + return $('
').multiEdit({ + context: context, + noSelect: true, + noHeaderActionsColumn: true, + reorder: { + moveDrag: { + action: function(args) { + var rule = args.context.multiRule[0]; + var prevItemId = args.prevItem ? args.prevItem.id : 0; + + var ruleOrder = []; + $.each(rolePermissions, function(idx, item) { + var itemId = item.id; + if (idx == 0 && prevItemId == 0) { + ruleOrder.push(rule.id); + } + if (itemId == rule.id) { + return true; + } + ruleOrder.push(item.id); + if (prevItemId == itemId) { + ruleOrder.push(rule.id); + } + }); + + $.ajax({ + url: createURL('updateRolePermission'), + data: { + roleid: rule.roleid, + ruleorder: ruleOrder.join() + }, + success: function(json) { + args.response.success(); + $(window).trigger('cloudStack.fullRefresh'); + }, + error: function(json) { + cloudStack.dialog.notice({ + message: 'message.role.ordering.fail' + }); + } + }); + } + } + }, + fields: { + 'rule': { + edit: true, + label: 'label.rule', + isOptional: false + }, + 'permission': { + label: 'label.permission', + select: function(args) { + args.response.success({ + data: [{ + name: 'allow', + description: 'Allow' + }, { + name: 'deny', + description: 'Deny' + }] + }); + } + }, + 'description': { + edit: true, + label: 'label.description', + isOptional: true + }, + 'always-hide': { + label: 'label.action', + addButton: true + } + }, + add: { + label: 'label.add', + action: function(args) { + var data = { + rule: args.data.rule, + permission: args.data.permission, + description: args.data.description, + roleid: args.context.roles[0].id + }; + + $.ajax({ + url: createURL('createRolePermission'), + data: data, + dataType: 'json', + success: function(json) { + var response = json.createrolepermissionresponse.rolepermission; + args.response.success({ + data: response + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + }, + actions: { + destroy: { + label: 'label.remove.rule', + action: function(args) { + $.ajax({ + url: createURL('deleteRolePermission'), + data: { + id: args.context.multiRule[0].id + }, + dataType: 'json', + success: function(data) { + args.response.success(); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listRolePermissions'), + data: { + roleid: args.context.roles[0].id + }, + dataType: 'json', + success: function(json) { + var rules = json.listrolepermissionsresponse.rolepermission; + if (rules) { + rolePermissions = rules; + } + args.response.success({ + data: rules + }); + } + }); + var setupAutocompletion = function() { + $($.find('input[name="rule"]')).autocomplete("destroy"); + $($.find('input[name="rule"]')).autocomplete({ + source: apiList, + autoFocus:true + }); + }; + if (apiList.length == 0) { + $.ajax({ + url: createURL("listApis"), + dataType: "json", + success: function(json) { + var response = json.listapisresponse.api; + $.each(response, function(idx, api) { + apiList.push(api.name); + }); + setupAutocompletion(); + } + }); + } else { + setupAutocompletion(); + } + } + }); + } + } + }, + actions: { + edit: { + label: 'label.edit.role', + action: function(args) { + var data = { + id: args.context.roles[0].id, + name: args.data.name, + description: args.data.description + }; + + $.ajax({ + url: createURL('updateRole'), + data: data, + success: function(json) { + args.response.success(); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + }, + remove: { + label: 'label.delete.role', + messages: { + confirm: function(args) { + return 'label.delete.role'; + }, + notification: function(args) { + return 'label.delete.role'; + } + }, + action: function(args) { + $.ajax({ + url: createURL("deleteRole&id=" + args.context.roles[0].id), + dataType: "json", + success: function(json) { + var response = json.deleteroleresponse; + args.response.success({ + data: response + }); + } + }); + }, + notification: { + poll: function(args) { + args.complete(); + } + } + } + } + } + } + } +})(jQuery, cloudStack); diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 7b4b26a0ca2a..88d728e76ffb 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -1112,6 +1112,17 @@ cloudStack.converters = { return "Domain-Admin"; } }, + toAccountType: function(roleType) { + if (roleType == 'User') { + return 0; + } else if (roleType == 'Admin') { + return 1; + } else if (roleType == 'DomainAdmin') { + return 2; + } else if (roleType == 'ResourceAdmin') { + return 3; + } + }, toAlertType: function(alertCode) { switch (alertCode) { case 0: diff --git a/utils/src/main/java/com/cloud/utils/ListUtils.java b/utils/src/main/java/com/cloud/utils/ListUtils.java new file mode 100644 index 000000000000..fa9332f119da --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/ListUtils.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 com.cloud.utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ListUtils { + public static List toListOfInterface(final List items) { + if (items != null) { + return new ArrayList<>(items); + } + return Collections.emptyList(); + } +} diff --git a/utils/src/main/java/com/cloud/utils/PropertiesUtil.java b/utils/src/main/java/com/cloud/utils/PropertiesUtil.java index 4cb89f7531d6..c0da87a192d3 100644 --- a/utils/src/main/java/com/cloud/utils/PropertiesUtil.java +++ b/utils/src/main/java/com/cloud/utils/PropertiesUtil.java @@ -34,6 +34,10 @@ public class PropertiesUtil { private static final Logger s_logger = Logger.getLogger(PropertiesUtil.class); + public static String getDefaultApiCommandsFileName() { + return "commands.properties"; + } + /** * Searches the class path and local paths to find the config file. * @param path path to find. if it starts with / then it's absolute path.