vpc offering check access, list response changes

Signed-off-by: Abhishek Kumar <abhishek.kumar@shapeblue.com>
This commit is contained in:
Abhishek Kumar 2019-04-12 14:15:41 +05:30 committed by Abhishek Kumar
parent 366b253bf2
commit d068417736
11 changed files with 157 additions and 23 deletions

View File

@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd;
import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd;
import org.apache.cloudstack.api.command.user.vpc.ListVPCOfferingsCmd;
import com.cloud.utils.Pair;
@ -36,8 +37,7 @@ public interface VpcProvisioningService {
Map serviceCapabilitystList,
Long serviceOfferingId, List<Long> domainIds, List<Long> zoneIds);
Pair<List<? extends VpcOffering>,Integer> listVpcOfferings(Long id, String name, String displayText, List<String> supportedServicesStr, Boolean isDefault, String keyword,
String state, Long startIndex, Long pageSizeVal);
Pair<List<? extends VpcOffering>,Integer> listVpcOfferings(ListVPCOfferingsCmd cmd);
/**
* @param offId

View File

@ -28,6 +28,7 @@ import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
import com.cloud.dc.DataCenter;
import com.cloud.domain.Domain;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
@ -104,6 +105,8 @@ public interface AccountService {
void checkAccess(Account account, NetworkOffering nof, DataCenter zone) throws PermissionDeniedException;
void checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException;
void checkAccess(User user, ControlledEntity entity);
void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException;

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.acl;
import com.cloud.dc.DataCenter;
import com.cloud.domain.Domain;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
@ -142,4 +143,6 @@ public interface SecurityChecker extends Adapter {
boolean checkAccess(Account account, DiskOffering dof, DataCenter zone) throws PermissionDeniedException;
boolean checkAccess(Account account, NetworkOffering nof, DataCenter zone) throws PermissionDeniedException;
boolean checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException;
}

View File

@ -25,6 +25,7 @@ import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.VpcOfferingResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.log4j.Logger;
import com.cloud.network.vpc.VpcOffering;
@ -60,6 +61,13 @@ public class ListVPCOfferingsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "list VPC offerings by state")
private String state;
@Parameter(name = ApiConstants.ZONE_ID,
type = CommandType.UUID,
entityType = ZoneResponse.class,
description = "id of zone disk offering is associated with",
since = "4.13")
private Long zoneId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -87,6 +95,10 @@ public class ListVPCOfferingsCmd extends BaseListCmd {
return state;
}
public Long getZoneId() {
return zoneId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -94,8 +106,7 @@ public class ListVPCOfferingsCmd extends BaseListCmd {
@Override
public void execute() {
Pair<List<? extends VpcOffering>, Integer> offerings =
_vpcProvSvc.listVpcOfferings(getId(), getVpcOffName(), getDisplayText(), getSupportedServices(), isDefault, this.getKeyword(), getState(),
this.getStartIndex(), this.getPageSizeVal());
_vpcProvSvc.listVpcOfferings(this);
ListResponse<VpcOfferingResponse> response = new ListResponse<VpcOfferingResponse>();
List<VpcOfferingResponse> offeringResponses = new ArrayList<VpcOfferingResponse>();
for (VpcOffering offering : offerings.first()) {

View File

@ -171,7 +171,6 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
@ -287,8 +286,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
RemoteAccessVpnDao _remoteAccessVpnDao;
@Inject
VpcVirtualNetworkApplianceService _routerService;
@Inject
AccountManager accountManager;
List<NetworkGuru> networkGurus;
@ -2166,7 +2163,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
final NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
final DataCenterVO zone = _dcDao.findById(zoneId);
accountManager.checkAccess(owner, ntwkOff, zone);
// this method supports only guest network creation
if (ntwkOff.getTrafficType() != TrafficType.Guest) {
s_logger.warn("Only guest networks can be created using this method");

View File

@ -46,6 +46,7 @@ import com.cloud.domain.Domain;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
@ -446,6 +447,11 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
// TODO Auto-generated method stub
}
@Override
public void checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException {
// TODO Auto-generated method stub
}
@Override
public Map<String, String> getKeys(GetUserKeysCmd cmd){
return null;

View File

@ -34,6 +34,7 @@ import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
@ -74,7 +75,9 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
@Inject
ServiceOfferingDetailsDao serviceOfferingDetailsDao;
@Inject
NetworkOfferingDetailsDao networkserviceOfferingDetailsDao;
NetworkOfferingDetailsDao networkOfferingDetailsDao;
@Inject
NetworkOfferingDetailsDao vpcOfferingDetailsDao;
protected DomainChecker() {
super();
@ -270,7 +273,7 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
|| account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN
|| _accountService.isDomainAdmin(account.getId())
|| account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
final List<Long> doDomainIds = networkserviceOfferingDetailsDao.findDomainIds(nof.getId());
final List<Long> doDomainIds = networkOfferingDetailsDao.findDomainIds(nof.getId());
if (doDomainIds.isEmpty()) {
isAccess = true;
} else {
@ -285,7 +288,45 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
}
// Check for zones
if (isAccess && nof != null && zone != null) {
final List<Long> doZoneIds = networkserviceOfferingDetailsDao.findZoneIds(nof.getId());
final List<Long> doZoneIds = networkOfferingDetailsDao.findZoneIds(nof.getId());
isAccess = doZoneIds.isEmpty() || doZoneIds.contains(zone.getId());
}
return isAccess;
}
@Override
public boolean checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException {
boolean isAccess = false;
// Check fo domains
if (account == null || vof == null) {
isAccess = true;
} else {
//admin has all permissions
if (_accountService.isRootAdmin(account.getId())) {
isAccess = true;
}
//if account is normal user or domain admin
//check if account's domain is a child of offering's domain (Note: This is made consistent with the list command for disk offering)
else if (_accountService.isNormalUser(account.getId())
|| account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN
|| _accountService.isDomainAdmin(account.getId())
|| account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
final List<Long> doDomainIds = vpcOfferingDetailsDao.findDomainIds(vof.getId());
if (doDomainIds.isEmpty()) {
isAccess = true;
} else {
for (Long domainId : doDomainIds) {
if (_domainDao.isChildDomain(domainId, account.getDomainId())) {
isAccess = true;
break;
}
}
}
}
}
// Check for zones
if (isAccess && vof != null && zone != null) {
final List<Long> doZoneIds = vpcOfferingDetailsDao.findZoneIds(vof.getId());
isAccess = doZoneIds.isEmpty() || doZoneIds.contains(zone.getId());
}
return isAccess;

View File

@ -1058,6 +1058,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
}
throw ex;
}
_accountMgr.checkAccess(caller, ntwkOff, _dcDao.findById(zoneId));
// validate physical network and zone
// Check if physical network exists
PhysicalNetwork pNtwk = null;
@ -2015,6 +2017,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
}
_accountMgr.checkAccess(callerAccount, null, true, network);
_accountMgr.checkAccess(callerAccount, offering, _dcDao.findById(network.getDataCenterId()));
if (name != null) {
network.setName(name);
@ -2521,6 +2524,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
Vpc vpc = _vpcDao.findById(vpcId);
_accountMgr.checkAccess(account, null, true, vpc);
_accountMgr.checkAccess(account, _vpcOfferingDao.findById(vpcOfferingId), _dcDao.findById(vpc.getZoneId()));
if (vpc.getVpcOfferingId() == vpcOfferingId) {
return vpc;

View File

@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@ -44,6 +45,7 @@ import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd;
import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd;
import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd;
import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd;
import org.apache.cloudstack.api.command.user.vpc.ListVPCOfferingsCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
@ -51,6 +53,8 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import com.cloud.api.query.dao.VpcOfferingJoinDao;
import com.cloud.api.query.vo.VpcOfferingJoinVO;
import com.cloud.configuration.Config;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenter;
@ -143,6 +147,7 @@ import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.ReservationContextImpl;
import com.cloud.vm.dao.DomainRouterDao;
import com.google.common.base.Strings;
public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvisioningService, VpcService {
private static final Logger s_logger = Logger.getLogger(VpcManagerImpl.class);
@ -158,6 +163,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
@Inject
VpcOfferingDao _vpcOffDao;
@Inject
VpcOfferingJoinDao vpcOfferingJoinDao;
@Inject
VpcOfferingDetailsDao vpcOfferingDetailsDao;
@Inject
VpcOfferingServiceMapDao _vpcOffSvcMapDao;
@ -638,13 +645,23 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
@Override
public Pair<List<? extends VpcOffering>, Integer> listVpcOfferings(final Long id, final String name, final String displayText, final List<String> supportedServicesStr,
final Boolean isDefault, final String keyword, final String state, final Long startIndex, final Long pageSizeVal) {
final Filter searchFilter = new Filter(VpcOfferingVO.class, "created", false, null, null);
final SearchCriteria<VpcOfferingVO> sc = _vpcOffDao.createSearchCriteria();
public Pair<List<? extends VpcOffering>, Integer> listVpcOfferings(ListVPCOfferingsCmd cmd) {
Account caller = CallContext.current().getCallingAccount();
final Long id = cmd.getId();
final String name = cmd.getVpcOffName();
final String displayText = cmd.getDisplayText();
final List<String> supportedServicesStr = cmd.getSupportedServices();
final Boolean isDefault = cmd.getIsDefault();
final String keyword = cmd.getKeyword();
final String state = cmd.getState();
final Long startIndex = cmd.getStartIndex();
final Long pageSizeVal = cmd.getPageSizeVal();
final Long zoneId = cmd.getZoneId();
final Filter searchFilter = new Filter(VpcOfferingJoinVO.class, "created", false, null, null);
final SearchCriteria<VpcOfferingJoinVO> sc = vpcOfferingJoinDao.createSearchCriteria();
if (keyword != null) {
final SearchCriteria<VpcOfferingVO> ssc = _vpcOffDao.createSearchCriteria();
final SearchCriteria<VpcOfferingJoinVO> ssc = vpcOfferingJoinDao.createSearchCriteria();
ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%");
ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
@ -671,13 +688,45 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
sc.addAnd("id", SearchCriteria.Op.EQ, id);
}
final List<VpcOfferingVO> offerings = _vpcOffDao.search(sc, searchFilter);
if (zoneId != null) {
SearchBuilder<VpcOfferingJoinVO> sb = vpcOfferingJoinDao.createSearchBuilder();
sb.and("zoneId", sb.entity().getZoneId(), Op.FIND_IN_SET);
sb.or("zId", sb.entity().getZoneId(), Op.NULL);
sb.done();
SearchCriteria<VpcOfferingJoinVO> zoneSC = sb.create();
zoneSC.setParameters("zoneId", String.valueOf(zoneId));
sc.addAnd("zoneId", SearchCriteria.Op.SC, zoneSC);
}
final List<VpcOfferingJoinVO> offerings = vpcOfferingJoinDao.search(sc, searchFilter);
// Remove offerings that are not associated with caller's domain
// TODO: Better approach
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && CollectionUtils.isNotEmpty(offerings)) {
ListIterator<VpcOfferingJoinVO> it = offerings.listIterator();
while (it.hasNext()) {
VpcOfferingJoinVO offering = it.next();
if(!Strings.isNullOrEmpty(offering.getDomainId())) {
boolean toRemove = true;
String[] domainIdsArray = offering.getDomainId().split(",");
for (String domainIdString : domainIdsArray) {
Long dId = Long.valueOf(domainIdString.trim());
if (domainDao.isChildDomain(dId, caller.getDomainId())) {
toRemove = false;
break;
}
}
if (toRemove) {
it.remove();
}
}
}
}
// filter by supported services
final boolean listBySupportedServices = supportedServicesStr != null && !supportedServicesStr.isEmpty() && !offerings.isEmpty();
if (listBySupportedServices) {
final List<VpcOfferingVO> supportedOfferings = new ArrayList<VpcOfferingVO>();
final List<VpcOfferingJoinVO> supportedOfferings = new ArrayList<>();
Service[] supportedServices = null;
if (listBySupportedServices) {
@ -694,7 +743,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
}
for (final VpcOfferingVO offering : offerings) {
for (final VpcOfferingJoinVO offering : offerings) {
if (areServicesSupportedByVpcOffering(offering.getId(), supportedServices)) {
supportedOfferings.add(offering);
}
@ -702,15 +751,13 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
final List<? extends VpcOffering> wPagination = StringUtils.applyPagination(supportedOfferings, startIndex, pageSizeVal);
if (wPagination != null) {
final Pair<List<? extends VpcOffering>, Integer> listWPagination = new Pair<List<? extends VpcOffering>, Integer>(wPagination, supportedOfferings.size());
return listWPagination;
return new Pair<>(wPagination, supportedOfferings.size());
}
return new Pair<List<? extends VpcOffering>, Integer>(supportedOfferings, supportedOfferings.size());
} else {
final List<? extends VpcOffering> wPagination = StringUtils.applyPagination(offerings, startIndex, pageSizeVal);
if (wPagination != null) {
final Pair<List<? extends VpcOffering>, Integer> listWPagination = new Pair<List<? extends VpcOffering>, Integer>(wPagination, offerings.size());
return listWPagination;
return new Pair<>(wPagination, offerings.size());
}
return new Pair<List<? extends VpcOffering>, Integer>(offerings, offerings.size());
}
@ -874,6 +921,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
// Validate vpc offering
final VpcOfferingVO vpcOff = _vpcOffDao.findById(vpcOffId);
_accountMgr.checkAccess(caller, vpcOff, _dcDao.findById(zoneId));
if (vpcOff == null || vpcOff.getState() != State.Enabled) {
final InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find vpc offering in " + State.Enabled + " state by specified id");
if (vpcOff == null) {

View File

@ -115,6 +115,7 @@ import com.cloud.network.security.SecurityGroupManager;
import com.cloud.network.security.dao.SecurityGroupDao;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcManager;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.network.vpn.RemoteAccessVpnService;
import com.cloud.network.vpn.Site2SiteVpnManager;
import com.cloud.offering.DiskOffering;
@ -2875,6 +2876,21 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + nof);
}
@Override
public void checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException {
for (SecurityChecker checker : _securityCheckers) {
if (checker.checkAccess(account, vof, zone)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Access granted to " + account + " to " + vof + " by " + checker.getName());
}
return;
}
}
assert false : "How can all of the security checkers pass on checking this caller?";
throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + vof);
}
@Override
public void checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException {
for (SecurityChecker checker : _securityCheckers) {

View File

@ -41,6 +41,7 @@ import com.cloud.domain.Domain;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
@ -228,6 +229,11 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco
// TODO Auto-generated method stub
}
@Override
public void checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException {
// TODO Auto-generated method stub
}
@Override
public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) {
// TODO Auto-generated method stub