Added the domain checker code and checks for a host of commands. This replaces the previous mechanism, and provides a way for us to validate the command executor as to whether he has access to the zone.

This commit is contained in:
abhishek 2010-11-08 17:49:28 -08:00
parent 3bcee34f97
commit 11ea13fd7d
6 changed files with 131 additions and 30 deletions

View File

@ -3,6 +3,7 @@
*/
package com.cloud.acl;
import com.cloud.dc.DataCenter;
import com.cloud.domain.Domain;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.user.Account;
@ -53,6 +54,8 @@ public interface SecurityChecker extends Adapter {
* @throws PermissionDeniedException if this adapter is suppose to authenticate ownership and the check failed.
*/
boolean checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException;
boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException;
// We should be able to use this method to check against commands. For example, we can
// annotate the command with access annotations and this method can use it to extract

View File

@ -13,4 +13,5 @@ public interface DataCenter extends Grouping {
String getDns1();
String getDns2();
String getGuestNetworkCidr();
Long getDomainId();
}

View File

@ -20,7 +20,9 @@ package com.cloud.acl;
import javax.ejb.Local;
import com.cloud.api.BaseCmd;
import com.cloud.dc.DataCenter;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.storage.LaunchPermissionVO;
@ -97,4 +99,71 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
Account account = _accountDao.findById(user.getAccountId());
return checkAccess(account, entity);
}
@Override
public boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException {
if(account == null || zone.getDomainId() == null){//public zone
return true;
}else{
//admin has all permissions
if(account.getType() == Account.ACCOUNT_TYPE_ADMIN){
return true;
}
//if account is normal user
//check if account's domain is a child of zone's domain
else if(account.getType() == Account.ACCOUNT_TYPE_NORMAL){
if(account.getDomainId() == zone.getDomainId()){
return true; //zone and account at exact node
}else{
DomainVO domainRecord = _domainDao.findById(account.getDomainId());
if(domainRecord != null)
{
while(true){
if(domainRecord.getId() == zone.getDomainId()){
//found as a child
return true;
}
if(domainRecord.getParent() != null)
domainRecord = _domainDao.findById(domainRecord.getParent());
else
break;
}
}
}
//not found
return false;
}
//if account is domain admin
//check if the account's domain is either child of zone's domain, or if zone's domain is child of account's domain
else if(account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN){
if(account.getDomainId() == zone.getDomainId()){
return true; //zone and account at exact node
}else{
DomainVO zoneDomainRecord = _domainDao.findById(zone.getDomainId());
DomainVO accountDomainRecord = _domainDao.findById(account.getDomainId());
if(accountDomainRecord != null)
{
DomainVO localRecord = accountDomainRecord;
while(true){
if(localRecord.getId() == zone.getDomainId()){
//found as a child
return true;
}
if(localRecord.getParent() != null)
localRecord = _domainDao.findById(localRecord.getParent());
else
break;
}
}
//didn't find in upper tree
if(zoneDomainRecord.getPath().contains(accountDomainRecord.getPath())){
return true;
}
}
//not found
return false;
}
}
return false;
}
}

View File

@ -19,12 +19,15 @@ package com.cloud.configuration;
import java.util.List;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.user.Account;
import com.cloud.utils.component.Manager;
/**
@ -144,5 +147,8 @@ public interface ConfigurationManager extends Manager {
* @return String containing a comma separated list of tags
*/
String listToCsvTags(List<String> tags);
void checkAccess(Account caller, DataCenter zone)
throws PermissionDeniedException;
}

View File

@ -29,6 +29,7 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.acl.SecurityChecker;
import com.cloud.api.BaseCmd;
import com.cloud.api.ServerApiException;
import com.cloud.api.commands.CreateCfgCmd;
@ -56,8 +57,8 @@ import com.cloud.dc.HostPodVO;
import com.cloud.dc.Pod;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDao;
@ -80,8 +81,8 @@ import com.cloud.network.NetworkManager;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.offering.ServiceOffering;
import com.cloud.offering.NetworkOffering.GuestIpType;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
@ -95,6 +96,7 @@ import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
@ -136,6 +138,8 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
@Inject SecondaryStorageVmDao _secStorageDao;
@Inject AccountManager _accountMgr;
@Inject NetworkManager _networkMgr;
@Inject(adapter=SecurityChecker.class)
Adapters<SecurityChecker> _secChecker;
private int _maxVolumeSizeInGb;
@ -1363,7 +1367,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
String vlanGateway = cmd.getGateway();
String vlanNetmask = cmd.getNetmask();
//check for hypervisor type to be xenserver
//check for hypervisor type to be xenserver
String hypervisorType = _configDao.getValue("hypervisor.type");
if(hypervisorType.equalsIgnoreCase("xenserver")) {
@ -1393,11 +1397,13 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
throw new InvalidParameterValueException("Please specify a valid zone.");
}
//check if the account's domain is a child of the zone's domain, for adding vlan ip ranges
if(domainId != null && !_domainDao.isChildDomain(zone.getDomainId(), domainId)){
//this is for account specific case, as domainId != null
throw new PermissionDeniedException("The account associated with specific domain id:"+domainId+" doesn't have permissions to add vlan ip ranges for the zone:"+zone.getId());
}
// //check if the account's domain is a child of the zone's domain, for adding vlan ip ranges
// if(domainId != null && !_domainDao.isChildDomain(zone.getDomainId(), domainId)){
// //this is for account specific case, as domainId != null
// throw new PermissionDeniedException("The account associated with specific domain id:"+domainId+" doesn't have permissions to add vlan ip ranges for the zone:"+zone.getId());
// }
//ACL check
checkAccess(account, zone);
boolean associateIpRangeToAccount = false;
if (vlanType.equals(VlanType.VirtualNetwork)) {
@ -2215,4 +2221,21 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura
return deleteVlanAndPublicIpRange(userId, vlanDbId);
}
@Override
public void checkAccess(Account caller, DataCenter zone) throws PermissionDeniedException {
for (SecurityChecker checker : _secChecker) {
if (checker.checkAccess(caller, zone)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Access granted to " + caller + " to zone:" + zone.getId() + " by " + checker.getName());
}
return;
}else{
throw new PermissionDeniedException("Access denied to "+caller+" by "+checker.getName());
}
}
assert false : "How can all of the security checkers pass on checking this caller?";
throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to zone:" + zone.getId());
}
}

View File

@ -60,6 +60,8 @@ import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import com.cloud.acl.DomainChecker;
import com.cloud.acl.SecurityChecker;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.GetVncPortAnswer;
@ -150,6 +152,7 @@ import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
@ -163,6 +166,7 @@ import com.cloud.dc.dao.DataCenterIpAddressDaoImpl;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventState;
@ -272,6 +276,7 @@ import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.Inject;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
@ -393,7 +398,7 @@ public class ManagementServerImpl implements ManagementServer {
private boolean _networkGroupsEnabled = false;
private boolean _isHypervisorSnapshotCapable = false;
protected ManagementServerImpl() {
ComponentLocator locator = ComponentLocator.getLocator(Name);
_lunDao = locator.getDao(PreallocatedLunDao.class);
@ -461,7 +466,7 @@ public class ManagementServerImpl implements ManagementServer {
_snapMgr = locator.getManager(SnapshotManager.class);
_networkGroupMgr = locator.getManager(NetworkGroupManager.class);
_uploadMonitor = locator.getManager(UploadMonitor.class);
_userAuthenticators = locator.getAdapters(UserAuthenticator.class);
if (_userAuthenticators == null || !_userAuthenticators.isSet()) {
s_logger.error("Unable to find an user authenticator.");
@ -1116,7 +1121,8 @@ public class ManagementServerImpl implements ManagementServer {
String[] networkGroups = null;
Long sizeObj = cmd.getSize();
long size = (sizeObj == null) ? 0 : sizeObj;
Account userAccount = null;
DataCenterVO dc = _dcDao.findById(dataCenterId);
if (dc == null) {
throw new InvalidParameterValueException("Unable to find zone: " + dataCenterId);
@ -1128,7 +1134,7 @@ public class ManagementServerImpl implements ManagementServer {
throw new PermissionDeniedException("Failed to deploy VM, invalid domain id (" + domainId + ") given.");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount == null) {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
@ -1147,25 +1153,18 @@ public class ManagementServerImpl implements ManagementServer {
if(domainId == null){
domainId = dc.getDomainId(); //get the domain id from zone
if(domainId == null){
//do nothing (public zone case)
}
else{
//check if this account has the permission to deploy a vm in this domain
if(ctxAccount != null){
if((ctxAccount.getType() == Account.ACCOUNT_TYPE_NORMAL) || ctxAccount.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN){
if(domainId == ctxAccount.getDomainId()){
//user in same domain as dedicated zone
}
else if ((!_domainDao.isChildDomain(domainId,ctxAccount.getDomainId()))){
//may need to revisit domain admin case for leaves
throw new PermissionDeniedException("Failed to deploy VM, user does not have permission to deploy a vm within this dedicated private zone under domain id:"+domainId);
}
}
}
}
}
if(domainId == null){
//do nothing (public zone case)
}
else{
if(userAccount != null){
_configMgr.checkAccess(userAccount, dc);//user deploying his own vm
}else{
_configMgr.checkAccess(ctxAccount, dc);
}
}
List<String> netGrpList = cmd.getNetworkGroupList();
if ((netGrpList != null) && !netGrpList.isEmpty()) {