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

View File

@ -49,6 +49,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; 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.Role;
import org.apache.cloudstack.acl.RoleService; import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.RoleType;
@ -176,6 +178,8 @@ public class ExtensionsManagerImplTest {
private VMTemplateDao templateDao; private VMTemplateDao templateDao;
@Mock @Mock
private RoleService roleService; private RoleService roleService;
@Mock
private AccountService accountService;
@Before @Before
public void setUp() { 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 @Test
public void createCustomActionResponse_SetsBasicFields() { public void createCustomActionResponse_SetsBasicFields() {
ExtensionCustomAction action = mock(ExtensionCustomAction.class); ExtensionCustomAction action = mock(ExtensionCustomAction.class);