Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

  • Use the commands.properties and 'authorized' mechanism to specify who can invoke the API.
  • Additionally, specify what entity the API Cmd operates on in entityType attribute of the @APICommand annotation.

    Code Block
    @APICommand(name = "deployVirtualMachine", ..... entityType = { VirtualMachine.class })
    public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd {
    ...
    }
  • IAM service will read these permissions from both inputs and load it to the DB, So any change to commands.properties file should take effect on a restart as it used to be.
  • However remember both of them allow setting permissions for CloudStack's default policies only. (User/Resource Domain Admin/Domain Admins/Root Admin Policy)
  • Custom Policies: While IAM feature will support creating custom policies, the permissions for these custom policies need to be set separately using the IAM APIs

...

  • Until 4.4, CloudStack did not distinguish between a read-only access Vs read-and-use access Vs operate access. 
  • CloudStack access control layer always checked if the caller is owner of the entity and granted all types of access based on that. 
  • With IAM feature following are the types of entity access one can specify:
    1. ListEntry  (read only access)
    2. UseEntry  (read and use access)
    3. OperateEntry (operate/execute access)

Code Block
bordertrue
<p>ExampleExample: A domainAdmin registers a template T and allows a regular user of the domain to launch a VM using that template.</p><p>Entity
Entity: TemplateT<br />Principal1:&nbsp;Template T
Principal1: domainAdmin, Access allowed: OperateEntry&nbsp;&nbsp; (operate access since he can invoke delete/updatepermissions operations on the template)<br />Principal2
Principal2: normal domain user, Access allowed: UseEntry&nbsp; (the user can only list the template and use it for launching VM)</p>

 

IAM At API layer: use @ACL

...

  • create APIs : one needs @ACL(accessType = AccessType.UseEntry) on all the entities required to be used for creating the desired new entity
  • update/delete APIs: These modify or operate on an entity and change its state. @ACL(accessType = AccessType.OperateEntry) should be used in these APIs on the parameter that identifies the main entity being modified.

 

true
Section
border
Code Block
Example:

DeployVMCmd:  This is a create API: Add @ACL(accessType = AccessType.UseEntry access for all entities like template, network

Start/Stop/Reboot/Destroy/AttachXXXTOVM: These are the update/delete APIs. Add @ACL(accessType = AccessType.OperateEntry)
access
 for VM
ID parameter that identifies the VM entity being operated on
 ID

 

IAM At Service Layer:

CS Service layer logic uses  "accountManager.checkAccess" to invoke the SecurityCheckers to do access control. Instead, one should try to use @ACL annotation on the API parameters that have to be checked for access.

...

Code Block
        Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(cmd.getDomainId(), cmd.isRecursive(), null);
        _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedDomains, permittedAccounts, permittedResources, domainIdRecursiveListProject, cmd.listAll(), false, "listFirewallRules");
		.......
        SearchBuilder<FirewallRuleVO> sb = _firewallDao.createSearchBuilder();
        _accountMgr.buildACLSearchBuilder(sb, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria);
		......
        SearchCriteria<FirewallRuleVO> sc = sb.create();
        _accountMgr.buildACLSearchCriteria(sc, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria);

 

 

Command and Response View Separation

For some commands that can be invoked by both admin and user, if you want to provide different response contents to root admin and non-root user, for example, some response fields are only visible to root admin. We have defined two enumeration types (ResponseView.Full and ResponseView.Restricted) for these two types of response views. You should split your API command to two classes: API for admin that will return Full response view and may take additional admin-only parameters and API for user that will return Restricted response view. For example, previous ListVMsCmd has been splitted into two classes: ListVMsCmdByAdmin and ListVMsCmd. The naming convention is that the API command class that returns Full response view should have a suffix "ByAdmin". We also introduced a new annotation (responseView) in @APICommand to specify which response view should be returned from this command. Normally, ***ByAdmin class can be extended from its restricted view class. Here is an example of this command split and response view annotation:

Code Block
@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, 
entityType = { VirtualMachine.class })
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;
}

In execute() of these two command classes, we should make a distinction to create different response content based on responseView annotation.