Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6D5D8105CE for ; Thu, 10 Oct 2013 05:04:41 +0000 (UTC) Received: (qmail 41773 invoked by uid 500); 10 Oct 2013 05:04:40 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 41579 invoked by uid 500); 10 Oct 2013 05:04:40 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 41567 invoked by uid 99); 10 Oct 2013 05:04:38 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Oct 2013 05:04:38 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 6B5EC913C28; Thu, 10 Oct 2013 05:04:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: mchen@apache.org To: commits@cloudstack.apache.org Message-Id: <59e617a8f389486091c714093a8b4886@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: updated refs/heads/rbac to 2b4703b Date: Thu, 10 Oct 2013 05:04:38 +0000 (UTC) Updated Branches: refs/heads/rbac f59e47b26 -> 2b4703b6e Change ListVMsCmd to use new role and entity permission information. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2b4703b6 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2b4703b6 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2b4703b6 Branch: refs/heads/rbac Commit: 2b4703b6e62e47a14e8cadd04e7d0dbf601de6f7 Parents: f59e47b Author: Min Chen Authored: Wed Oct 9 21:56:52 2013 -0700 Committer: Min Chen Committed: Wed Oct 9 21:56:52 2013 -0700 ---------------------------------------------------------------------- .../cloudstack/acl/AclRolePermission.java | 2 + .../org/apache/cloudstack/acl/AclService.java | 8 + .../apache/cloudstack/acl/PermissionScope.java | 23 ++- .../cloudstack/acl/AclEntityPermissionVO.java | 10 +- .../cloudstack/acl/AclRolePermissionVO.java | 22 ++- .../acl/dao/AclEntityPermissionDao.java | 4 + .../acl/dao/AclEntityPermissionDaoImpl.java | 21 +++ .../acl/dao/AclRolePermissionDao.java | 4 + .../acl/dao/AclRolePermissionDaoImpl.java | 22 +++ .../com/cloud/api/query/QueryManagerImpl.java | 16 +- server/src/com/cloud/user/AccountManager.java | 9 +- .../src/com/cloud/user/AccountManagerImpl.java | 169 ++++++++++++++++--- .../apache/cloudstack/acl/AclServiceImpl.java | 64 +++++++ .../com/cloud/user/MockAccountManagerImpl.java | 7 + 14 files changed, 345 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/api/src/org/apache/cloudstack/acl/AclRolePermission.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/acl/AclRolePermission.java b/api/src/org/apache/cloudstack/acl/AclRolePermission.java index 4ec16bc..69259e2 100644 --- a/api/src/org/apache/cloudstack/acl/AclRolePermission.java +++ b/api/src/org/apache/cloudstack/acl/AclRolePermission.java @@ -27,5 +27,7 @@ public interface AclRolePermission extends InternalIdentity { AccessType getAccessType(); + PermissionScope getScope(); + boolean isAllowed(); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/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 0866b2f..c7a1174 100644 --- a/api/src/org/apache/cloudstack/acl/AclService.java +++ b/api/src/org/apache/cloudstack/acl/AclService.java @@ -20,6 +20,8 @@ import java.util.List; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import com.cloud.utils.Pair; + public interface AclService { /** @@ -76,6 +78,12 @@ public interface AclService { List getAclRoles(long accountId); + List getAclGroups(long accountId); + + AclRolePermission getAclRolePermission(long accountId, String entityType, AccessType accessType); + + Pair, List> getAclEntityPermission(long accountId, String entityType, AccessType accessType); + boolean isAPIAccessibleForRoles(String apiName, List roles); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/api/src/org/apache/cloudstack/acl/PermissionScope.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/acl/PermissionScope.java b/api/src/org/apache/cloudstack/acl/PermissionScope.java index f33e4c3..5e72747 100644 --- a/api/src/org/apache/cloudstack/acl/PermissionScope.java +++ b/api/src/org/apache/cloudstack/acl/PermissionScope.java @@ -1,7 +1,24 @@ package org.apache.cloudstack.acl; public enum PermissionScope { - ACCOUNT, - DOMAIN, - REGION; + ACCOUNT(1), + DOMAIN(2), + REGION(3); + + private int _scale; + + private PermissionScope(int scale) { + _scale = scale; + } + + public int getScale() { + return _scale; + } + + public boolean greaterThan(PermissionScope s) { + if (_scale > s.getScale()) + return true; + else + return false; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/engine/schema/src/org/apache/cloudstack/acl/AclEntityPermissionVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/acl/AclEntityPermissionVO.java b/engine/schema/src/org/apache/cloudstack/acl/AclEntityPermissionVO.java index 4e0f3c0..151e9c0 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/AclEntityPermissionVO.java +++ b/engine/schema/src/org/apache/cloudstack/acl/AclEntityPermissionVO.java @@ -41,7 +41,7 @@ public class AclEntityPermissionVO implements AclEntityPermission { AccessType accessType; @Column(name = "permission") - private boolean permission; + private boolean allowed; @Column(name = GenericDao.REMOVED_COLUMN) private Date removed; @@ -60,7 +60,7 @@ public class AclEntityPermissionVO implements AclEntityPermission { this.entityId = entityId; this.entityUuid = entityUuid; accessType = atype; - this.permission = permission; + allowed = permission; } @Override @@ -123,7 +123,11 @@ public class AclEntityPermissionVO implements AclEntityPermission { @Override public boolean isAllowed() { - return permission; + return allowed; + } + + public void setAllowed(boolean allowed) { + this.allowed = allowed; } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/engine/schema/src/org/apache/cloudstack/acl/AclRolePermissionVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/acl/AclRolePermissionVO.java b/engine/schema/src/org/apache/cloudstack/acl/AclRolePermissionVO.java index d866d91..b0fb230 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/AclRolePermissionVO.java +++ b/engine/schema/src/org/apache/cloudstack/acl/AclRolePermissionVO.java @@ -46,8 +46,12 @@ public class AclRolePermissionVO implements AclRolePermission { @Enumerated(value = EnumType.STRING) AccessType accessType; + @Column(name = "scope") + @Enumerated(value = EnumType.STRING) + PermissionScope scope; + @Column(name = "permission") - private boolean permission; + private boolean allowed; public AclRolePermissionVO() { @@ -93,7 +97,21 @@ public class AclRolePermissionVO implements AclRolePermission { } @Override + public PermissionScope getScope() { + return scope; + } + + public void setScope(PermissionScope scope) { + this.scope = scope; + } + + @Override public boolean isAllowed() { - return permission; + return allowed; } + + public void setAllowed(boolean allowed) { + this.allowed = allowed; + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDao.java index 58c3478..74427a1 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDao.java +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDao.java @@ -16,6 +16,8 @@ // under the License. package org.apache.cloudstack.acl.dao; +import java.util.List; + import org.apache.cloudstack.acl.AclEntityPermissionVO; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -25,4 +27,6 @@ public interface AclEntityPermissionDao extends GenericDao findEntityIdByGroupAndPermission(long groupId, String entityType, AccessType accessType, boolean isAllowed); + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDaoImpl.java index 482c9f3..aa7aaf4 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDaoImpl.java +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclEntityPermissionDaoImpl.java @@ -16,6 +16,8 @@ // under the License. package org.apache.cloudstack.acl.dao; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import javax.naming.ConfigurationException; @@ -47,6 +49,7 @@ public class AclEntityPermissionDaoImpl extends GenericDaoBase findEntityIdByGroupAndPermission(long groupId, String entityType, AccessType accessType, boolean isAllowed) { + List idList = new ArrayList(); + SearchCriteria sc = findByGroupEntity.create(); + sc.setParameters("groupId", groupId); + sc.setParameters("entityType", entityType); + sc.setParameters("allowed", isAllowed); + sc.setParameters("accessType", accessType); + List permList = listBy(sc); + if (permList != null) { + for (AclEntityPermissionVO perm : permList) { + idList.add(perm.getEntityId()); + } + } + return idList; + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDao.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDao.java index b877e87..d249963 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDao.java +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDao.java @@ -25,6 +25,10 @@ import com.cloud.utils.db.GenericDao; public interface AclRolePermissionDao extends GenericDao { + AclRolePermissionVO findByRoleEntityAndPermission(long roleId, String entityType, AccessType accessType, boolean isAllowed); + + AclRolePermissionVO findByRoleAndEntity(long roleId, String entityType, AccessType accessType); + List listByRoleAndEntity(long roleId, String entityType, AccessType accessType); List listByRole(long roleId); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDaoImpl.java b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDaoImpl.java index ee34470..9ae81b2 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDaoImpl.java +++ b/engine/schema/src/org/apache/cloudstack/acl/dao/AclRolePermissionDaoImpl.java @@ -49,12 +49,34 @@ public class AclRolePermissionDaoImpl extends GenericDaoBase sc = findByRoleEntity.create(); + sc.setParameters("roleId", roleId); + sc.setParameters("entityType", entityType); + sc.setParameters("accessType", accessType); + sc.setParameters("entityTypeStar", "*"); + sc.setParameters("allowed", isAllowed); + return findOneBy(sc); + } + + @Override + public AclRolePermissionVO findByRoleAndEntity(long roleId, String entityType, AccessType accessType) { + SearchCriteria sc = findByRoleEntity.create(); + sc.setParameters("roleId", roleId); + sc.setParameters("entityType", entityType); + sc.setParameters("accessType", accessType); + sc.setParameters("entityTypeStar", "*"); + return findOneBy(sc); + } + + @Override public List listByRoleAndEntity(long roleId, String entityType, AccessType accessType) { SearchCriteria sc = findByRoleEntity.create(); sc.setParameters("roleId", roleId); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/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 3f27915..04d5964 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -30,9 +30,12 @@ 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; @@ -349,6 +352,9 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { @Inject AclGroupDao _aclGroupDao; + @Inject + AclService _aclService; + /* * (non-Javadoc) * @@ -730,6 +736,11 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Account caller = CallContext.current().getCallingAccount(); List permittedAccounts = new ArrayList(); + // get granted or denied entity instance permissions + Pair, List> idPair = _aclService.getAclEntityPermission(caller.getId(), AclEntityType.VM.toString(), AccessType.ListEntry); + List grantedIds = idPair.first(); + List revokedIds = idPair.second(); + boolean listAll = cmd.listAll(); Long id = cmd.getId(); Ternary domainIdRecursiveListProject = new Ternary( @@ -745,10 +756,9 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // first search distinct vm id by using query criteria and pagination SearchBuilder sb = _userVmJoinDao.createSearchBuilder(); - sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct - // ids + sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct ids _accountMgr.buildACLViewSearchBuilder(sb, domainId, isRecursive, permittedAccounts, - listProjectResourcesCriteria); + listProjectResourcesCriteria, grantedIds, revokedIds); Map tags = cmd.getTags(); String hypervisor = cmd.getHypervisor(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/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 2e909c8..0fac6ed 100755 --- a/server/src/com/cloud/user/AccountManager.java +++ b/server/src/com/cloud/user/AccountManager.java @@ -90,6 +90,9 @@ public interface AccountManager extends AccountService { void buildACLViewSearchBuilder(SearchBuilder sb, Long domainId, boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria); + void buildACLViewSearchBuilder(SearchBuilder sb, Long domainId, + boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria, List grantedIds, List revokedIds); + void buildACLSearchCriteria(SearchCriteria sc, Long domainId, boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria); @@ -140,7 +143,7 @@ public interface AccountManager extends AccountService { * @param accountId * @return account object */ - Account enableAccount(String accountName, Long domainId, Long accountId); + Account enableAccount(String accountName, Long domainId, Long accountId); /** * Deletes user by Id @@ -155,7 +158,7 @@ public interface AccountManager extends AccountService { * @param userId * @return UserAccount object */ - UserAccount updateUser(UpdateUserCmd cmd); + UserAccount updateUser(UpdateUserCmd cmd); /** * Disables a user by userId @@ -187,5 +190,5 @@ public interface AccountManager extends AccountService { * @param accountId * @return account object */ - Account lockAccount(String accountName, Long domainId, Long accountId); + Account lockAccount(String accountName, Long domainId, Long accountId); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/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 de528f1..db21b3d 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -40,12 +40,17 @@ import javax.naming.ConfigurationException; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.AclEntityType; import org.apache.cloudstack.acl.AclGroupAccountMapVO; +import org.apache.cloudstack.acl.AclRolePermission; +import org.apache.cloudstack.acl.AclService; import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.dao.AclGroupAccountMapDao; +import org.apache.cloudstack.acl.dao.AclRolePermissionDao; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; @@ -253,6 +258,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M private AclGroupAccountMapDao _aclGroupAccountDao; @Inject + private AclService _aclService; + + @Inject + private AclRolePermissionDao _aclRolePermissionDao; + + @Inject public com.cloud.region.ha.GlobalLoadBalancingRulesService _gslbService; private List _userAuthenticators; @@ -2194,6 +2205,93 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } } +// @Override +// public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List +// permittedAccounts, Ternary domainIdRecursiveListProject, +// boolean listAll, boolean forProjectInvitation) { +// Long domainId = domainIdRecursiveListProject.first(); +// if (domainId != null) { +// Domain domain = _domainDao.findById(domainId); +// if (domain == null) { +// throw new InvalidParameterValueException("Unable to find domain by id " + domainId); +// } +// // check permissions +// checkAccess(caller, domain); +// } +// +// 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) { +// checkAccess(caller, null, false, userAccount); +// //check permissions +// 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 (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { +// 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 { +// if (id == null) { +// domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources); +// } +// if (permittedAccounts.isEmpty() && domainId == null) { +// if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { +// permittedAccounts.add(caller.getId()); +// } else if (!listAll) { +// if (id == null) { +// permittedAccounts.add(caller.getId()); +// } else if (!isRootAdmin(caller.getId())) { +// domainIdRecursiveListProject.first(caller.getDomainId()); +// domainIdRecursiveListProject.second(true); +// } +// } else if (domainId == null) { +// if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { +// domainIdRecursiveListProject.first(caller.getDomainId()); +// domainIdRecursiveListProject.second(true); +// } +// } +// } else if (domainId != null) { +// if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { +// permittedAccounts.add(caller.getId()); +// } +// } +// +// } +// } + @Override public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List permittedAccounts, Ternary domainIdRecursiveListProject, @@ -2208,6 +2306,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M checkAccess(caller, domain); } + if (id != null) { + // look for an individual entity, no other permission criteria are needed + return; + } + if (accountName != null) { if (projectId != null) { throw new InvalidParameterValueException("Account and projectId can't be specified together"); @@ -2253,34 +2356,27 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } } } else { - if (id == null) { - domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources); - } - if (permittedAccounts.isEmpty() && domainId == null) { - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - permittedAccounts.add(caller.getId()); - } else if (!listAll) { - if (id == null) { - permittedAccounts.add(caller.getId()); - } else if (!isRootAdmin(caller.getId())) { - domainIdRecursiveListProject.first(caller.getDomainId()); - domainIdRecursiveListProject.second(true); - } - } else if (domainId == null) { - if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { - domainIdRecursiveListProject.first(caller.getDomainId()); - domainIdRecursiveListProject.second(true); - } - } - } else if (domainId != null) { - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources); + // get caller role permission on VM List + AclRolePermission rolePerm = _aclService.getAclRolePermission(caller.getId(), AclEntityType.VM.toString(), AccessType.ListEntry); + if (rolePerm == null) { + // no list entry permission + throw new PermissionDeniedException("Caller has no role permission assigned to list VM"); + } + if (permittedAccounts.isEmpty()) { + // no account name is specified + if (rolePerm.getScope() == PermissionScope.ACCOUNT || !listAll) { + // only resource owner can see it, only match account permittedAccounts.add(caller.getId()); + } else { + // match domain tree based on cmd.isRecursive flag or not + domainIdRecursiveListProject.first(caller.getDomainId()); } } - } } + @Override public void buildACLViewSearchBuilder(SearchBuilder sb, Long domainId, boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria) { @@ -2305,6 +2401,35 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } @Override + public void buildACLViewSearchBuilder(SearchBuilder sb, Long domainId, boolean isRecursive, List permittedAccounts, + ListProjectResourcesCriteria listProjectResourcesCriteria, List grantedIds, List revokedIds) { + sb.and().op("accountIdIN", sb.entity().getAccountId(), SearchCriteria.Op.IN); + sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); + + if (((permittedAccounts.isEmpty()) && (domainId != null) && isRecursive)) { + // if accountId isn't specified, we can do a domain match for the + // admin case if isRecursive is true + sb.and("domainPath", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE); + } + + if (listProjectResourcesCriteria != null) { + if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.ListProjectResourcesOnly) { + sb.and("accountType", sb.entity().getAccountType(), SearchCriteria.Op.EQ); + } else if (listProjectResourcesCriteria == Project.ListProjectResourcesCriteria.SkipProjectResources) { + sb.and("accountType", sb.entity().getAccountType(), SearchCriteria.Op.NEQ); + } + } + if (!grantedIds.isEmpty()) { + sb.or("idIN", sb.entity().getId(), SearchCriteria.Op.IN); + } + sb.cp(); + if (!revokedIds.isEmpty()) { + sb.and("idNIN", sb.entity().getId(), SearchCriteria.Op.NIN); + } + + } + + @Override public void buildACLViewSearchCriteria(SearchCriteria sc, Long domainId, boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/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 c7990eb..85d70ac 100644 --- a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java +++ b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java @@ -18,7 +18,9 @@ package org.apache.cloudstack.acl; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; @@ -47,6 +49,7 @@ import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.dao.AccountDao; import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; @@ -554,6 +557,67 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager { } @Override + public AclRolePermission getAclRolePermission(long accountId, String entityType, AccessType accessType) { + List roles = getAclRoles(accountId); + AclRolePermission curPerm = null; + for (AclRole role : roles) { + AclRolePermission perm = _rolePermissionDao.findByRoleEntityAndPermission(role.getId(), entityType, accessType, true); + if (perm == null) + continue; + if (curPerm == null) { + curPerm = perm; + } else if (perm.getScope().greaterThan(curPerm.getScope())) { + // pick the more relaxed allowed permission + curPerm = perm; + } + } + + return curPerm; + } + + @Override + public List getAclGroups(long accountId) { + + GenericSearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder(Long.class); + groupSB.selectField(groupSB.entity().getAclGroupId()); + groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ); + SearchCriteria groupSc = groupSB.create(); + + List groupIds = _aclGroupAccountMapDao.customSearch(groupSc, null); + + SearchBuilder sb = _aclGroupDao.createSearchBuilder(); + sb.and("ids", sb.entity().getId(), Op.IN); + SearchCriteria sc = sb.create(); + sc.setParameters("ids", groupIds.toArray(new Object[groupIds.size()])); + List groups = _aclGroupDao.search(sc, null); + + return new ArrayList(groups); + } + + @Override + public Pair, List> getAclEntityPermission(long accountId, String entityType, AccessType accessType) { + List groups = getAclGroups(accountId); + if (groups == null || groups.size() == 0) { + return new Pair, List>(new ArrayList(), new ArrayList()); + } + Set allowedIds = new HashSet(); + Set deniedIds = new HashSet(); + for (AclGroup grp : groups) { + // get allowed id and denied list for each group + List allowedIdList = _entityPermissionDao.findEntityIdByGroupAndPermission(grp.getId(), entityType, accessType, true); + if (allowedIdList != null) { + allowedIds.addAll(allowedIdList); + } + List deniedIdList = _entityPermissionDao.findEntityIdByGroupAndPermission(grp.getId(), entityType, accessType, false); + if (deniedIdList != null) { + deniedIds.addAll(deniedIdList); + } + } + return new Pair, List>(new ArrayList(allowedIds), new ArrayList(deniedIds)) + ; + } + + @Override public boolean isAPIAccessibleForRoles(String apiName, List roles) { boolean accessible = false; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b4703b6/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 3638eb2..a933e70 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -287,6 +287,13 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco } @Override + public void buildACLViewSearchBuilder(SearchBuilder sb, Long domainId, boolean isRecursive, List permittedAccounts, + ListProjectResourcesCriteria listProjectResourcesCriteria, List grantedIds, List revokedIds) { + // TODO Auto-generated method stub + + } + + @Override public void buildACLViewSearchCriteria(SearchCriteria sc, Long domainId, boolean isRecursive, List permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria) { // TODO Auto-generated method stub