Updated Branches: refs/heads/rbac 9d0d96225 -> f3ef86d29
QueryChecker interface and ACL search criteria to be used for query api for entities with db views created. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/11c0c263 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/11c0c263 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/11c0c263 Branch: refs/heads/rbac Commit: 11c0c263f217bcfa7809f16e0eb14c749f5b4e67 Parents: 9d0d962 Author: Min Chen <min.c...@citrix.com> Authored: Fri Nov 22 16:36:38 2013 -0800 Committer: Min Chen <min.c...@citrix.com> Committed: Fri Nov 22 16:36:38 2013 -0800 ---------------------------------------------------------------------- .../org/apache/cloudstack/acl/AclService.java | 8 +- .../org/apache/cloudstack/acl/QueryChecker.java | 25 ---- .../contrail/management/MockAccountManager.java | 16 +++ .../com/cloud/api/query/QueryManagerImpl.java | 23 +--- server/src/com/cloud/user/AccountManager.java | 9 ++ .../src/com/cloud/user/AccountManagerImpl.java | 128 +++++++++++++++++++ .../apache/cloudstack/acl/AclServiceImpl.java | 18 +++ .../com/cloud/user/MockAccountManagerImpl.java | 16 +++ 8 files changed, 201 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/api/src/org/apache/cloudstack/acl/AclService.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/acl/AclService.java b/api/src/org/apache/cloudstack/acl/AclService.java index 749fc15..dbdcf0b 100644 --- a/api/src/org/apache/cloudstack/acl/AclService.java +++ b/api/src/org/apache/cloudstack/acl/AclService.java @@ -20,8 +20,8 @@ import java.util.List; import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import com.cloud.utils.Pair; import com.cloud.user.Account; +import com.cloud.utils.Pair; public interface AclService { @@ -89,4 +89,10 @@ public interface AclService { List<AclRole> getEffectiveRoles(Account caller, ControlledEntity entity); + List<Long> getGrantedDomains(long accountId, AclEntityType entityType, String action); + + List<Long> getGrantedAccounts(long accountId, AclEntityType entityType, String action); + + List<Long> getGrantedResources(long accountId, AclEntityType entityType, String action); + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/api/src/org/apache/cloudstack/acl/QueryChecker.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/acl/QueryChecker.java b/api/src/org/apache/cloudstack/acl/QueryChecker.java index bbe9a2e..e8e9cf3 100644 --- a/api/src/org/apache/cloudstack/acl/QueryChecker.java +++ b/api/src/org/apache/cloudstack/acl/QueryChecker.java @@ -36,15 +36,6 @@ public interface QueryChecker extends Adapter { List<Long> getAuthorizedDomains(Account caller, AclEntityType entityType); /** - * List denied 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> getDeniedDomains(Account caller, AclEntityType entityType); - - /** * List granted accounts for the caller, given a specific entity type. * * @param caller account to check against. @@ -53,14 +44,6 @@ public interface QueryChecker extends Adapter { */ List<Long> getAuthorizedAccounts(Account caller, AclEntityType entityType); - /** - * List denied 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> getDeniedAccounts(Account caller, AclEntityType entityType); /** * List granted resources for the caller, given a specific entity type. @@ -71,13 +54,5 @@ public interface QueryChecker extends Adapter { */ List<Long> getAuthorizedResources(Account caller, AclEntityType entityType); - /** - * List denied 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> getDeniedResources(Account caller, AclEntityType entityType); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java index 1b018f9..23a0413 100644 --- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java +++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/MockAccountManager.java @@ -397,6 +397,22 @@ public class MockAccountManager extends ManagerBase implements AccountManager { // TODO Auto-generated method stub return false; } + + @Override + public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedDomains, List<Long> permittedAccounts, + List<Long> permittedResources, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation, + String action) { + // TODO Auto-generated method stub + + } + + @Override + public void buildACLViewSearchCriteria(SearchCriteria<? extends ControlledEntity> sc, SearchCriteria<? extends ControlledEntity> aclSc, boolean isRecursive, + List<Long> permittedDomains, List<Long> permittedAccounts, List<Long> permittedResources, ListProjectResourcesCriteria listProjectResourcesCriteria) { + // TODO Auto-generated method stub + + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/server/src/com/cloud/api/query/QueryManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index f55fcd8..37f4632 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -29,12 +29,10 @@ import javax.inject.Inject; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; -import org.apache.cloudstack.acl.AclEntityType; import org.apache.cloudstack.acl.AclGroup; import org.apache.cloudstack.acl.AclRole; import org.apache.cloudstack.acl.AclService; import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.dao.AclGroupDao; import org.apache.cloudstack.acl.dao.AclRoleDao; import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO; @@ -749,20 +747,17 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { private Pair<List<UserVmJoinVO>, Integer> searchForUserVMsInternal(ListVMsCmd cmd) { Account caller = CallContext.current().getCallingAccount(); + List<Long> permittedDomains = new ArrayList<Long>(); List<Long> permittedAccounts = new ArrayList<Long>(); - - // get granted or denied entity instance permissions - Pair<List<Long>, List<Long>> idPair = _aclService.getAclEntityPermission(caller.getId(), AclEntityType.VM.toString(), AccessType.ListEntry); - List<Long> grantedIds = idPair.first(); - List<Long> revokedIds = idPair.second(); + List<Long> permittedResources = new ArrayList<Long>(); boolean listAll = cmd.listAll(); Long id = cmd.getId(); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>( cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, - domainIdRecursiveListProject, listAll, false); - Long domainId = domainIdRecursiveListProject.first(); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedDomains, permittedAccounts, permittedResources, + domainIdRecursiveListProject, listAll, false, "listVirtualMachines"); + //Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); @@ -773,10 +768,6 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { SearchBuilder<UserVmJoinVO> sb = _userVmJoinDao.createSearchBuilder(); sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids - // build acl search builder condition - _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, - listProjectResourcesCriteria, grantedIds, revokedIds); - Map<String, String> tags = cmd.getTags(); String hypervisor = cmd.getHypervisor(); Object name = cmd.getName(); @@ -854,10 +845,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // populate the search criteria with the values passed in SearchCriteria<UserVmJoinVO> sc = sb.create(); + SearchCriteria<UserVmJoinVO> aclSc = _userVmJoinDao.createSearchCriteria(); // building ACL search criteria - _accountMgr.buildACLViewSearchCriteria(sc, domainId, isRecursive, permittedAccounts, - listProjectResourcesCriteria, grantedIds, revokedIds); + _accountMgr.buildACLViewSearchCriteria(sc, aclSc, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria); if (tags != null && !tags.isEmpty()) { SearchCriteria<UserVmJoinVO> tagSc = _userVmJoinDao.createSearchCriteria(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/server/src/com/cloud/user/AccountManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java index 24bf648..ed5ff17 100755 --- a/server/src/com/cloud/user/AccountManager.java +++ b/server/src/com/cloud/user/AccountManager.java @@ -107,6 +107,15 @@ public interface AccountManager extends AccountService { void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedAccounts, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation); + // new ACL model routine for query api based on db views + void buildACLSearchParameters(Account caller, Long id, + String accountName, Long projectId, List<Long> permittedDomains, List<Long> permittedAccounts, List<Long> permittedResources, + Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation, String action); + + void buildACLViewSearchCriteria(SearchCriteria<? extends ControlledEntity> sc, SearchCriteria<? extends ControlledEntity> aclSc, boolean isRecursive, + List<Long> permittedDomains, List<Long> permittedAccounts, + List<Long> permittedResources, ListProjectResourcesCriteria listProjectResourcesCriteria); + /** * Deletes a user by userId * http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/server/src/com/cloud/user/AccountManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 6a5b29c..1e32aef 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -2537,4 +2537,132 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return _userAccountDao.getUserByApiKey(apiKey); } + @Override + public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedDomains, List<Long> permittedAccounts, + List<Long> permittedResources, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation, + String action) { + Long domainId = domainIdRecursiveListProject.first(); + if (domainId != null) { + // look for entity in the given domain + Domain domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + } + // check permissions + checkAccess(caller, domain); + } + + if (id != null) { + // look for an individual entity, no other permission criteria are needed + permittedResources.add(id); + return; + } + + if (accountName != null) { + if (projectId != null) { + throw new InvalidParameterValueException("Account and projectId can't be specified together"); + } + + Account userAccount = null; + Domain domain = null; + if (domainId != null) { + userAccount = _accountDao.findActiveAccount(accountName, domainId); + domain = _domainDao.findById(domainId); + } else { + userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId()); + domain = _domainDao.findById(caller.getDomainId()); + } + + if (userAccount != null) { + //check permissions + checkAccess(caller, null, false, userAccount); + permittedAccounts.add(userAccount.getId()); + } else { + throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid()); + } + } + + // set project information + if (projectId != null) { + if (!forProjectInvitation) { + if (projectId.longValue() == -1) { + if (isNormalUser(caller.getId())) { + permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId())); + } else { + domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.ListProjectResourcesOnly); + } + } else { + Project project = _projectMgr.getProject(projectId); + if (project == null) { + throw new InvalidParameterValueException("Unable to find project by id " + projectId); + } + if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) { + throw new PermissionDeniedException("Account " + caller + " can't access project id=" + projectId); + } + permittedAccounts.add(project.getProjectAccountId()); + } + } + } else { + domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources); + + // search for policy permissions associated with caller to get all his authorized domains, accounts, and resources + // Assumption: if a domain is in grantedDomains, then all the accounts under this domain will not be returned in "grantedAccounts". Similarly, if an account + // is in grantedAccounts, then all the resources owned by this account will not be returned in "grantedResources". + List<Long> grantedDomains = _aclService.getGrantedDomains(caller.getId(), AclEntityType.VM, action); + List<Long> grantedAccounts = _aclService.getGrantedAccounts(caller.getId(), AclEntityType.VM, action); + List<Long> grantedResources = _aclService.getGrantedResources(caller.getId(), AclEntityType.VM, action); + + if (domainId != null) { + // specific domain is specified + if (grantedDomains.contains(domainId)) { + permittedDomains.add(domainId); + } else { + for (Long acctId : grantedAccounts) { + Account acct = _accountDao.findById(acctId); + if (acct != null && acct.getDomainId() == domainId) { + permittedAccounts.add(acctId); + } + } + permittedResources.addAll(grantedResources); + } + } else if (permittedAccounts.isEmpty()) { + // neither domain nor account is not specified + permittedDomains.addAll(grantedDomains); + permittedAccounts.addAll(grantedAccounts); + permittedResources.addAll(grantedResources); + } + } + + } + + @Override + public void buildACLViewSearchCriteria(SearchCriteria<? extends ControlledEntity> sc, SearchCriteria<? extends ControlledEntity> aclSc, boolean isRecursive, + List<Long> permittedDomains, + List<Long> permittedAccounts, List<Long> permittedResources, ListProjectResourcesCriteria listProjectResourcesCriteria) { + + if (listProjectResourcesCriteria != null) { + sc.addAnd("accountType", SearchCriteria.Op.EQ, Account.ACCOUNT_TYPE_PROJECT); + } + + // Note that this may have limitations on number of permitted domains, accounts, or resource ids are allowed due to sql package size limitation + if (!permittedDomains.isEmpty()) { + if (isRecursive) { + for (int i = 0; i < permittedDomains.size(); i++) { + Domain domain = _domainDao.findById(permittedDomains.get(i)); + aclSc.addOr("domainPath" + i, SearchCriteria.Op.LIKE, domain.getPath() + "%"); + } + } else { + aclSc.addOr("domainIdIN", SearchCriteria.Op.IN, permittedDomains.toArray()); + } + } + if (!permittedAccounts.isEmpty()) { + aclSc.addOr("accountIdIN", SearchCriteria.Op.IN, permittedAccounts.toArray()); + } + if (!permittedResources.isEmpty()) { + aclSc.addOr("idIn", SearchCriteria.Op.IN, permittedResources.toArray()); + } + + sc.addAnd("accountIdIn", SearchCriteria.Op.SC, aclSc); + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/server/src/org/apache/cloudstack/acl/AclServiceImpl.java ---------------------------------------------------------------------- diff --git a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java index c7badd0..320b542 100644 --- a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java +++ b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java @@ -689,4 +689,22 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager { return roles; } + @Override + public List<Long> getGrantedDomains(long accountId, AclEntityType entityType, String action) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<Long> getGrantedAccounts(long accountId, AclEntityType entityType, String action) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<Long> getGrantedResources(long accountId, AclEntityType entityType, String action) { + // TODO Auto-generated method stub + return null; + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/11c0c263/server/test/com/cloud/user/MockAccountManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index 085670c..cf3bc6a 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -362,4 +362,20 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco return false; } + @Override + public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List<Long> permittedDomains, List<Long> permittedAccounts, + List<Long> permittedResources, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation, + String action) { + // TODO Auto-generated method stub + + } + + @Override + public void buildACLViewSearchCriteria(SearchCriteria<? extends ControlledEntity> sc, SearchCriteria<? extends ControlledEntity> aclSc, boolean isRecursive, + List<Long> permittedDomains, List<Long> permittedAccounts, List<Long> permittedResources, ListProjectResourcesCriteria listProjectResourcesCriteria) { + // TODO Auto-generated method stub + + } + + }