mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fix deleteUser API to prevent deletion of the caller (#8691)
Co-authored-by: Lucas Martins <lucas.martins@scclouds.com.br>
This commit is contained in:
parent
d171582163
commit
c8a4575bcd
@ -84,11 +84,10 @@ public class DeleteUserCmd extends BaseCmd {
|
|||||||
public void execute() {
|
public void execute() {
|
||||||
CallContext.current().setEventDetails("UserId: " + getId());
|
CallContext.current().setEventDetails("UserId: " + getId());
|
||||||
boolean result = _regionService.deleteUser(this);
|
boolean result = _regionService.deleteUser(this);
|
||||||
if (result) {
|
if (!result) {
|
||||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
|
||||||
this.setResponseObject(response);
|
|
||||||
} else {
|
|
||||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete user");
|
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete user");
|
||||||
}
|
}
|
||||||
|
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||||
|
this.setResponseObject(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2064,13 +2064,20 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
@Override
|
@Override
|
||||||
@ActionEvent(eventType = EventTypes.EVENT_USER_DELETE, eventDescription = "deleting User")
|
@ActionEvent(eventType = EventTypes.EVENT_USER_DELETE, eventDescription = "deleting User")
|
||||||
public boolean deleteUser(DeleteUserCmd deleteUserCmd) {
|
public boolean deleteUser(DeleteUserCmd deleteUserCmd) {
|
||||||
UserVO user = getValidUserVO(deleteUserCmd.getId());
|
final Long id = deleteUserCmd.getId();
|
||||||
|
User caller = CallContext.current().getCallingUser();
|
||||||
|
UserVO user = getValidUserVO(id);
|
||||||
Account account = _accountDao.findById(user.getAccountId());
|
Account account = _accountDao.findById(user.getAccountId());
|
||||||
|
|
||||||
|
if (caller.getId() == id) {
|
||||||
|
Domain domain = _domainDao.findById(account.getDomainId());
|
||||||
|
throw new InvalidParameterValueException(String.format("The caller is requesting to delete itself. As a security measure, ACS will not allow this operation." +
|
||||||
|
" To delete user %s (ID: %s, Domain: %s), request to another user with permission to execute the operation.", user.getUsername(), user.getUuid(), domain.getUuid()));
|
||||||
|
}
|
||||||
|
|
||||||
// don't allow to delete the user from the account of type Project
|
// don't allow to delete the user from the account of type Project
|
||||||
checkAccountAndAccess(user, account);
|
checkAccountAndAccess(user, account);
|
||||||
return _userDao.remove(deleteUserCmd.getId());
|
return _userDao.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2145,7 +2152,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAccountAndAccess(UserVO user, Account account) {
|
protected void checkAccountAndAccess(UserVO user, Account account) {
|
||||||
// don't allow to delete the user from the account of type Project
|
// don't allow to delete the user from the account of type Project
|
||||||
if (account.getType() == Account.Type.PROJECT) {
|
if (account.getType() == Account.Type.PROJECT) {
|
||||||
throw new InvalidParameterValueException("Project users cannot be deleted or moved.");
|
throw new InvalidParameterValueException("Project users cannot be deleted or moved.");
|
||||||
@ -2155,7 +2162,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||||||
CallContext.current().putContextParameter(User.class, user.getUuid());
|
CallContext.current().putContextParameter(User.class, user.getUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserVO getValidUserVO(long id) {
|
protected UserVO getValidUserVO(long id) {
|
||||||
UserVO user = _userDao.findById(id);
|
UserVO user = _userDao.findById(id);
|
||||||
|
|
||||||
if (user == null || user.getRemoved() != null) {
|
if (user == null || user.getRemoved() != null) {
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import com.cloud.vm.UserVmVO;
|
|||||||
import com.cloud.vm.VMInstanceVO;
|
import com.cloud.vm.VMInstanceVO;
|
||||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||||
|
import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
|
||||||
import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
|
import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
|
||||||
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
|
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
|
||||||
import org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupResponse;
|
import org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupResponse;
|
||||||
@ -48,6 +49,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockedStatic;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
@ -91,6 +93,12 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
@Mock
|
@Mock
|
||||||
private Account accountMock;
|
private Account accountMock;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DomainVO domainVoMock;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AccountVO accountVoMock;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ProjectAccountVO projectAccountVO;
|
private ProjectAccountVO projectAccountVO;
|
||||||
@Mock
|
@Mock
|
||||||
@ -190,6 +198,42 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||||||
Mockito.verify(_accountDao, Mockito.atLeastOnce()).markForCleanup(Mockito.eq(42l));
|
Mockito.verify(_accountDao, Mockito.atLeastOnce()).markForCleanup(Mockito.eq(42l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test (expected = InvalidParameterValueException.class)
|
||||||
|
public void deleteUserTestIfUserIdIsEqualToCallerIdShouldThrowException() {
|
||||||
|
try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
|
||||||
|
DeleteUserCmd cmd = Mockito.mock(DeleteUserCmd.class);
|
||||||
|
CallContext callContextMock = Mockito.mock(CallContext.class);
|
||||||
|
callContextMocked.when(CallContext::current).thenReturn(callContextMock);
|
||||||
|
|
||||||
|
Mockito.doReturn(userVoMock).when(callContextMock).getCallingUser();
|
||||||
|
Mockito.doReturn(1L).when(cmd).getId();
|
||||||
|
Mockito.doReturn(userVoMock).when(accountManagerImpl).getValidUserVO(Mockito.anyLong());
|
||||||
|
Mockito.doReturn(accountVoMock).when(_accountDao).findById(Mockito.anyLong());
|
||||||
|
Mockito.doReturn(domainVoMock).when(_domainDao).findById(Mockito.anyLong());
|
||||||
|
Mockito.doReturn(1L).when(userVoMock).getId();
|
||||||
|
|
||||||
|
accountManagerImpl.deleteUser(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deleteUserTestIfUserIdIsNotEqualToCallerIdShouldNotThrowException() {
|
||||||
|
try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
|
||||||
|
DeleteUserCmd cmd = Mockito.mock(DeleteUserCmd.class);
|
||||||
|
CallContext callContextMock = Mockito.mock(CallContext.class);
|
||||||
|
callContextMocked.when(CallContext::current).thenReturn(callContextMock);
|
||||||
|
|
||||||
|
Mockito.doReturn(userVoMock).when(callContextMock).getCallingUser();
|
||||||
|
Mockito.doReturn(1L).when(cmd).getId();
|
||||||
|
Mockito.doReturn(userVoMock).when(accountManagerImpl).getValidUserVO(Mockito.anyLong());
|
||||||
|
Mockito.doReturn(accountVoMock).when(_accountDao).findById(Mockito.anyLong());
|
||||||
|
Mockito.doReturn(2L).when(userVoMock).getId();
|
||||||
|
|
||||||
|
Mockito.doNothing().when(accountManagerImpl).checkAccountAndAccess(Mockito.any(), Mockito.any());
|
||||||
|
accountManagerImpl.deleteUser(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthenticateUser() throws UnknownHostException {
|
public void testAuthenticateUser() throws UnknownHostException {
|
||||||
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> successAuthenticationPair = new Pair<>(true, null);
|
Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> successAuthenticationPair = new Pair<>(true, null);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user