bug 11236: domainAdmin/regularUser can edit/delete/copy/extract Public template/iso only if it was created by them. They still can use/see public template/iso when execute list/deploy/attachIso commands. Root admin can operate with other people templates w/o any restrictions.

status 11236: resolved fixed
This commit is contained in:
alena 2011-08-24 14:26:36 -07:00
parent 9de41dd600
commit e3f179844e
21 changed files with 113 additions and 171 deletions

View File

@ -35,6 +35,11 @@ import com.cloud.utils.component.Adapter;
* the management stack for users and accounts.
*/
public interface SecurityChecker extends Adapter {
public enum AccessType {
ListEntry,
ModifyEntry,
}
/**
* Checks if the account owns the object.
*
@ -60,10 +65,11 @@ public interface SecurityChecker extends Adapter {
*
* @param caller account to check against.
* @param entity object that the account is trying to access.
* @param accessType TODO
* @return true if access allowed. false if this adapter cannot provide permission.
* @throws PermissionDeniedException if this adapter is suppose to authenticate ownership and the check failed.
*/
boolean checkAccess(Account caller, ControlledEntity entity) throws PermissionDeniedException;
boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType) throws PermissionDeniedException;
/**
* Checks if the user belongs to an account that can access the object.

View File

@ -28,7 +28,6 @@ import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.async.AsyncJob;
import com.cloud.event.EventTypes;

View File

@ -28,7 +28,6 @@ import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.StoragePoolResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.async.AsyncJob;

View File

@ -25,15 +25,12 @@ import java.util.Set;
import org.apache.log4j.Logger;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseCmd;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.async.AsyncJob;
import com.cloud.storage.Storage;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.template.VirtualMachineTemplate.TemplateFilter;
import com.cloud.user.Account;
import com.cloud.user.UserContext;

View File

@ -26,7 +26,6 @@ import com.cloud.api.BaseCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.TemplateResponse;
import com.cloud.exception.InvalidParameterValueException;

View File

@ -18,7 +18,6 @@
package com.cloud.api.commands;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
@ -36,7 +35,6 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.utils.Pair;
@Implementation(description="Registers an existing template into the Cloud.com cloud. ", responseObject=TemplateResponse.class)
public class RegisterTemplateCmd extends BaseCmd {

View File

@ -74,14 +74,13 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
}
@Override
public boolean checkAccess(Account caller, ControlledEntity entity) throws PermissionDeniedException {
public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType) throws PermissionDeniedException {
if (entity instanceof VirtualMachineTemplate) {
VirtualMachineTemplate template = (VirtualMachineTemplate)entity;
Account owner = _accountDao.findById(template.getAccountId());
// validate that the template is usable by the account
if (!template.isPublicTemplate()) {
Account owner = _accountDao.findById(template.getAccountId());
if (BaseCmd.isRootAdmin(caller.getType()) || (owner.getId() == caller.getId())) {
return true;
}
@ -92,6 +91,13 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
if (permission == null) {
throw new PermissionDeniedException(caller + " does not have permission to launch instances from " + template);
}
} else {
// Domain admin and regular user can delete/modify only templates created by them
if (accessType != null && accessType == AccessType.ModifyEntry) {
if (!BaseCmd.isRootAdmin(caller.getType()) && owner.getId() != caller.getId()) {
throw new PermissionDeniedException("Domain Admin and regular users can modify only their own Public templates");
}
}
}
return true;
@ -109,7 +115,7 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
@Override
public boolean checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException {
Account account = _accountDao.findById(user.getAccountId());
return checkAccess(account, entity);
return checkAccess(account, entity, null);
}
@Override

View File

@ -307,7 +307,7 @@ public class AsyncJobManagerImpl implements AsyncJobManager, ClusterManagerListe
throw new PermissionDeniedException("Account " + caller + " is not authorized to see job id=" + job.getId());
}
} else if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
_accountMgr.checkAccess(caller, jobOwner);
_accountMgr.checkAccess(caller, null, jobOwner);
}
return queryAsyncJobResult(cmd.getId());

View File

@ -544,7 +544,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied");
}
_accountMgr.checkAccess(caller, ipOwner);
_accountMgr.checkAccess(caller, null, ipOwner);
DataCenterVO zone = null;
if (zoneId != null) {
@ -654,7 +654,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
IpAddress ipToAssoc = getIp(cmd.getEntityId());
if (ipToAssoc != null) {
_accountMgr.checkAccess(caller, ipToAssoc);
_accountMgr.checkAccess(caller, null, ipToAssoc);
owner = _accountMgr.getAccount(ipToAssoc.getAccountId());
} else {
s_logger.debug("Unable to find ip address by id: " + cmd.getEntityId());
@ -1413,7 +1413,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
if (ipVO.getAllocatedToAccountId() != null) {
_accountMgr.checkAccess(caller, ipVO);
_accountMgr.checkAccess(caller, null, ipVO);
}
if (ipVO.isSourceNat()) {
@ -1856,7 +1856,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
accountId = owner.getId();
}
}
@ -2046,7 +2046,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
throw new PermissionDeniedException("Account " + caller.getAccountName() + " does not own network id=" + networkId + ", permission denied");
}
} else {
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
}
User callerUser = _accountMgr.getActiveUser(UserContext.current().getCallerUserId());
@ -2378,7 +2378,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
throw new InvalidParameterValueException("Network is not in the right state to be restarted. Correct states are: " + Network.State.Implemented + ", " + Network.State.Setup);
}
_accountMgr.checkAccess(callerAccount, network);
_accountMgr.checkAccess(callerAccount, null, network);
boolean success = true;
@ -3033,7 +3033,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (tags != null && tags.size() > 1) {
throw new InvalidParameterException("Unable to support more than one tag on network yet");
}
_accountMgr.checkAccess(caller, network);
_accountMgr.checkAccess(caller, null, network);
// Don't allow to update system network - make an exception for the Guest network in Basic zone
NetworkOffering offering = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());

View File

@ -186,7 +186,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
if (ipAddressVO == null || !ipAddressVO.readyToUse()) {
throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for firewall rules yet");
}
_accountMgr.checkAccess(caller, ipAddressVO);
_accountMgr.checkAccess(caller, null, ipAddressVO);
}
if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
@ -298,7 +298,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
@Override
public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, Purpose purpose) {
// Validate ip address
_accountMgr.checkAccess(caller, ipAddress);
_accountMgr.checkAccess(caller, null, ipAddress);
Long networkId = ipAddress.getAssociatedWithNetworkId();
if (networkId == null) {
@ -383,7 +383,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
if (caller != null) {
_accountMgr.checkAccess(caller, rules.toArray(new FirewallRuleVO[rules.size()]));
_accountMgr.checkAccess(caller, null, rules.toArray(new FirewallRuleVO[rules.size()]));
}
try {
@ -407,7 +407,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
throw new InvalidParameterValueException("Unable to find " + ruleId + " having purpose " + Purpose.Firewall);
}
_accountMgr.checkAccess(caller, rule);
_accountMgr.checkAccess(caller, null, rule);
revokeRule(rule, caller, userId, false);
@ -436,7 +436,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma
@DB
public void revokeRule(FirewallRuleVO rule, Account caller, long userId, boolean needUsageEvent) {
if (caller != null) {
_accountMgr.checkAccess(caller, rule);
_accountMgr.checkAccess(caller, null, rule);
}
Transaction txn = Transaction.currentTxn();

View File

@ -225,7 +225,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
throw new InvalidParameterException("Invalid load balancer value: " + loadBalancerId);
}
_accountMgr.checkAccess(caller.getCaller(), loadBalancer);
_accountMgr.checkAccess(caller.getCaller(), null, loadBalancer);
try {
loadBalancer.setState(FirewallRule.State.Add);
@ -298,7 +298,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
throw new InvalidParameterValueException("Unable to find load balancer rule " + loadBalancerId);
}
_accountMgr.checkAccess(caller, rule);
_accountMgr.checkAccess(caller, null, rule);
return deleteLoadBalancerRule(loadBalancerId, apply, caller, ctx.getCallerUserId());
}
@ -406,7 +406,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
}
NetworkVO network = _networkDao.findById(networkId);
_accountMgr.checkAccess(caller.getCaller(), ipAddr);
_accountMgr.checkAccess(caller.getCaller(), null, ipAddr);
// verify that lb service is supported by the network
if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) {
@ -653,7 +653,7 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager,
return null;
}
_accountMgr.checkAccess(caller, loadBalancer);
_accountMgr.checkAccess(caller, null, loadBalancer);
List<UserVmVO> loadBalancerInstances = new ArrayList<UserVmVO>();
List<LoadBalancerVMMapVO> vmLoadBalancerMappings = null;

View File

@ -457,7 +457,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
throw new InvalidParameterValueException("Unable to find router by id " + routerId + ".");
}
_accountMgr.checkAccess(account, router);
_accountMgr.checkAccess(account, null, router);
UserVO user = _userDao.findById(UserContext.current().getCallerUserId());
@ -1864,7 +1864,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
if (router == null) {
throw new InvalidParameterValueException("Unable to find router by id " + routerId + ".");
}
_accountMgr.checkAccess(account, router);
_accountMgr.checkAccess(account, null, router);
Account owner = _accountMgr.getAccount(router.getAccountId());

View File

@ -115,8 +115,8 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new InvalidParameterValueException("Invalid user vm: " + userVm.getId());
}
_accountMgr.checkAccess(caller, ipAddress);
_accountMgr.checkAccess(caller, userVm);
_accountMgr.checkAccess(caller, null, ipAddress);
_accountMgr.checkAccess(caller, null, userVm);
// validate that IP address and userVM belong to the same account
if (ipAddress.getAllocatedToAccountId().longValue() != userVm.getAccountId()) {
@ -136,8 +136,8 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
return;
}
_accountMgr.checkAccess(caller, rule);
_accountMgr.checkAccess(caller, userVm);
_accountMgr.checkAccess(caller, null, rule);
_accountMgr.checkAccess(caller, null, userVm);
if (userVm.getState() == VirtualMachine.State.Destroyed || userVm.getState() == VirtualMachine.State.Expunging) {
throw new InvalidParameterValueException("Invalid user vm: " + userVm.getId());
@ -395,7 +395,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new InvalidParameterValueException("Unable to find " + ruleId);
}
_accountMgr.checkAccess(caller, rule);
_accountMgr.checkAccess(caller, null, rule);
return revokePortForwardingRuleInternal(ruleId, caller, ctx.getCallerUserId(), apply);
}
@ -427,7 +427,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new InvalidParameterValueException("Unable to find " + ruleId);
}
_accountMgr.checkAccess(caller, rule);
_accountMgr.checkAccess(caller, null, rule);
return revokeStaticNatRuleInternal(ruleId, caller, ctx.getCallerUserId(), apply);
}
@ -538,7 +538,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
if (ipAddressVO == null || !ipAddressVO.readyToUse()) {
throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for port forwarding rules yet");
}
_accountMgr.checkAccess(caller, ipAddressVO);
_accountMgr.checkAccess(caller, null, ipAddressVO);
}
if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
@ -604,7 +604,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
if (caller != null) {
_accountMgr.checkAccess(caller, rules.toArray(new PortForwardingRuleVO[rules.size()]));
_accountMgr.checkAccess(caller, null, rules.toArray(new PortForwardingRuleVO[rules.size()]));
}
try {
@ -652,7 +652,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
if (caller != null) {
_accountMgr.checkAccess(caller, staticNatRules.toArray(new StaticNatRule[staticNatRules.size()]));
_accountMgr.checkAccess(caller, null, staticNatRules.toArray(new StaticNatRule[staticNatRules.size()]));
}
try {
@ -676,7 +676,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
if (caller != null) {
_accountMgr.checkAccess(caller, rules.toArray(new PortForwardingRuleVO[rules.size()]));
_accountMgr.checkAccess(caller, null, rules.toArray(new PortForwardingRuleVO[rules.size()]));
}
try {
@ -702,7 +702,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
if (caller != null) {
_accountMgr.checkAccess(caller, rules.toArray(new FirewallRule[rules.size()]));
_accountMgr.checkAccess(caller, null, rules.toArray(new FirewallRule[rules.size()]));
}
for (FirewallRuleVO rule : rules) {
@ -731,7 +731,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
if (caller != null) {
_accountMgr.checkAccess(caller, ips.toArray(new IPAddressVO[ips.size()]));
_accountMgr.checkAccess(caller, null, ips.toArray(new IPAddressVO[ips.size()]));
}
List<StaticNat> staticNats = new ArrayList<StaticNat>();
@ -768,7 +768,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
if (ipAddressVO == null || !ipAddressVO.readyToUse()) {
throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for port forwarding rules yet");
}
_accountMgr.checkAccess(caller, ipAddressVO);
_accountMgr.checkAccess(caller, null, ipAddressVO);
}
if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
@ -1096,7 +1096,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
}
if (caller != null) {
_accountMgr.checkAccess(caller, sourceIp);
_accountMgr.checkAccess(caller, null, sourceIp);
}
//create new static nat rule

View File

@ -607,7 +607,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
}
// Verify permissions
_accountMgr.checkAccess(caller, securityGroup);
_accountMgr.checkAccess(caller, null, securityGroup);
Long domainId = owner.getDomainId();
if (protocol == null) {
@ -684,7 +684,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
}
// Check permissions
_accountMgr.checkAccess(caller, groupVO);
_accountMgr.checkAccess(caller, null, groupVO);
authorizedGroups.add(groupVO);
}
@ -767,7 +767,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
// Check permissions
SecurityGroup securityGroup = _securityGroupDao.findById(rule.getSecurityGroupId());
_accountMgr.checkAccess(caller, securityGroup);
_accountMgr.checkAccess(caller, null, securityGroup);
SecurityGroupVO groupHandle = null;
final Transaction txn = Transaction.currentTxn();
@ -1268,7 +1268,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
}
// check permissions
_accountMgr.checkAccess(caller, group);
_accountMgr.checkAccess(caller, null, group);
final Transaction txn = Transaction.currentTxn();
txn.start();
@ -1313,7 +1313,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
if (userVM == null) {
throw new InvalidParameterValueException("Unable to list network groups for virtual machine instance " + instanceId + "; instance not found.");
}
_accountMgr.checkAccess(caller, userVM);
_accountMgr.checkAccess(caller, null, userVM);
return listSecurityGroupRulesByVM(instanceId.longValue());
}
@ -1329,7 +1329,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
if (account == null) {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
_accountMgr.checkAccess(caller, account);
_accountMgr.checkAccess(caller, null, account);
accountId = account.getId();
}
}

View File

@ -108,7 +108,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
throw new InvalidParameterValueException("Unable to create remote access vpn, invalid public IP address id" + publicIpId);
}
_accountMgr.checkAccess(caller, ipAddr);
_accountMgr.checkAccess(caller, null, ipAddr);
if (!ipAddr.readyToUse() || ipAddr.getAssociatedWithNetworkId() == null) {
throw new InvalidParameterValueException("The Ip address is not ready to be used yet: " + ipAddr.getAddress());
@ -211,7 +211,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
return;
}
_accountMgr.checkAccess(caller, vpn);
_accountMgr.checkAccess(caller, null, vpn);
Network network = _networkMgr.getNetwork(vpn.getNetworkId());
@ -297,7 +297,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
if (owner == null) {
throw new InvalidParameterValueException("Unable to add vpn user: Another operation active");
}
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
long userCount = _vpnUsersDao.getVpnUserCount(owner.getId());
if (userCount >= _userLimit) {
@ -317,7 +317,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
if (user == null) {
throw new InvalidParameterValueException("Could not find vpn user " + username);
}
_accountMgr.checkAccess(caller, user);
_accountMgr.checkAccess(caller, null, user);
user.setState(State.Revoke);
_vpnUsersDao.update(user.getId(), user);
@ -328,7 +328,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
public List<? extends VpnUser> listVpnUsers(long vpnOwnerId, String userName) {
Account caller = UserContext.current().getCaller();
Account owner = _accountDao.findById(vpnOwnerId);
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
return _vpnUsersDao.listByAccount(vpnOwnerId);
}
@ -341,7 +341,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
throw new InvalidParameterValueException("Unable to find your vpn: " + vpnId);
}
_accountMgr.checkAccess(caller, vpn);
_accountMgr.checkAccess(caller, null, vpn);
@ -378,7 +378,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
public boolean applyVpnUsers(long vpnOwnerId) {
Account caller = UserContext.current().getCaller();
Account owner = _accountDao.findById(vpnOwnerId);
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
s_logger.debug("Applying vpn users for " + owner);
List<RemoteAccessVpnVO> vpns = _remoteAccessVpnDao.findByAccount(vpnOwnerId);
@ -535,7 +535,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
+ " is not associated with an account.");
}
}
_accountMgr.checkAccess(caller, publicIp);
_accountMgr.checkAccess(caller, null, publicIp);
}

View File

@ -53,6 +53,7 @@ import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import com.cloud.acl.SecurityChecker.AccessType;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
@ -1710,7 +1711,7 @@ public class ManagementServerImpl implements ManagementServer {
// if template is not public, perform permission check here
if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
Account owner = _accountMgr.getAccount(template.getAccountId());
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
}
templateZonePairSet.add(new Pair<Long, Long>(template.getId(), zoneId));
}
@ -1793,7 +1794,7 @@ public class ManagementServerImpl implements ManagementServer {
throw new InvalidParameterValueException("Unable to find account by id " + accountId);
}
_accountMgr.checkAccess(caller, account);
_accountMgr.checkAccess(caller, null, account);
}
if (domainId != null) {
@ -1809,7 +1810,7 @@ public class ManagementServerImpl implements ManagementServer {
throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain " + domainId);
}
_accountMgr.checkAccess(caller, account);
_accountMgr.checkAccess(caller, null, account);
}
}
@ -2011,7 +2012,7 @@ public class ManagementServerImpl implements ManagementServer {
}
// do a permission check
_accountMgr.checkAccess(account, template);
_accountMgr.checkAccess(account, AccessType.ModifyEntry, template);
boolean updateNeeded = !(name == null && displayText == null && format == null && guestOSId == null && passwordEnabled == null && bootable == null);
if (!updateNeeded) {
@ -3345,7 +3346,7 @@ public class ManagementServerImpl implements ManagementServer {
}
}
_accountMgr.checkAccess(caller, template);
_accountMgr.checkAccess(caller, AccessType.ModifyEntry, template);
// If command is executed via 8096 port, set userId to the id of System account (1)
if (userId == null) {
@ -3485,7 +3486,7 @@ public class ManagementServerImpl implements ManagementServer {
}
if (!template.isPublicTemplate()) {
_accountMgr.checkAccess(caller, template);
_accountMgr.checkAccess(caller, null, template);
}
List<String> accountNames = new ArrayList<String>();
@ -4126,7 +4127,7 @@ public class ManagementServerImpl implements ManagementServer {
}
// check permissions
_accountMgr.checkAccess(caller, _accountMgr.getAccount(user.getAccountId()));
_accountMgr.checkAccess(caller, null, _accountMgr.getAccount(user.getAccountId()));
String cloudIdentifier = _configDao.getValue("cloud.identifier");
if (cloudIdentifier == null) {
@ -4323,7 +4324,7 @@ public class ManagementServerImpl implements ManagementServer {
extractMode = mode.equals(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD;
}
_accountMgr.checkAccess(account, volume);
_accountMgr.checkAccess(account, null, volume);
// If mode is upload perform extra checks on url and also see if there is an ongoing upload on the same.
if (extractMode == Upload.Mode.FTP_UPLOAD) {
URI uri = new URI(url);
@ -4772,7 +4773,7 @@ public class ManagementServerImpl implements ManagementServer {
}
// make permission check
_accountMgr.checkAccess(caller, vm);
_accountMgr.checkAccess(caller, null, vm);
_userVmDao.loadDetails(vm);
String password = vm.getDetail("Encrypted.Password");

View File

@ -1283,7 +1283,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma
}
// Verify permissions
_accountMgr.checkAccess(caller, volume);
_accountMgr.checkAccess(caller, null, volume);
Account owner = _accountMgr.getAccount(volume.getAccountId());
if (_accountMgr.resourceLimitExceeded(owner, ResourceType.snapshot)) {

View File

@ -33,6 +33,7 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.acl.SecurityChecker.AccessType;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DestroyCommand;
@ -63,7 +64,6 @@ import com.cloud.event.UsageEventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.HostVO;
@ -217,7 +217,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
@Override
public Long extract(ExtractTemplateCmd cmd) {
Account account = UserContext.current().getCaller();
Account caller = UserContext.current().getCaller();
Long templateId = cmd.getId();
Long zoneId = cmd.getZoneId();
String url = cmd.getUrl();
@ -225,7 +225,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
Long eventId = cmd.getStartEventId();
// FIXME: async job needs fixing
return extract(account, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr);
return extract(caller, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr);
}
@Override
@ -239,7 +239,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
return vmTemplate;
}
private Long extract(Account account, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) {
private Long extract(Account caller, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) {
String desc = "template";
if (isISO) {
desc = "ISO";
@ -268,20 +268,12 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
throw new IllegalArgumentException("Please specify a valid zone.");
}
/*
* GLOBAL ADMINS - always allowed to extract
* OTHERS - allowed to extract if
* 1) Its own template and extractable=true
* 2) Its not its own template but public=true and extractable=true
*/
if (account!=null && account.getType() != Account.ACCOUNT_TYPE_ADMIN){//Not a ROOT Admin
if (template.getAccountId() == account.getId() && template.isExtractable()){
}else if (template.getAccountId() != account.getId() && template.isPublicTemplate() && template.isExtractable()){
}else{
throw new PermissionDeniedException("Unable to extract " + desc + "=" + templateId + " - permission denied.");
}
if (!template.isExtractable()) {
throw new InvalidParameterValueException("Unable to extract template id=" + templateId + " as it's not extractable");
}
_accountMgr.checkAccess(caller, AccessType.ModifyEntry, template);
List<HostVO> sservers = _storageMgr.getSecondaryStorageHosts(zoneId);
VMTemplateHostVO tmpltHostRef = null;
@ -592,10 +584,9 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
Long userId = UserContext.current().getCallerUserId();
Long sourceZoneId = cmd.getSourceZoneId();
Long destZoneId = cmd.getDestinationZoneId();
Account account = UserContext.current().getCaller();
Account caller = UserContext.current().getCaller();
//Verify parameters
if (sourceZoneId == destZoneId) {
throw new InvalidParameterValueException("Please specify different source and destination zones.");
}
@ -625,16 +616,13 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
if ( srcSecHost == null ) {
throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId );
}
//Verify account information
String errMsg = "Unable to copy template " + templateId;
userId = accountAndUserValidation(account, userId, null, template, errMsg);
_accountMgr.checkAccess(caller, AccessType.ModifyEntry, template);
boolean success = copy(userId, template, srcSecHost, sourceZone, dstZone);
if (success) {
return template;
} else {
s_logger.warn(errMsg);
}
return null;
@ -784,7 +772,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
@Override
@ActionEvent(eventType = EventTypes.EVENT_ISO_DETACH, eventDescription = "detaching ISO", async = true)
public boolean detachIso(DetachIsoCmd cmd) {
Account account = UserContext.current().getCaller();
Account caller = UserContext.current().getCaller();
Long userId = UserContext.current().getCallerUserId();
Long vmId = cmd.getVirtualMachineId();
@ -798,6 +786,8 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
if (userVM == null) {
throw new InvalidParameterValueException("Please specify a valid VM.");
}
_accountMgr.checkAccess(caller, null, userVM);
Long isoId = userVM.getIsoId();
if (isoId == null) {
@ -809,12 +799,8 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
if (vmState != State.Running && vmState != State.Stopped) {
throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running.");
}
String errMsg = "Unable to detach ISO " + isoId + " from virtual machine";
userId = accountAndUserValidation(account, userId, vmInstanceCheck, null, errMsg);
return attachISOToVM(vmId, userId, isoId, false); //attach=false => detach
return attachISOToVM(vmId, userId, isoId, false); //attach=false => detach
}
@Override
@ -836,14 +822,15 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
throw new InvalidParameterValueException("Unable to find an ISO with id " + isoId);
}
//check permissions
_accountMgr.checkAccess(caller, null, iso);
_accountMgr.checkAccess(caller, null, vm);
State vmState = vm.getState();
if (vmState != State.Running && vmState != State.Stopped) {
throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running.");
}
String errMsg = "Unable to attach ISO" + isoId + "to virtual machine " + vmId;
userId = accountAndUserValidation(caller, userId, vm, iso, errMsg);
if ("xen-pv-drv-iso".equals(iso.getDisplayText()) && vm.getHypervisorType() != Hypervisor.HypervisorType.XenServer){
throw new InvalidParameterValueException("Cannot attach Xenserver PV drivers to incompatible hypervisor " + vm.getHypervisorType());
}
@ -869,40 +856,6 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
}
return success;
}
private Long accountAndUserValidation(Account caller, Long userId, UserVmVO userVm, VMTemplateVO template, String msg) throws PermissionDeniedException{
if (caller != null) {
if (!isAdmin(caller.getType())) {
if ((userVm != null) && (caller.getId() != userVm.getAccountId())) {
throw new PermissionDeniedException(msg + ". Permission denied.");
}
if ((template != null) && (!template.isPublicTemplate() && (caller.getId() != template.getAccountId()) && (template.getTemplateType() != TemplateType.PERHOST))) {
throw new PermissionDeniedException(msg + ". Permission denied.");
}
} else {
if (userVm != null) {
_accountMgr.checkAccess(caller, userVm);
}
if (template != null && !template.isPublicTemplate()) {
Account templateOwner = _accountDao.findById(template.getAccountId());
_accountMgr.checkAccess(caller, templateOwner);
}
}
}
return userId;
}
private static boolean isAdmin(short accountType) {
return ((accountType == Account.ACCOUNT_TYPE_ADMIN) ||
(accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) ||
(accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) ||
(accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN));
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_DELETE, eventDescription = "deleting template", async = true)
@ -915,16 +868,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
throw new InvalidParameterValueException("unable to find template with id " + templateId);
}
if (template != null) {
Account templateOwner = _accountDao.findById(template.getAccountId());
if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
if (caller.getId() != templateOwner.getId()) {
throw new PermissionDeniedException("Account " + caller + " can't operate with template id=" + template.getId());
}
} else if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
_accountMgr.checkAccess(caller, templateOwner);
}
}
_accountMgr.checkAccess(caller, AccessType.ModifyEntry, template);
if (template.getFormat() == ImageFormat.ISO) {
throw new InvalidParameterValueException("Please specify a valid template.");
@ -946,17 +890,8 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
throw new InvalidParameterValueException("unable to find iso with id " + templateId);
}
if (template != null) {
Account templateOwner = _accountDao.findById(template.getAccountId());
if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) {
if (caller.getId() != templateOwner.getId()) {
throw new PermissionDeniedException("Account " + caller + " can't operate with iso id=" + template.getId());
}
} else if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) {
_accountMgr.checkAccess(caller, templateOwner);
}
}
_accountMgr.checkAccess(caller, AccessType.ModifyEntry, template);
if (template.getFormat() != ImageFormat.ISO) {
throw new InvalidParameterValueException("Please specify a valid iso.");
}

View File

@ -21,6 +21,7 @@ package com.cloud.user;
import java.util.List;
import com.cloud.acl.ControlledEntity;
import com.cloud.acl.SecurityChecker.AccessType;
import com.cloud.api.commands.CreateUserCmd;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceCount.ResourceType;
@ -122,7 +123,7 @@ public interface AccountManager extends AccountService {
void checkAccess(Account account, Domain domain) throws PermissionDeniedException;
void checkAccess(Account account, ControlledEntity... entities) throws PermissionDeniedException;
void checkAccess(Account account, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException;
boolean cleanupAccount(AccountVO account, long callerUserId, Account caller);

View File

@ -37,6 +37,7 @@ import org.apache.log4j.Logger;
import com.cloud.acl.ControlledEntity;
import com.cloud.acl.SecurityChecker;
import com.cloud.acl.SecurityChecker.AccessType;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.commands.CreateAccountCmd;
import com.cloud.api.commands.CreateUserCmd;
@ -907,7 +908,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
}
@Override
public void checkAccess(Account caller, ControlledEntity... entities) {
public void checkAccess(Account caller, AccessType accessType, ControlledEntity... entities) {
HashMap<Long, List<ControlledEntity>> domains = new HashMap<Long, List<ControlledEntity>>();
for (ControlledEntity entity : entities) {
@ -926,7 +927,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
}
boolean granted = false;
for (SecurityChecker checker : _securityCheckers) {
if (checker.checkAccess(caller, entity)) {
if (checker.checkAccess(caller, entity, accessType)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Access to " + entity + " granted to " + caller + " by " + checker.getName());
}
@ -1431,7 +1432,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
throw new PermissionDeniedException("user id : " + id + " is system account, update is not allowed");
}
checkAccess(UserContext.current().getCaller(), account);
checkAccess(UserContext.current().getCaller(), null, account);
if (firstName != null) {
user.setFirstname(firstName);
@ -1634,7 +1635,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
// If the user is a System user, return an error. We do not allow this
AccountVO account = _accountDao.findById(accountId);
checkAccess(UserContext.current().getCaller(), account);
checkAccess(UserContext.current().getCaller(), null, account);
if ((account != null) && (account.getId() == Account.ACCOUNT_ID_SYSTEM)) {
throw new PermissionDeniedException("Account id : " + accountId + " is a system account, delete is not allowed");
}
@ -1813,7 +1814,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag
if ((user != null) && (user.getAccountId() == Account.ACCOUNT_ID_SYSTEM)) {
throw new InvalidParameterValueException("Account id : " + user.getAccountId() + " is a system account, delete for user associated with this account is not allowed");
}
checkAccess(UserContext.current().getCaller(), _accountDao.findById(user.getAccountId()));
checkAccess(UserContext.current().getCaller(), null, _accountDao.findById(user.getAccountId()));
return _userDao.remove(id);
}

View File

@ -542,7 +542,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
// If the account is not an admin, check that the volume and the virtual machine are owned by the account that was
// passed in
_accountMgr.checkAccess(account, volume);
_accountMgr.checkAccess(account, null, volume);
/*
* if (account != null) { if (!isAdmin(account.getType())) { if (account.getId() != volume.getAccountId()) { throw new
* PermissionDeniedException("Unable to find volume with ID: " + volumeId + " for account: " + account.getAccountName()
@ -735,7 +735,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
// If the account is not an admin, check that the volume is owned by the account that was passed in
_accountMgr.checkAccess(account, volume);
_accountMgr.checkAccess(account, null, volume);
/*
* if (!isAdmin) { if (account.getId() != volume.getAccountId()) { throw new
* InvalidParameterValueException("Unable to find volume with ID: " + volumeId + " for account: " +
@ -2040,7 +2040,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
// Verify that caller can perform actions in behalf of vm owner
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
// Get default guest network in Basic zone
Network defaultNetwork = _networkMgr.getSystemNetworkByZoneAndTrafficType(zone.getId(), TrafficType.Guest);
@ -2100,7 +2100,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
boolean isVmWare = (template.getHypervisorType() == HypervisorType.VMware || (hypervisor != null && hypervisor == HypervisorType.VMware));
//Verify that caller can perform actions in behalf of vm owner
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
// If no network is specified, find system security group enabled network
if (networkIdList == null || networkIdList.isEmpty()) {
@ -2208,7 +2208,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
// Verify that caller can perform actions in behalf of vm owner
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
if (networkIdList == null || networkIdList.isEmpty()) {
NetworkVO defaultNetwork = null;
@ -2326,7 +2326,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, String hostName, String displayName, Account owner, Long diskOfferingId,
Long diskSize, List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map<Long, String> requestedIps, String defaultNetworkIp, String keyboard) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException {
_accountMgr.checkAccess(caller, owner);
_accountMgr.checkAccess(caller, null, owner);
long accountId = owner.getId();
assert !(requestedIps != null && defaultNetworkIp != null) : "requestedIp list and defaultNetworkIp should never be specified together";
@ -2387,7 +2387,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
// Check templates permissions
if (!template.isPublicTemplate()) {
Account templateOwner = _accountMgr.getAccount(template.getAccountId());
_accountMgr.checkAccess(owner, templateOwner);
_accountMgr.checkAccess(owner, null, templateOwner);
}
// If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk