cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sw...@apache.org
Subject [7/9] git commit: updated refs/heads/master to bee2bdc
Date Wed, 11 May 2016 06:04:23 GMT
CLOUDSTACK-8562: DB-Backed Dynamic Role Based API Access Checker

This feature allows root administrators to define new roles and associate API
permissions to them.

A limited form of role-based access control for the CloudStack management server
API is provided through a properties file, commands.properties, embedded in the
WAR distribution. Therefore, customizing API permissions requires unpacking the
distribution and modifying this file consistently on all servers. The old system
also does not permit the specification of additional roles.

FS:
https://cwiki.apache.org/confluence/display/CLOUDSTACK/Dynamic+Role+Based+API+Access+Checker+for+CloudStack

DB-Backed Dynamic Role Based API Access Checker for CloudStack brings following
changes, features and use-cases:
- Moves the API access definitions from commands.properties to the mgmt server DB
- Allows defining custom roles (such as a read-only ROOT admin) beyond the
  current set of four (4) roles
- All roles will resolve to one of the four known roles types (Admin, Resource
  Admin, Domain Admin and User) which maintains this association by requiring
  all new defined roles to specify a role type.
- Allows changes to roles and API permissions per role at runtime including additions or
  removal of roles and/or modifications of permissions, without the need
  of restarting management server(s)

Upgrade/installation notes:
- The feature will be enabled by default for new installations, existing
  deployments will continue to use the older static role based api access checker
  with an option to enable this feature
- During fresh installation or upgrade, the upgrade paths will add four default
  roles based on the four default role types
- For ease of migration, at the time of upgrade commands.properties will be used
  to add existing set of permissions to the default roles. cloud.account
  will have a new role_id column which will be populated based on default roles
  as well

Dynamic-roles migration tool: scripts/util/migrate-dynamicroles.py
- Allows admins to migrate to the dynamic role based checker at a future date
- Performs a harder one-way migrate and update
- Migrates rules from existing commands.properties file into db and deprecates it
- Enables an internal hidden switch to enable dynamic role based checker feature

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/4347776a
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/4347776a
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/4347776a

Branch: refs/heads/master
Commit: 4347776ac6ef9ae86fb016862f4a6b2376f8319a
Parents: 95abb6e
Author: Rohit Yadav <rohit.yadav@shapeblue.com>
Authored: Tue Mar 15 09:16:06 2016 +0100
Committer: Rohit Yadav <rohit.yadav@shapeblue.com>
Committed: Wed May 11 09:45:19 2016 +0530

----------------------------------------------------------------------
 .travis.yml                                     |   4 +-
 api/src/com/cloud/event/EventTypes.java         |  18 +
 api/src/com/cloud/user/Account.java             |   2 +
 api/src/com/cloud/user/AccountService.java      |   4 +-
 api/src/org/apache/cloudstack/acl/Role.java     |  27 +
 .../apache/cloudstack/acl/RolePermission.java   |  31 +
 .../org/apache/cloudstack/acl/RoleService.java  |  52 ++
 api/src/org/apache/cloudstack/acl/RoleType.java |  80 +-
 api/src/org/apache/cloudstack/acl/Rule.java     |  54 ++
 .../org/apache/cloudstack/api/ApiConstants.java |   7 +
 api/src/org/apache/cloudstack/api/BaseCmd.java  |   7 +-
 .../command/admin/account/CreateAccountCmd.java |  17 +-
 .../api/command/admin/acl/CreateRoleCmd.java    | 105 +++
 .../admin/acl/CreateRolePermissionCmd.java      | 124 +++
 .../api/command/admin/acl/DeleteRoleCmd.java    |  83 ++
 .../admin/acl/DeleteRolePermissionCmd.java      |  83 ++
 .../admin/acl/ListRolePermissionsCmd.java       | 106 +++
 .../api/command/admin/acl/ListRolesCmd.java     | 128 +++
 .../api/command/admin/acl/UpdateRoleCmd.java    | 108 +++
 .../admin/acl/UpdateRolePermissionCmd.java      | 104 +++
 .../api/command/admin/config/UpdateCfgCmd.java  |  12 +
 .../user/config/ListCapabilitiesCmd.java        |   1 +
 .../api/response/AccountResponse.java           |  27 +
 .../api/response/CapabilitiesResponse.java      |   8 +
 .../api/response/RolePermissionResponse.java    | 101 +++
 .../cloudstack/api/response/RoleResponse.java   |  63 ++
 .../cloudstack/api/response/UserResponse.java   |  27 +
 .../org/apache/cloudstack/acl/RoleTypeTest.java | 100 ++
 .../org/apache/cloudstack/acl/RuleTest.java     |  98 ++
 .../admin/account/CreateAccountCmdTest.java     |  10 +-
 .../api/command/test/UpdateCfgCmdTest.java      |  28 +-
 .../classes/resources/messages.properties       |   8 +
 client/pom.xml                                  |   5 +
 debian/cloudstack-management.install            |   1 -
 debian/control                                  |   2 +-
 developer/developer-prefill.sql                 |   5 +
 .../spring-engine-schema-core-daos-context.xml  |   2 +
 .../com/cloud/upgrade/dao/Upgrade481to490.java  |  75 +-
 engine/schema/src/com/cloud/user/AccountVO.java |  31 +-
 .../src/com/cloud/user/dao/AccountDao.java      |   2 +
 .../src/com/cloud/user/dao/AccountDaoImpl.java  |  19 +-
 .../apache/cloudstack/acl/RolePermissionVO.java | 120 +++
 .../src/org/apache/cloudstack/acl/RoleVO.java   | 106 +++
 .../org/apache/cloudstack/acl/dao/RoleDao.java  |  29 +
 .../apache/cloudstack/acl/dao/RoleDaoImpl.java  |  61 ++
 .../cloudstack/acl/dao/RolePermissionsDao.java  |  49 +
 .../acl/dao/RolePermissionsDaoImpl.java         | 166 ++++
 plugins/acl/dynamic-role-based/pom.xml          |  32 +
 .../acl-dynamic-role-based/module.properties    |  18 +
 .../spring-acl-dynamic-role-based-context.xml   |  33 +
 .../acl/DynamicRoleBasedAPIAccessChecker.java   | 144 +++
 .../DynamicRoleBasedAPIAccessCheckerTest.java   | 164 ++++
 .../acl/StaticRoleBasedAPIAccessChecker.java    |  48 +-
 .../api/command/user/discovery/ListApisCmd.java |   3 +-
 .../manager/BaremetalVlanManagerImpl.java       |  27 +-
 .../contrail/management/MockAccountManager.java |   8 +-
 plugins/pom.xml                                 |   1 +
 .../api/command/LdapCreateAccountCmd.java       |  41 +-
 .../api/command/LdapImportUsersCmd.java         |  20 +-
 .../api/command/LinkDomainToLdapCmd.java        |   3 +-
 .../cloudstack/ldap/LdapAuthenticator.java      |   4 +-
 .../ldap/LdapImportUsersCmdSpec.groovy          |   2 +-
 scripts/util/migrate-dynamicroles.py            | 136 +++
 .../spring-server-core-managers-context.xml     |   2 +
 server/src/com/cloud/api/ApiDBUtils.java        |  27 +-
 .../com/cloud/api/ApiResponseGsonHelper.java    |   2 +-
 server/src/com/cloud/api/ApiServer.java         |   8 +-
 .../com/cloud/api/query/vo/AccountJoinVO.java   |   7 +
 .../cloud/api/query/vo/UserAccountJoinVO.java   |   7 +
 .../api/response/ApiResponseSerializer.java     |   2 +-
 .../com/cloud/projects/ProjectManagerImpl.java  |   2 +-
 .../cloud/server/ConfigurationServerImpl.java   |   6 +-
 server/src/com/cloud/user/AccountManager.java   |   2 +-
 .../src/com/cloud/user/AccountManagerImpl.java  |  37 +-
 .../apache/cloudstack/acl/RoleManagerImpl.java  | 264 ++++++
 .../com/cloud/user/MockAccountManagerImpl.java  |   6 +-
 .../iam/RoleBasedAPIAccessChecker.java          |   2 +-
 .../db/db/create-default-role-api-mappings.sql  | 902 +++++++++++++++++++
 setup/db/db/schema-481to490-cleanup.sql         | 188 ++++
 setup/db/db/schema-481to490.sql                 |  35 +
 setup/db/server-setup.sql                       |   3 +-
 setup/db/server-setup.xml                       |   7 +
 test/integration/smoke/test_dynamicroles.py     | 537 +++++++++++
 test/integration/smoke/test_staticroles.py      | 134 +++
 tools/apidoc/gen_toc.py                         |   1 +
 tools/marvin/marvin/cloudstackConnection.py     |   2 +-
 tools/marvin/marvin/lib/base.py                 |  89 +-
 ui/css/cloudstack3.css                          |  16 +
 ui/dictionary.jsp                               |   7 +
 ui/dictionary2.jsp                              |   1 +
 ui/images/icons.png                             | Bin 61164 -> 48358 bytes
 ui/index.jsp                                    |   1 +
 ui/plugins/quota/quota.js                       |  16 +-
 ui/scripts/accounts.js                          |  31 +-
 ui/scripts/accountsWizard.js                    |  38 +-
 ui/scripts/cloudStack.js                        |   3 +-
 ui/scripts/roles.js                             | 388 ++++++++
 ui/scripts/sharedFunctions.js                   |  11 +
 .../main/java/com/cloud/utils/ListUtils.java    |  31 +
 .../java/com/cloud/utils/PropertiesUtil.java    |   4 +
 100 files changed, 5633 insertions(+), 170 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index d160e48..9d9822c 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"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 7349c1f..23de152 100644
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -66,6 +66,8 @@ import com.cloud.user.User;
 import com.cloud.vm.Nic;
 import com.cloud.vm.NicSecondaryIp;
 import com.cloud.vm.VirtualMachine;
+import org.apache.cloudstack.acl.Role;
+import org.apache.cloudstack.acl.RolePermission;
 import org.apache.cloudstack.config.Configuration;
 import org.apache.cloudstack.usage.Usage;
 
@@ -166,6 +168,14 @@ public class EventTypes {
     public static final String EVENT_GLOBAL_LOAD_BALANCER_DELETE = "GLOBAL.LB.DELETE";
     public static final String EVENT_GLOBAL_LOAD_BALANCER_UPDATE = "GLOBAL.LB.UPDATE";
 
+    // Role events
+    public static final String EVENT_ROLE_CREATE = "ROLE.CREATE";
+    public static final String EVENT_ROLE_UPDATE = "ROLE.UPDATE";
+    public static final String EVENT_ROLE_DELETE = "ROLE.DELETE";
+    public static final String EVENT_ROLE_PERMISSION_CREATE = "ROLE.PERMISSION.CREATE";
+    public static final String EVENT_ROLE_PERMISSION_UPDATE = "ROLE.PERMISSION.UPDATE";
+    public static final String EVENT_ROLE_PERMISSION_DELETE = "ROLE.PERMISSION.DELETE";
+
     // Account events
     public static final String EVENT_ACCOUNT_ENABLE = "ACCOUNT.ENABLE";
     public static final String EVENT_ACCOUNT_DISABLE = "ACCOUNT.DISABLE";
@@ -605,6 +615,14 @@ public class EventTypes {
         entityEventDetails.put(EVENT_LB_CERT_ASSIGN, LoadBalancer.class);
         entityEventDetails.put(EVENT_LB_CERT_REMOVE, LoadBalancer.class);
 
+        // Role events
+        entityEventDetails.put(EVENT_ROLE_CREATE, Role.class);
+        entityEventDetails.put(EVENT_ROLE_UPDATE, Role.class);
+        entityEventDetails.put(EVENT_ROLE_DELETE, Role.class);
+        entityEventDetails.put(EVENT_ROLE_PERMISSION_CREATE, RolePermission.class);
+        entityEventDetails.put(EVENT_ROLE_PERMISSION_UPDATE, RolePermission.class);
+        entityEventDetails.put(EVENT_ROLE_PERMISSION_DELETE, RolePermission.class);
+
         // Account events
         entityEventDetails.put(EVENT_ACCOUNT_ENABLE, Account.class);
         entityEventDetails.put(EVENT_ACCOUNT_DISABLE, Account.class);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/com/cloud/user/Account.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/user/Account.java b/api/src/com/cloud/user/Account.java
index b912e51..58cedcd 100644
--- a/api/src/com/cloud/user/Account.java
+++ b/api/src/com/cloud/user/Account.java
@@ -46,6 +46,8 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity {
 
     public short getType();
 
+    public Long getRoleId();
+
     public State getState();
 
     public Date getRemoved();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/com/cloud/user/AccountService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java
index 7cc1e30..959a710 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<String, String> details, String accountUUID, String userUUID);
+        short accountType, Long roleId, Long domainId, String networkDomain, Map<String, String> 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<String, String> details, String accountUUID, String userUUID, User.Source source);
 
     /**

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/acl/Role.java
----------------------------------------------------------------------
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 0000000..b05d886
--- /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();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/acl/RolePermission.java
----------------------------------------------------------------------
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 0000000..0157a66
--- /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();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/acl/RoleService.java
----------------------------------------------------------------------
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 0000000..59eef51
--- /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<Boolean> 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<RolePermission> newOrder);
+    boolean deleteRolePermission(final RolePermission rolePermission);
+
+    List<Role> listRoles();
+    List<Role> findRolesByName(final String name);
+    List<Role> findRolesByType(final RoleType roleType);
+    List<RolePermission> findAllPermissionsBy(final Long roleId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/acl/RoleType.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/acl/RoleType.java b/api/src/org/apache/cloudstack/acl/RoleType.java
index 90e3d1e..a8a64a5 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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/acl/Rule.java
----------------------------------------------------------------------
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 0000000..2792010
--- /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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 6f3152b..4904925 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";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/BaseCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java
index 360b277..5be7519 100644
--- a/api/src/org/apache/cloudstack/api/BaseCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseCmd.java
@@ -30,6 +30,7 @@ import java.util.regex.Pattern;
 import javax.inject.Inject;
 
 import com.cloud.utils.HttpUtils;
+import org.apache.cloudstack.acl.RoleService;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.acl.RoleType;
@@ -85,6 +86,7 @@ import com.cloud.vm.snapshot.VMSnapshotService;
 
 public abstract class BaseCmd {
     private static final Logger s_logger = Logger.getLogger(BaseCmd.class.getName());
+    public static final String RESPONSE_SUFFIX = "response";
     public static final String RESPONSE_TYPE_XML = HttpUtils.RESPONSE_TYPE_XML;
     public static final String RESPONSE_TYPE_JSON = HttpUtils.RESPONSE_TYPE_JSON;
     public static final String USER_ERROR_MESSAGE = "Internal error executing command, please contact your system administrator";
@@ -104,12 +106,13 @@ public abstract class BaseCmd {
     @Parameter(name = "response", type = CommandType.STRING)
     private String responseType;
 
-
     @Inject
     public ConfigurationService _configService;
     @Inject
     public AccountService _accountService;
     @Inject
+    public RoleService roleService;
+    @Inject
     public UserVmService _userVmService;
     @Inject
     public ManagementService _mgr;
@@ -323,7 +326,7 @@ public abstract class BaseCmd {
             if (allowedRoles.length > 0) {
                 roleIsAllowed = false;
                 for (final RoleType allowedRole : allowedRoles) {
-                    if (allowedRole.getValue() == caller.getType()) {
+                    if (allowedRole.getAccountType() == caller.getType()) {
                         roleIsAllowed = true;
                         break;
                     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
----------------------------------------------------------------------
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 b55ce71..2e1fbd6 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 
+import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.ApiErrorCode;
@@ -31,6 +32,7 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView;
 import org.apache.cloudstack.api.ServerApiException;
 import org.apache.cloudstack.api.response.AccountResponse;
 import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.RoleResponse;
 import org.apache.cloudstack.context.CallContext;
 
 import com.cloud.user.Account;
@@ -55,10 +57,12 @@ public class CreateAccountCmd extends BaseCmd {
 
     @Parameter(name = ApiConstants.ACCOUNT_TYPE,
                type = CommandType.SHORT,
-               required = true,
                description = "Type of the account.  Specify 0 for user, 1 for root admin, and 2 for domain admin")
     private Short accountType;
 
+    @Parameter(name = ApiConstants.ROLE_ID, type = CommandType.UUID, entityType = RoleResponse.class, description = "Creates the account under the specified role.")
+    private Long roleId;
+
     @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "Creates the user under the specified domain.")
     private Long domainId;
 
@@ -106,7 +110,11 @@ public class CreateAccountCmd extends BaseCmd {
     }
 
     public Short getAccountType() {
-        return accountType;
+        return RoleType.getAccountTypeByRole(roleService.findRole(roleId), accountType);
+    }
+
+    public Long getRoleId() {
+        return RoleType.getRoleByAccountType(roleId, accountType);
     }
 
     public Long getDomainId() {
@@ -178,7 +186,7 @@ public class CreateAccountCmd extends BaseCmd {
         validateParams();
         CallContext.current().setEventDetails("Account Name: " + getAccountName() + ", Domain Id:" + getDomainId());
         UserAccount userAccount =
-            _accountService.createUserAccount(getUsername(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimeZone(), getAccountName(), getAccountType(),
+            _accountService.createUserAccount(getUsername(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimeZone(), getAccountName(), getAccountType(), getRoleId(),
                 getDomainId(), getNetworkDomain(), getDetails(), getAccountUUID(), getUserUUID());
         if (userAccount != null) {
             AccountResponse response = _responseGenerator.createUserAccountResponse(ResponseView.Full, userAccount);
@@ -196,5 +204,8 @@ public class CreateAccountCmd extends BaseCmd {
         if(StringUtils.isEmpty(getPassword())) {
             throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Empty passwords are not allowed");
         }
+        if (getAccountType() == null && (getRoleId() == null || getRoleId() < 1L)) {
+            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Neither account type and role ID are not provided");
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java
----------------------------------------------------------------------
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 0000000..994573d
--- /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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/CreateRolePermissionCmd.java
----------------------------------------------------------------------
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 0000000..aeb3f4e
--- /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);
+     }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRoleCmd.java
----------------------------------------------------------------------
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 0000000..bd4a7cd
--- /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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/DeleteRolePermissionCmd.java
----------------------------------------------------------------------
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 0000000..9c7dc7c
--- /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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolePermissionsCmd.java
----------------------------------------------------------------------
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 0000000..f20abf4
--- /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<RolePermission> rolePermissions, final Long roleId) {
+        final Role roleProvided = roleService.findRole(roleId);
+        final ListResponse<RolePermissionResponse> response = new ListResponse<>();
+        final List<RolePermissionResponse> 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<RolePermission> rolePermissions = roleService.findAllPermissionsBy(getRoleId());
+        setupResponse(rolePermissions, getRoleId());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/ListRolesCmd.java
----------------------------------------------------------------------
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 0000000..5cf870b
--- /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<Role> roles) {
+        final ListResponse<RoleResponse> response = new ListResponse<>();
+        final List<RoleResponse> 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<Role> 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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRoleCmd.java
----------------------------------------------------------------------
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 0000000..e17fc6f
--- /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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
----------------------------------------------------------------------
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 0000000..055265c
--- /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<Long> rulePermissionOrder;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Long getRoleId() {
+        return roleId;
+    }
+
+    public List<Long> 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<RolePermission> 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java
----------------------------------------------------------------------
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 0124d59..45f790f 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java
@@ -16,6 +16,8 @@
 // under the License.
 package org.apache.cloudstack.api.command.admin.config;
 
+import com.google.common.base.Strings;
+import org.apache.cloudstack.acl.RoleService;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.api.APICommand;
@@ -81,6 +83,10 @@ public class UpdateCfgCmd extends BaseCmd {
         return cfgName;
     }
 
+    public void setCfgName(final String cfgName) {
+        this.cfgName = cfgName;
+    }
+
     public String getValue() {
         return value;
     }
@@ -117,6 +123,12 @@ public class UpdateCfgCmd extends BaseCmd {
 
     @Override
     public void execute() {
+        if (Strings.isNullOrEmpty(getCfgName())) {
+            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Empty configuration name provided");
+        }
+        if (getCfgName().equalsIgnoreCase(RoleService.EnableDynamicApiChecker.key())) {
+            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Restricted configuration update not allowed");
+        }
         Configuration cfg = _configService.updateConfiguration(this);
         if (cfg != null) {
             ConfigurationResponse response = _responseGenerator.createConfigurationResponse(cfg);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java
----------------------------------------------------------------------
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 24486a3..9c52656 100644
--- a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java
@@ -47,6 +47,7 @@ public class ListCapabilitiesCmd extends BaseCmd {
         Map<String, Object> 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"));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/response/AccountResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java
index 2e50c51..7b48a1e 100644
--- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java
@@ -21,6 +21,7 @@ import java.util.Map;
 
 import com.google.gson.annotations.SerializedName;
 
+import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseResponse;
 import org.apache.cloudstack.api.EntityReference;
@@ -43,6 +44,18 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
     @Param(description = "account type (admin, domain-admin, user)")
     private Short accountType;
 
+    @SerializedName(ApiConstants.ROLE_ID)
+    @Param(description = "the ID of the role")
+    private String roleId;
+
+    @SerializedName(ApiConstants.ROLE_TYPE)
+    @Param(description = "the type of the role (Admin, ResourceAdmin, DomainAdmin, User)")
+    private String roleType;
+
+    @SerializedName(ApiConstants.ROLE_NAME)
+    @Param(description = "the name of the role")
+    private String roleName;
+
     @SerializedName(ApiConstants.DOMAIN_ID)
     @Param(description = "id of the Domain the account belongs too")
     private String domainId;
@@ -260,6 +273,20 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
         this.accountType = accountType;
     }
 
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+    public void setRoleType(RoleType roleType) {
+        if (roleType != null) {
+            this.roleType = roleType.name();
+        }
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
     public void setDomainId(String domainId) {
         this.domainId = domainId;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java
index 623a0a2..bcdad46 100644
--- a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java
@@ -28,6 +28,10 @@ public class CapabilitiesResponse extends BaseResponse {
     @Param(description = "true if security groups support is enabled, false otherwise")
     private boolean securityGroupsEnabled;
 
+    @SerializedName("dynamicrolesenabled")
+    @Param(description = "true if dynamic role-based api checker is enabled, false otherwise")
+    private boolean dynamicRolesEnabled;
+
     @SerializedName("cloudstackversion")
     @Param(description = "version of the cloud stack")
     private String cloudStackVersion;
@@ -84,6 +88,10 @@ public class CapabilitiesResponse extends BaseResponse {
         this.securityGroupsEnabled = securityGroupsEnabled;
     }
 
+    public void setDynamicRolesEnabled(boolean dynamicRolesEnabled) {
+        this.dynamicRolesEnabled = dynamicRolesEnabled;
+    }
+
     public void setCloudStackVersion(String cloudStackVersion) {
         this.cloudStackVersion = cloudStackVersion;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/response/RolePermissionResponse.java
----------------------------------------------------------------------
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 0000000..ac1c529
--- /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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4347776a/api/src/org/apache/cloudstack/api/response/RoleResponse.java
----------------------------------------------------------------------
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 0000000..fd4bf28
--- /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;
+    }
+}


Mime
View raw message