extensions: custom action entity access

This commit is contained in:
Abhishek Kumar 2025-10-17 12:40:23 +05:30 committed by Harikrishna Patnala
parent e7a55a766c
commit d8766418e0
2 changed files with 38 additions and 0 deletions

View File

@ -129,6 +129,7 @@ import com.cloud.org.Cluster;
import com.cloud.serializer.GsonHelper;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
import com.cloud.user.AccountService;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.component.PluggableService;
@ -212,6 +213,9 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
@Inject
RoleService roleService;
@Inject
AccountService accountService;
private ScheduledExecutorService extensionPathStateCheckExecutor;
protected String getDefaultExtensionRelativePath(String name) {
@ -1354,6 +1358,7 @@ public class ExtensionsManagerImpl extends ManagerBase implements ExtensionsMana
clusterId = host.getClusterId();
} else if (entity instanceof VirtualMachine) {
VirtualMachine virtualMachine = (VirtualMachine)entity;
accountService.checkAccess(caller, null, true, virtualMachine);
if (!Hypervisor.HypervisorType.External.equals(virtualMachine.getHypervisorType())) {
logger.error("Invalid {} specified as VM resource for running {}", entity, customActionVO);
throw new InvalidParameterValueException(error);

View File

@ -49,6 +49,8 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.user.AccountService;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.acl.RoleType;
@ -176,6 +178,8 @@ public class ExtensionsManagerImplTest {
private VMTemplateDao templateDao;
@Mock
private RoleService roleService;
@Mock
private AccountService accountService;
@Before
public void setUp() {
@ -1640,6 +1644,35 @@ public class ExtensionsManagerImplTest {
}
}
@Test(expected = PermissionDeniedException.class)
public void runCustomAction_CheckAccessThrowsException() throws Exception {
RunCustomActionCmd cmd = mock(RunCustomActionCmd.class);
when(cmd.getCustomActionId()).thenReturn(1L);
when(cmd.getResourceId()).thenReturn("vm-123");
when(cmd.getParameters()).thenReturn(Map.of("param1", "value1"));
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
when(extensionCustomActionDao.findById(1L)).thenReturn(actionVO);
when(actionVO.isEnabled()).thenReturn(true);
when(actionVO.getResourceType()).thenReturn(ExtensionCustomAction.ResourceType.VirtualMachine);
when(actionVO.getAllowedRoleTypes()).thenReturn(RoleType.toCombinedMask(List.of(RoleType.Admin, RoleType.DomainAdmin, RoleType.User)));
ExtensionVO extensionVO = mock(ExtensionVO.class);
when(extensionDao.findById(anyLong())).thenReturn(extensionVO);
when(extensionVO.getState()).thenReturn(Extension.State.Enabled);
VirtualMachine vm = mock(VirtualMachine.class);
when(entityManager.findByUuid(eq(VirtualMachine.class), anyString())).thenReturn(vm);
doThrow(PermissionDeniedException.class).when(accountService).checkAccess(any(Account.class), eq(null), eq(true), eq(vm));
try (MockedStatic<CallContext> ignored = mockStatic(CallContext.class)) {
mockCallerRole(RoleType.User);
CustomActionResultResponse result = extensionsManager.runCustomAction(cmd);
assertFalse(result.getSuccess());
}
}
@Test
public void createCustomActionResponse_SetsBasicFields() {
ExtensionCustomAction action = mock(ExtensionCustomAction.class);