diff --git a/services/iam/plugin/pom.xml b/services/iam/plugin/pom.xml
new file mode 100644
index 00000000000..7ee3feb5e4b
--- /dev/null
+++ b/services/iam/plugin/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+ cloud-plugin-iam
+ Apache CloudStack IAM - Plugin
+
+ org.apache.cloudstack
+ cloudstack-service-iam
+ 4.3.0-SNAPSHOT
+ ../pom.xml
+
+
diff --git a/services/iam/plugin/resources/META-INF/cloudstack/acl-role-based-access-checkers/module.properties b/services/iam/plugin/resources/META-INF/cloudstack/acl-role-based-access-checkers/module.properties
new file mode 100644
index 00000000000..206e1b0e6d1
--- /dev/null
+++ b/services/iam/plugin/resources/META-INF/cloudstack/acl-role-based-access-checkers/module.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+name=acl-role-based-access-checkers
+parent=api
\ No newline at end of file
diff --git a/services/iam/plugin/resources/META-INF/cloudstack/acl-role-based-access-checkers/spring-acl-role-based-access-checkers-context.xml b/services/iam/plugin/resources/META-INF/cloudstack/acl-role-based-access-checkers/spring-acl-role-based-access-checkers-context.xml
new file mode 100644
index 00000000000..78b233da309
--- /dev/null
+++ b/services/iam/plugin/resources/META-INF/cloudstack/acl-role-based-access-checkers/spring-acl-role-based-access-checkers-context.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/AclService.java b/services/iam/plugin/src/org/apache/cloudstack/acl/AclService.java
new file mode 100644
index 00000000000..c8d8b48867b
--- /dev/null
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/AclService.java
@@ -0,0 +1,66 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.acl;
+
+import java.util.List;
+
+import org.apache.cloudstack.acl.AclPolicyPermission.Permission;
+
+import com.cloud.user.Account;
+
+public interface AclService {
+
+ /* ACL group related interfaces */
+ AclGroup createAclGroup(Account caller, String aclGroupName, String description);
+
+ boolean deleteAclGroup(Long aclGroupId);
+
+ List listAclGroups(long accountId);
+
+ AclGroup addAccountsToGroup(List acctIds, Long groupId);
+
+ AclGroup removeAccountsFromGroup(List acctIds, Long groupId);
+
+ /* ACL Policy related interfaces */
+ AclPolicy createAclPolicy(Account caller, String aclPolicyName, String description, Long parentPolicyId);
+
+ boolean deleteAclPolicy(long aclPolicyId);
+
+ List listAclPolicies(long accountId);
+
+ AclGroup attachAclPoliciesToGroup(List roleIds, Long groupId);
+
+ AclGroup removeAclPoliciesFromGroup(List roleIds, Long groupId);
+
+ AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action, Permission perm);
+
+ AclPolicy removeAclPermissionFromAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action);
+
+ AclPolicyPermission getAclPolicyPermission(long accountId, String entityType, String action);
+
+ boolean isAPIAccessibleForPolicies(String apiName, List policies);
+
+ List getEffectivePolicies(Account caller, ControlledEntity entity);
+
+ /* Visibility related interfaces */
+ List getGrantedDomains(long accountId, String action);
+
+ List getGrantedAccounts(long accountId, String action);
+
+ List getGrantedResources(long accountId, String action);
+
+}
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/AclServiceImpl.java b/services/iam/plugin/src/org/apache/cloudstack/acl/AclServiceImpl.java
new file mode 100644
index 00000000000..3581ef07303
--- /dev/null
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/AclServiceImpl.java
@@ -0,0 +1,736 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.acl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclPolicyPermission.Permission;
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
+import org.apache.cloudstack.acl.dao.AclApiPermissionDao;
+import org.apache.cloudstack.acl.dao.AclGroupAccountMapDao;
+import org.apache.cloudstack.acl.dao.AclGroupDao;
+import org.apache.cloudstack.acl.dao.AclGroupPolicyMapDao;
+import org.apache.cloudstack.acl.dao.AclPolicyDao;
+import org.apache.cloudstack.acl.dao.AclPolicyPermissionDao;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.api.ApiServerService;
+import com.cloud.domain.Domain;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Volume;
+import com.cloud.template.VirtualMachineTemplate;
+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.component.Manager;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.db.GenericSearchBuilder;
+import com.cloud.utils.db.JoinBuilder.JoinType;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionStatus;
+
+@Local(value = {AclService.class})
+public class AclServiceImpl extends ManagerBase implements AclService, Manager {
+
+ public static final Logger s_logger = Logger.getLogger(AclServiceImpl.class);
+ private String _name;
+
+ @Inject
+ AccountManager _accountMgr;
+
+ @Inject
+ AccountDao _accountDao;
+
+ @Inject
+ AclPolicyDao _aclPolicyDao;
+
+ @Inject
+ AclGroupDao _aclGroupDao;
+
+ @Inject
+ EntityManager _entityMgr;
+
+ @Inject
+ AclGroupPolicyMapDao _aclGroupPolicyMapDao;
+
+ @Inject
+ AclGroupAccountMapDao _aclGroupAccountMapDao;
+
+ // @Inject
+ // AclApiPermissionDao _apiPermissionDao;
+
+ @Inject
+ AclPolicyPermissionDao _policyPermissionDao;
+
+ @Inject
+ ApiServerService _apiServer;
+
+
+ public static HashMap entityClassMap = new HashMap();
+
+ static {
+ entityClassMap.put("VirtualMachine", UserVm.class);
+ entityClassMap.put("Volume", Volume.class);
+ entityClassMap.put("Template", VirtualMachineTemplate.class);
+ entityClassMap.put("Snapshot", Snapshot.class);
+ // To be filled in later depending on the entity permission grant scope
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_CREATE, eventDescription = "Creating Acl Group", create = true)
+ public AclGroup createAclGroup(Account caller, String aclGroupName, String description) {
+ Long domainId = caller.getDomainId();
+
+ if (!_accountMgr.isRootAdmin(caller.getAccountId())) {
+ // domain admin can only create role for his domain
+ if (caller.getDomainId() != domainId.longValue()) {
+ throw new PermissionDeniedException("Can't create acl group in domain " + domainId + ", permission denied");
+ }
+ }
+ // check if the role is already existing
+ AclGroup grp = _aclGroupDao.findByName(domainId, aclGroupName);
+ if (grp != null) {
+ throw new InvalidParameterValueException(
+ "Unable to create acl group with name " + aclGroupName
+ + " already exisits for domain " + domainId);
+ }
+ AclGroupVO rvo = new AclGroupVO(aclGroupName, description);
+ rvo.setAccountId(caller.getAccountId());
+ rvo.setDomainId(domainId);
+
+ return _aclGroupDao.persist(rvo);
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_DELETE, eventDescription = "Deleting Acl Group")
+ public boolean deleteAclGroup(final Long aclGroupId) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Role entity
+ final AclGroup grp = _aclGroupDao.findById(aclGroupId);
+ if (grp == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + aclGroupId
+ + "; failed to delete acl group.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, grp);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove this group related entry in acl_group_role_map
+ List groupPolicyMap = _aclGroupPolicyMapDao.listByGroupId(grp.getId());
+ if (groupPolicyMap != null) {
+ for (AclGroupPolicyMapVO gr : groupPolicyMap) {
+ _aclGroupPolicyMapDao.remove(gr.getId());
+ }
+ }
+
+ // remove this group related entry in acl_group_account table
+ List groupAcctMap = _aclGroupAccountMapDao.listByGroupId(grp.getId());
+ if (groupAcctMap != null) {
+ for (AclGroupAccountMapVO grpAcct : groupAcctMap) {
+ _aclGroupAccountMapDao.remove(grpAcct.getId());
+ }
+ }
+
+ // remove this group from acl_group table
+ _aclGroupDao.remove(aclGroupId);
+ }
+ });
+
+ return true;
+ }
+
+ @Override
+ public List listAclGroups(long accountId) {
+
+ GenericSearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder(Long.class);
+ groupSB.selectFields(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);
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Adding accounts to acl group")
+ public AclGroup addAccountsToGroup(final List acctIds, final Long groupId) {
+ final Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to add accounts to acl group.");
+ }
+ // check group permissions
+ _accountMgr.checkAccess(caller, null, true, group);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_account_map table
+ for (Long acctId : acctIds) {
+ // check account permissions
+ Account account = _accountDao.findById(acctId);
+ if (account == null) {
+ throw new InvalidParameterValueException("Unable to find account: " + acctId
+ + "; failed to add account to acl group.");
+ }
+ _accountMgr.checkAccess(caller, null, true, account);
+
+ AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
+ if (grMap == null) {
+ // not there already
+ grMap = new AclGroupAccountMapVO(groupId, acctId);
+ _aclGroupAccountMapDao.persist(grMap);
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Removing accounts from acl group")
+ public AclGroup removeAccountsFromGroup(final List acctIds, final Long groupId) {
+ final Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to remove accounts from acl group.");
+ }
+ // check group permissions
+ _accountMgr.checkAccess(caller, null, true, group);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove entries from acl_group_account_map table
+ for (Long acctId : acctIds) {
+ // check account permissions
+ Account account = _accountDao.findById(acctId);
+ if (account == null) {
+ throw new InvalidParameterValueException("Unable to find account: " + acctId
+ + "; failed to add account to acl group.");
+ }
+ _accountMgr.checkAccess(caller, null, true, account);
+
+ AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
+ if (grMap != null) {
+ // not removed yet
+ _aclGroupAccountMapDao.remove(grMap.getId());
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_CREATE, eventDescription = "Creating Acl Policy", create = true)
+ public AclPolicy createAclPolicy(Account caller, final String aclPolicyName, final String description, final Long parentPolicyId) {
+ Long domainId = caller.getDomainId();
+
+ if (!_accountMgr.isRootAdmin(caller.getAccountId())) {
+ // domain admin can only create role for his domain
+ if (caller.getDomainId() != domainId.longValue()) {
+ throw new PermissionDeniedException("Can't create acl role in domain " + domainId + ", permission denied");
+ }
+ }
+ // check if the role is already existing
+ AclPolicy ro = _aclPolicyDao.findByName(domainId, aclPolicyName);
+ if (ro != null) {
+ throw new InvalidParameterValueException(
+ "Unable to create acl policy with name " + aclPolicyName
+ + " already exisits for domain " + domainId);
+ }
+
+ final long account_id = caller.getAccountId();
+ final long domain_id = domainId;
+ AclPolicy role = Transaction.execute(new TransactionCallback() {
+ @Override
+ public AclPolicy doInTransaction(TransactionStatus status) {
+ AclPolicyVO rvo = new AclPolicyVO(aclPolicyName, description);
+ rvo.setAccountId(account_id);
+ rvo.setDomainId(domain_id);
+ AclPolicy role = _aclPolicyDao.persist(rvo);
+ if (parentPolicyId != null) {
+ // copy parent role permissions
+ List perms = _policyPermissionDao.listByPolicy(parentPolicyId);
+ if (perms != null) {
+ for (AclPolicyPermissionVO perm : perms) {
+ perm.setAclPolicyId(role.getId());
+ _policyPermissionDao.persist(perm);
+ }
+ }
+ }
+ return role;
+ }
+ });
+
+
+ return role;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_DELETE, eventDescription = "Deleting Acl Policy")
+ public boolean deleteAclPolicy(final long aclPolicyId) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Policy entity
+ final AclPolicy policy = _aclPolicyDao.findById(aclPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + aclPolicyId
+ + "; failed to delete acl policy.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, policy);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove this role related entry in acl_group_role_map
+ List groupPolicyMap = _aclGroupPolicyMapDao.listByPolicyId(policy.getId());
+ if (groupPolicyMap != null) {
+ for (AclGroupPolicyMapVO gr : groupPolicyMap) {
+ _aclGroupPolicyMapDao.remove(gr.getId());
+ }
+ }
+
+ // remove this policy related entry in acl_policy_permission table
+ List policyPermMap = _policyPermissionDao.listByPolicy(policy.getId());
+ if (policyPermMap != null) {
+ for (AclPolicyPermissionVO policyPerm : policyPermMap) {
+ _policyPermissionDao.remove(policyPerm.getId());
+ }
+ }
+
+ // remove this role from acl_role table
+ _aclPolicyDao.remove(aclPolicyId);
+ }
+ });
+
+ return true;
+ }
+
+
+ @Override
+ public List listAclPolicies(long accountId) {
+
+ // static policies of the account
+ SearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder();
+ groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
+
+ GenericSearchBuilder policySB = _aclGroupPolicyMapDao.createSearchBuilder(Long.class);
+ policySB.selectFields(policySB.entity().getAclPolicyId());
+ policySB.join("accountgroupjoin", groupSB, groupSB.entity().getAclGroupId(), policySB.entity().getAclGroupId(),
+ JoinType.INNER);
+ policySB.done();
+ SearchCriteria policySc = policySB.create();
+ policySc.setJoinParameters("accountgroupjoin", "account", accountId);
+
+ List policyIds = _aclGroupPolicyMapDao.customSearch(policySc, null);
+
+ SearchBuilder sb = _aclPolicyDao.createSearchBuilder();
+ sb.and("ids", sb.entity().getId(), Op.IN);
+ SearchCriteria sc = sb.create();
+ sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
+ List policies = _aclPolicyDao.customSearch(sc, null);
+
+ return new ArrayList(policies);
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Attaching policy to acl group")
+ public AclGroup attachAclPoliciesToGroup(final List policyIds, final Long groupId) {
+ final Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to add roles to acl group.");
+ }
+ // check group permissions
+ _accountMgr.checkAccess(caller, null, true, group);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_policy_map table
+ for (Long policyId : policyIds) {
+ // check policy permissions
+ AclPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policies to acl group.");
+ }
+ _accountMgr.checkAccess(caller, null, true, policy);
+
+ AclGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
+ if (grMap == null) {
+ // not there already
+ grMap = new AclGroupPolicyMapVO(groupId, policyId);
+ _aclGroupPolicyMapDao.persist(grMap);
+ }
+ }
+ }
+ });
+
+ return group;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Removing policies from acl group")
+ public AclGroup removeAclPoliciesFromGroup(final List policyIds, final Long groupId) {
+ final Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to remove roles from acl group.");
+ }
+ // check group permissions
+ _accountMgr.checkAccess(caller, null, true, group);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_role_map table
+ for (Long policyId : policyIds) {
+ // check policy permissions
+ AclPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policies to acl group.");
+ }
+ _accountMgr.checkAccess(caller, null, true, policy);
+
+ AclGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
+ if (grMap != null) {
+ // not removed yet
+ _aclGroupPolicyMapDao.remove(grMap.getId());
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ /*
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_GRANT, eventDescription = "Granting permission to Acl Role")
+ public AclP addAclPermissionToAclPolicy(final long aclRoleId, final List apiNames) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Role entity
+ AclRole role = _aclPolicyDao.findById(aclRoleId);
+ if (role == null) {
+ throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
+ + "; failed to grant permission to role.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, role);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_api_permission table
+ for (String api : apiNames) {
+ AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
+ if (perm == null) {
+ // not there already
+ perm = new AclApiPermissionVO(aclRoleId, api);
+ _apiPermissionDao.persist(perm);
+ }
+ }
+ }
+ });
+
+ return role;
+
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_REVOKE, eventDescription = "Revoking permission from Acl Role")
+ public AclRole revokeApiPermissionFromAclRole(final long aclRoleId, final List apiNames) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Role entity
+ AclRole role = _aclPolicyDao.findById(aclRoleId);
+ if (role == null) {
+ throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
+ + "; failed to revoke permission from role.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, role);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove entries from acl_api_permission table
+ for (String api : apiNames) {
+ AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
+ if (perm != null) {
+ // not removed yet
+ _apiPermissionDao.remove(perm.getId());
+ }
+ }
+ }
+ });
+ return role;
+ }
+ */
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_GRANT, eventDescription = "Granting acl permission to Acl Policy")
+ public AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action, Permission perm) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Policy entity
+ AclPolicy policy = _aclPolicyDao.findById(aclPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + aclPolicyId
+ + "; failed to add permission to policy.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, policy);
+
+ // get the entity and check permission
+ Class entityClass = entityClassMap.get(entityType);
+ if (entityClass == null) {
+ throw new InvalidParameterValueException("Entity type " + entityType + " permission granting is not supported yet");
+ }
+ if (scope == PermissionScope.RESOURCE && scopeId != null) {
+ ControlledEntity entity = (ControlledEntity)_entityMgr.findById(entityClass, scopeId);
+ if (entity == null) {
+ throw new InvalidParameterValueException("Unable to find entity " + entityType + " by id: " + scopeId);
+ }
+ _accountMgr.checkAccess(caller, null, true, entity);
+ }
+
+ // add entry in acl_policy_permission table
+ AclPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(aclPolicyId, entityType, scope, scopeId, action, perm);
+ if (permit == null) {
+ // not there already
+ Class> cmdClass = _apiServer.getCmdClass(action);
+ AccessType accessType = null;
+ if (BaseListCmd.class.isAssignableFrom(cmdClass)) {
+ accessType = AccessType.ListEntry;
+ }
+ permit = new AclPolicyPermissionVO(aclPolicyId, action, entityType, accessType,
+ scope, scopeId, perm);
+ _policyPermissionDao.persist(permit);
+ }
+ return policy;
+
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_REVOKE, eventDescription = "Revoking acl permission from Acl Policy")
+ public AclPolicy removeAclPermissionFromAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Policy entity
+ AclPolicy policy = _aclPolicyDao.findById(aclPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + aclPolicyId
+ + "; failed to revoke permission from policy.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, policy);
+
+ // get the entity and check permission
+ Class entityClass = entityClassMap.get(entityType);
+ if (entityClass == null) {
+ throw new InvalidParameterValueException("Entity type " + entityType + " permission revoke is not supported yet");
+ }
+ if (scope == PermissionScope.RESOURCE && scopeId != null) {
+ ControlledEntity entity = (ControlledEntity)_entityMgr.findById(entityClass, scopeId);
+ if (entity == null) {
+ throw new InvalidParameterValueException("Unable to find entity " + entityType + " by id: " + scopeId);
+ }
+ _accountMgr.checkAccess(caller, null, true, entity);
+ }
+
+ // remove entry from acl_entity_permission table
+ AclPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(aclPolicyId, entityType, scope, scopeId, action, null);
+ if (permit != null) {
+ // not removed yet
+ _policyPermissionDao.remove(permit.getId());
+ }
+ return policy;
+ }
+
+
+
+ @Override
+ public AclPolicyPermission getAclPolicyPermission(long accountId, String entityType, String action) {
+ List roles = listAclPolicies(accountId);
+ AclPolicyPermission curPerm = null;
+ for (AclPolicy role : roles) {
+ AclPolicyPermissionVO perm = _policyPermissionDao.findByPolicyAndEntity(role.getId(), entityType, null, null, action, Permission.Allow);
+ 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 boolean isAPIAccessibleForPolicies(String apiName, List policies) {
+
+ boolean accessible = false;
+
+ List policyIds = new ArrayList();
+ for (AclPolicy policy : policies) {
+ policyIds.add(policy.getId());
+ }
+
+ SearchBuilder sb = _policyPermissionDao.createSearchBuilder();
+ sb.and("action", sb.entity().getAction(), Op.EQ);
+ sb.and("policyId", sb.entity().getAclPolicyId(), Op.IN);
+
+ SearchCriteria sc = sb.create();
+ sc.setParameters("policyId", policyIds.toArray(new Object[policyIds.size()]));
+
+ List permissions = _policyPermissionDao.customSearch(sc, null);
+
+ if (permissions != null && !permissions.isEmpty()) {
+ accessible = true;
+ }
+
+ return accessible;
+ }
+
+ @Override
+ public List getEffectivePolicies(Account caller, ControlledEntity entity) {
+
+ // Get the static Policies of the Caller
+ List policies = listAclPolicies(caller.getId());
+
+ // add any dynamic policies w.r.t the entity
+ if (caller.getId() == entity.getAccountId()) {
+ // The caller owns the entity
+ AclPolicy owner = _aclPolicyDao.findByName(Domain.ROOT_DOMAIN, "RESOURCE_OWNER");
+ policies.add(owner);
+ }
+
+ return policies;
+ }
+
+ @Override
+ public List getGrantedDomains(long accountId, String action) {
+ // Get the static Policies of the Caller
+ List policies = listAclPolicies(accountId);
+ // for each policy, find granted permission with Domain scope
+ List domainIds = new ArrayList();
+ for (AclPolicy policy : policies) {
+ List pp = _policyPermissionDao.listGrantedByActionAndScope(policy.getId(), action, PermissionScope.DOMAIN);
+ if (pp != null) {
+ for (AclPolicyPermissionVO p : pp) {
+ if (p.getScopeId() != null) {
+ domainIds.add(p.getScopeId());
+ }
+ }
+ }
+ }
+ return domainIds;
+ }
+
+ @Override
+ public List getGrantedAccounts(long accountId, String action) {
+ // Get the static Policies of the Caller
+ List policies = listAclPolicies(accountId);
+ // for each policy, find granted permission with Account scope
+ List accountIds = new ArrayList();
+ for (AclPolicy policy : policies) {
+ List pp = _policyPermissionDao.listGrantedByActionAndScope(policy.getId(), action, PermissionScope.ACCOUNT);
+ if (pp != null) {
+ for (AclPolicyPermissionVO p : pp) {
+ if (p.getScopeId() != null) {
+ accountIds.add(p.getScopeId());
+ }
+ }
+ }
+ }
+ return accountIds;
+ }
+
+ @Override
+ public List getGrantedResources(long accountId, String action) {
+ // Get the static Policies of the Caller
+ List policies = listAclPolicies(accountId);
+ // for each policy, find granted permission with Resource scope
+ List entityIds = new ArrayList();
+ for (AclPolicy policy : policies) {
+ List pp = _policyPermissionDao.listGrantedByActionAndScope(policy.getId(), action, PermissionScope.RESOURCE);
+ if (pp != null) {
+ for (AclPolicyPermissionVO p : pp) {
+ if (p.getScopeId() != null) {
+ entityIds.add(p.getScopeId());
+ }
+ }
+ }
+ }
+ return entityIds;
+ }
+
+}
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/RoleBasedAPIAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/RoleBasedAPIAccessChecker.java
new file mode 100644
index 00000000000..23f25ca1254
--- /dev/null
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/RoleBasedAPIAccessChecker.java
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.acl.api;
+
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.APIChecker;
+import org.apache.cloudstack.acl.AclPolicy;
+import org.apache.cloudstack.acl.AclRole;
+import org.apache.cloudstack.acl.AclService;
+import org.apache.log4j.Logger;
+
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.user.User;
+import com.cloud.utils.component.AdapterBase;
+
+// This is the Role Based API access checker that grab's the account's roles
+// based on the set of roles, access is granted if any of the role has access to the api
+@Local(value=APIChecker.class)
+public class RoleBasedAPIAccessChecker extends AdapterBase implements APIChecker {
+
+ protected static final Logger s_logger = Logger.getLogger(RoleBasedAPIAccessChecker.class);
+
+ @Inject AccountService _accountService;
+ @Inject AclService _aclService;
+
+ protected RoleBasedAPIAccessChecker() {
+ super();
+ }
+
+ @Override
+ public boolean checkAccess(User user, String commandName)
+ throws PermissionDeniedException {
+ Account account = _accountService.getAccount(user.getAccountId());
+ if (account == null) {
+ throw new PermissionDeniedException("The account id=" + user.getAccountId() + "for user id=" + user.getId() + "is null");
+ }
+
+ List policies = _aclService.listAclPolicies(account.getAccountId());
+
+
+ boolean isAllowed = _aclService.isAPIAccessibleForPolicies(commandName, policies);
+ if (!isAllowed) {
+ throw new PermissionDeniedException("The API does not exist or is blacklisted. api: " + commandName);
+ }
+ return isAllowed;
+ }
+
+}
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/entity/RoleBasedEntityAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/acl/entity/RoleBasedEntityAccessChecker.java
new file mode 100644
index 00000000000..c057bc02a91
--- /dev/null
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/entity/RoleBasedEntityAccessChecker.java
@@ -0,0 +1,131 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.acl.entity;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.acl.AclPolicy;
+import org.apache.cloudstack.acl.AclPolicyPermissionVO;
+import org.apache.cloudstack.acl.AclService;
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.acl.AclEntityType;
+import org.apache.cloudstack.acl.PermissionScope;
+import org.apache.cloudstack.acl.SecurityChecker;
+import org.apache.cloudstack.acl.dao.AclGroupAccountMapDao;
+import org.apache.cloudstack.acl.dao.AclPolicyPermissionDao;
+import org.apache.log4j.Logger;
+
+import com.cloud.acl.DomainChecker;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.vm.VirtualMachine;
+
+public class RoleBasedEntityAccessChecker extends DomainChecker implements SecurityChecker {
+
+ private static final Logger s_logger = Logger.getLogger(RoleBasedEntityAccessChecker.class.getName());
+
+ @Inject
+ AccountService _accountService;
+ @Inject
+ AclService _aclService;
+
+ @Inject DomainDao _domainDao;
+
+ @Inject
+ AclGroupAccountMapDao _aclGroupAccountMapDao;
+
+ @Inject
+ AclPolicyPermissionDao _policyPermissionDao;
+
+
+ @Override
+ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType)
+ throws PermissionDeniedException {
+ return checkAccess(caller, entity, accessType, null);
+ }
+
+ @Override
+ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action)
+ throws PermissionDeniedException {
+
+ String entityType = entity.getEntityType().toString();
+
+ if (accessType == null) {
+ accessType = AccessType.ListEntry;
+ }
+
+ // get all Policies of this caller w.r.t the entity
+ List policies = _aclService.getEffectivePolicies(caller, entity);
+ HashMap policyPermissionMap = new HashMap();
+
+ for (AclPolicy policy : policies) {
+ List permissions = new ArrayList();
+
+ if (action != null) {
+ permissions = _policyPermissionDao.listByPolicyActionAndEntity(policy.getId(),
+ action, entityType);
+ } else {
+ permissions = _policyPermissionDao.listByPolicyAccessAndEntity(policy.getId(), accessType, entityType);
+ }
+ for (AclPolicyPermissionVO permission : permissions) {
+ if (checkPermissionScope(caller, permission.getScope(), entity)) {
+ if (permission.getEntityType().equals(entityType)) {
+ policyPermissionMap.put(policy, permission.getPermission().isGranted());
+ break;
+ } else if (permission.getEntityType().equals("*")) {
+ policyPermissionMap.put(policy, permission.getPermission().isGranted());
+ }
+ }
+ }
+ if (policyPermissionMap.containsKey(policy) && policyPermissionMap.get(policy)) {
+ return true;
+ }
+ }
+
+ if (!policies.isEmpty()) { // Since we reach this point, none of the
+ // roles granted access
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Account " + caller + " does not have permission to access resource " + entity
+ + " for access type: " + accessType);
+ }
+ throw new PermissionDeniedException(caller + " does not have permission to access resource " + entity);
+ }
+
+ return false;
+ }
+
+ private boolean checkPermissionScope(Account caller, PermissionScope scope, ControlledEntity entity) {
+
+ if(scope.equals(PermissionScope.ACCOUNT)){
+ if(caller.getAccountId() == entity.getAccountId()){
+ return true;
+ }
+ }else if(scope.equals(PermissionScope.DOMAIN)){
+ if (_domainDao.isChildDomain(caller.getDomainId(), entity.getDomainId())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/entity/RoleBasedEntityQueryChecker.java b/services/iam/plugin/src/org/apache/cloudstack/acl/entity/RoleBasedEntityQueryChecker.java
new file mode 100644
index 00000000000..7ddc8fdeaa5
--- /dev/null
+++ b/services/iam/plugin/src/org/apache/cloudstack/acl/entity/RoleBasedEntityQueryChecker.java
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.acl.entity;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclEntityType;
+import org.apache.cloudstack.acl.QueryChecker;
+
+import com.cloud.user.Account;
+import com.cloud.utils.component.AdapterBase;
+
+public class RoleBasedEntityQueryChecker extends AdapterBase implements QueryChecker {
+
+ private static final Logger s_logger = Logger.getLogger(RoleBasedEntityQueryChecker.class.getName());
+
+ @Override
+ public List getAuthorizedDomains(Account caller, AclEntityType entityType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List getAuthorizedAccounts(Account caller, AclEntityType entityType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List getAuthorizedResources(Account caller, AclEntityType entityType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/services/iam/pom.xml b/services/iam/pom.xml
new file mode 100644
index 00000000000..babb9c8685a
--- /dev/null
+++ b/services/iam/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+ cloudstack-service-iam
+ Apache CloudStack IAM Service
+ pom
+
+ org.apache.cloudstack
+ cloudstack-services
+ 4.3.0-SNAPSHOT
+ ../pom.xml
+
+
+ install
+
+
+ plugin
+ server
+
+
diff --git a/services/iam/server/pom.xml b/services/iam/server/pom.xml
new file mode 100644
index 00000000000..cf6dcf2ca98
--- /dev/null
+++ b/services/iam/server/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+ cloud-iam
+ Apache CloudStack IAM - Server
+
+ org.apache.cloudstack
+ cloudstack-service-iam
+ 4.3.0-SNAPSHOT
+ ../pom.xml
+
+
+
+ log4j
+ log4j
+
+
+ com.google.code.gson
+ gson
+
+
+ commons-codec
+ commons-codec
+
+
+ org.apache.cloudstack
+ cloud-utils
+ ${project.version}
+
+
+ org.apache.cloudstack
+ cloud-api
+ ${project.version}
+
+
+
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/AclGroup.java b/services/iam/server/src/org/apache/cloudstack/iam/api/AclGroup.java
new file mode 100644
index 00000000000..a64ca7f3fd8
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/AclGroup.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api;
+
+public interface AclGroup {
+
+ String getName();
+
+ String getDescription();
+
+ long getId();
+
+ String getUuid();
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/AclPolicy.java b/services/iam/server/src/org/apache/cloudstack/iam/api/AclPolicy.java
new file mode 100644
index 00000000000..0794888acb3
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/AclPolicy.java
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api;
+
+public interface AclPolicy {
+
+ String getName();
+
+ String getDescription();
+
+ public enum PolicyType {
+ Static, Dynamic
+ }
+
+ long getId();
+
+ String getUuid();
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/AclPolicyPermission.java b/services/iam/server/src/org/apache/cloudstack/iam/api/AclPolicyPermission.java
new file mode 100644
index 00000000000..38e5d05eb1f
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/AclPolicyPermission.java
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api;
+
+
+public interface AclPolicyPermission {
+
+ String getAction();
+
+ long getAclPolicyId();
+
+ String getEntityType();
+
+ String getAccessType();
+
+ String getScope();
+
+ Long getScopeId();
+
+ Permission getPermission();
+
+ public enum Permission {
+ Allow(true), Deny(false);
+
+ boolean result;
+
+ Permission(boolean result) {
+ this.result = result;
+ }
+
+ public boolean isGranted() {
+ return result;
+ }
+ }
+
+ long getId();
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java
new file mode 100644
index 00000000000..0532abb7863
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.api.AclPolicyPermission.Permission;
+
+public interface IAMService {
+
+ /* ACL group related interfaces */
+ AclGroup createAclGroup(String aclGroupName, String description, String path);
+
+ boolean deleteAclGroup(Long aclGroupId);
+
+ List listAclGroups(long accountId);
+
+ AclGroup addAccountsToGroup(List acctIds, Long groupId);
+
+ AclGroup removeAccountsFromGroup(List acctIds, Long groupId);
+
+ /* ACL Policy related interfaces */
+ AclPolicy createAclPolicy(String aclPolicyName, String description, Long parentPolicyId);
+
+ boolean deleteAclPolicy(long aclPolicyId);
+
+ List listAclPolicies(long accountId);
+
+ AclGroup attachAclPoliciesToGroup(List policyIds, Long groupId);
+
+ AclGroup removeAclPoliciesFromGroup(List policyIds, Long groupId);
+
+ AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId,
+ String action, String accessType, Permission perm);
+
+ AclPolicy removeAclPermissionFromAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId,
+ String action);
+
+ boolean isAPIAccessibleForPolicies(String apiName, List policies);
+
+ List getGrantedEntities(long accountId, String action, String scope);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/AddAccountToAclGroupCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/AddAccountToAclGroupCmd.java
new file mode 100644
index 00000000000..c8289daabdf
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/AddAccountToAclGroupCmd.java
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "addAccountToAclGroup", description = "add account to an acl group", responseObject = AclGroupResponse.class)
+public class AddAccountToAclGroupCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(AddAccountToAclGroupCmd.class.getName());
+ private static final String s_name = "addaccounttoaclgroupresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
+ required = true, description = "The ID of the acl group")
+ private Long id;
+
+ @ACL
+ @Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of account id that are going to be assigned to the acl group.")
+ private List accountIdList;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getId() {
+ return id;
+ }
+
+
+ public List getAccountIdList() {
+ return accountIdList;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException,
+ InsufficientCapacityException, ServerApiException {
+ CallContext.current().setEventDetails("Acl group Id: " + getId());
+ AclGroup result = _aclService.addAccountsToGroup(accountIdList, id);
+ if (result != null){
+ AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add accounts to acl group");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_GROUP_UPDATE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "adding accounts to acl group";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclGroup;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/AddAclPermissionToAclPolicyCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/AddAclPermissionToAclPolicyCmd.java
new file mode 100644
index 00000000000..ea3736c540d
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/AddAclPermissionToAclPolicyCmd.java
@@ -0,0 +1,144 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclPolicy;
+import org.apache.cloudstack.acl.AclPolicyPermission.Permission;
+import org.apache.cloudstack.acl.PermissionScope;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclPolicyResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "addAclPermissionToAclPolicy", description = "Add Acl permission to an acl policy", responseObject = AclPolicyResponse.class)
+public class AddAclPermissionToAclPolicyCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(AddAclPermissionToAclPolicyCmd.class.getName());
+ private static final String s_name = "addaclpermissiontoaclpolicyresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclPolicyResponse.class,
+ required = true, description = "The ID of the acl policy")
+ private Long id;
+
+ @Parameter(name = ApiConstants.ACL_ACTION, type = CommandType.STRING, required = true, description = "action api name.")
+ private String action;
+
+ @Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, required = false, description = "entity class simple name.")
+ private String entityType;
+
+ @Parameter(name = ApiConstants.ACL_SCOPE, type = CommandType.STRING,
+ required = false, description = "acl permission scope")
+ private String scope;
+
+ @Parameter(name = ApiConstants.ACL_SCOPE_ID, type = CommandType.UUID, required = false, description = "The ID of the permission scope id")
+ private Long scopeId;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getId() {
+ return id;
+ }
+
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getEntityType() {
+ return entityType;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public Long getScopeId() {
+ return scopeId;
+ }
+
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException,
+ InsufficientCapacityException, ServerApiException {
+ CallContext.current().setEventDetails("Acl policy Id: " + getId());
+ // Only explicit ALLOW is supported for this release, no explicit deny
+ AclPolicy result = _aclService.addAclPermissionToAclPolicy(id, entityType, PermissionScope.valueOf(scope), scopeId, action, Permission.Allow);
+ if (result != null) {
+ AclPolicyResponse response = _responseGenerator.createAclPolicyResponse(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to grant permission to acl policy " + getId());
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_POLICY_GRANT;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "granting permission to acl policy";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclPolicy;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/AttachAclPolicyToAclGroupCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/AttachAclPolicyToAclGroupCmd.java
new file mode 100644
index 00000000000..719950e682d
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/AttachAclPolicyToAclGroupCmd.java
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.AclPolicyResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "attachAclPolicyToAclGroup", description = "attach acl policy to an acl group", responseObject = AclGroupResponse.class)
+public class AttachAclPolicyToAclGroupCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(AttachAclPolicyToAclGroupCmd.class.getName());
+ private static final String s_name = "attachaclpolicytoaclgroupresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
+ required = true, description = "The ID of the acl group")
+ private Long id;
+
+ @ACL
+ @Parameter(name = ApiConstants.ACL_POLICIES, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AclPolicyResponse.class, description = "comma separated list of acl policy id that are going to be applied to the acl group.")
+ private List policyIdList;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getId() {
+ return id;
+ }
+
+
+ public List getPolicyIdList() {
+ return policyIdList;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException,
+ InsufficientCapacityException, ServerApiException {
+ CallContext.current().setEventDetails("Acl group Id: " + getId());
+ AclGroup result = _aclService.attachAclPoliciesToGroup(policyIdList, id);
+ if (result != null){
+ AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add roles to acl group");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_GROUP_UPDATE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "adding acl roles to acl group";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclGroup;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/CreateAclGroupCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/CreateAclGroupCmd.java
new file mode 100644
index 00000000000..3654d0d1295
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/CreateAclGroupCmd.java
@@ -0,0 +1,162 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCreateCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.user.Account;
+
+@APICommand(name = "createAclGroup", responseObject = AclGroupResponse.class, description = "Creates an acl group")
+public class CreateAclGroupCmd extends BaseAsyncCreateCmd {
+ public static final Logger s_logger = Logger.getLogger(CreateAclGroupCmd.class.getName());
+
+ private static final String s_name = "createaclgroupresponse";
+
+ // ///////////////////////////////////////////////////
+ // ////////////// API parameters /////////////////////
+ // ///////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an account for the acl group. Must be used with domainId.")
+ private String accountName;
+
+ @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the acl group", entityType = DomainResponse.class)
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the acl group")
+ private String description;
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the acl group")
+ private String name;
+
+
+ // ///////////////////////////////////////////////////
+ // ///////////////// Accessors ///////////////////////
+ // ///////////////////////////////////////////////////
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+
+ // ///////////////////////////////////////////////////
+ // ///////////// API Implementation///////////////////
+ // ///////////////////////////////////////////////////
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ Account account = CallContext.current().getCallingAccount();
+ if ((account == null) || _accountService.isAdmin(account.getType())) {
+ if ((domainId != null) && (accountName != null)) {
+ Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
+ if (userAccount != null) {
+ return userAccount.getId();
+ }
+ }
+ }
+
+ if (account != null) {
+ return account.getId();
+ }
+
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
+ // command to SYSTEM so ERROR events
+ // are tracked
+ }
+
+ @Override
+ public void execute() {
+ AclGroup grp = _entityMgr.findById(AclGroup.class, getEntityId());
+ if (grp != null) {
+ AclGroupResponse response = _responseGenerator.createAclGroupResponse(grp);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create acl group:" + name);
+ }
+ }
+
+ @Override
+ public void create() throws ResourceAllocationException {
+ Account account = CallContext.current().getCallingAccount();
+ AclGroup result = _aclService.createAclGroup(account, name, description);
+ if (result != null) {
+ setEntityId(result.getId());
+ setEntityUuid(result.getUuid());
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create acl group entity" + name);
+ }
+
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_GROUP_CREATE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "creating Acl group";
+ }
+
+ @Override
+ public String getCreateEventType() {
+ return EventTypes.EVENT_ACL_GROUP_CREATE;
+ }
+
+ @Override
+ public String getCreateEventDescription() {
+ return "creating acl group";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclGroup;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/CreateAclPolicyCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/CreateAclPolicyCmd.java
new file mode 100644
index 00000000000..6628a82f971
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/CreateAclPolicyCmd.java
@@ -0,0 +1,169 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclPolicy;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCreateCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclPolicyResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.user.Account;
+
+@APICommand(name = "createAclPolicy", responseObject = AclPolicyResponse.class, description = "Creates an acl policy")
+public class CreateAclPolicyCmd extends BaseAsyncCreateCmd {
+ public static final Logger s_logger = Logger.getLogger(CreateAclPolicyCmd.class.getName());
+
+ private static final String s_name = "createaclpolicyresponse";
+
+ // ///////////////////////////////////////////////////
+ // ////////////// API parameters /////////////////////
+ // ///////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an account for the acl policy. Must be used with domainId.")
+ private String accountName;
+
+ @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the acl policy", entityType = DomainResponse.class)
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the acl policy")
+ private String description;
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the acl policy")
+ private String name;
+
+ @ACL
+ @Parameter(name = ApiConstants.ACL_PARENT_POLICY_ID, type = CommandType.UUID, description = "The ID of parent acl policy.", entityType = AclPolicyResponse.class)
+ private Long parentPolicyId;
+
+
+ // ///////////////////////////////////////////////////
+ // ///////////////// Accessors ///////////////////////
+ // ///////////////////////////////////////////////////
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Long getParentPolicyId() {
+ return parentPolicyId;
+ }
+
+ // ///////////////////////////////////////////////////
+ // ///////////// API Implementation///////////////////
+ // ///////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ Account account = CallContext.current().getCallingAccount();
+ if ((account == null) || _accountService.isAdmin(account.getType())) {
+ if ((domainId != null) && (accountName != null)) {
+ Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
+ if (userAccount != null) {
+ return userAccount.getId();
+ }
+ }
+ }
+
+ if (account != null) {
+ return account.getId();
+ }
+
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this
+ // command to SYSTEM so ERROR events
+ // are tracked
+ }
+
+ @Override
+ public void execute() {
+ AclPolicy policy = _entityMgr.findById(AclPolicy.class, getEntityId());
+ if (policy != null) {
+ AclPolicyResponse response = _responseGenerator.createAclPolicyResponse(policy);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create acl policy:" + name);
+ }
+ }
+
+ @Override
+ public void create() throws ResourceAllocationException {
+ Account account = CallContext.current().getCallingAccount();
+ AclPolicy result = _aclService.createAclPolicy(account, name, description, parentPolicyId);
+ if (result != null) {
+ setEntityId(result.getId());
+ setEntityUuid(result.getUuid());
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create acl policy entity" + name);
+ }
+
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_POLICY_CREATE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "creating Acl policy";
+ }
+
+ @Override
+ public String getCreateEventType() {
+ return EventTypes.EVENT_ACL_POLICY_CREATE;
+ }
+
+ @Override
+ public String getCreateEventDescription() {
+ return "creating acl policy";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclPolicy;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/DeleteAclGroupCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/DeleteAclGroupCmd.java
new file mode 100644
index 00000000000..110c1b528fa
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/DeleteAclGroupCmd.java
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "deleteAclGroup", description = "Deletes acl group", responseObject = SuccessResponse.class)
+public class DeleteAclGroupCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DeleteAclGroupCmd.class.getName());
+ private static final String s_name = "deleteaclgroupresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the acl group.", required = true, entityType = AclGroupResponse.class)
+ private Long id;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = _aclService.deleteAclGroup(id);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete acl group");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_GROUP_DELETE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "Deleting Acl group";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclGroup;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/DeleteAclPolicyCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/DeleteAclPolicyCmd.java
new file mode 100644
index 00000000000..06df62f4187
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/DeleteAclPolicyCmd.java
@@ -0,0 +1,96 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclPolicyResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "deleteAclPolicy", description = "Deletes acl policy", responseObject = SuccessResponse.class)
+public class DeleteAclPolicyCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DeleteAclPolicyCmd.class.getName());
+ private static final String s_name = "deleteaclpolicyresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the acl role.", required = true, entityType = AclPolicyResponse.class)
+ private Long id;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = _aclService.deleteAclPolicy(id);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete acl policy");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_POLICY_DELETE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "Deleting Acl role";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclPolicy;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/ListAclGroupsCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/ListAclGroupsCmd.java
new file mode 100644
index 00000000000..e6f732c0633
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/ListAclGroupsCmd.java
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+
+
+@APICommand(name = "listAclGroups", description = "Lists acl groups", responseObject = AclGroupResponse.class)
+public class ListAclGroupsCmd extends BaseListDomainResourcesCmd {
+ public static final Logger s_logger = Logger.getLogger(ListAclGroupsCmd.class.getName());
+
+ private static final String s_name = "listaclgroupsresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists acl groups by name")
+ private String aclGroupName;
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the acl group by the id provided", entityType = AclGroupResponse.class)
+ private Long id;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+ public String getAclGroupName() {
+ return aclGroupName;
+ }
+
+
+ public Long getId(){
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+
+ ListResponse response = _queryService.listAclGroups(id, aclGroupName, getDomainId(),
+ getStartIndex(), getPageSizeVal());
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclGroup;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/ListAclPoliciesCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/ListAclPoliciesCmd.java
new file mode 100644
index 00000000000..5a99da0d045
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/ListAclPoliciesCmd.java
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListDomainResourcesCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.AclPolicyResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+
+
+@APICommand(name = "listAclPolicies", description = "Lists acl policies", responseObject = AclPolicyResponse.class)
+public class ListAclPoliciesCmd extends BaseListDomainResourcesCmd {
+ public static final Logger s_logger = Logger.getLogger(ListAclPoliciesCmd.class.getName());
+
+ private static final String s_name = "listaclpoliciesresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists acl policies by name")
+ private String aclPolicyName;
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the acl policy by the id provided", entityType = AclPolicyResponse.class)
+ private Long id;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+ public String getAclPolicyName() {
+ return aclPolicyName;
+ }
+
+
+ public Long getId(){
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+
+ ListResponse response = _queryService.listAclPolicies(id, aclPolicyName, getDomainId(),
+ getStartIndex(), getPageSizeVal());
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclPolicy;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAccountFromAclGroupCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAccountFromAclGroupCmd.java
new file mode 100644
index 00000000000..8d8d28a7673
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAccountFromAclGroupCmd.java
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "removeAccountFromAclGroup", description = "remove accounts from an acl group", responseObject = AclGroupResponse.class)
+public class RemoveAccountFromAclGroupCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(RemoveAccountFromAclGroupCmd.class.getName());
+ private static final String s_name = "removeaccountfromaclgroupresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
+ required = true, description = "The ID of the acl group")
+ private Long id;
+
+ @ACL
+ @Parameter(name = ApiConstants.ACCOUNTS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AccountResponse.class, description = "comma separated list of account id that are going to be assigned to the acl group.")
+ private List accountIdList;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getId() {
+ return id;
+ }
+
+
+ public List getAccountIdList() {
+ return accountIdList;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException,
+ InsufficientCapacityException, ServerApiException {
+ CallContext.current().setEventDetails("Acl group Id: " + getId());
+ AclGroup result = _aclService.removeAccountsFromGroup(accountIdList, id);
+ if (result != null){
+ AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove accounts from acl group");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_GROUP_UPDATE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "removing accounts from acl group";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclGroup;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAclPermissionFromAclPolicyCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAclPermissionFromAclPolicyCmd.java
new file mode 100644
index 00000000000..dc8ff33e9b9
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAclPermissionFromAclPolicyCmd.java
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclPolicy;
+import org.apache.cloudstack.acl.PermissionScope;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclPolicyResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "removeAclPermissionFromAclPolicy", description = "Remove acl permission from an acl policy", responseObject = AclPolicyResponse.class)
+public class RemoveAclPermissionFromAclPolicyCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(RemoveAclPermissionFromAclPolicyCmd.class.getName());
+ private static final String s_name = "removeaclpermissionfromaclpolicyresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclPolicyResponse.class,
+ required = true, description = "The ID of the acl policy")
+ private Long id;
+
+ @Parameter(name = ApiConstants.ACL_ACTION, type = CommandType.STRING, required = true, description = "action api name.")
+ private String action;
+
+ @Parameter(name = ApiConstants.ENTITY_TYPE, type = CommandType.STRING, required = false, description = "entity class simple name.")
+ private String entityType;
+
+ @Parameter(name = ApiConstants.ACL_SCOPE, type = CommandType.STRING,
+ required = false, description = "acl permission scope")
+ private String scope;
+
+ @Parameter(name = ApiConstants.ACL_SCOPE_ID, type = CommandType.UUID, required = false, description = "The ID of the permission scope id")
+ private Long scopeId;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getId() {
+ return id;
+ }
+
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getEntityType() {
+ return entityType;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public Long getScopeId() {
+ return scopeId;
+ }
+
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException,
+ InsufficientCapacityException, ServerApiException {
+ CallContext.current().setEventDetails("Acl policy Id: " + getId());
+ AclPolicy result = _aclService.removeAclPermissionFromAclPolicy(id, entityType, PermissionScope.valueOf(scope), scopeId, action);
+ if (result != null) {
+ AclPolicyResponse response = _responseGenerator.createAclPolicyResponse(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove permission from acl policy " + getId());
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_POLICY_REVOKE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "removing permission from acl policy";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclPolicy;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAclPolicyFromAclGroupCmd.java b/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAclPolicyFromAclGroupCmd.java
new file mode 100644
index 00000000000..39958c0466b
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/api/command/RemoveAclPolicyFromAclGroupCmd.java
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.api.command;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.acl.AclGroup;
+import org.apache.cloudstack.api.ACL;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandJobType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.AclGroupResponse;
+import org.apache.cloudstack.api.response.AclPolicyResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+
+
+@APICommand(name = "removeAclPolicyFromAclGroup", description = "remove acl policy from an acl group", responseObject = AclGroupResponse.class)
+public class RemoveAclPolicyFromAclGroupCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(RemoveAclPolicyFromAclGroupCmd.class.getName());
+ private static final String s_name = "removeaclpolicyfromaclgroupresponse";
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+
+ @ACL
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AclGroupResponse.class,
+ required = true, description = "The ID of the acl group")
+ private Long id;
+
+ @ACL
+ @Parameter(name = ApiConstants.ACL_POLICIES, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AclPolicyResponse.class, description = "comma separated list of acl policy id that are going to be applied to the acl group.")
+ private List policyIdList;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getId() {
+ return id;
+ }
+
+
+ public List getRoleIdList() {
+ return policyIdList;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException,
+ InsufficientCapacityException, ServerApiException {
+ CallContext.current().setEventDetails("Acl group Id: " + getId());
+ AclGroup result = _aclService.removeAclPoliciesFromGroup(policyIdList, id);
+ if (result != null){
+ AclGroupResponse response = _responseGenerator.createAclGroupResponse(result);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add roles to acl group");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_ACL_GROUP_UPDATE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "removing acl roles from acl group";
+ }
+
+ @Override
+ public ApiCommandJobType getInstanceType() {
+ return ApiCommandJobType.AclGroup;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupAccountMapVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupAccountMapVO.java
new file mode 100644
index 00000000000..d39317afa0f
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupAccountMapVO.java
@@ -0,0 +1,78 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("acl_group_account_map"))
+public class AclGroupAccountMapVO {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "group_id")
+ private long aclGroupId;
+
+ @Column(name = "account_id")
+ private long accountId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public AclGroupAccountMapVO() {
+ }
+
+ public AclGroupAccountMapVO(long aclGroupId, long accountId) {
+ this.aclGroupId = aclGroupId;
+ this.accountId = accountId;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public long getAclGroupId() {
+ return aclGroupId;
+ }
+
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupPolicyMapVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupPolicyMapVO.java
new file mode 100644
index 00000000000..0dfef09181f
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupPolicyMapVO.java
@@ -0,0 +1,79 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("acl_group_policy_map"))
+public class AclGroupPolicyMapVO {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ @Column(name = "group_id")
+ private long aclGroupId;
+
+ @Column(name = "policy_id")
+ private long aclPolicyId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public AclGroupPolicyMapVO() {
+ }
+
+ public AclGroupPolicyMapVO(long aclGroupId, long aclPolicyId) {
+ this.aclGroupId = aclGroupId;
+ this.aclPolicyId = aclPolicyId;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public long getAclGroupId() {
+ return aclGroupId;
+ }
+
+
+ public long getAclPolicyId() {
+ return aclPolicyId;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupVO.java
new file mode 100644
index 00000000000..892803d7461
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/AclGroupVO.java
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.iam.api.AclGroup;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("acl_group"))
+public class AclGroupVO implements AclGroup {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "description")
+ private String description;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ @Column(name = "path")
+ private String path;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public AclGroupVO() {
+ uuid = UUID.randomUUID().toString();
+ }
+
+ public AclGroupVO(String name, String description) {
+ this.name = name;
+ this.description = description;
+ uuid = UUID.randomUUID().toString();
+ path = "/";
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyPermissionVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyPermissionVO.java
new file mode 100644
index 00000000000..87f490b0b38
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyPermissionVO.java
@@ -0,0 +1,172 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.iam.api.AclPolicyPermission;
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("acl_policy_permission"))
+public class AclPolicyPermissionVO implements AclPolicyPermission {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "policy_id")
+ private long aclPolicyId;
+
+ @Column(name = "action")
+ private String action;
+
+ @Column(name = "resource_type")
+ private String entityType;
+
+ @Column(name = "access_type")
+ private String accessType;
+
+ @Column(name = "scope")
+ private String scope;
+
+ @Column(name = "scope_id")
+ private Long scopeId;
+
+ @Column(name = "permission")
+ @Enumerated(value = EnumType.STRING)
+ private Permission permission;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ public AclPolicyPermissionVO() {
+
+ }
+
+ public AclPolicyPermissionVO(long aclPolicyId, String action, String entityType, String accessType, String scope,
+ Long scopeId, Permission permission) {
+ this.aclPolicyId = aclPolicyId;
+ this.action = action;
+ this.entityType = entityType;
+ this.accessType = accessType;
+ this.scope = scope;
+ this.scopeId = scopeId;
+ this.permission = permission;
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public long getAclPolicyId() {
+ return aclPolicyId;
+ }
+
+
+ public void setAclPolicyId(long aclPolicyId) {
+ this.aclPolicyId = aclPolicyId;
+ }
+
+ @Override
+ public String getEntityType() {
+ return entityType;
+ }
+
+ @Override
+ public String getAccessType() {
+ return accessType;
+ }
+
+
+ public void setEntityType(String entityType) {
+ this.entityType = entityType;
+ }
+
+ public void setAccessType(String accessType) {
+ this.accessType = accessType;
+ }
+
+ @Override
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+
+
+ @Override
+ public String getAction() {
+ return action;
+ }
+
+ @Override
+ public Long getScopeId() {
+ // TODO
+ // handle special -1 scopeId, current caller domain, account
+ /*
+ * if ( scopeId < 0 ){ Account caller =
+ * CallContext.current().getCallingAccount(); if ( scope ==
+ * PermissionScope.DOMAIN){ return caller.getDomainId(); } else if
+ * (scope == PermissionScope.ACCOUNT) { return caller.getAccountId(); }
+ * }
+ */
+ return scopeId;
+ }
+
+ @Override
+ public Permission getPermission() {
+ return permission;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public void setScopeId(Long scopeId) {
+ this.scopeId = scopeId;
+ }
+
+ public void setPermission(Permission permission) {
+ this.permission = permission;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyVO.java
new file mode 100644
index 00000000000..e6e30ca7ea5
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyVO.java
@@ -0,0 +1,136 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.iam.api.AclPolicy;
+
+import com.cloud.utils.db.GenericDao;
+
+@Entity
+@Table(name = ("acl_policy"))
+public class AclPolicyVO implements AclPolicy {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "description")
+ private String description;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ @Column(name = "domain_id")
+ private long domainId;
+
+ @Column(name = "account_id")
+ private long accountId;
+
+ @Column(name = GenericDao.REMOVED_COLUMN)
+ private Date removed;
+
+ @Column(name = GenericDao.CREATED_COLUMN)
+ private Date created;
+
+ @Column(name = "policy_type")
+ @Enumerated(value = EnumType.STRING)
+ private AclPolicy.PolicyType policyType;
+
+ public AclPolicyVO() {
+ uuid = UUID.randomUUID().toString();
+ }
+
+ public AclPolicyVO(String name, String description) {
+ this.name = name;
+ this.description = description;
+ uuid = UUID.randomUUID().toString();
+ policyType = AclPolicy.PolicyType.Static;
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+
+ @Override
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public Date getRemoved() {
+ return removed;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public long getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(long domainId) {
+ this.domainId = domainId;
+ }
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(long accountId) {
+ this.accountId = accountId;
+ }
+
+ public AclPolicy.PolicyType getPolicyType() {
+ return policyType;
+ }
+
+ public void setPolicyType(AclPolicy.PolicyType policyType) {
+ this.policyType = policyType;
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java
new file mode 100644
index 00000000000..3ec32e34a7e
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java
@@ -0,0 +1,543 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.iam.api.AclGroup;
+import org.apache.cloudstack.iam.api.AclPolicy;
+import org.apache.cloudstack.iam.api.AclPolicyPermission.Permission;
+import org.apache.cloudstack.iam.api.IAMService;
+import org.apache.cloudstack.iam.server.dao.AclGroupAccountMapDao;
+import org.apache.cloudstack.iam.server.dao.AclGroupDao;
+import org.apache.cloudstack.iam.server.dao.AclGroupPolicyMapDao;
+import org.apache.cloudstack.iam.server.dao.AclPolicyDao;
+import org.apache.cloudstack.iam.server.dao.AclPolicyPermissionDao;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+import com.cloud.utils.component.Manager;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.db.GenericSearchBuilder;
+import com.cloud.utils.db.JoinBuilder.JoinType;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionStatus;
+
+@Local(value = {IAMService.class})
+public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
+
+ public static final Logger s_logger = Logger.getLogger(IAMServiceImpl.class);
+ private String _name;
+
+ @Inject
+ AclPolicyDao _aclPolicyDao;
+
+ @Inject
+ AclGroupDao _aclGroupDao;
+
+ @Inject
+ EntityManager _entityMgr;
+
+ @Inject
+ AclGroupPolicyMapDao _aclGroupPolicyMapDao;
+
+ @Inject
+ AclGroupAccountMapDao _aclGroupAccountMapDao;
+
+ @Inject
+ AclPolicyPermissionDao _policyPermissionDao;
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_CREATE, eventDescription = "Creating Acl Group", create = true)
+ public AclGroup createAclGroup(String aclGroupName, String description, String path) {
+ // check if the role is already existing
+ AclGroup grp = _aclGroupDao.findByName(path, aclGroupName);
+ if (grp != null) {
+ throw new InvalidParameterValueException(
+ "Unable to create acl group with name " + aclGroupName
+ + " already exisits for path " + path);
+ }
+ AclGroupVO rvo = new AclGroupVO(aclGroupName, description);
+ rvo.setPath(path);
+
+ return _aclGroupDao.persist(rvo);
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_DELETE, eventDescription = "Deleting Acl Group")
+ public boolean deleteAclGroup(final Long aclGroupId) {
+ // get the Acl Group entity
+ final AclGroup grp = _aclGroupDao.findById(aclGroupId);
+ if (grp == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + aclGroupId
+ + "; failed to delete acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove this group related entry in acl_group_role_map
+ List groupPolicyMap = _aclGroupPolicyMapDao.listByGroupId(grp.getId());
+ if (groupPolicyMap != null) {
+ for (AclGroupPolicyMapVO gr : groupPolicyMap) {
+ _aclGroupPolicyMapDao.remove(gr.getId());
+ }
+ }
+
+ // remove this group related entry in acl_group_account table
+ List groupAcctMap = _aclGroupAccountMapDao.listByGroupId(grp.getId());
+ if (groupAcctMap != null) {
+ for (AclGroupAccountMapVO grpAcct : groupAcctMap) {
+ _aclGroupAccountMapDao.remove(grpAcct.getId());
+ }
+ }
+
+ // remove this group from acl_group table
+ _aclGroupDao.remove(aclGroupId);
+ }
+ });
+
+ return true;
+ }
+
+ @Override
+ public List listAclGroups(long accountId) {
+
+ GenericSearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder(Long.class);
+ groupSB.selectFields(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);
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Adding accounts to acl group")
+ public AclGroup addAccountsToGroup(final List acctIds, final Long groupId) {
+ final Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to add accounts to acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_account_map table
+ for (Long acctId : acctIds) {
+ // check account permissions
+ AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
+ if (grMap == null) {
+ // not there already
+ grMap = new AclGroupAccountMapVO(groupId, acctId);
+ _aclGroupAccountMapDao.persist(grMap);
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Removing accounts from acl group")
+ public AclGroup removeAccountsFromGroup(final List acctIds, final Long groupId) {
+ final Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to remove accounts from acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove entries from acl_group_account_map table
+ for (Long acctId : acctIds) {
+ AclGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
+ if (grMap != null) {
+ // not removed yet
+ _aclGroupAccountMapDao.remove(grMap.getId());
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_CREATE, eventDescription = "Creating Acl Policy", create = true)
+ public AclPolicy createAclPolicy(final String aclPolicyName, final String description, final Long parentPolicyId) {
+
+ // check if the policy is already existing
+ AclPolicy ro = _aclPolicyDao.findByName(aclPolicyName);
+ if (ro != null) {
+ throw new InvalidParameterValueException(
+ "Unable to create acl policy with name " + aclPolicyName
+ + " already exisits");
+ }
+
+ AclPolicy role = Transaction.execute(new TransactionCallback() {
+ @Override
+ public AclPolicy doInTransaction(TransactionStatus status) {
+ AclPolicyVO rvo = new AclPolicyVO(aclPolicyName, description);
+
+ AclPolicy role = _aclPolicyDao.persist(rvo);
+ if (parentPolicyId != null) {
+ // copy parent role permissions
+ List perms = _policyPermissionDao.listByPolicy(parentPolicyId);
+ if (perms != null) {
+ for (AclPolicyPermissionVO perm : perms) {
+ perm.setAclPolicyId(role.getId());
+ _policyPermissionDao.persist(perm);
+ }
+ }
+ }
+ return role;
+ }
+ });
+
+
+ return role;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_DELETE, eventDescription = "Deleting Acl Policy")
+ public boolean deleteAclPolicy(final long aclPolicyId) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Policy entity
+ final AclPolicy policy = _aclPolicyDao.findById(aclPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + aclPolicyId
+ + "; failed to delete acl policy.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove this role related entry in acl_group_role_map
+ List groupPolicyMap = _aclGroupPolicyMapDao.listByPolicyId(policy.getId());
+ if (groupPolicyMap != null) {
+ for (AclGroupPolicyMapVO gr : groupPolicyMap) {
+ _aclGroupPolicyMapDao.remove(gr.getId());
+ }
+ }
+
+ // remove this policy related entry in acl_policy_permission table
+ List policyPermMap = _policyPermissionDao.listByPolicy(policy.getId());
+ if (policyPermMap != null) {
+ for (AclPolicyPermissionVO policyPerm : policyPermMap) {
+ _policyPermissionDao.remove(policyPerm.getId());
+ }
+ }
+
+ // remove this role from acl_role table
+ _aclPolicyDao.remove(aclPolicyId);
+ }
+ });
+
+ return true;
+ }
+
+
+ @Override
+ public List listAclPolicies(long accountId) {
+
+ // static policies of the account
+ SearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder();
+ groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
+
+ GenericSearchBuilder policySB = _aclGroupPolicyMapDao.createSearchBuilder(Long.class);
+ policySB.selectFields(policySB.entity().getAclPolicyId());
+ policySB.join("accountgroupjoin", groupSB, groupSB.entity().getAclGroupId(), policySB.entity().getAclGroupId(),
+ JoinType.INNER);
+ policySB.done();
+ SearchCriteria policySc = policySB.create();
+ policySc.setJoinParameters("accountgroupjoin", "account", accountId);
+
+ List policyIds = _aclGroupPolicyMapDao.customSearch(policySc, null);
+
+ SearchBuilder sb = _aclPolicyDao.createSearchBuilder();
+ sb.and("ids", sb.entity().getId(), Op.IN);
+ SearchCriteria sc = sb.create();
+ sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
+ List policies = _aclPolicyDao.customSearch(sc, null);
+
+ return new ArrayList(policies);
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Attaching policy to acl group")
+ public AclGroup attachAclPoliciesToGroup(final List policyIds, final Long groupId) {
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to add roles to acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_policy_map table
+ for (Long policyId : policyIds) {
+ AclPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policies to acl group.");
+ }
+
+ AclGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
+ if (grMap == null) {
+ // not there already
+ grMap = new AclGroupPolicyMapVO(groupId, policyId);
+ _aclGroupPolicyMapDao.persist(grMap);
+ }
+ }
+ }
+ });
+
+ return group;
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_UPDATE, eventDescription = "Removing policies from acl group")
+ public AclGroup removeAclPoliciesFromGroup(final List policyIds, final Long groupId) {
+ final Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Group entity
+ AclGroup group = _aclGroupDao.findById(groupId);
+ if (group == null) {
+ throw new InvalidParameterValueException("Unable to find acl group: " + groupId
+ + "; failed to remove roles from acl group.");
+ }
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_group_role_map table
+ for (Long policyId : policyIds) {
+ AclPolicy policy = _aclPolicyDao.findById(policyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ + "; failed to add policies to acl group.");
+ }
+
+ AclGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
+ if (grMap != null) {
+ // not removed yet
+ _aclGroupPolicyMapDao.remove(grMap.getId());
+ }
+ }
+ }
+ });
+ return group;
+ }
+
+ /*
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_GRANT, eventDescription = "Granting permission to Acl Role")
+ public AclP addAclPermissionToAclPolicy(final long aclRoleId, final List apiNames) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Role entity
+ AclRole role = _aclPolicyDao.findById(aclRoleId);
+ if (role == null) {
+ throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
+ + "; failed to grant permission to role.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, role);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // add entries in acl_api_permission table
+ for (String api : apiNames) {
+ AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
+ if (perm == null) {
+ // not there already
+ perm = new AclApiPermissionVO(aclRoleId, api);
+ _apiPermissionDao.persist(perm);
+ }
+ }
+ }
+ });
+
+ return role;
+
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_REVOKE, eventDescription = "Revoking permission from Acl Role")
+ public AclRole revokeApiPermissionFromAclRole(final long aclRoleId, final List apiNames) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Role entity
+ AclRole role = _aclPolicyDao.findById(aclRoleId);
+ if (role == null) {
+ throw new InvalidParameterValueException("Unable to find acl role: " + aclRoleId
+ + "; failed to revoke permission from role.");
+ }
+ // check permissions
+ _accountMgr.checkAccess(caller, null, true, role);
+
+ Transaction.execute(new TransactionCallbackNoReturn() {
+ @Override
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ // remove entries from acl_api_permission table
+ for (String api : apiNames) {
+ AclApiPermissionVO perm = _apiPermissionDao.findByRoleAndApi(aclRoleId, api);
+ if (perm != null) {
+ // not removed yet
+ _apiPermissionDao.remove(perm.getId());
+ }
+ }
+ }
+ });
+ return role;
+ }
+ */
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_GRANT, eventDescription = "Granting acl permission to Acl Policy")
+ public AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId,
+ String action, String accessType, Permission perm) {
+ Account caller = CallContext.current().getCallingAccount();
+ // get the Acl Policy entity
+ AclPolicy policy = _aclPolicyDao.findById(aclPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + aclPolicyId
+ + "; failed to add permission to policy.");
+ }
+
+ // add entry in acl_policy_permission table
+ AclPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(aclPolicyId, entityType, scope, scopeId, action, perm);
+ if (permit == null) {
+ // not there already
+ permit = new AclPolicyPermissionVO(aclPolicyId, action, entityType, accessType, scope, scopeId, perm);
+ _policyPermissionDao.persist(permit);
+ }
+ return policy;
+
+ }
+
+ @DB
+ @Override
+ @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_REVOKE, eventDescription = "Revoking acl permission from Acl Policy")
+ public AclPolicy removeAclPermissionFromAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId,
+ String action) {
+ // get the Acl Policy entity
+ AclPolicy policy = _aclPolicyDao.findById(aclPolicyId);
+ if (policy == null) {
+ throw new InvalidParameterValueException("Unable to find acl policy: " + aclPolicyId
+ + "; failed to revoke permission from policy.");
+ }
+ // remove entry from acl_entity_permission table
+ AclPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(aclPolicyId, entityType, scope, scopeId, action, null);
+ if (permit != null) {
+ // not removed yet
+ _policyPermissionDao.remove(permit.getId());
+ }
+ return policy;
+ }
+
+
+
+ @Override
+ public boolean isAPIAccessibleForPolicies(String apiName, List policies) {
+
+ boolean accessible = false;
+
+ List policyIds = new ArrayList();
+ for (AclPolicy policy : policies) {
+ policyIds.add(policy.getId());
+ }
+
+ SearchBuilder sb = _policyPermissionDao.createSearchBuilder();
+ sb.and("action", sb.entity().getAction(), Op.EQ);
+ sb.and("policyId", sb.entity().getAclPolicyId(), Op.IN);
+
+ SearchCriteria sc = sb.create();
+ sc.setParameters("policyId", policyIds.toArray(new Object[policyIds.size()]));
+
+ List permissions = _policyPermissionDao.customSearch(sc, null);
+
+ if (permissions != null && !permissions.isEmpty()) {
+ accessible = true;
+ }
+
+ return accessible;
+ }
+
+
+ @Override
+ public List getGrantedEntities(long accountId, String action, String scope) {
+ // Get the static Policies of the Caller
+ List policies = listAclPolicies(accountId);
+ // for each policy, find granted permission within the given scope
+ List entityIds = new ArrayList();
+ for (AclPolicy policy : policies) {
+ List pp = _policyPermissionDao.listGrantedByActionAndScope(policy.getId(), action,
+ scope);
+ if (pp != null) {
+ for (AclPolicyPermissionVO p : pp) {
+ if (p.getScopeId() != null) {
+ entityIds.add(p.getScopeId());
+ }
+ }
+ }
+ }
+ return entityIds;
+ }
+
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupAccountMapDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupAccountMapDao.java
new file mode 100644
index 00000000000..58f69c3341d
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupAccountMapDao.java
@@ -0,0 +1,40 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.server.AclGroupAccountMapVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface AclGroupAccountMapDao extends GenericDao {
+
+ List listByGroupId(long groupId);
+
+ List listByAccountId(long accountId);
+
+ AclGroupAccountMapVO findAccountInAdminGroup(long accountId);
+
+ AclGroupAccountMapVO findByGroupAndAccount(long groupId, long acctId);
+
+ void removeAccountFromGroups(long accountId);
+
+ AclGroupAccountMapVO findAccountInDomainAdminGroup(long accountId);
+
+ AclGroupAccountMapVO findAccountInUserGroup(long accountId);
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupAccountMapDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupAccountMapDaoImpl.java
new file mode 100644
index 00000000000..32ce64ab369
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupAccountMapDaoImpl.java
@@ -0,0 +1,119 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.server.AclGroupAccountMapVO;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+public class AclGroupAccountMapDaoImpl extends GenericDaoBase implements AclGroupAccountMapDao {
+ private SearchBuilder ListByGroupId;
+ private SearchBuilder ListByAccountId;
+ private SearchBuilder _findByAccountAndGroupId;
+
+ public static final Logger s_logger = Logger.getLogger(AclGroupAccountMapDaoImpl.class.getName());
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ ListByGroupId = createSearchBuilder();
+ ListByGroupId.and("groupId", ListByGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ ListByGroupId.done();
+
+ ListByAccountId = createSearchBuilder();
+ ListByAccountId.and("accountId", ListByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
+ ListByAccountId.done();
+
+ _findByAccountAndGroupId = createSearchBuilder();
+ _findByAccountAndGroupId
+ .and("groupId", _findByAccountAndGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ _findByAccountAndGroupId.and("accountId", _findByAccountAndGroupId.entity().getAccountId(),
+ SearchCriteria.Op.EQ);
+ _findByAccountAndGroupId.done();
+
+ return true;
+ }
+
+ @Override
+ public List listByGroupId(long groupId) {
+ SearchCriteria sc = ListByGroupId.create();
+ sc.setParameters("groupId", groupId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByAccountId(long accountId) {
+ SearchCriteria sc = ListByAccountId.create();
+ sc.setParameters("accountId", accountId);
+ return listBy(sc);
+ }
+
+ @Override
+ public AclGroupAccountMapVO findAccountInAdminGroup(long accountId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", accountId);
+ sc.setParameters("groupId", 2);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public AclGroupAccountMapVO findAccountInDomainAdminGroup(long accountId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", accountId);
+ sc.setParameters("groupId", 3);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public AclGroupAccountMapVO findAccountInUserGroup(long accountId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", accountId);
+ sc.setParameters("groupId", 1);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public AclGroupAccountMapVO findByGroupAndAccount(long groupId, long acctId) {
+ SearchCriteria sc = _findByAccountAndGroupId.create();
+ sc.setParameters("accountId", acctId);
+ sc.setParameters("groupId", groupId);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public void removeAccountFromGroups(long accountId) {
+ SearchCriteria sc = ListByAccountId.create();
+ sc.setParameters("accountId", accountId);
+
+ int rowsRemoved = remove(sc);
+ if (rowsRemoved > 0) {
+ s_logger.debug("Removed account id=" + accountId + " from " + rowsRemoved + " groups");
+ }
+ }
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupDao.java
new file mode 100644
index 00000000000..aa62a0b558d
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupDao.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+
+import org.apache.cloudstack.iam.api.AclGroup;
+import org.apache.cloudstack.iam.server.AclGroupVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface AclGroupDao extends GenericDao {
+
+ AclGroup findByName(String path, String groupName);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupDaoImpl.java
new file mode 100644
index 00000000000..e091574c6b5
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupDaoImpl.java
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.api.AclGroup;
+import org.apache.cloudstack.iam.server.AclGroupVO;
+import org.springframework.stereotype.Component;
+
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+public class AclGroupDaoImpl extends GenericDaoBase implements AclGroupDao {
+ private SearchBuilder nameSearch;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ nameSearch = createSearchBuilder();
+ nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ);
+ nameSearch.and("path", nameSearch.entity().getPath(), SearchCriteria.Op.EQ);
+ nameSearch.done();
+
+
+ return true;
+ }
+
+ @Override
+ public AclGroup findByName(String path, String name) {
+ SearchCriteria sc = nameSearch.create();
+ sc.setParameters("name", name);
+ if (path != null) {
+ sc.setParameters("path", path);
+ }
+ return findOneBy(sc);
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupPolicyMapDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupPolicyMapDao.java
new file mode 100644
index 00000000000..a016fc5537a
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupPolicyMapDao.java
@@ -0,0 +1,16 @@
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+
+import org.apache.cloudstack.iam.server.AclGroupPolicyMapVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface AclGroupPolicyMapDao extends GenericDao {
+
+ List listByGroupId(long groupId);
+
+ List listByPolicyId(long policyId);
+
+ AclGroupPolicyMapVO findByGroupAndPolicy(long groupId, long policyId);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupPolicyMapDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupPolicyMapDaoImpl.java
new file mode 100644
index 00000000000..3ce2b8a4b56
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclGroupPolicyMapDaoImpl.java
@@ -0,0 +1,61 @@
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.server.AclGroupPolicyMapVO;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+public class AclGroupPolicyMapDaoImpl extends GenericDaoBase implements AclGroupPolicyMapDao {
+
+ private SearchBuilder ListByGroupId;
+ private SearchBuilder ListByPolicyId;
+ private SearchBuilder findByPolicyGroupId;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ ListByGroupId = createSearchBuilder();
+ ListByGroupId.and("groupId", ListByGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ ListByGroupId.done();
+
+ ListByPolicyId = createSearchBuilder();
+ ListByPolicyId.and("policyId", ListByPolicyId.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ ListByPolicyId.done();
+
+ findByPolicyGroupId = createSearchBuilder();
+ findByPolicyGroupId.and("policyId", findByPolicyGroupId.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ findByPolicyGroupId.and("groupId", findByPolicyGroupId.entity().getAclGroupId(), SearchCriteria.Op.EQ);
+ findByPolicyGroupId.done();
+
+ return true;
+ }
+
+ @Override
+ public List listByGroupId(long groupId) {
+ SearchCriteria sc = ListByGroupId.create();
+ sc.setParameters("groupId", groupId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByPolicyId(long policyId) {
+ SearchCriteria sc = ListByPolicyId.create();
+ sc.setParameters("policyId", policyId);
+ return listBy(sc);
+ }
+
+ @Override
+ public AclGroupPolicyMapVO findByGroupAndPolicy(long groupId, long policyId) {
+ SearchCriteria sc = findByPolicyGroupId.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("groupId", groupId);
+ return findOneBy(sc);
+ }
+}
\ No newline at end of file
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyDao.java
new file mode 100644
index 00000000000..a61c5de051b
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyDao.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+
+import org.apache.cloudstack.iam.api.AclPolicy;
+import org.apache.cloudstack.iam.server.AclPolicyVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface AclPolicyDao extends GenericDao {
+
+ AclPolicy findByName(String policyName);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyDaoImpl.java
new file mode 100644
index 00000000000..a1a81e68bc9
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyDaoImpl.java
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.api.AclPolicy;
+import org.apache.cloudstack.iam.server.AclPolicyVO;
+import org.springframework.stereotype.Component;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+public class AclPolicyDaoImpl extends GenericDaoBase implements AclPolicyDao {
+ private SearchBuilder nameSearch;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ nameSearch = createSearchBuilder();
+ nameSearch.and("name", nameSearch.entity().getName(), SearchCriteria.Op.EQ);
+ // nameSearch.and("domainId", nameSearch.entity().getDomainId(),
+ // SearchCriteria.Op.EQ);
+ nameSearch.done();
+
+
+ return true;
+ }
+
+ @Override
+ public AclPolicy findByName(String name) {
+ SearchCriteria sc = nameSearch.create();
+ sc.setParameters("name", name);
+
+ return findOneBy(sc);
+ }
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyPermissionDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyPermissionDao.java
new file mode 100644
index 00000000000..f2da895aa2f
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyPermissionDao.java
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+import java.util.List;
+import org.apache.cloudstack.iam.api.AclPolicyPermission.Permission;
+import org.apache.cloudstack.iam.server.AclPolicyPermissionVO;
+
+
+import com.cloud.utils.db.GenericDao;
+
+public interface AclPolicyPermissionDao extends GenericDao {
+
+ List listByPolicy(long policyId);
+
+ AclPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityType, String scope, Long scopeId,
+ String action, Permission perm);
+
+ List listGrantedByActionAndScope(long policyId, String action, String scope);
+
+ List listByPolicyActionAndEntity(long policyId, String action, String entityType);
+
+ List listByPolicyAccessAndEntity(long id, String accessType, String entityType);
+
+}
diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyPermissionDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyPermissionDaoImpl.java
new file mode 100644
index 00000000000..d738e007e48
--- /dev/null
+++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/AclPolicyPermissionDaoImpl.java
@@ -0,0 +1,115 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.iam.server.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.iam.api.AclPolicyPermission.Permission;
+import org.apache.cloudstack.iam.server.AclPolicyPermissionVO;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+public class AclPolicyPermissionDaoImpl extends GenericDaoBase implements
+ AclPolicyPermissionDao {
+
+ private SearchBuilder policyIdSearch;
+ private SearchBuilder fullSearch;
+ private SearchBuilder actionScopeSearch;
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ super.configure(name, params);
+
+ policyIdSearch = createSearchBuilder();
+ policyIdSearch.and("policyId", policyIdSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ policyIdSearch.done();
+
+ fullSearch = createSearchBuilder();
+ fullSearch.and("policyId", fullSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ fullSearch.and("entityType", fullSearch.entity().getEntityType(), SearchCriteria.Op.EQ);
+ fullSearch.and("scope", fullSearch.entity().getScope(), SearchCriteria.Op.EQ);
+ fullSearch.and("scopeId", fullSearch.entity().getScopeId(), SearchCriteria.Op.EQ);
+ fullSearch.and("action", fullSearch.entity().getAction(), SearchCriteria.Op.EQ);
+ fullSearch.and("permission", fullSearch.entity().getPermission(), SearchCriteria.Op.EQ);
+ fullSearch.and("accessType", fullSearch.entity().getAccessType(), SearchCriteria.Op.EQ);
+ fullSearch.done();
+
+ actionScopeSearch = createSearchBuilder();
+ actionScopeSearch.and("policyId", actionScopeSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
+ actionScopeSearch.and("scope", actionScopeSearch.entity().getScope(), SearchCriteria.Op.EQ);
+ actionScopeSearch.and("action", actionScopeSearch.entity().getAction(), SearchCriteria.Op.EQ);
+ actionScopeSearch.and("permission", actionScopeSearch.entity().getPermission(), SearchCriteria.Op.EQ);
+ actionScopeSearch.done();
+
+ return true;
+ }
+
+ @Override
+ public List listByPolicy(long policyId) {
+ SearchCriteria sc = policyIdSearch.create();
+ sc.setParameters("policyId", policyId);
+ return listBy(sc);
+ }
+
+ @Override
+ public AclPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityType, String scope, Long scopeId,
+ String action, Permission perm) {
+ SearchCriteria sc = fullSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("entityType", entityType);
+ sc.setParameters("scope", scope);
+ sc.setParameters("scopeId", scopeId);
+ sc.setParameters("action", action);
+ sc.setParameters("permission", perm);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public List listGrantedByActionAndScope(long policyId, String action, String scope) {
+ SearchCriteria sc = actionScopeSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("action", action);
+ sc.setParameters("scope", scope);
+ sc.setParameters("permission", Permission.Allow);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByPolicyActionAndEntity(long policyId, String action, String entityType) {
+ SearchCriteria sc = fullSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("entityType", entityType);
+ sc.setParameters("action", action);
+ return listBy(sc);
+ }
+
+ @Override
+ public List listByPolicyAccessAndEntity(long policyId, String accessType,
+ String entityType) {
+ SearchCriteria sc = fullSearch.create();
+ sc.setParameters("policyId", policyId);
+ sc.setParameters("entityType", entityType);
+ sc.setParameters("accessType", accessType);
+ return listBy(sc);
+ }
+
+}
diff --git a/services/pom.xml b/services/pom.xml
index c2f7f88ad88..81531df2e37 100644
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -33,5 +33,6 @@
console-proxy
secondary-storage
+ iam