Add support to grant acl permission to access an individual resource.

This commit is contained in:
Min Chen 2014-01-29 17:59:24 -08:00
parent 0063b60701
commit 81323dce5d
5 changed files with 80 additions and 0 deletions

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.acl.api;
import java.util.List;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.acl.api.response.AclGroupResponse;
import org.apache.cloudstack.acl.api.response.AclPolicyResponse;
import org.apache.cloudstack.api.response.ListResponse;
@ -64,6 +65,9 @@ public interface AclApiService extends PluggableService {
AclPolicyPermission getAclPolicyPermission(long accountId, String entityType, String action);
/* Utility routine to grant invidivual resource to list of accounts */
void grantEntityPermissioinToAccounts(String entityType, Long entityId, AccessType accessType, String action, List<Long> accountIds);
/* Response Generation */
AclPolicyResponse createAclPolicyResponse(AclPolicy policy);

View File

@ -17,6 +17,7 @@
package org.apache.cloudstack.acl.api;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -47,6 +48,7 @@ import org.apache.cloudstack.acl.api.command.RemoveAclPolicyFromAclGroupCmd;
import org.apache.cloudstack.acl.api.response.AclGroupResponse;
import org.apache.cloudstack.acl.api.response.AclPermissionResponse;
import org.apache.cloudstack.acl.api.response.AclPolicyResponse;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.context.CallContext;
@ -179,6 +181,22 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man
}
});
_messageBus.subscribe(EntityManager.MESSAGE_GRANT_ENTITY_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Map<String, Object> permit = (Map<String, Object>)obj;
if (permit != null) {
String entityType = (String)permit.get(ApiConstants.ENTITY_TYPE);
Long entityId = (Long)permit.get(ApiConstants.ENTITY_ID);
AccessType accessType = (AccessType)permit.get(ApiConstants.ACCESS_TYPE);
String action = (String)permit.get(ApiConstants.ACL_ACTION);
List<Long> acctIds = (List<Long>)permit.get(ApiConstants.ACCOUNTS);
s_logger.debug("MessageBus message: grant permission to an entity: (" + entityType + "," + entityId + ")");
grantEntityPermissioinToAccounts(entityType, entityId, accessType, action, acctIds);
}
}
});
return super.configure(name, params);
}
@ -469,6 +487,38 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man
return response;
}
@Override
public void grantEntityPermissioinToAccounts(String entityType, Long entityId, AccessType accessType, String action, List<Long> accountIds) {
// check if there is already a policy with only this permission added to it
AclPolicy policy = _iamSrv.getResourceGrantPolicy(entityType, entityId, accessType.toString(), action);
if (policy == null) {
// not found, just create a policy with resource grant permission
Account caller = CallContext.current().getCallingAccount();
String aclPolicyName = "policyGrant" + entityType + entityId;
String description = "Policy to grant permission to " + entityType + entityId;
policy = createAclPolicy(caller, aclPolicyName, description, null);
// add permission to this policy
addAclPermissionToAclPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, Permission.Allow);
}
// attach this policy to list of accounts if not attached already
Long policyId = policy.getId();
for (Long acctId : accountIds) {
if (!isPolicyAttachedToAccount(policyId, acctId)) {
attachAclPolicyToAccounts(policyId, Collections.singletonList(acctId));
}
}
}
private boolean isPolicyAttachedToAccount(Long policyId, Long accountId) {
List<AclPolicy> pList = listAclPolicies(accountId);
for (AclPolicy p : pList) {
if (p.getId() == policyId.longValue()) {
return true;
}
}
return false;
}
@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>();

View File

@ -66,6 +66,8 @@ public interface IAMService {
void removeAclPermissionForEntity(final String entityType, final Long entityId);
AclPolicy getResourceGrantPolicy(String entityType, Long entityId, String accessType, String action);
AclPolicy getResourceOwnerPolicy();
List<AclPolicyPermission> listPolicyPermissions(long policyId);

View File

@ -24,6 +24,7 @@ import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.PermissionScope;
import org.apache.cloudstack.iam.api.AclGroup;
import org.apache.cloudstack.iam.api.AclPolicy;
import org.apache.cloudstack.iam.api.AclPolicyPermission;
@ -387,6 +388,7 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
return policies;
}
@SuppressWarnings("unchecked")
@Override
public Pair<List<AclPolicy>, Integer> listAclPolicies(Long aclPolicyId, String aclPolicyName, String path, Long startIndex, Long pageSize) {
@ -706,4 +708,25 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager {
return _aclPolicyDao.findByName("RESOURCE_OWNER");
}
// search for policy with only one resource grant permission
@Override
public AclPolicy getResourceGrantPolicy(String entityType, Long entityId, String accessType, String action) {
List<AclPolicyVO> policyList = _aclPolicyDao.listAll();
for (AclPolicyVO policy : policyList){
List<AclPolicyPermission> pp = listPolicyPermissions(policy.getId());
if ( pp != null && pp.size() == 1){
// resource grant policy should only have one ACL permission assigned
AclPolicyPermission 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;
}
}

View File

@ -72,4 +72,5 @@ public interface EntityManager {
public <T, K extends Serializable> void remove(Class<T> entityType, K id);
public static final String MESSAGE_REMOVE_ENTITY_EVENT = "Message.RemoveEntity.Event";
public static final String MESSAGE_GRANT_ENTITY_EVENT = "Message.GrantEntity.Event";
}