Skip to content

Commit bf30cba

Browse files
server: do not NPE when a VPN provider returns no per-user result
applyVpnUsers sizes a Boolean[] finals to the user list but only populates it inside the if (results != null) block. A RemoteAccessVPNServiceProvider that returns null (for example when the VPN network has no router yet) leaves entries null, and the later consumption loop unboxed them with if (finals[i]), throwing NullPointerException and aborting the entire apply/add/remove-user operation. Treat a null entry as not-applied with Boolean.TRUE.equals.
1 parent 2cd8c5e commit bf30cba

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

server/src/main/java/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ public boolean applyVpnUsers(long vpnOwnerId, String userName, boolean forRemove
603603

604604
for (int i = 0; i < finals.length; i++) {
605605
final VpnUserVO user = users.get(i);
606-
if (finals[i]) {
606+
if (Boolean.TRUE.equals(finals[i])) {
607607
if (user.getState() == State.Add) {
608608
user.setState(State.Active);
609609
_vpnUsersDao.update(user.getId(), user);

server/src/test/java/com/cloud/network/vpn/RemoteAccessVpnManagerImplTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,23 @@
1515
package com.cloud.network.vpn;
1616

1717
import com.cloud.exception.InvalidParameterValueException;
18+
import com.cloud.network.VpnUser.State;
19+
import com.cloud.network.VpnUserVO;
20+
import com.cloud.network.dao.RemoteAccessVpnDao;
21+
import com.cloud.network.dao.RemoteAccessVpnVO;
22+
import com.cloud.network.dao.VpnUserDao;
23+
import com.cloud.network.element.RemoteAccessVPNServiceProvider;
24+
import com.cloud.user.Account;
25+
import com.cloud.user.AccountManager;
26+
import com.cloud.user.AccountVO;
27+
import com.cloud.user.dao.AccountDao;
1828
import com.cloud.utils.exception.CloudRuntimeException;
1929
import com.cloud.utils.net.NetUtils;
2030
import junit.framework.TestCase;
31+
import org.apache.cloudstack.context.CallContext;
32+
import org.springframework.test.util.ReflectionTestUtils;
33+
34+
import java.util.Collections;
2135
import org.junit.Assert;
2236
import org.junit.Test;
2337
import org.junit.runner.RunWith;
@@ -222,4 +236,40 @@ public void validateHandleExceptionOnValidateIpRangeErrorWhenInvalidParameterVal
222236

223237
assertEquals(expectedMessage, assertThrows.getMessage());
224238
}
239+
240+
@Test
241+
public void applyVpnUsersHandlesNullProviderResultWithoutNpe() throws Exception {
242+
RemoteAccessVpnManagerImpl mgr = new RemoteAccessVpnManagerImpl();
243+
244+
AccountDao accountDao = Mockito.mock(AccountDao.class);
245+
AccountManager accountMgr = Mockito.mock(AccountManager.class);
246+
VpnUserDao vpnUsersDao = Mockito.mock(VpnUserDao.class);
247+
RemoteAccessVpnDao remoteAccessVpnDao = Mockito.mock(RemoteAccessVpnDao.class);
248+
RemoteAccessVPNServiceProvider provider = Mockito.mock(RemoteAccessVPNServiceProvider.class);
249+
ReflectionTestUtils.setField(mgr, "_accountDao", accountDao);
250+
ReflectionTestUtils.setField(mgr, "_accountMgr", accountMgr);
251+
ReflectionTestUtils.setField(mgr, "_vpnUsersDao", vpnUsersDao);
252+
ReflectionTestUtils.setField(mgr, "_remoteAccessVpnDao", remoteAccessVpnDao);
253+
ReflectionTestUtils.setField(mgr, "_vpnServiceProviders", Collections.singletonList(provider));
254+
255+
Mockito.when(accountDao.findById(1L)).thenReturn(Mockito.mock(AccountVO.class));
256+
257+
RemoteAccessVpnVO vpn = Mockito.mock(RemoteAccessVpnVO.class);
258+
Mockito.when(vpn.getNetworkId()).thenReturn(null);
259+
Mockito.when(remoteAccessVpnDao.findByAccount(1L)).thenReturn(Collections.singletonList(vpn));
260+
261+
VpnUserVO user = Mockito.mock(VpnUserVO.class);
262+
Mockito.when(user.getState()).thenReturn(State.Revoke);
263+
Mockito.when(vpnUsersDao.listByAccount(1L)).thenReturn(Collections.singletonList(user));
264+
265+
Mockito.when(provider.applyVpnUsers(Mockito.eq(vpn), Mockito.anyList())).thenReturn(null);
266+
267+
try (MockedStatic<CallContext> callContextMock = Mockito.mockStatic(CallContext.class)) {
268+
CallContext callContext = Mockito.mock(CallContext.class);
269+
callContextMock.when(CallContext::current).thenReturn(callContext);
270+
Mockito.when(callContext.getCallingAccount()).thenReturn(Mockito.mock(Account.class));
271+
272+
Assert.assertTrue(mgr.applyVpnUsers(1L, "someuser", false));
273+
}
274+
}
225275
}

0 commit comments

Comments
 (0)