Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents
indent20px
styledisc

Background

Currently CloudStack provides very limited IAM services and there are several drawbacks within those services:

...

Architecture and Design description

IAM Taxonomy

Gliffy Diagram
sizeL
nameiamTaxonomy

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:

...

The IAM plugin will provide another implementation 'PolicyBasedAccessChecker' of the SecurityChecker interface. We will also have to add to this interface some more methods or change some signatures to facilitate group, policy and api name (action) based access control.

Code Block

/**
* 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;

....
}

...

IAM Plugin 'PolicyBasedAccessChecker' will implement the APIChecker interface.

Code Block

// APIChecker checks the ownership and access control to API requests
public interface APIChecker extends Adapter {
    // Interface for checking access for a role using apiname
    // If true, apiChecker has checked the operation
    // If false, apiChecker is unable to handle the operation or not implemented
    // On exception, checkAccess failed don't allow
    boolean checkAccess(User user, String apiCommandName) throws PermissionDeniedException;
}

...

Besides SecurityChecker and APIChecker interface, IAM plugin will also implement another QueryChecker interface to allow CloudStack to do proper row filter in ListAPI based on caller's policy. In this phase, we only support explicitly grant permission, not deny permission.

Code Block

/**
* QueryChecker returns granted domain, or account or resources for caller.
*/
public interface QueryChecker extends Adapter {

...

/**
* List granted domains for the caller, given a specific entity type.
*
* @param caller account to check against.
* @param entityType entity type
* @return list of domain Ids granted to the caller account.
*/
List<Long> getAuthorizedDomains(Account caller, String entityType);

/**
* List granted accounts for the caller, given a specific entity type.
*
* @param caller account to check against.
* @param entityType entity type
* @return list of domain Ids granted to the caller account.
*/
List<Long> getAuthorizedAccounts(Account caller, String entityType);


/**
* List granted resources for the caller, given a specific entity type.
*
* @param caller account to check against.
* @param entityType entity type
* @return list of domain Ids granted to the caller account.
*/
List<Long> getAuthorizedResources(Account caller, String entityType);

...

  1. 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.
  2. 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.

    Code Block
    
    @APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted)
    public class ListVMsCmd extends BaseListTaggedResourcesCmd {
    ......
    }
    
    @APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Full)
    public class ListVMsCmdByAdmin extends ListVMsCmd {
        /////////////////////////////////////////////////////
        //////////////// API parameters /////////////////////
        /////////////////////////////////////////////////////
    
        @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType=HostResponse.class,
                description="the host ID")
        private Long hostId;
    
        @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
                description="the pod ID")
        private Long podId;
    
        @Parameter(name=ApiConstants.STORAGE_ID, type=CommandType.UUID, entityType=StoragePoolResponse.class,
                description="the storage ID where vm's volumes belong to")
        private Long storageId;
    }
    

    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. By separating the command class into admin cmd class and user cmd class, we can also restrict valid input parameters for different account. For example, in this case, when Admin invokes listVirtualMachine api, he/she can pass hostId, podId and storageId, which parameters are not applicable for end user.

Default Policy

Default Policy Generation Flow

...

The StartVMCmd will contain an annotation on the field that needs to be checked for access:

Code Block

@APICommand(name = "startVirtualMachine", responseObject = UserVmResponse.class, description = "Starts a virtual machine.")
public class StartVMCmd extends BaseAsyncCmd {
    public static final Logger s_logger = Logger.getLogger(StartVMCmd.class.getName());

    private static final String s_name = "startvirtualmachineresponse";

    // ///////////////////////////////////////////////////
    // ////////////// API parameters /////////////////////
    // ///////////////////////////////////////////////////

    @ACL(action="startVirtualMachine")
    @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType=UserVmResponse.class,
            required = true, description = "The ID of the virtual machine")
    private Long id;

...

What should be the method of ‘creating a custom Policy/Role’?
For this release, creating a custom policy is supported through API only.
For further releases, we can provide either a UI or a config file + policy language mechanism to facilitate the custom policy creation.

Component Design

IAM feature will be making use of CloudStack's plugin framework and will be implemented as a separate plugin. The end goal is to be able to host the IAM server as an independent service listening at an endpoint which the CS API service calls to do access checks.

IAM plugin will be developed under cloudstack-services project so that in future it can be easily separated as a service.

Following is the code base structure for the IAM feature:

 

Image Added

 

cloud-iam service will be having two parts:

  •  plugin
    • This will be a CloudStack plugin and will integrate with CloudStack API/Server projects for all ACL related functionality through adapter implementations that get injected in the core CS components.
    • Contains implementations of all the ACL related adapter interfaces of CloudStack namely, SecurityChecker, APIChecker and the new QuerySelector
    • Contains the new ACL APIs related to group/policy/permission CRUD operations and APIS related to account-group associations.
  •  server
    • This will be an implementation of the pure IAM/RBAC model and is independent of any CloudStack terminology
    • Contains IAM interfaces dealing with group-policy-permission
    • Contains a GenericDao based implementation of these interfaces
    • Thus in order to work with a different IAM implementation say LDAP/AD based, one will have to implement the IAM server interfaces. The plugin portion and its integration with CS will not be affected.

...

 

Following component diagram illustrates these boundaries:

Gliffy Diagram
nameIAM_component_deployment