This commit is contained in:
Min Chen 2013-10-07 14:32:29 -07:00
commit 4499a7bfa0
10 changed files with 377 additions and 18 deletions

View File

@ -12,4 +12,6 @@ public interface AclEntityPermission extends InternalIdentity {
Long getEntityId();
AccessType getAccessType();
boolean isAllowed();
}

View File

@ -0,0 +1,31 @@
// 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 org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.InternalIdentity;
public interface AclRolePermission extends InternalIdentity {
Long getAclRoleId();
String getEntityType();
AccessType getAccessType();
boolean isAllowed();
}

View File

@ -32,7 +32,7 @@ public class AclEntityPermissionVO implements AclEntityPermission {
@Column(name = "entity_id")
private long entityId;
@Column(name = "entity_uuid")
private String entityUuid;
@ -40,6 +40,9 @@ public class AclEntityPermissionVO implements AclEntityPermission {
@Enumerated(value = EnumType.STRING)
AccessType accessType;
@Column(name = "permission")
private boolean permission;
@Column(name = GenericDao.REMOVED_COLUMN)
private Date removed;
@ -50,14 +53,16 @@ public class AclEntityPermissionVO implements AclEntityPermission {
}
public AclEntityPermissionVO(long groupId, String entityType, long entityId, String entityUuid, AccessType atype) {
public AclEntityPermissionVO(long groupId, String entityType, long entityId, String entityUuid, AccessType atype,
boolean permission) {
aclGroupId = groupId;
this.entityType = entityType;
this.entityId = entityId;
this.entityUuid = entityUuid;
accessType = atype;
this.permission = permission;
}
@Override
public long getId() {
return id;
@ -115,4 +120,10 @@ public class AclEntityPermissionVO implements AclEntityPermission {
public Date getCreated() {
return created;
}
@Override
public boolean isAllowed() {
return permission;
}
}

View File

@ -0,0 +1,99 @@
// 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 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.acl.SecurityChecker.AccessType;
@Entity
@Table(name = ("acl_role_permission"))
public class AclRolePermissionVO implements AclRolePermission {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "role_id")
private long aclRoleId;
@Column(name = "entity_type")
private String entityType;
@Column(name = "access_type")
@Enumerated(value = EnumType.STRING)
AccessType accessType;
@Column(name = "permission")
private boolean permission;
public AclRolePermissionVO() {
}
public AclRolePermissionVO(long roleId, String entityType, AccessType atype) {
aclRoleId = roleId;
this.entityType = entityType;
accessType = atype;
}
@Override
public long getId() {
return id;
}
@Override
public Long getAclRoleId() {
return aclRoleId;
}
@Override
public String getEntityType() {
return entityType;
}
@Override
public AccessType getAccessType() {
return accessType;
}
public void setAclRoleId(long aclRoleId) {
this.aclRoleId = aclRoleId;
}
public void setEntityType(String entityType) {
this.entityType = entityType;
}
public void setAccessType(AccessType accessType) {
this.accessType = accessType;
}
@Override
public boolean isAllowed() {
return permission;
}
}

View File

@ -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.acl.dao;
import org.apache.cloudstack.acl.AclRolePermissionVO;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import com.cloud.utils.db.GenericDao;
public interface AclRolePermissionDao extends GenericDao<AclRolePermissionVO, Long> {
AclRolePermissionVO findByRoleAndEntity(long roleId, String entityType, AccessType accessType);
}

View File

@ -0,0 +1,62 @@
// 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.dao;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.acl.AclRolePermissionVO;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@Component
public class AclRolePermissionDaoImpl extends GenericDaoBase<AclRolePermissionVO, Long> implements AclRolePermissionDao {
private SearchBuilder<AclRolePermissionVO> findByRoleEntity;
public AclRolePermissionDaoImpl()
{
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
findByRoleEntity = createSearchBuilder();
findByRoleEntity.and("roleId", findByRoleEntity.entity().getAclRoleId(), SearchCriteria.Op.EQ);
findByRoleEntity.and("entityType", findByRoleEntity.entity().getEntityType(), SearchCriteria.Op.EQ);
findByRoleEntity.and("accessType", findByRoleEntity.entity().getAccessType(), SearchCriteria.Op.EQ);
findByRoleEntity.done();
return true;
}
@Override
public AclRolePermissionVO findByRoleAndEntity(long roleId, String entityType, AccessType accessType) {
SearchCriteria<AclRolePermissionVO> sc = findByRoleEntity.create();
sc.setParameters("roleId", roleId);
sc.setParameters("entityType", entityType);
sc.setParameters("accessType", accessType);
return findOneBy(sc);
}
}

View File

@ -16,15 +16,10 @@
// under the License.
package org.apache.cloudstack.acl.api;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.acl.APIChecker;
import org.apache.cloudstack.acl.AclRole;
@ -35,12 +30,10 @@ import com.cloud.exception.PermissionDeniedException;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.user.User;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.PluggableService;
// This is the default API access checker that grab's the user's account
// based on the account type, access is granted
// 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 {

View File

@ -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.acl.entity;
import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.acl.AclGroupAccountMapVO;
import org.apache.cloudstack.acl.AclRole;
import org.apache.cloudstack.acl.AclService;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.acl.dao.AclGroupAccountMapDao;
import org.apache.cloudstack.acl.dao.AclGroupDao;
import com.cloud.acl.DomainChecker;
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 {
@Inject
AccountService _accountService;
@Inject
AclService _aclService;
@Inject
AclGroupAccountMapDao _aclGroupAccountMapDao;
@Override
public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType)
throws PermissionDeniedException {
// check if explicit allow/deny is present for this entity in
// acl_entity_permission
List<AclGroupAccountMapVO> acctGroups = _aclGroupAccountMapDao.listByAccountId(caller.getId());
// Is Caller RootAdmin? Yes, granted true
if (_accountService.isRootAdmin(caller.getId())) {
return true;
}
// Is Caller Owner of the entity? Yes, granted true
if (caller.getId() == entity.getAccountId()) {
return true;
}
// Get the Roles of the Caller
List<AclRole> roles = _aclService.getAclRoles(caller.getId());
// Do you have DomainAdmin Role? If yes can access the entity in the
// domaintree
// check the entity grant table
return false;
}
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.acl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -49,6 +50,11 @@ 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;
@Local(value = {AclService.class})
@ -253,7 +259,7 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager {
if (entity instanceof Identity) {
entityUuid = ((Identity)entity).getUuid();
}
perm = new AclEntityPermissionVO(aclGroupId, entityType, entityId, entityUuid, accessType);
perm = new AclEntityPermissionVO(aclGroupId, entityType, entityId, entityUuid, accessType, true);
_entityPermissionDao.persist(perm);
}
return group;
@ -507,14 +513,53 @@ public class AclServiceImpl extends ManagerBase implements AclService, Manager {
@Override
public List<AclRole> getAclRoles(long accountId) {
// TODO Auto-generated method stub
return null;
SearchBuilder<AclGroupAccountMapVO> groupSB = _aclGroupAccountMapDao.createSearchBuilder();
groupSB.and("account", groupSB.entity().getAccountId(), Op.EQ);
GenericSearchBuilder<AclGroupRoleMapVO, Long> roleSB = _aclGroupRoleMapDao.createSearchBuilder(Long.class);
roleSB.selectField(roleSB.entity().getAclRoleId());
roleSB.join("accountgroupjoin", groupSB, groupSB.entity().getAclGroupId(), roleSB.entity().getAclGroupId(),
JoinType.INNER);
roleSB.done();
SearchCriteria<Long> roleSc = roleSB.create();
roleSc.setJoinParameters("accountgroupjoin", "account", accountId);
List<Long> roleIds = _aclGroupRoleMapDao.customSearch(roleSc, null);
SearchBuilder<AclRoleVO> sb = _aclRoleDao.createSearchBuilder();
sb.and("ids", sb.entity().getId(), Op.IN);
SearchCriteria<AclRoleVO> sc = sb.create();
sc.setParameters("ids", roleIds.toArray(new Object[roleIds.size()]));
List<AclRoleVO> roles = _aclRoleDao.customSearch(sc, null);
return new ArrayList<AclRole>(roles);
}
@Override
public boolean isAPIAccessibleForRoles(String apiName, List<AclRole> roles) {
// TODO Auto-generated method stub
return false;
boolean accessible = false;
List<Long> roleIds = new ArrayList<Long>();
for (AclRole role : roles) {
roleIds.add(role.getId());
}
SearchBuilder<AclApiPermissionVO> sb = _apiPermissionDao.createSearchBuilder();
sb.and("apiName", sb.entity().getApiName(), Op.EQ);
sb.and("roleId", sb.entity().getAclRoleId(), Op.IN);
SearchCriteria<AclApiPermissionVO> sc = sb.create();
sc.setParameters("roleId", roleIds.toArray(new Object[roleIds.size()]));
List<AclApiPermissionVO> permissions = _apiPermissionDao.customSearch(sc, null);
if (permissions != null && !permissions.isEmpty()) {
accessible = true;
}
return accessible;
}
}

View File

@ -362,13 +362,23 @@ CREATE TABLE `cloud`.`acl_entity_permission` (
`entity_type` varchar(100) NOT NULL,
`entity_id` bigint unsigned NOT NULL,
`entity_uuid` varchar(40),
`access_type` varchar(40) NOT NULL,
`access_type` varchar(40) NOT NULL,
`permission` int(1) unsigned NOT NULL COMMENT '1 allowed, 0 for denied',
`removed` datetime COMMENT 'date the permission was revoked',
`created` datetime COMMENT 'date the permission was granted',
PRIMARY KEY (`id`),
CONSTRAINT `fk_acl_entity_permission__group_id` FOREIGN KEY(`group_id`) REFERENCES `acl_group` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`acl_role_permission` (
`id` bigint unsigned NOT NULL UNIQUE auto_increment,
`role_id` bigint unsigned NOT NULL,
`entity_type` varchar(100) NOT NULL,
`access_type` varchar(40) NOT NULL,
`permission` int(1) unsigned NOT NULL COMMENT '1 allowed, 0 for denied',
PRIMARY KEY (`id`),
CONSTRAINT `fk_acl_role_permission___role_id` FOREIGN KEY(`role_id`) REFERENCES `acl_role` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP VIEW IF EXISTS `cloud`.`acl_role_view`;
CREATE VIEW `cloud`.`acl_role_view` AS