Background
Currently CloudStack provides very limited IAM services and there are several drawbacks within those services:
- Offers few roles out of the box (user and admin) with prebaked access control for these roles. There is no way to create additional roles with customized permissions.
- Some resources have access control baked into them. E.g., shared networks, projects etc.
- We have to create special dedicate API to grant permissions.
Goal for this feature would be to address these limitations and offer true IAM services in a phased manner
Architecture and Design description
IAM Taxonomy
Group
Group contains a number of CloudStack accounts. Customers should be able to Create, Edit, List and Delete Groups. Editing includes adding or removing accounts to or from a group. For backwards compatibility, out of box, CloudStack will provide 3 default groups:
- Root Admin Group
- Domain Admin Group
- End User Group
Account
Account is just our current CloudStack Account, all the permission controls are done at Account level. We can assign an Account to more than one Group.
User
CloudStack user just contains login credentials, and this is not the level that we are performing permission control.
Policy
Policy is a set of permission. Customer should be able to attach several policies to a Group to define the permission for that group. By default, we have the following 3 types of policy templates:
- Root Admin Policy: have permissions to all resources in the CloudStack.
- Domain Admin Policy: have permissions to all resources under the belonging domain.
- Resource Owner Policy: have permissions to all owned resources.
Other than that, customer should be able to define customized policies by grant or deny permission to customize permissions for the group. So far, for cross-account permission grant, we are currently supporting the following 3 types of granting/denying:
- Grant by Domain and Resource Type: grant permissions to all resources of the given resource type under the given domain.
- Grant by Account and Resource Type: grant permissions to all resources of the given resource type under the given account.
- Grant by individual resource: grant permission to an individual resource.
Permission
A policy consists of set of Permissions. A Permission is a way of defining access control.
Using Permission, customer defines what actions are allowed or denied, on what resources, under which account or domain.
A single permission definition consists of:
- Action (API Name)
- Allow / Deny
- Scope (Account | Domain | Resource)
- Scope Id (Id of the above defined scope)
- Resource Type
Response View (Column Filter)
Currently CloudStack supports two different views: Admin view for root admin user, User view for domain admin and end user. With IAM added, we still need to support this for newly added account groups. Analogy to row filter controlled by Permission, this is like column filter. For this release, we are not supporting dynamic column filter at API level, instead, out-of-box, we will provide two static response views: Admin view and User view. When user is creating a group, they can specify what kind of view that this group account should see.
IAM Schema
![](/confluence/download/attachments/34838986/iam_schema.png?version=4&modificationDate=1394748493000&api=v2)
IAM API
New API's
- createAclGroup
- String name - name of the ACL group. Required
- String description - short decsription
- String domainId - UUID of the domain of the account owning the acl group
- deleteAclGroup
- String id - UUID of the ACL group. Required
- listAclGroups
- String name - name of the ACL group.
- String id - UUID of the ACL group.
- addAccountToAclGroup
- String id - UUID of the ACL group. Required
- List<String> accounts - comma separated list of account id that are going to be assigned to the acl group
- removeAccountFromAclGroup
- String id - UUID of the ACL group. Required
- List<String> accounts - comma separated list of account id that are going to be removed from the acl group
- createAclPolicy
- String name - name of the ACL Policy. Required
- String description - short decsription
- String domainId - UUID of the domain of the account owning the acl policy
- deleteAclPolicy
- String id - UUID of the ACL Policy. Required
- listAclPolicies
- String name - name of the ACL policy.
- String id - UUID of the ACL policy.
- attachAclPolicyToAclGroup
- String id - UUID of the ACL group. Required
- List<String> policies - comma separated list of policy ids that are going to be assigned to the acl group
- removeAclPolicyFromAclGroup
- String id - UUID of the ACL group. Required
- List<String> policies- comma separated list of policy ids that are going to be revoked from the acl group
- createAclPermission
- String action - name of the API allowed/denied. Required
- String permission - "Allow"/ "Deny"
- String scope- ("Account" / "Domain" / "Resource")
- String scope id - UUID of the Scope
- String resourceType
- addAclPermissionToAclPolicy
- String id - UUID of the ACL policy. Required
- List<String> permissionIds - comma separated list of permission ids that are going to be added to the acl policy
- removeAclPermissionFromAclPolicy
- String id - UUID of the ACL policy. Required
- List<String> permission Ids - comma separated list of permission ids that are going to be removed from the acl policy
IAM Interface
CloudStack currently has a domain-tree based implementation of access checks, namely com.cloud.acl.DomainChecker. This implementation is based on the an adapter interface of Cloudstack - org.apache.cloudstack.acl.SecurityChecker that defines the basic ACL interface to check ownership and access control to objects within the account/ domain.
The IAM plugin will provide another implementation of the SecurityChecker intrerface. We will also have to add to this interface some more methods or change some signatures to facilitate policy and Action based access control.
/**
* SecurityChecker checks the ownership and access control to objects within
*/
public interface SecurityChecker extends Adapter {
...
/**
* Checks if the account can access the object.
*
* @param caller
* account to check against.
* @param entity
* object that the account is trying to access.
* @param accessType
*
* @param action
*
* @return true if access allowed. false if this adapter cannot provide permission.
* @throws PermissionDeniedException
* if this adapter is suppose to authenticate ownership and the check failed.
*/
boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action) throws PermissionDeniedException;
....
}
Response View
Currently CloudStack provides different response views for Root admin and non-root user, some response fields are only visible to root admin. Basically we have provided two static response views (Admin view and User view), domain admin will also a User view. With new IAM service introduced, we should also allow customers to be able to specify what view should be applied to the new Acl group when they are creating a new customized Acl group, for example, customer care group. To achieve that, we will implement as follows:
- We will have a column in AclGroup db table to record what view to be used for this group. From Acl group creation UI, user can pick which view to be associated with this group. Note that in this release, we are not going to support full-fledged column filter (that is, allowing users to pick arbitrary columns to be see for each API). We are only supporting static view association at the Acl group level.
- We will separate all current both admin and user allowed API commands to two classes: API for admin and API for user. For example, previous ListVMsCmd will be splitted into two classes: ListVMsCmdByAdmin and ListVMsCmd.
@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.User)
public class ListVMsCmd extends BaseListTaggedResourcesCmd {
......
}
@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Admin)
public class ListVMsCmdByAdmin extends ListVMsCmd {
......
}
Note that ListVMsCmdByAdmin and ListVMsCmd are sharing the same API name "listVirtualMachines". From client perspective, this is transparent to them, CloudStack API client will still just invoke previous listVirtualMachine API, and CloudStack API server will internally consult with IAM plugin to determine the group associated with the invoking user and then determine which internal Cmd class to be invoked. There is a new attribute "responseView" introduced for @APICommand annoation, which can be used to instruct CloudStack to generate different response view. The other