From 1dfdcf51cb3495e3585081a53f41a4c75af3161c Mon Sep 17 00:00:00 2001 From: abhishek Date: Tue, 30 Nov 2010 12:59:04 -0800 Subject: [PATCH] another good point for checkin, added the domain checker for checks against service offerings, whilst deploying virtual machines --- api/src/com/cloud/acl/SecurityChecker.java | 3 ++ server/src/com/cloud/acl/DomainChecker.java | 49 +++++++++++++++++++ .../configuration/ConfigurationManager.java | 5 +- .../ConfigurationManagerImpl.java | 19 ++++++- .../cloud/server/ManagementServerImpl.java | 10 ++++ 5 files changed, 84 insertions(+), 2 deletions(-) diff --git a/api/src/com/cloud/acl/SecurityChecker.java b/api/src/com/cloud/acl/SecurityChecker.java index e835d9d2241..e745607dab4 100644 --- a/api/src/com/cloud/acl/SecurityChecker.java +++ b/api/src/com/cloud/acl/SecurityChecker.java @@ -6,6 +6,7 @@ package com.cloud.acl; import com.cloud.dc.DataCenter; import com.cloud.domain.Domain; import com.cloud.exception.PermissionDeniedException; +import com.cloud.offering.ServiceOffering; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.component.Adapter; @@ -57,6 +58,8 @@ public interface SecurityChecker extends Adapter { boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException; + public boolean checkAccess(Account account, ServiceOffering so) 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 // OwnedBy and PartOf interfaces on the object and use it to verify against a user. diff --git a/server/src/com/cloud/acl/DomainChecker.java b/server/src/com/cloud/acl/DomainChecker.java index 95dca17171b..ae434f1509a 100644 --- a/server/src/com/cloud/acl/DomainChecker.java +++ b/server/src/com/cloud/acl/DomainChecker.java @@ -25,6 +25,7 @@ import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.PermissionDeniedException; +import com.cloud.offering.ServiceOffering; import com.cloud.storage.LaunchPermissionVO; import com.cloud.storage.dao.LaunchPermissionDao; import com.cloud.template.VirtualMachineTemplate; @@ -100,6 +101,54 @@ public class DomainChecker extends AdapterBase implements SecurityChecker { return checkAccess(account, entity); } + + @Override + public boolean checkAccess(Account account, ServiceOffering so) throws PermissionDeniedException + { + if(account == null || so.getDomainId() == null) + {//public offering + 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 || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) + { + if(account.getDomainId() == so.getDomainId()) + { + return true; //service offering and account at exact node + } + else + { + DomainVO domainRecord = _domainDao.findById(account.getDomainId()); + if(domainRecord != null) + { + while(true) + { + if(domainRecord.getId() == so.getDomainId()) + { + //found as a child + return true; + } + if(domainRecord.getParent() != null) + domainRecord = _domainDao.findById(domainRecord.getParent()); + else + break; + } + } + } + } + } + //not found + return false; + } + @Override public boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException { if(account == null || zone.getDomainId() == null){//public zone diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index 75df0ec0b95..a1cee1a56b8 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -26,6 +26,7 @@ import com.cloud.dc.HostPodVO; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.PermissionDeniedException; +import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; import com.cloud.user.Account; @@ -153,5 +154,7 @@ public interface ConfigurationManager extends Manager { void checkAccess(Account caller, DataCenter zone) throws PermissionDeniedException; - + + void checkAccess(Account caller, ServiceOffering so) + throws PermissionDeniedException; } diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 4fefb4683ba..98feff6fa85 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2311,7 +2311,24 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura return deleteVlanAndPublicIpRange(userId, vlanDbId); } - + + @Override + public void checkAccess(Account caller, ServiceOffering so) throws PermissionDeniedException { + for (SecurityChecker checker : _secChecker) { + if (checker.checkAccess(caller, so)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access granted to " + caller + " to service offering:" + so.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 service offering:" + so.getId()); + } + @Override public void checkAccess(Account caller, DataCenter zone) throws PermissionDeniedException { for (SecurityChecker checker : _secChecker) { diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 5167de6d50a..69e6702909b 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1196,6 +1196,16 @@ public class ManagementServerImpl implements ManagementServer { throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId); } + if(offering.getDomainId() == null){ + //do nothing as offering is public + }else{ + if(userAccount != null){ + _configMgr.checkAccess(userAccount, offering);//user deploying his own vm + }else{ + _configMgr.checkAccess(ctxAccount, offering); + } + } + VMTemplateVO template = _templateDao.findById(templateId); // Make sure a valid template ID was specified if (template == null) {