Introduction

A limited form of role-based api 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. This system also does not permit the specification of additional roles. The aim of the db-backed dynamic role based api-access checker feature is to improve upon the existing static mechanism, make it dynamic while maintaining backward compatibility, usage and assumptions around account type; while we explore for a better solution.

This feature will make the following modifications CloudStack’s role-based api access checker system to increase its robustness and flexibility:

Bug Reference

CLOUDSTACK-8562

Document History

Version

Author / Reviewer

Date

1.0

Rohit Yadav / ACS-dev community

24/March/2016

  

 

Use cases

The following are some common use cases for db-backed dynamic role based api-access checker feature:

Feature Specification

Currently, the APIChecker interface defines the mechanism to enforce role-based access controls on API calls. This interface is implemented by API plugins to provide alternative permission storage and enforcement schemes. To support this enhancement a new plugin will implement a DynamicRoleBasedAPIAccessChecker that will store the permission definitions in the management server database. This plugin will also contain API endpoints and user interface extensions to support the run time modification of the available roles, as well as, their API permission mappings.

When upgrading, CloudStack will continue to use the StaticRoleBasedAPIChecker, but will provide the ability to switch to DynamicRoleBasedAPIAccessChecker using a global setting. All new installations though will default to the DynamicRoleBasedAPIAccessChecker with a goal to deprecate the current StaticRoleBasedAPIChecker with future releases. For insuring the root admin is not locked out of the system, user/account that are root admin (of role type Admin and role id:1) will be allowed to access all APIs.

The client UI will only be modified to determine the user’s role type dynamically. It will not be modified to enable/disable elements based on a user’s permissions. Therefore, all actions would be rendered in the UI, say for a read-only admin. If a user attempts to invoke actions for which they do have access, an error message will be displayed. Finally, the plugin will be built assuming that all management servers in a cluster use the same APIChecker plugin implementation (e.g. StaticRoleBaseAPIChecker, DynamicRoleBasedAPIAccessChecker, etc).

CloudStack UI and management server have assumptions around role types. Therefore, to support this all dynamic roles will resolve to one of the four role types:  Admin, ResourceAdminDomainAdmin and User. To maintain this semantic, the system will ensure that four default roles always exist tied to these four role types.

Implementation

APIs

Both roles and role-permissions related APIs can only be allowed for and executed by root admins.

Role Management Related 

Role Permissions Related

Note: A role permission rule can be a string with a wildcard (*) which will be expanded as \w* to do regex based matching against requested API's name.

Account Creation Changes

APIChecker Implementation 

Implement  DynamicRoleBasedAPIAccessChecker that implements checkAccess() based on whether the user's role was allowed to request an API by querying the database.

The process of checking user account access for a request API will be as follows:

A PermissionDeniedException will be thrown when API needs to be denied for a caller user account.

Example - to create a read-only role, such a role need to first allow all list operation, i.e. list*-allow rule and then explicitly say a *-deny rule to avoid any API that may be allowed/enabled due to annotation rules.

Schema

A. Table for Dynamic roles

roles:
id (bigint, auto increment),
uuid (varchar, unique),
name (varchar, unique),
role_type (enum/string),
description (text),
removed (datetime)

B. Table for mappings between roles and enabled apis

role_permissions:
id (bigint, auto increment),
role_id (bigint),
rule (varchar),
permission (allow or deny, enum/string),
description (text) 

C. Changes to existing tables

Introduce new column in cloud.accounts table: role_id
The getRoleType() method for Accounts will use the dynamic roles table to translate the account to a role type.
Introduction of the role_id column in accounts table would also require us to make rebuild view with the column: account_view and user_view.

D. Data migration and Upgrade Strategy

Older installations can migrate to the new DynamicRoleBasedAPIAccessChecker, for this the old rules from commands.properties will need to be migrated to the role_permissions table. This can be done in a Java based upgrade path.

As an example, this python script shows how we can read rules from the commands.properties file and insert the enabled APIs in the role_permissions table: https://gist.github.com/bhaisaab/646f9bf27ab2198f8b2d

DB upgrade path process:

E. Upgrade recommendations for future API/Plugin author

New APIs can be enabled by default by setting list of allowed roletypes in @ApiCommand authroized field to set default rules. So, after upgrading CloudStack when new plugins will bring in new APIs; if those APIs don't match any pre-defined allow/deny rules, their annotations will be used to check against calling user account's role type to determine API access. Alternatively, for a given set of roles by listing roles of a given type (admin, resource admin, domain admin or user) and they can add upgrade path which will add permission to allow their new apis for a set of roles in role_permissions table. Set of new APIs per release can be listed in all future release notes and after an upgrade the root admins can choose to add/remove API permissions for roles at their discretion. 

API Docs

The purpose of the API doc is to share information about an API to its users. With this feature, there might be various roles with various API permissions. Also the previous API docs for root admin, domain admin and user were based on the default commands.properties file, which could be different in different deployments. It is proposed that with this feature, we can remove commands.properties file and fix the ApiXmlDocWriter such that it outputs a unified API doc covering all the APIs available in a release irrespective of available user type or roles (root domain, domain or user etc).

UI Changes

List of available roles to shown in dropdown, in ui/scripts/accounts.js, so that admin define roles can be selected when an account is created. Role and role-rule management from UI.

Testing

Marvin tests cases

Regression tests