blob: 4ae694b50ff06a870f546ce92521bccf948e58cc [file] [log] [blame]
// 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 java.util.Map;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.iam.api.IAMGroup;
import org.apache.cloudstack.iam.api.IAMPolicy;
import org.apache.cloudstack.iam.api.IAMPolicyPermission;
import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission;
import org.apache.cloudstack.iam.api.IAMService;
import org.apache.cloudstack.iam.server.dao.IAMAccountPolicyMapDao;
import org.apache.cloudstack.iam.server.dao.IAMGroupAccountMapDao;
import org.apache.cloudstack.iam.server.dao.IAMGroupDao;
import org.apache.cloudstack.iam.server.dao.IAMGroupPolicyMapDao;
import org.apache.cloudstack.iam.server.dao.IAMPolicyDao;
import org.apache.cloudstack.iam.server.dao.IAMPolicyPermissionDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
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.Filter;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
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;
public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
public static final Logger s_logger = Logger.getLogger(IAMServiceImpl.class);
private String _name;
@Inject
IAMPolicyDao _aclPolicyDao;
@Inject
IAMGroupDao _aclGroupDao;
@Inject
EntityManager _entityMgr;
@Inject
IAMGroupPolicyMapDao _aclGroupPolicyMapDao;
@Inject
IAMAccountPolicyMapDao _aclAccountPolicyMapDao;
@Inject
IAMGroupAccountMapDao _aclGroupAccountMapDao;
@Inject
IAMPolicyPermissionDao _policyPermissionDao;
private Cache _iamCache;
private void createIAMCache(final Map<String, ? extends Object> params) {
final String value = (String)params.get("cache.size");
if (value != null) {
final CacheManager cm = CacheManager.create();
final int maxElements = NumbersUtil.parseInt(value, 0);
final int live = NumbersUtil.parseInt((String)params.get("cache.time.to.live"), 300);
final int idle = NumbersUtil.parseInt((String)params.get("cache.time.to.idle"), 300);
_iamCache = new Cache(getName(), maxElements, false, live == -1, live == -1 ? Integer.MAX_VALUE : live, idle);
cm.addCache(_iamCache);
s_logger.info("IAM Cache created: " + _iamCache.toString());
} else {
_iamCache = null;
}
}
@Override
public void addToIAMCache(Object accessKey, Object allowDeny) {
if (_iamCache != null) {
try {
s_logger.debug("Put IAM access check for " + accessKey + " in cache");
_iamCache.put(new Element(accessKey, allowDeny));
} catch (final Exception e) {
s_logger.debug("Can't put " + accessKey + " to IAM cache", e);
}
}
}
@Override
public void invalidateIAMCache() {
//This may need to use event bus to publish to other MS, but event bus now is missing this functionality to handle PublishScope.GLOBAL
if (_iamCache != null) {
s_logger.debug("Invalidate IAM cache");
_iamCache.removeAll();
}
}
@Override
public Object getFromIAMCache(Object accessKey) {
if (_iamCache != null) {
final Element element = _iamCache.get(accessKey);
return element == null ? null : element.getObjectValue();
}
return null;
}
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
boolean result = super.configure(name, params);
// create IAM cache
createIAMCache(params);
return result;
}
@DB
@Override
public IAMGroup createIAMGroup(String iamGroupName, String description, String path) {
// check if the group is already existing
IAMGroup grp = _aclGroupDao.findByName(path, iamGroupName);
if (grp != null) {
throw new InvalidParameterValueException(
"Unable to create acl group with name " + iamGroupName
+ " already exists for path " + path);
}
IAMGroupVO rvo = new IAMGroupVO(iamGroupName, description);
rvo.setPath(path);
return _aclGroupDao.persist(rvo);
}
@DB
@Override
public boolean deleteIAMGroup(final Long iamGroupId) {
// get the Acl Group entity
final IAMGroup grp = _aclGroupDao.findById(iamGroupId);
if (grp == null) {
throw new InvalidParameterValueException("Unable to find acl group: " + iamGroupId
+ "; failed to delete acl group.");
}
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
// remove this group related entry in acl_group_policy_map
List<IAMGroupPolicyMapVO> groupPolicyMap = _aclGroupPolicyMapDao.listByGroupId(grp.getId());
if (groupPolicyMap != null) {
for (IAMGroupPolicyMapVO gr : groupPolicyMap) {
_aclGroupPolicyMapDao.remove(gr.getId());
}
}
// remove this group related entry in acl_group_account table
List<IAMGroupAccountMapVO> groupAcctMap = _aclGroupAccountMapDao.listByGroupId(grp.getId());
if (groupAcctMap != null) {
for (IAMGroupAccountMapVO grpAcct : groupAcctMap) {
_aclGroupAccountMapDao.remove(grpAcct.getId());
}
}
// remove this group from acl_group table
_aclGroupDao.remove(iamGroupId);
}
});
invalidateIAMCache();
return true;
}
@SuppressWarnings("unchecked")
@Override
public List<IAMGroup> listIAMGroups(long accountId) {
GenericSearchBuilder<IAMGroupAccountMapVO, Long> groupSB = _aclGroupAccountMapDao.createSearchBuilder(Long.class);
groupSB.selectFields(groupSB.entity().getAclGroupId());
groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
SearchCriteria<Long> groupSc = groupSB.create();
groupSc.setParameters("account", accountId);
List<Long> groupIds = _aclGroupAccountMapDao.customSearch(groupSc, null);
if (groupIds == null || groupIds.isEmpty()) {
return new ArrayList<IAMGroup>();
}
SearchBuilder<IAMGroupVO> sb = _aclGroupDao.createSearchBuilder();
sb.and("ids", sb.entity().getId(), Op.IN);
SearchCriteria<IAMGroupVO> sc = sb.create();
sc.setParameters("ids", groupIds.toArray(new Object[groupIds.size()]));
@SuppressWarnings("rawtypes")
List groups = _aclGroupDao.search(sc, null);
return groups;
}
@DB
@Override
public IAMGroup addAccountsToGroup(final List<Long> acctIds, final Long groupId) {
// get the Acl Group entity
IAMGroup 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
IAMGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
if (grMap == null) {
// not there already
grMap = new IAMGroupAccountMapVO(groupId, acctId);
_aclGroupAccountMapDao.persist(grMap);
}
}
}
});
invalidateIAMCache();
return group;
}
@DB
@Override
public IAMGroup removeAccountsFromGroup(final List<Long> acctIds, final Long groupId) {
// get the Acl Group entity
IAMGroup 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) {
IAMGroupAccountMapVO grMap = _aclGroupAccountMapDao.findByGroupAndAccount(groupId, acctId);
if (grMap != null) {
// not removed yet
_aclGroupAccountMapDao.remove(grMap.getId());
}
}
}
});
invalidateIAMCache();
return group;
}
@Override
public List<Long> listAccountsByGroup(long groupId) {
List<IAMGroupAccountMapVO> grpAcctMap = _aclGroupAccountMapDao.listByGroupId(groupId);
if (grpAcctMap == null || grpAcctMap.size() == 0) {
return new ArrayList<Long>();
}
List<Long> accts = new ArrayList<Long>();
for (IAMGroupAccountMapVO grpAcct : grpAcctMap) {
accts.add(grpAcct.getAccountId());
}
return accts;
}
@Override
public Pair<List<IAMGroup>, Integer> listIAMGroups(Long iamGroupId, String iamGroupName, String path, Long startIndex, Long pageSize) {
if (iamGroupId != null) {
IAMGroup group = _aclGroupDao.findById(iamGroupId);
if (group == null) {
throw new InvalidParameterValueException("Unable to find acl group by id " + iamGroupId);
}
}
Filter searchFilter = new Filter(IAMGroupVO.class, "id", true, startIndex, pageSize);
SearchBuilder<IAMGroupVO> sb = _aclGroupDao.createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
SearchCriteria<IAMGroupVO> sc = sb.create();
if (iamGroupName != null) {
sc.setParameters("name", iamGroupName);
}
if (iamGroupId != null) {
sc.setParameters("id", iamGroupId);
}
sc.setParameters("path", path + "%");
Pair<List<IAMGroupVO>, Integer> groups = _aclGroupDao.searchAndCount(sc, searchFilter);
return new Pair<List<IAMGroup>, Integer>(new ArrayList<IAMGroup>(groups.first()), groups.second());
}
@Override
public List<IAMGroup> listParentIAMGroups(long groupId) {
IAMGroup group = _aclGroupDao.findById(groupId);
if (group == null) {
throw new InvalidParameterValueException("Unable to find acl group by id " + groupId);
}
String path = group.getPath();
List<String> pathList = new ArrayList<String>();
String[] parts = path.split("/");
for (String part : parts) {
int start = path.indexOf(part);
if (start > 0) {
String subPath = path.substring(0, start);
pathList.add(subPath);
}
}
if (pathList.isEmpty()) {
return new ArrayList<IAMGroup>();
}
SearchBuilder<IAMGroupVO> sb = _aclGroupDao.createSearchBuilder();
sb.and("paths", sb.entity().getPath(), SearchCriteria.Op.IN);
SearchCriteria<IAMGroupVO> sc = sb.create();
sc.setParameters("paths", pathList.toArray());
List<IAMGroupVO> groups = _aclGroupDao.search(sc, null);
return new ArrayList<IAMGroup>(groups);
}
@DB
@Override
public IAMPolicy createIAMPolicy(final String iamPolicyName, final String description, final Long parentPolicyId, final String path) {
// check if the policy is already existing
IAMPolicy ro = _aclPolicyDao.findByName(iamPolicyName);
if (ro != null) {
throw new InvalidParameterValueException(
"Unable to create acl policy with name " + iamPolicyName
+ " already exists");
}
IAMPolicy role = Transaction.execute(new TransactionCallback<IAMPolicy>() {
@Override
public IAMPolicy doInTransaction(TransactionStatus status) {
IAMPolicyVO rvo = new IAMPolicyVO(iamPolicyName, description);
rvo.setPath(path);
IAMPolicy role = _aclPolicyDao.persist(rvo);
if (parentPolicyId != null) {
// copy parent role permissions
List<IAMPolicyPermissionVO> perms = _policyPermissionDao.listByPolicy(parentPolicyId);
if (perms != null) {
for (IAMPolicyPermissionVO perm : perms) {
perm.setAclPolicyId(role.getId());
_policyPermissionDao.persist(perm);
}
}
}
return role;
}
});
return role;
}
@DB
@Override
public boolean deleteIAMPolicy(final long iamPolicyId) {
// get the Acl Policy entity
final IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ "; failed to delete acl policy.");
}
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
// remove this policy related entry in acl_group_policy_map
List<IAMGroupPolicyMapVO> groupPolicyMap = _aclGroupPolicyMapDao.listByPolicyId(policy.getId());
if (groupPolicyMap != null) {
for (IAMGroupPolicyMapVO gr : groupPolicyMap) {
_aclGroupPolicyMapDao.remove(gr.getId());
}
}
// remove this policy related entry in acl_account_policy_map table
List<IAMAccountPolicyMapVO> policyAcctMap = _aclAccountPolicyMapDao.listByPolicyId(policy.getId());
if (policyAcctMap != null) {
for (IAMAccountPolicyMapVO policyAcct : policyAcctMap) {
_aclAccountPolicyMapDao.remove(policyAcct.getId());
}
}
// remove this policy related entry in acl_policy_permission table
List<IAMPolicyPermissionVO> policyPermMap = _policyPermissionDao.listByPolicy(policy.getId());
if (policyPermMap != null) {
for (IAMPolicyPermissionVO policyPerm : policyPermMap) {
_policyPermissionDao.remove(policyPerm.getId());
}
}
// remove this role from acl_role table
_aclPolicyDao.remove(iamPolicyId);
}
});
invalidateIAMCache();
return true;
}
@SuppressWarnings("unchecked")
@Override
public List<IAMPolicy> listIAMPolicies(long accountId) {
// static policies of the account
SearchBuilder<IAMGroupAccountMapVO> groupSB = _aclGroupAccountMapDao.createSearchBuilder();
groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
GenericSearchBuilder<IAMGroupPolicyMapVO, Long> 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<Long> policySc = policySB.create();
policySc.setJoinParameters("accountgroupjoin", "account", accountId);
List<Long> policyIds = _aclGroupPolicyMapDao.customSearch(policySc, null);
// add policies directly attached to the account
List<IAMAccountPolicyMapVO> acctPolicies = _aclAccountPolicyMapDao.listByAccountId(accountId);
for (IAMAccountPolicyMapVO p : acctPolicies) {
policyIds.add(p.getIamPolicyId());
}
if (policyIds.size() == 0) {
return new ArrayList<IAMPolicy>();
}
SearchBuilder<IAMPolicyVO> sb = _aclPolicyDao.createSearchBuilder();
sb.and("ids", sb.entity().getId(), Op.IN);
SearchCriteria<IAMPolicyVO> sc = sb.create();
sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
@SuppressWarnings("rawtypes")
List policies = _aclPolicyDao.customSearch(sc, null);
return policies;
}
@SuppressWarnings("unchecked")
@Override
public List<IAMPolicy> listIAMPoliciesByGroup(long groupId) {
List<IAMGroupPolicyMapVO> policyGrpMap = _aclGroupPolicyMapDao.listByGroupId(groupId);
if (policyGrpMap == null || policyGrpMap.size() == 0) {
return new ArrayList<IAMPolicy>();
}
List<Long> policyIds = new ArrayList<Long>();
for (IAMGroupPolicyMapVO pg : policyGrpMap) {
policyIds.add(pg.getAclPolicyId());
}
SearchBuilder<IAMPolicyVO> sb = _aclPolicyDao.createSearchBuilder();
sb.and("ids", sb.entity().getId(), Op.IN);
SearchCriteria<IAMPolicyVO> sc = sb.create();
sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
@SuppressWarnings("rawtypes")
List policies = _aclPolicyDao.customSearch(sc, null);
return policies;
}
@SuppressWarnings("unchecked")
@Override
public List<IAMPolicy> listRecursiveIAMPoliciesByGroup(long groupId) {
List<IAMGroupPolicyMapVO> policyGrpMap = _aclGroupPolicyMapDao.listByGroupId(groupId);
if (policyGrpMap == null || policyGrpMap.size() == 0) {
return new ArrayList<IAMPolicy>();
}
List<Long> policyIds = new ArrayList<Long>();
for (IAMGroupPolicyMapVO pg : policyGrpMap) {
policyIds.add(pg.getAclPolicyId());
}
SearchBuilder<IAMPolicyPermissionVO> permSb = _policyPermissionDao.createSearchBuilder();
permSb.and("isRecursive", permSb.entity().isRecursive(), Op.EQ);
SearchBuilder<IAMPolicyVO> sb = _aclPolicyDao.createSearchBuilder();
sb.and("ids", sb.entity().getId(), Op.IN);
sb.join("recursivePerm", permSb, sb.entity().getId(), permSb.entity().getAclPolicyId(),
JoinBuilder.JoinType.INNER);
SearchCriteria<IAMPolicyVO> sc = sb.create();
sc.setParameters("ids", policyIds.toArray(new Object[policyIds.size()]));
sc.setJoinParameters("recursivePerm", "isRecursive", true);
@SuppressWarnings("rawtypes")
List policies = _aclPolicyDao.customSearch(sc, null);
return policies;
}
@SuppressWarnings("unchecked")
@Override
public Pair<List<IAMPolicy>, Integer> listIAMPolicies(Long iamPolicyId, String iamPolicyName, String path, Long startIndex, Long pageSize) {
if (iamPolicyId != null) {
IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy by id " + iamPolicyId);
}
}
Filter searchFilter = new Filter(IAMPolicyVO.class, "id", true, startIndex, pageSize);
SearchBuilder<IAMPolicyVO> sb = _aclPolicyDao.createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
SearchCriteria<IAMPolicyVO> sc = sb.create();
if (iamPolicyName != null) {
sc.setParameters("name", iamPolicyName);
}
if (iamPolicyId != null) {
sc.setParameters("id", iamPolicyId);
}
sc.setParameters("path", path + "%");
Pair<List<IAMPolicyVO>, Integer> policies = _aclPolicyDao.searchAndCount(sc, searchFilter);
@SuppressWarnings("rawtypes")
List policyList = policies.first();
return new Pair<List<IAMPolicy>, Integer>(policyList, policies.second());
}
@DB
@Override
public IAMGroup attachIAMPoliciesToGroup(final List<Long> policyIds, final Long groupId) {
// get the Acl Group entity
IAMGroup 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) {
IAMPolicy policy = _aclPolicyDao.findById(policyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ "; failed to add policies to acl group.");
}
IAMGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
if (grMap == null) {
// not there already
grMap = new IAMGroupPolicyMapVO(groupId, policyId);
_aclGroupPolicyMapDao.persist(grMap);
}
}
}
});
invalidateIAMCache();
return group;
}
@DB
@Override
public IAMGroup removeIAMPoliciesFromGroup(final List<Long> policyIds, final Long groupId) {
// get the Acl Group entity
IAMGroup 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) {
IAMPolicy policy = _aclPolicyDao.findById(policyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ "; failed to add policies to acl group.");
}
IAMGroupPolicyMapVO grMap = _aclGroupPolicyMapDao.findByGroupAndPolicy(groupId, policyId);
if (grMap != null) {
// not removed yet
_aclGroupPolicyMapDao.remove(grMap.getId());
}
}
}
});
invalidateIAMCache();
return group;
}
@Override
public void attachIAMPolicyToAccounts(final Long policyId, final List<Long> acctIds) {
IAMPolicy policy = _aclPolicyDao.findById(policyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ "; failed to add policy to account.");
}
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
// add entries in acl_group_policy_map table
for (Long acctId : acctIds) {
IAMAccountPolicyMapVO acctMap = _aclAccountPolicyMapDao.findByAccountAndPolicy(acctId, policyId);
if (acctMap == null) {
// not there already
acctMap = new IAMAccountPolicyMapVO(acctId, policyId);
_aclAccountPolicyMapDao.persist(acctMap);
}
}
}
});
invalidateIAMCache();
}
@Override
public void removeIAMPolicyFromAccounts(final Long policyId, final List<Long> acctIds) {
IAMPolicy policy = _aclPolicyDao.findById(policyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + policyId
+ "; failed to add policy to account.");
}
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
// add entries in acl_group_policy_map table
for (Long acctId : acctIds) {
IAMAccountPolicyMapVO acctMap = _aclAccountPolicyMapDao.findByAccountAndPolicy(acctId, policyId);
if (acctMap != null) {
// exists
_aclAccountPolicyMapDao.remove(acctMap.getId());
}
}
}
});
invalidateIAMCache();
}
@DB
@Override
public IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, String scope, Long scopeId,
String action, String accessType, Permission perm, Boolean recursive) {
// get the Acl Policy entity
IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ "; failed to add permission to policy.");
}
// add entry in acl_policy_permission table
IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope,
scopeId, action, perm, accessType);
if (permit == null) {
// not there already
permit = new IAMPolicyPermissionVO(iamPolicyId, action, entityType, accessType, scope, scopeId, perm,
recursive);
_policyPermissionDao.persist(permit);
}
invalidateIAMCache();
return policy;
}
@DB
@Override
public IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, String scope, Long scopeId,
String action) {
// get the Acl Policy entity
IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ "; failed to revoke permission from policy.");
}
// remove entry from acl_entity_permission table
IAMPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(iamPolicyId, entityType, scope,
scopeId, action, Permission.Allow, null);
if (permit != null) {
// not removed yet
_policyPermissionDao.remove(permit.getId());
}
invalidateIAMCache();
return policy;
}
@DB
@Override
public void removeIAMPermissionForEntity(final String entityType, final Long entityId) {
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
// remove entry from acl_entity_permission table
List<IAMPolicyPermissionVO> permitList = _policyPermissionDao.listByEntity(entityType, entityId);
for (IAMPolicyPermissionVO permit : permitList) {
long policyId = permit.getAclPolicyId();
_policyPermissionDao.remove(permit.getId());
// remove the policy if there are no other permissions
if ((_policyPermissionDao.listByPolicy(policyId)).isEmpty()) {
deleteIAMPolicy(policyId);
}
}
}
});
invalidateIAMCache();
}
@DB
@Override
public IAMPolicy resetIAMPolicy(long iamPolicyId) {
// get the Acl Policy entity
IAMPolicy policy = _aclPolicyDao.findById(iamPolicyId);
if (policy == null) {
throw new InvalidParameterValueException("Unable to find acl policy: " + iamPolicyId
+ "; failed to reset the policy.");
}
SearchBuilder<IAMPolicyPermissionVO> sb = _policyPermissionDao.createSearchBuilder();
sb.and("policyId", sb.entity().getAclPolicyId(), SearchCriteria.Op.EQ);
sb.and("scope", sb.entity().getScope(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<IAMPolicyPermissionVO> permissionSC = sb.create();
permissionSC.setParameters("policyId", iamPolicyId);
_policyPermissionDao.expunge(permissionSC);
invalidateIAMCache();
return policy;
}
@Override
public boolean isActionAllowedForPolicies(String action, List<IAMPolicy> policies) {
boolean allowed = false;
if (policies == null || policies.size() == 0) {
return allowed;
}
List<Long> policyIds = new ArrayList<Long>();
for (IAMPolicy policy : policies) {
policyIds.add(policy.getId());
}
SearchBuilder<IAMPolicyPermissionVO> sb = _policyPermissionDao.createSearchBuilder();
sb.and("action", sb.entity().getAction(), Op.EQ);
sb.and("policyId", sb.entity().getAclPolicyId(), Op.IN);
SearchCriteria<IAMPolicyPermissionVO> sc = sb.create();
sc.setParameters("policyId", policyIds.toArray(new Object[policyIds.size()]));
sc.setParameters("action", action);
List<IAMPolicyPermissionVO> permissions = _policyPermissionDao.customSearch(sc, null);
if (permissions != null && !permissions.isEmpty()) {
allowed = true;
}
return allowed;
}
@Override
public List<Long> getGrantedEntities(long accountId, String action, String scope) {
// Get the static Policies of the Caller
List<IAMPolicy> policies = listIAMPolicies(accountId);
// for each policy, find granted permission within the given scope
List<Long> entityIds = new ArrayList<Long>();
for (IAMPolicy policy : policies) {
List<IAMPolicyPermissionVO> pp = _policyPermissionDao.listByPolicyActionAndScope(policy.getId(), action,
scope, null);
if (pp != null) {
for (IAMPolicyPermissionVO p : pp) {
if (p.getScopeId() != null) {
entityIds.add(p.getScopeId());
}
}
}
}
return entityIds;
}
@Override
@SuppressWarnings("unchecked")
public List<IAMPolicyPermission> listPolicyPermissions(long policyId) {
@SuppressWarnings("rawtypes")
List pp = _policyPermissionDao.listByPolicy(policyId);
return pp;
}
@SuppressWarnings("unchecked")
@Override
public List<IAMPolicyPermission> listPolicyPermissionsByScope(long policyId, String action, String scope,
String accessType) {
@SuppressWarnings("rawtypes")
List pp = _policyPermissionDao.listByPolicyActionAndScope(policyId, action, scope, accessType);
return pp;
}
@SuppressWarnings("unchecked")
@Override
public List<IAMPolicyPermission> listPolicyPermissionByActionAndEntity(long policyId, String action,
String entityType) {
@SuppressWarnings("rawtypes")
List pp = _policyPermissionDao.listByPolicyActionAndEntity(policyId, action, entityType);
return pp;
}
@SuppressWarnings("unchecked")
@Override
public List<IAMPolicyPermission> listPolicyPermissionByAccessAndEntity(long policyId, String accessType,
String entityType) {
@SuppressWarnings("rawtypes")
List pp = _policyPermissionDao.listByPolicyAccessAndEntity(policyId, accessType, entityType);
return pp;
}
@Override
public IAMPolicy getResourceOwnerPolicy() {
return _aclPolicyDao.findByName("RESOURCE_OWNER");
}
// search for policy with only one resource grant permission
@Override
public IAMPolicy getResourceGrantPolicy(String entityType, Long entityId, String accessType, String action) {
List<IAMPolicyVO> policyList = _aclPolicyDao.listAll();
for (IAMPolicyVO policy : policyList) {
List<IAMPolicyPermission> pp = listPolicyPermissions(policy.getId());
if (pp != null && pp.size() == 1) {
// resource grant policy should only have one ACL permission assigned
IAMPolicyPermission permit = pp.get(0);
if (permit.getEntityType().equals(entityType) && permit.getScope().equals(PermissionScope.RESOURCE.toString())
&& permit.getScopeId().longValue() == entityId.longValue()) {
if (accessType != null && permit.getAccessType().equals(accessType)) {
return policy;
} else if (action != null && permit.getAction().equals(action)) {
return policy;
}
}
}
}
return null;
}
}