use of org.apache.cloudstack.acl.SecurityChecker.AccessType in project cloudstack by apache.
the class RoleBasedEntityAccessChecker method checkAccess.
@Override
public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action) throws PermissionDeniedException {
if (caller == null) {
throw new InvalidParameterValueException("Caller cannot be passed as NULL to IAM!");
}
if (entity == null && action == null) {
throw new InvalidParameterValueException("Entity and action cannot be both NULL in checkAccess!");
}
// check IAM cache first
String accessKey = buildAccessCacheKey(caller, entity, accessType, action);
CheckAccessResult allowDeny = (CheckAccessResult) _iamSrv.getFromIAMCache(accessKey);
if (allowDeny != null) {
s_logger.debug("IAM access check for " + accessKey + " from cache: " + allowDeny.isAllow());
if (allowDeny.isAllow()) {
return true;
} else {
if (allowDeny.getDenyMsg() != null) {
throw new PermissionDeniedException(allowDeny.getDenyMsg());
} else {
return false;
}
}
}
if (entity == null && action != null) {
// check if caller can do this action
List<IAMPolicy> policies = _iamSrv.listIAMPolicies(caller.getAccountId());
boolean isAllowed = _iamSrv.isActionAllowedForPolicies(action, policies);
if (!isAllowed) {
String msg = "The action '" + action + "' not allowed for account " + caller;
_iamSrv.addToIAMCache(accessKey, new CheckAccessResult(msg));
throw new PermissionDeniedException(msg);
}
_iamSrv.addToIAMCache(accessKey, new CheckAccessResult(true));
return true;
}
// if a Project entity, skip
Account entityAccount = _accountService.getAccount(entity.getAccountId());
if (entityAccount != null && entityAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) {
_iamSrv.addToIAMCache(accessKey, new CheckAccessResult(false));
return false;
}
String entityType = null;
if (entity.getEntityType() != null) {
entityType = entity.getEntityType().getSimpleName();
}
if (accessType == null) {
accessType = AccessType.UseEntry;
}
// get all Policies of this caller by considering recursive domain group policy
List<IAMPolicy> policies = getEffectivePolicies(caller);
HashMap<IAMPolicy, Boolean> policyPermissionMap = new HashMap<IAMPolicy, Boolean>();
for (IAMPolicy policy : policies) {
List<IAMPolicyPermission> permissions = new ArrayList<IAMPolicyPermission>();
if (action != null) {
permissions = _iamSrv.listPolicyPermissionByActionAndEntity(policy.getId(), action, entityType);
if (permissions.isEmpty()) {
if (accessType != null) {
for (AccessType type : AccessType.values()) {
if (type.ordinal() >= accessType.ordinal()) {
permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(), type.toString(), entityType));
}
}
}
}
} else {
if (accessType != null) {
for (AccessType type : AccessType.values()) {
if (type.ordinal() >= accessType.ordinal()) {
permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(), type.toString(), entityType));
}
}
}
}
for (IAMPolicyPermission permission : permissions) {
if (checkPermissionScope(caller, permission.getScope(), permission.getScopeId(), 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)) {
_iamSrv.addToIAMCache(accessKey, new CheckAccessResult(true));
return true;
}
}
if (!policies.isEmpty()) {
// Since we reach this point, none of the
// roles granted access
String msg = "Account " + caller + " does not have permission to access resource " + entity + " for access type: " + accessType;
if (s_logger.isDebugEnabled()) {
s_logger.debug(msg);
}
_iamSrv.addToIAMCache(accessKey, new CheckAccessResult(msg));
throw new PermissionDeniedException(msg);
}
_iamSrv.addToIAMCache(accessKey, new CheckAccessResult(false));
return false;
}
use of org.apache.cloudstack.acl.SecurityChecker.AccessType in project cloudstack by apache.
the class ParamProcessWorker method doAccessChecks.
private void doAccessChecks(BaseCmd cmd, Map<Object, AccessType> entitiesToAccess) {
Account caller = CallContext.current().getCallingAccount();
List<Long> entityOwners = cmd.getEntityOwnerIds();
Account[] owners = null;
if (entityOwners != null) {
owners = entityOwners.stream().map(id -> _accountMgr.getAccount(id)).toArray(Account[]::new);
} else {
owners = new Account[] { _accountMgr.getAccount(cmd.getEntityOwnerId()) };
}
if (cmd instanceof BaseAsyncCreateCmd) {
// check that caller can access the owner account.
_accountMgr.checkAccess(caller, null, false, owners);
}
if (!entitiesToAccess.isEmpty()) {
// check that caller can access the owner account.
_accountMgr.checkAccess(caller, null, false, owners);
for (Map.Entry<Object, AccessType> entry : entitiesToAccess.entrySet()) {
Object entity = entry.getKey();
if (entity instanceof ControlledEntity) {
_accountMgr.checkAccess(caller, entry.getValue(), true, (ControlledEntity) entity);
} else if (entity instanceof InfrastructureEntity) {
// FIXME: Move this code in adapter, remove code from
// Account manager
}
}
}
}
use of org.apache.cloudstack.acl.SecurityChecker.AccessType in project cloudstack by apache.
the class ParamProcessWorker method processParameters.
@SuppressWarnings({ "unchecked", "rawtypes" })
public void processParameters(final BaseCmd cmd, final Map params) {
final Map<Object, AccessType> entitiesToAccess = new HashMap<Object, AccessType>();
final List<Field> cmdFields = cmd.getParamFields();
for (final Field field : cmdFields) {
final Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
final Object paramObj = params.get(parameterAnnotation.name());
if (paramObj == null) {
if (parameterAnnotation.required()) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to missing parameter " + parameterAnnotation.name());
}
continue;
}
if (parameterAnnotation.required()) {
validateNonEmptyString(paramObj, parameterAnnotation.name());
}
// marshall the parameter into the correct type and set the field value
try {
validateField(paramObj, parameterAnnotation);
setFieldValue(field, cmd, paramObj, parameterAnnotation);
} catch (final IllegalArgumentException argEx) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Unable to execute API command " + cmd.getCommandName() + " due to invalid value " + paramObj + " for parameter " + parameterAnnotation.name());
}
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value " + paramObj + " for parameter " + parameterAnnotation.name());
} catch (final ParseException parseEx) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Invalid date parameter " + paramObj + " passed to command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
}
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to parse date " + paramObj + " for command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + ", please pass dates in the format mentioned in the api documentation");
} catch (final InvalidParameterValueException invEx) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage());
} catch (final CloudRuntimeException cloudEx) {
s_logger.error("CloudRuntimeException", cloudEx);
// and IllegalAccessException setting one of the parameters.
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Internal error executing API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
}
// check access on the resource this field points to
try {
final ACL checkAccess = field.getAnnotation(ACL.class);
final CommandType fieldType = parameterAnnotation.type();
if (checkAccess != null) {
if (parameterAnnotation.entityType() != null && parameterAnnotation.entityType().length > 0 && parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class) != null) {
final Class<?>[] entityList = parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class).value();
// Id or list of id's/name's
switch(fieldType) {
case LIST:
final CommandType listType = parameterAnnotation.collectionType();
switch(listType) {
case LONG:
case UUID:
final List<Long> listParam = (List<Long>) field.get(cmd);
for (final Long entityId : listParam) {
for (final Class entity : entityList) {
final Object entityObj = _entityMgr.findById(entity, entityId);
if (entityObj != null) {
entitiesToAccess.put(entityObj, checkAccess.accessType());
break;
}
}
}
break;
/*
* case STRING: List<String> listParam = new
* ArrayList<String>(); listParam =
* (List)field.get(cmd); for(String entityName:
* listParam){ ControlledEntity entityObj =
* (ControlledEntity )daoClassInstance(entityId);
* entitiesToAccess.add(entityObj); } break;
*/
default:
break;
}
break;
case LONG:
case UUID:
for (final Class entity : entityList) {
final Object entityObj = _entityMgr.findById(entity, (Long) field.get(cmd));
if (entityObj != null) {
entitiesToAccess.put(entityObj, checkAccess.accessType());
break;
}
}
break;
default:
break;
}
}
}
} catch (final IllegalArgumentException e) {
throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]", e);
} catch (final IllegalAccessException e) {
throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]", e);
}
}
doAccessChecks(cmd, entitiesToAccess);
}
use of org.apache.cloudstack.acl.SecurityChecker.AccessType in project cloudstack by apache.
the class IAMApiServiceImpl method configure.
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
_messageBus.subscribe(AccountManager.MESSAGE_ADD_ACCOUNT_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
HashMap<Long, Long> acctGroupMap = (HashMap<Long, Long>) obj;
for (Long accountId : acctGroupMap.keySet()) {
Long groupId = acctGroupMap.get(accountId);
s_logger.debug("MessageBus message: new Account Added: " + accountId + ", adding it to groupId :" + groupId);
addAccountToIAMGroup(accountId, groupId);
// add it to domain group too
AccountVO account = _accountDao.findById(accountId);
Domain domain = _domainDao.findById(account.getDomainId());
if (domain != null) {
List<IAMGroup> domainGroups = listDomainGroup(domain);
if (domainGroups != null) {
for (IAMGroup group : domainGroups) {
addAccountToIAMGroup(accountId, new Long(group.getId()));
}
}
}
}
}
});
_messageBus.subscribe(AccountManager.MESSAGE_REMOVE_ACCOUNT_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long accountId = ((Long) obj);
if (accountId != null) {
s_logger.debug("MessageBus message: Account removed: " + accountId + ", releasing the group associations");
removeAccountFromIAMGroups(accountId);
}
}
});
_messageBus.subscribe(DomainManager.MESSAGE_ADD_DOMAIN_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long domainId = ((Long) obj);
if (domainId != null) {
s_logger.debug("MessageBus message: new Domain created: " + domainId + ", creating a new group");
Domain domain = _domainDao.findById(domainId);
_iamSrv.createIAMGroup("DomainGrp-" + domain.getUuid(), "Domain group", domain.getPath());
}
}
});
_messageBus.subscribe(DomainManager.MESSAGE_REMOVE_DOMAIN_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long domainId = ((Long) obj);
if (domainId != null) {
s_logger.debug("MessageBus message: Domain removed: " + domainId + ", removing the domain group");
Domain domain = _domainDao.findById(domainId);
List<IAMGroup> groups = listDomainGroup(domain);
for (IAMGroup group : groups) {
_iamSrv.deleteIAMGroup(group.getId());
}
}
}
});
_messageBus.subscribe(TemplateManager.MESSAGE_REGISTER_PUBLIC_TEMPLATE_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long templateId = (Long) obj;
if (templateId != null) {
s_logger.debug("MessageBus message: new public template registered: " + templateId + ", grant permission to default root admin, domain admin and normal user policies");
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false);
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false);
_iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false);
}
}
});
_messageBus.subscribe(TemplateManager.MESSAGE_RESET_TEMPLATE_PERMISSION_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Long templateId = (Long) obj;
if (templateId != null) {
s_logger.debug("MessageBus message: reset template permission: " + templateId);
resetTemplatePermission(templateId);
}
}
});
_messageBus.subscribe(EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Pair<Class<?>, Long> entity = (Pair<Class<?>, Long>) obj;
if (entity != null) {
String entityType = entity.first().getSimpleName();
Long entityId = entity.second();
s_logger.debug("MessageBus message: delete an entity: (" + entityType + "," + entityId + "), remove its related permission");
_iamSrv.removeIAMPermissionForEntity(entityType, entityId);
}
}
});
_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) {
Class<?> entityType = (Class<?>) 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.IAM_ACTION);
List<Long> acctIds = (List<Long>) permit.get(ApiConstants.ACCOUNTS);
s_logger.debug("MessageBus message: grant accounts permission to an entity: (" + entityType + "," + entityId + ")");
grantEntityPermissioinToAccounts(entityType.getSimpleName(), entityId, accessType, action, acctIds);
}
}
});
_messageBus.subscribe(EntityManager.MESSAGE_REVOKE_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) {
Class<?> entityType = (Class<?>) 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.IAM_ACTION);
List<Long> acctIds = (List<Long>) permit.get(ApiConstants.ACCOUNTS);
s_logger.debug("MessageBus message: revoke from accounts permission to an entity: (" + entityType + "," + entityId + ")");
revokeEntityPermissioinFromAccounts(entityType.getSimpleName(), entityId, accessType, action, acctIds);
}
}
});
_messageBus.subscribe(EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, new MessageSubscriber() {
@Override
public void onPublishMessage(String senderAddress, String subject, Object obj) {
Map<String, Object> params = (Map<String, Object>) obj;
if (params != null) {
addDomainWideResourceAccess(params);
}
}
});
return super.configure(name, params);
}
use of org.apache.cloudstack.acl.SecurityChecker.AccessType in project cloudstack by apache.
the class RoleBasedAPIAccessChecker method addDefaultAclPolicyPermission.
private void addDefaultAclPolicyPermission(String apiName, Class<?> cmdClass, RoleType role) {
AccessType accessType = null;
Class<?>[] entityTypes = null;
PermissionScope permissionScope = PermissionScope.ACCOUNT;
Long policyId = getDefaultPolicyId(role);
switch(role) {
case User:
permissionScope = PermissionScope.ACCOUNT;
break;
case Admin:
permissionScope = PermissionScope.ALL;
break;
case DomainAdmin:
permissionScope = PermissionScope.DOMAIN;
break;
case ResourceAdmin:
permissionScope = PermissionScope.DOMAIN;
break;
}
boolean addAccountScopedUseEntry = false;
if (cmdClass != null) {
BaseCmd cmdObj;
try {
cmdObj = (BaseCmd) cmdClass.newInstance();
if (cmdObj instanceof BaseListCmd) {
if (permissionScope == PermissionScope.ACCOUNT) {
accessType = AccessType.UseEntry;
} else {
accessType = AccessType.ListEntry;
addAccountScopedUseEntry = true;
}
} else {
accessType = AccessType.OperateEntry;
}
} catch (Exception e) {
throw new CloudRuntimeException(String.format("%s is claimed as an API command, but it cannot be instantiated", cmdClass.getName()));
}
APICommand at = cmdClass.getAnnotation(APICommand.class);
entityTypes = at.entityType();
}
if (entityTypes == null || entityTypes.length == 0) {
_iamSrv.addIAMPermissionToIAMPolicy(policyId, null, permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false);
if (addAccountScopedUseEntry) {
_iamSrv.addIAMPermissionToIAMPolicy(policyId, null, PermissionScope.ACCOUNT.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, AccessType.UseEntry.toString(), Permission.Allow, false);
}
} else {
for (Class<?> entityType : entityTypes) {
_iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.getSimpleName(), permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false);
if (addAccountScopedUseEntry) {
_iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.getSimpleName(), PermissionScope.ACCOUNT.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, AccessType.UseEntry.toString(), Permission.Allow, false);
}
}
}
}
Aggregations