Security concerns:

1) Sensitive information in requests should never be sent using query parameters.  The URLs (including the query parameters with the sensitive values) are frequently saved in many places downstream (e.g., browser cache, proxy servers, etc.)  Existing APIs such as addBaremetalDhcp, addBaremetalHost, addBaremetalPxeKickStartServer, addBaremetalPxePingServer, addCiscoVnmcResource, addCluster, addExternalFirewall, addExternalLoadBalancer, addF5LoadBalancer, addHost, addImageStore, addNetscalarLoadBalancer, addNiciraNvpDevice, addPaloAltoFirewall, addS3, addSRXFirewall, addStratosphereSsp, addUcsManager, addVmwareDc, addVpnUser, createAccount, createUser, createVolumeOnFiler, login, updateCloudToUseObjectStore, updateHostPassword, updateUser, uploadCustomCertificate, uploadSslCert and such should probably require that their request parameters be sent in a HTTP POST body.

2) Responses should contain only the information requested; sensitive parameters such as passwords or keys must only be returned if they are explicitly requested and even then only for parameters which CloudStack has created.  CloudStack could return its users' secret keys, for example, but there is no reason that CloudStack should return Xen host passwords, S3 secret keys, etc.  The 4.x design includes the complete state of an object instance in the response for every API which manipulates the object.  Examples:  The removeNicFromVirtualMachine API returns the VM password in the response, the disableUser API returns the user's secret key in the response, the addS3 API returns the S3 secret key, and so on.

3) Guards need to be put into place to prevent XSS and other malicious payloads from making it into the database

naming

the naming of API calls and - parameters are not consistent leading to them not being as intuitive as could be to the application programmers leveraging them. This is a place holder to list such occasions so we can address them on going into 5.0. Please add to this list.

  • DeployVM - most create calls are being called Create... some aren't
  • The use of GuestCidrs for the cidrs af a remote peer of a vpn connection

API Gap with IAM

In developing IAM feature, we realized that serveral areas of current APIs which are not compatible with correct and real IAM model we have introduced. For these reasons, we have to disable IAM feature in 4.4 release to keep API backward compatibility.

List APIs

Current implementation of the list APIs is tied tightly with the default roles  (root admin,domainadmin, regular user), and we have hard-coded logic baked in to handle these three out-of-box roles differently.The List APIs do not interpret the listing parameters in a standard way across board. Depending on which role is invoking the call, the logic assumes some default behavior in the given context and provides results by ignoring the passed listing parameter. Most contradictory parameters are these four: listall, isrecursive, domainid, account.  Here is a summary of current API behavior in handling these four APIs;

 

 

Category

listAll

isRecursive

Result

Both domainId and account are provided

IGNORED

IGNORED

 Only list resources owned by the given account, even though the specified account is a root admin or domain admin. Basically listAll and isRecursive flags are totally ignored.

Neither domainId nor account is provided

(caller = NORMAL USER)

IGNORED

IGNORED

Only list resources owned by the caller.  Basically listAll and isRecursive flags are totally ignored.

Neither domainId nor account is provided

(caller = ROOT ADMIN)

TRUE

IGNORED

Always list all the authorized resources for the root admin, isRecursive flag is ignored.

 

FALSE

IGNORED

Only list resources owned by the root admin

Neither domainid nor account is provided

(caller = DOMAIN ADMIN)

TRUE

IGNORED

Always list all the authorized resource along the domain tree, ignore passed isRecursive flag and internally set it to always TRUE.

 

FALSE

IGNORED

Only list resources owned by the domain admin. isRecursive flag is not taking effect

Only domainId is provided

(caller = NORMAL USER)

IGNORED

IGNORED

Only list resources owned by the caller.

Only domainId is provided

(caller = ROOT/DOMAIN ADMIN)

IGNORED

TRUE

List the authorized resources along the domain tree.

 

IGNORED

FALSE

List the authorized resources only for the given domain.

 

 

There are several issues with current behavior:

  • Interpretation of specified (domainid, account) is different for different list APIs. For most APIs, it is interpreted just as a filter, that is, show resources owned by the passed account. But for listNetworks, it is interpreted as "impersonation", that is, showing resources that can be used by the passed account.
  • isRecursive flag meaning is not consistently followed.  For Domain admin, if listAll=true, no matter what isRecursive is passed, it will always show all the resources along his domain hierarchy. But this is not similarly followed by ROOT ADMIN logic.
  • There is no clear definition of which one takes precedence, listAll or isRecursive, some cases, listAll override isRecursive. Other times, isRecursive override listAll. From apidoc, nobody can figure out what should be the expected results when they intermingle together.

With this hard-coded baked logic specific to each account type, the implementation will be very hard to extend to handle true IAM usecases with customized roles introduced, since we need to define what the meaning of these parameters for those customized roles. With real IAM, the listing should follow a standard pattern and work with the list API parameters irrespective of who is the caller - the IAM policies attached to the caller should drive the results. In IAM, we have proposed the following standard semantics for these 4 parameters:

 

  • listAll flag is always taking precedence to provide a superset of content to be filtered by other query parameters. listAll is defaulted to FALSE if not passed.

listAll = true  ---- the super set should contain all the resources that caller can READ.  (Before IAM grant introduced, READ resources will be all the authorized resources that can be seen)

listAll = false  ---- the super set should contain all the resources that caller can USE.     (Before IAM grant introduced, USE resources will be self owned resources

  • isRecursive should only take effect when only domainid (but no account) is passed, it will further filter contents returned from listAll evaluation related to the provided domain. isRecursive is defaulted to false if not passed no matter whether listAll is passed or not.

isRecursive = true ---- filter the content from listAll evaluation to resources within that domain tree.

isRecursive = false ---- filter the content from listAll evaluation to resources only of that domain.

  • When (domainid, account) is passed, we will just treat it another filter of content from listAll evaluation to resources owned by the given account. This is just another filter criteria, NOT some kind of impersonation. What this means is if listAll=false and account passed in is different from caller, then nothing should be returned. But current cloudstack implementation may behave differently, we need to document this change.
  • We will communicate this same semantics for current fixed account type (NORMAL, ROOT ADMIN, DOMAIN ADMIN) and customized groups/roles extended from IAM. There will be no special/different hard-coded interpretation of these parameters based on different account type anymore.

 

Create APIs

  • The owner of the entities being created is implicitly derived from other entities used in the creation. This will break granting, even if user A grants a resource to user B, the entity created by user B is still owned by user A.

Example: AssociateIpAddress from a Network, always sets the Network owner as the owner of the IpAddress acquired newly. This implicit derivation will break IAM granting across accounts. Since if Account A grants her network to Account B, the IpAddress Account B acquires will still be owned by account A. So the grant does not really work.

  • Incorrect impersonation implementation. For some create APIs, they accept (domainId, account) parameters to allow admin to perform this create operation on behalf of the passed account. But internally service layer access checker is still based on the caller (admin itself instead of the impersonated person), this is incorrect. To make this work in current API, CloudStack code has to give absolute power to root admin, which is violating IAM rules.

Impersonation Semantics

Few CS APIs accept account-domain parameters as a way to indicate impersonation, but this is not followed across all APIs. So to support impersonation via IAM, we need to change APIs to deprecate these (account, domainId) impersonation and come up with a new impersonate API to have a standard impersonation mechanism.

 

  • No labels