From c8d44d92a76efe6dd197128dab8faf5f0f8ac85b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 17 Sep 2025 02:34:31 +0530 Subject: [PATCH] api,server: fix entity access Added access check for: - createNetworkACL - listNetworkACLs - listResourceDetails - listVirtualMachinesUsageHistory - listVolumesUsageHistory Signed-off-by: Abhishek Kumar --- .../com/cloud/server/ResourceManagerUtil.java | 1 + .../metrics/MetricsServiceImpl.java | 76 ++++++++- .../metrics/MetricsServiceImplTest.java | 155 +++++++++++++++--- .../com/cloud/api/query/QueryManagerImpl.java | 2 +- .../network/vpc/NetworkACLServiceImpl.java | 3 + .../cloud/tags/ResourceManagerUtilImpl.java | 11 ++ 6 files changed, 217 insertions(+), 31 deletions(-) diff --git a/api/src/main/java/com/cloud/server/ResourceManagerUtil.java b/api/src/main/java/com/cloud/server/ResourceManagerUtil.java index 9a3b51a70d5..f5081cbe307 100644 --- a/api/src/main/java/com/cloud/server/ResourceManagerUtil.java +++ b/api/src/main/java/com/cloud/server/ResourceManagerUtil.java @@ -18,6 +18,7 @@ package com.cloud.server; public interface ResourceManagerUtil { long getResourceId(String resourceId, ResourceTag.ResourceObjectType resourceType); + long getResourceId(String resourceId, ResourceTag.ResourceObjectType resourceType, boolean checkAccess); String getUuid(String resourceId, ResourceTag.ResourceObjectType resourceType); ResourceTag.ResourceObjectType getResourceType(String resourceTypeStr); void checkResourceAccessible(Long accountId, Long domainId, String exceptionMessage); diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index 0ef094d3d4e..c305d9312ba 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -22,6 +22,7 @@ import static com.cloud.utils.NumbersUtil.toReadableSize; import java.lang.reflect.InvocationTargetException; import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -32,8 +33,6 @@ import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.dc.ClusterVO; -import com.cloud.utils.Ternary; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ListClustersMetricsCmd; import org.apache.cloudstack.api.ListDbMetricsCmd; @@ -100,6 +99,7 @@ import com.cloud.capacity.CapacityManager; import com.cloud.capacity.dao.CapacityDao; import com.cloud.capacity.dao.CapacityDaoImpl; import com.cloud.cluster.dao.ManagementServerHostDao; +import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenter; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; @@ -112,6 +112,7 @@ import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.network.router.VirtualRouter; import com.cloud.org.Cluster; +import com.cloud.projects.Project; import com.cloud.server.DbStatsCollection; import com.cloud.server.ManagementServerHostStats; import com.cloud.server.StatsCollector; @@ -124,6 +125,7 @@ import com.cloud.usage.dao.UsageJobDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; import com.cloud.utils.db.DbProperties; import com.cloud.utils.db.DbUtil; import com.cloud.utils.db.Filter; @@ -184,6 +186,10 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements private static Gson gson = new Gson(); + private final List AccountTypesWithRecursiveUsageAccess = Arrays.asList( + Account.Type.ADMIN, Account.Type.DOMAIN_ADMIN, Account.Type.READ_ONLY_ADMIN + ); + protected MetricsServiceImpl() { super(); } @@ -245,17 +251,30 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements * @return the list of VMs. */ protected Pair, Integer> searchForUserVmsInternal(ListVMsUsageHistoryCmd cmd) { + final Long id = cmd.getId(); + Account caller = CallContext.current().getCallingAccount(); + List permittedAccounts = new ArrayList<>(); + boolean recursive = AccountTypesWithRecursiveUsageAccess.contains(caller.getType()); + Ternary domainIdRecursiveListProject = new Ternary<>(null, recursive, null); + accountMgr.buildACLSearchParameters(caller, id, null, null, permittedAccounts, domainIdRecursiveListProject, true, false); + Long domainId = domainIdRecursiveListProject.first(); + Boolean isRecursive = domainIdRecursiveListProject.second(); + Project.ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + Filter searchFilter = new Filter(UserVmVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); String name = cmd.getName(); String keyword = cmd.getKeyword(); SearchBuilder sb = userVmDao.createSearchBuilder(); + sb.select(null, SearchCriteria.Func.DISTINCT, sb.entity().getId()); // select distinct + accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN); sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); SearchCriteria sc = sb.create(); + accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); if (CollectionUtils.isNotEmpty(ids)) { sc.setParameters("idIN", ids.toArray()); } @@ -269,7 +288,14 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements sc.addAnd("displayName", SearchCriteria.Op.SC, ssc); } - return userVmDao.searchAndCount(sc, searchFilter); + Pair, Integer> uniqueVmPair = userVmDao.searchAndCount(sc, searchFilter); + Integer count = uniqueVmPair.second(); + if (count == 0) { + return new Pair<>(new ArrayList<>(), count); + } + List vmIds = uniqueVmPair.first().stream().map(UserVmVO::getId).collect(Collectors.toList()); + List vms = userVmDao.listByIds(vmIds); + return new Pair<>(vms, count); } /** @@ -331,17 +357,49 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements * @return the list of VMs. */ protected Pair, Integer> searchForVolumesInternal(ListVolumesUsageHistoryCmd cmd) { + final Long id = cmd.getId(); + Account caller = CallContext.current().getCallingAccount(); + List permittedAccounts = new ArrayList<>(); + boolean recursive = AccountTypesWithRecursiveUsageAccess.contains(caller.getType()); + Ternary domainIdRecursiveListProject = new Ternary<>(null, recursive, null); + accountMgr.buildACLSearchParameters(caller, id, null, null, permittedAccounts, domainIdRecursiveListProject, true, false); + Long domainId = domainIdRecursiveListProject.first(); + Boolean isRecursive = domainIdRecursiveListProject.second(); + Project.ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + Filter searchFilter = new Filter(VolumeVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); String name = cmd.getName(); String keyword = cmd.getKeyword(); SearchBuilder sb = volumeDao.createSearchBuilder(); + sb.select(null, SearchCriteria.Func.DISTINCT, sb.entity().getId()); // select distinct + accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); sb.and("idIN", sb.entity().getId(), SearchCriteria.Op.IN); sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); + boolean shouldListSystemVmVolumes = accountMgr.isRootAdmin(CallContext.current().getCallingAccountId()); + List vmIds = new ArrayList<>(); + if (!shouldListSystemVmVolumes) { + SearchBuilder vmSearch = userVmDao.createSearchBuilder(); + vmSearch.select(null, SearchCriteria.Func.DISTINCT, vmSearch.entity().getId()); + accountMgr.buildACLSearchBuilder(vmSearch, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + SearchCriteria vmSc = vmSearch.create(); + accountMgr.buildACLSearchCriteria(vmSc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + List vms = userVmDao.search(vmSc, null); + vmIds = vms.stream().map(UserVmVO::getId).collect(Collectors.toList()); + if (vmIds.isEmpty()) { + sb.and("instanceIdNull", sb.entity().getInstanceId(), SearchCriteria.Op.NULL); + } else { + sb.and().op("instanceIdNull", sb.entity().getInstanceId(), SearchCriteria.Op.NULL); + sb.or("instanceIds", sb.entity().getInstanceId(), SearchCriteria.Op.IN); + sb.cp(); + } + } + SearchCriteria sc = sb.create(); + accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); if (CollectionUtils.isNotEmpty(ids)) { sc.setParameters("idIN", ids.toArray()); } @@ -354,8 +412,18 @@ public class MetricsServiceImpl extends MutualExclusiveIdsManagerBase implements ssc.addOr("state", SearchCriteria.Op.EQ, keyword); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } + if (!shouldListSystemVmVolumes && CollectionUtils.isNotEmpty(vmIds)) { + sc.setParameters("instanceIds", vmIds.toArray()); + } - return volumeDao.searchAndCount(sc, searchFilter); + Pair, Integer> uniqueVolumePair = volumeDao.searchAndCount(sc, searchFilter); + Integer count = uniqueVolumePair.second(); + if (count == 0) { + return new Pair<>(new ArrayList<>(), count); + } + List volumeIds = uniqueVolumePair.first().stream().map(VolumeVO::getId).collect(Collectors.toList()); + List volumes = volumeDao.listByIds(volumeIds); + return new Pair<>(volumes, count); } /** diff --git a/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java b/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java index b37be68b3e4..9184d744410 100644 --- a/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java +++ b/plugins/metrics/src/test/java/org/apache/cloudstack/metrics/MetricsServiceImplTest.java @@ -19,13 +19,16 @@ package org.apache.cloudstack.metrics; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.cloudstack.api.ListVMsUsageHistoryCmd; +import org.apache.cloudstack.api.ListVolumesUsageHistoryCmd; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.response.VmMetricsStatsResponse; import org.apache.commons.lang3.time.DateUtils; import org.junit.Assert; @@ -35,12 +38,18 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; import com.cloud.utils.Pair; +import com.cloud.utils.db.Filter; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.vm.UserVmVO; @@ -75,6 +84,12 @@ public class MetricsServiceImplTest { @Mock VmStatsDao vmStatsDaoMock; + @Mock + AccountManager accountManager; + + @Mock + VolumeDao volumeDao; + @Captor ArgumentCaptor stringCaptor1, stringCaptor2; @@ -95,12 +110,26 @@ public class MetricsServiceImplTest { @Mock VmStatsVO vmStatsVOMock; + @Mock + Account mockAccount; + @Mock + ListVolumesUsageHistoryCmd listVolumesUsageHistoryCmdMock; + @Mock + VolumeVO volumeVOMock; + @Mock + SearchBuilder volumeSearchBuilderMock; + @Mock + SearchCriteria volumeSearchCriteriaMock; + @Mock + Filter filterMock; + private void prepareSearchCriteriaWhenUseSetParameters() { Mockito.doNothing().when(scMock).setParameters(Mockito.anyString(), Mockito.any()); } private void preparesearchForUserVmsInternalTest() { + Mockito.when(mockAccount.getType()).thenReturn(Account.Type.NORMAL); expectedVmListAndCounter = new Pair<>(Arrays.asList(userVmVOMock), 1); Mockito.doReturn(1L).when(listVMsUsageHistoryCmdMock).getStartIndex(); @@ -111,8 +140,10 @@ public class MetricsServiceImplTest { Mockito.doReturn(userVmVOMock).when(sbMock).entity(); Mockito.doReturn(scMock).when(sbMock).create(); - Mockito.doReturn(new Pair, Integer>(Arrays.asList(userVmVOMock), 1)) + Mockito.doReturn(expectedVmListAndCounter) .when(userVmDaoMock).searchAndCount(Mockito.any(), Mockito.any()); + Mockito.doReturn(expectedVmListAndCounter.first()) + .when(userVmDaoMock).listByIds(Mockito.anyList()); } @Test @@ -124,12 +155,17 @@ public class MetricsServiceImplTest { Mockito.doReturn(null).when(listVMsUsageHistoryCmdMock).getName(); Mockito.doReturn(null).when(listVMsUsageHistoryCmdMock).getKeyword(); - Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(mockAccount); + Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); - Mockito.verify(scMock).setParameters(stringCaptor1.capture(), objectArrayCaptor.capture()); - Assert.assertEquals("idIN", stringCaptor1.getValue()); - Assert.assertEquals(fakeVmId1, objectArrayCaptor.getAllValues().get(0)[0]); - Assert.assertEquals(expectedVmListAndCounter, result); + Mockito.verify(scMock).setParameters(stringCaptor1.capture(), objectArrayCaptor.capture()); + Assert.assertEquals("idIN", stringCaptor1.getValue()); + Assert.assertEquals(fakeVmId1, objectArrayCaptor.getAllValues().get(0)[0]); + Assert.assertEquals(expectedVmListAndCounter, result); + } } @Test @@ -141,13 +177,17 @@ public class MetricsServiceImplTest { Mockito.doReturn(expected).when(listVMsUsageHistoryCmdMock).getIds(); Mockito.doReturn(null).when(listVMsUsageHistoryCmdMock).getName(); Mockito.doReturn(null).when(listVMsUsageHistoryCmdMock).getKeyword(); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(mockAccount); + Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); - Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); - - Mockito.verify(scMock).setParameters(stringCaptor1.capture(), objectArrayCaptor.capture()); - Assert.assertEquals("idIN", stringCaptor1.getValue()); - Assert.assertArrayEquals(expected.toArray(), objectArrayCaptor.getAllValues().get(0)); - Assert.assertEquals(expectedVmListAndCounter, result); + Mockito.verify(scMock).setParameters(stringCaptor1.capture(), objectArrayCaptor.capture()); + Assert.assertEquals("idIN", stringCaptor1.getValue()); + Assert.assertArrayEquals(expected.toArray(), objectArrayCaptor.getAllValues().get(0)); + Assert.assertEquals(expectedVmListAndCounter, result); + } } @Test @@ -159,12 +199,17 @@ public class MetricsServiceImplTest { Mockito.doReturn("fakeName").when(listVMsUsageHistoryCmdMock).getName(); Mockito.doReturn(null).when(listVMsUsageHistoryCmdMock).getKeyword(); - Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(mockAccount); + Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); - Mockito.verify(scMock).setParameters(stringCaptor1.capture(), objectArrayCaptor.capture()); - Assert.assertEquals("displayName", stringCaptor1.getValue()); - Assert.assertEquals("%fakeName%", objectArrayCaptor.getValue()[0]); - Assert.assertEquals(expectedVmListAndCounter, result); + Mockito.verify(scMock).setParameters(stringCaptor1.capture(), objectArrayCaptor.capture()); + Assert.assertEquals("displayName", stringCaptor1.getValue()); + Assert.assertEquals("%fakeName%", objectArrayCaptor.getValue()[0]); + Assert.assertEquals(expectedVmListAndCounter, result); + } } @Test @@ -177,16 +222,21 @@ public class MetricsServiceImplTest { Mockito.doReturn(null).when(listVMsUsageHistoryCmdMock).getName(); Mockito.doReturn("fakeKeyword").when(listVMsUsageHistoryCmdMock).getKeyword(); - Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(mockAccount); + Pair, Integer> result = spy.searchForUserVmsInternal(listVMsUsageHistoryCmdMock); - Mockito.verify(scMock, Mockito.times(2)).addOr(stringCaptor1.capture(), opCaptor.capture(), objectArrayCaptor.capture()); - List conditions = stringCaptor1.getAllValues(); - List params = objectArrayCaptor.getAllValues(); - Assert.assertEquals("displayName", conditions.get(0)); - Assert.assertEquals("state", conditions.get(1)); - Assert.assertEquals("%fakeKeyword%", params.get(0)[0]); - Assert.assertEquals("fakeKeyword", params.get(1)[0]); - Assert.assertEquals(expectedVmListAndCounter, result); + Mockito.verify(scMock, Mockito.times(2)).addOr(stringCaptor1.capture(), opCaptor.capture(), objectArrayCaptor.capture()); + List conditions = stringCaptor1.getAllValues(); + List params = objectArrayCaptor.getAllValues(); + Assert.assertEquals("displayName", conditions.get(0)); + Assert.assertEquals("state", conditions.get(1)); + Assert.assertEquals("%fakeKeyword%", params.get(0)[0]); + Assert.assertEquals("fakeKeyword", params.get(1)[0]); + Assert.assertEquals(expectedVmListAndCounter, result); + } } @Test @@ -317,4 +367,57 @@ public class MetricsServiceImplTest { spy.createStatsResponse(Arrays.asList(vmStatsVOMock)); } + + @Test + public void searchForVolumesInternalWithValidParameters() { + Mockito.doReturn(null).when(listVolumesUsageHistoryCmdMock).getId(); + Mockito.doReturn(Arrays.asList(1L, 2L)).when(listVolumesUsageHistoryCmdMock).getIds(); + Mockito.doReturn("volumeName").when(listVolumesUsageHistoryCmdMock).getName(); + Mockito.doReturn("keyword").when(listVolumesUsageHistoryCmdMock).getKeyword(); + Mockito.doReturn(volumeSearchBuilderMock).when(volumeDao).createSearchBuilder(); + Mockito.doReturn(volumeVOMock).when(volumeSearchBuilderMock).entity(); + SearchBuilder vmSearchBuilderMock = Mockito.mock(SearchBuilder.class); + Mockito.doReturn(vmSearchBuilderMock).when(userVmDaoMock).createSearchBuilder(); + Mockito.doReturn(userVmVOMock).when(vmSearchBuilderMock).entity(); + Mockito.doReturn(volumeSearchCriteriaMock).when(volumeSearchBuilderMock).create(); + Mockito.doReturn(volumeSearchCriteriaMock).when(volumeDao).createSearchCriteria(); + Mockito.doReturn(new Pair<>(Arrays.asList(volumeVOMock), 1)).when(volumeDao).searchAndCount(Mockito.any(), Mockito.any()); + Mockito.doReturn(Arrays.asList(volumeVOMock)).when(volumeDao).listByIds(Mockito.anyList()); + + + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(mockAccount); + Pair, Integer> result = spy.searchForVolumesInternal(listVolumesUsageHistoryCmdMock); + + Assert.assertNotNull(result); + Assert.assertEquals(1, result.second().intValue()); + Assert.assertEquals(volumeVOMock, result.first().get(0)); + } + } + + @Test + public void searchForVolumesInternalWithValidParametersNoItem() { + Mockito.doReturn(1L).when(listVolumesUsageHistoryCmdMock).getId(); + Mockito.doReturn(volumeSearchBuilderMock).when(volumeDao).createSearchBuilder(); + Mockito.doReturn(volumeVOMock).when(volumeSearchBuilderMock).entity(); + Mockito.doReturn(volumeSearchCriteriaMock).when(volumeSearchBuilderMock).create(); + Mockito.doReturn(new Pair<>(Collections.emptyList(), 0)).when(volumeDao).searchAndCount(Mockito.any(), Mockito.any()); + + + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(mockAccount); + Mockito.when(callContextMock.getCallingAccountId()).thenReturn(1L); + Mockito.when(accountManager.isRootAdmin(1L)).thenReturn(true); + Mockito.when(mockAccount.getType()).thenReturn(Account.Type.ADMIN); + Pair, Integer> result = spy.searchForVolumesInternal(listVolumesUsageHistoryCmdMock); + + Assert.assertNotNull(result); + Assert.assertEquals(0, result.second().intValue()); + } + } + } diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 6fb9ab515cb..6ed2fed9cb6 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -5335,7 +5335,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q //Validation - 1.3 if (resourceIdStr != null) { - resourceId = resourceManagerUtil.getResourceId(resourceIdStr, resourceType); + resourceId = resourceManagerUtil.getResourceId(resourceIdStr, resourceType, true); } List detailList = new ArrayList<>(); diff --git a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java index 0791ca7ecd3..f99ea6b9b8c 100644 --- a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -483,6 +483,8 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ throw new InvalidParameterValueException("Cannot create Network ACL Item. ACL Id or network Id is required"); } Network network = networkModel.getNetwork(createNetworkACLCmd.getNetworkId()); + Account caller = CallContext.current().getCallingAccount(); + _accountMgr.checkAccess(caller, null, true, network); if (network.getVpcId() == null) { throw new InvalidParameterValueException("Network: " + network.getUuid() + " does not belong to VPC"); } @@ -744,6 +746,7 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ if (networkId != null) { final Network network = _networkDao.findById(networkId); + _accountMgr.checkAccess(caller, null, true, network); aclId = network.getNetworkACLId(); if (aclId == null) { // No aclId associated with the network. diff --git a/server/src/main/java/com/cloud/tags/ResourceManagerUtilImpl.java b/server/src/main/java/com/cloud/tags/ResourceManagerUtilImpl.java index c02f4136863..82d69992cdf 100644 --- a/server/src/main/java/com/cloud/tags/ResourceManagerUtilImpl.java +++ b/server/src/main/java/com/cloud/tags/ResourceManagerUtilImpl.java @@ -22,6 +22,7 @@ import java.util.Objects; import javax.inject.Inject; +import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.context.CallContext; @@ -128,6 +129,11 @@ public class ResourceManagerUtilImpl implements ResourceManagerUtil { @Override public long getResourceId(String resourceId, ResourceTag.ResourceObjectType resourceType) { + return getResourceId(resourceId, resourceType, false); + } + + @Override + public long getResourceId(String resourceId, ResourceTag.ResourceObjectType resourceType, boolean checkAccess) { Class clazz = s_typeMap.get(resourceType); Object entity = entityMgr.findByUuid(clazz, resourceId); if (entity != null) { @@ -138,6 +144,11 @@ public class ResourceManagerUtilImpl implements ResourceManagerUtil { } entity = entityMgr.findById(clazz, resourceId); if (entity != null) { + if (checkAccess && entity instanceof ControlledEntity) { + ControlledEntity controlledEntity = (ControlledEntity)entity; + Account caller = CallContext.current().getCallingAccount(); + accountMgr.checkAccess(caller, null, false, controlledEntity); + } return ((InternalIdentity)entity).getId(); } throw new InvalidParameterValueException("Unable to find resource by id " + resourceId + " and type " + resourceType);