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