mirror of https://github.com/apache/cloudstack.git
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:
parent
3bcee34f97
commit
11ea13fd7d
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -13,4 +13,5 @@ public interface DataCenter extends Grouping {
|
|||
String getDns1();
|
||||
String getDns2();
|
||||
String getGuestNetworkCidr();
|
||||
Long getDomainId();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue