From 0b1aaf514f7957a252ce71bcfbe5c7e3cecd5625 Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Tue, 8 Oct 2013 15:36:23 -0700 Subject: [PATCH] More logic to Role based checker --- .../org/apache/cloudstack/acl/AclRole.java | 4 ++ .../org/apache/cloudstack/acl/AclService.java | 3 ++ .../org/apache/cloudstack/acl/AclRoleVO.java | 14 +++++++ .../entity/RoleBasedEntityAccessChecker.java | 39 ++++++++++++++++--- .../apache/cloudstack/acl/AclServiceImpl.java | 18 +++++++++ setup/db/db/schema-420to430.sql | 15 +++---- 6 files changed, 80 insertions(+), 13 deletions(-) diff --git a/api/src/org/apache/cloudstack/acl/AclRole.java b/api/src/org/apache/cloudstack/acl/AclRole.java index 33248799a5b..207aece26d1 100644 --- a/api/src/org/apache/cloudstack/acl/AclRole.java +++ b/api/src/org/apache/cloudstack/acl/AclRole.java @@ -28,4 +28,8 @@ public interface AclRole extends PartOf, InternalIdentity, Identity { String getDescription(); // Long getParentRoleId(); + + public enum RoleType { + Static, Dynamic + } } diff --git a/api/src/org/apache/cloudstack/acl/AclService.java b/api/src/org/apache/cloudstack/acl/AclService.java index c7a1174910a..749fc155845 100644 --- a/api/src/org/apache/cloudstack/acl/AclService.java +++ b/api/src/org/apache/cloudstack/acl/AclService.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import com.cloud.utils.Pair; +import com.cloud.user.Account; public interface AclService { @@ -86,4 +87,6 @@ public interface AclService { boolean isAPIAccessibleForRoles(String apiName, List roles); + List getEffectiveRoles(Account caller, ControlledEntity entity); + } diff --git a/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java b/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java index 767fdfeddaf..30ba4726399 100644 --- a/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java +++ b/engine/schema/src/org/apache/cloudstack/acl/AclRoleVO.java @@ -21,6 +21,8 @@ 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; @@ -55,6 +57,10 @@ public class AclRoleVO implements AclRole { @Column(name = GenericDao.CREATED_COLUMN) private Date created; + @Column(name = "role_type") + @Enumerated(value = EnumType.STRING) + private AclRole.RoleType roleType; + public AclRoleVO() { uuid = UUID.randomUUID().toString(); } @@ -63,6 +69,7 @@ public class AclRoleVO implements AclRole { this.name = name; this.description = description; uuid = UUID.randomUUID().toString(); + this.roleType = AclRole.RoleType.Static; } @Override @@ -107,4 +114,11 @@ public class AclRoleVO implements AclRole { this.domainId = domainId; } + public RoleType getRoleType() { + return roleType; + } + + public void setRoleType(RoleType roleType) { + this.roleType = roleType; + } } diff --git a/plugins/acl/role-based-access-checkers/src/org/apache/cloudstack/acl/entity/RoleBasedEntityAccessChecker.java b/plugins/acl/role-based-access-checkers/src/org/apache/cloudstack/acl/entity/RoleBasedEntityAccessChecker.java index 21ced06b28a..5be8836a1b5 100644 --- a/plugins/acl/role-based-access-checkers/src/org/apache/cloudstack/acl/entity/RoleBasedEntityAccessChecker.java +++ b/plugins/acl/role-based-access-checkers/src/org/apache/cloudstack/acl/entity/RoleBasedEntityAccessChecker.java @@ -21,8 +21,10 @@ import java.util.List; import javax.inject.Inject; import org.apache.cloudstack.acl.AclEntityPermissionVO; +import org.apache.cloudstack.acl.AclEntityType; import org.apache.cloudstack.acl.AclGroupAccountMapVO; import org.apache.cloudstack.acl.AclRole; +import org.apache.cloudstack.acl.AclRolePermissionVO; import org.apache.cloudstack.acl.AclService; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; @@ -30,6 +32,7 @@ import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.dao.AclEntityPermissionDao; import org.apache.cloudstack.acl.dao.AclGroupAccountMapDao; import org.apache.cloudstack.acl.dao.AclGroupDao; +import org.apache.cloudstack.acl.dao.AclRolePermissionDao; import org.apache.cloudstack.api.InternalIdentity; import org.apache.log4j.Logger; @@ -55,11 +58,14 @@ public class RoleBasedEntityAccessChecker extends DomainChecker implements Secur @Inject AclEntityPermissionDao _entityPermissionDao; + @Inject + AclRolePermissionDao _rolePermissionDao; + @Override public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType) throws PermissionDeniedException { - String entityType = ""; + String entityType = AclEntityType.VM.toString(); // check if explicit allow/deny is present for this entity in // acl_entity_permission @@ -96,14 +102,35 @@ public class RoleBasedEntityAccessChecker extends DomainChecker implements Secur if (caller.getId() == entity.getAccountId()) { return true; } - // Get the Roles of the Caller - List roles = _aclService.getAclRoles(caller.getId()); - // Do you have DomainAdmin Role? If yes can access the entity in the - // domaintree + // get all Roles of this caller w.r.t the entity + List roles = _aclService.getEffectiveRoles(caller, entity); - // check the entity grant table + for (AclRole role : roles) { + AclRolePermissionVO permission = _rolePermissionDao.findByRoleAndEntity(role.getId(), entityType, + accessType); + boolean operationAllowedForAll = true; + if (permission.getEntityType().equals(entityType)) { + if (permission.isAllowed()) { + return true; + } else { + 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); + } + } else if (permission.getEntityType().equals("*")) { + if (permission.isAllowed()) { + operationAllowedForAll = true; + } else { + operationAllowedForAll = false; + } + } + + } return false; diff --git a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java index 85d70accd1e..f879d2b5552 100644 --- a/server/src/org/apache/cloudstack/acl/AclServiceImpl.java +++ b/server/src/org/apache/cloudstack/acl/AclServiceImpl.java @@ -38,6 +38,7 @@ import org.apache.cloudstack.acl.dao.AclRolePermissionDao; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.context.CallContext; +import com.cloud.domain.Domain; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -534,6 +535,7 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager { @Override public List getAclRoles(long accountId) { + // static roles of the account SearchBuilder groupSB = _aclGroupAccountMapDao.createSearchBuilder(); groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ); @@ -643,4 +645,20 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager { return accessible; } + @Override + public List getEffectiveRoles(Account caller, ControlledEntity entity) { + + // Get the static Roles of the Caller + List roles = getAclRoles(caller.getId()); + + // add any dynamic roles w.r.t the entity + if (caller.getId() == entity.getAccountId()) { + // The caller owns the entity + AclRole owner = _aclRoleDao.findByName(Domain.ROOT_DOMAIN, "RESOURCE_OWNER"); + roles.add(owner); + } + + return roles; + } + } diff --git a/setup/db/db/schema-420to430.sql b/setup/db/db/schema-420to430.sql index 259c936852e..eb4dfff74d6 100644 --- a/setup/db/db/schema-420to430.sql +++ b/setup/db/db/schema-420to430.sql @@ -312,9 +312,10 @@ CREATE TABLE `cloud`.`acl_role` ( `name` varchar(255) NOT NULL, `description` varchar(255) default NULL, `uuid` varchar(40), - `domain_id` bigint unsigned NOT NULL, + `domain_id` bigint unsigned NOT NULL, `removed` datetime COMMENT 'date the role was removed', `created` datetime COMMENT 'date the role was created', + `role_type` varchar(64) DEFAULT 'Static' COMMENT 'Static or Dynamic', PRIMARY KEY (`id`), INDEX `i_acl_role__removed`(`removed`), CONSTRAINT `uc_acl_role__uuid` UNIQUE (`uuid`) @@ -332,12 +333,12 @@ CREATE TABLE `cloud`.`acl_group_role_map` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (1, 'NORMAL', 'Domain user role', UUID(), 1, Now()); -INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (2, 'ADMIN', 'Root admin role', UUID(), 1, Now()); -INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (3, 'DOMAIN_ADMIN', 'Domain admin role', UUID(), 1, Now()); -INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (4, 'RESOURCE_DOMAIN_ADMIN', 'Resource domain admin role', UUID(), 1, Now()); -INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (5, 'READ_ONLY_ADMIN', 'Read only admin role', UUID(), 1, Now()); -INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (6, 'RESOURCE_OWNER', 'Resource owner role', UUID(), -1, Now()); +INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (1, 'NORMAL', 'Domain user role', UUID(), 1, Now(), 'Static'); +INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (2, 'ADMIN', 'Root admin role', UUID(), 1, Now(), 'Static'); +INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (3, 'DOMAIN_ADMIN', 'Domain admin role', UUID(), 1, Now(), 'Static'); +INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (4, 'RESOURCE_DOMAIN_ADMIN', 'Resource domain admin role', UUID(), 1, Now(), 'Static'); +INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (5, 'READ_ONLY_ADMIN', 'Read only admin role', UUID(), 1, Now(), 'Static'); +INSERT IGNORE INTO `cloud`.`acl_role` (id, name, description, uuid, domain_id, created) VALUES (6, 'RESOURCE_OWNER', 'Resource owner role', UUID(), 1, Now(), 'Dynamic'); INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, domain_id, created) VALUES (1, 'NORMAL', 'Domain user group', UUID(), 1, Now()); INSERT IGNORE INTO `cloud`.`acl_group` (id, name, description, uuid, domain_id, created) VALUES (2, 'ADMIN', 'Root admin group', UUID(), 1, Now());