Enforce user limit on number of vpn users

This commit is contained in:
Chiradeep Vittal 2010-11-18 18:38:13 -08:00
parent 8e4f05075b
commit 394554770e
6 changed files with 59 additions and 17 deletions

View File

@ -25,5 +25,6 @@ import com.cloud.utils.db.GenericDao;
public interface VpnUserDao extends GenericDao<VpnUserVO, Long> {
List<VpnUserVO> listByAccount(Long accountId);
VpnUserVO findByAccountAndUsername(Long acccountId, String userName);
VpnUserVO findByAccountAndUsername(Long acccountId, String userName);
long getVpnUserCount(Long accountId);
}

View File

@ -24,13 +24,16 @@ import javax.ejb.Local;
import com.cloud.network.VpnUserVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Func;
@Local(value={VpnUserDao.class})
public class VpnUserDaoImpl extends GenericDaoBase<VpnUserVO, Long> implements VpnUserDao {
private final SearchBuilder<VpnUserVO> AccountSearch;
private final SearchBuilder<VpnUserVO> AccountNameSearch;
private final GenericSearchBuilder<VpnUserVO, Long> VpnUserCount;
protected VpnUserDaoImpl() {
@ -43,6 +46,11 @@ public class VpnUserDaoImpl extends GenericDaoBase<VpnUserVO, Long> implements V
AccountNameSearch.and("accountId", AccountNameSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountNameSearch.and("username", AccountNameSearch.entity().getUsername(), SearchCriteria.Op.EQ);
AccountNameSearch.done();
VpnUserCount = createSearchBuilder(Long.class);
VpnUserCount.and("accountId", VpnUserCount.entity().getAccountId(), SearchCriteria.Op.EQ);
VpnUserCount.select(null, Func.COUNT, null);
VpnUserCount.done();
}
@Override
@ -59,5 +67,17 @@ public class VpnUserDaoImpl extends GenericDaoBase<VpnUserVO, Long> implements V
sc.setParameters("username", userName);
return findOneBy(sc);
}
@Override
public long getVpnUserCount(Long accountId) {
SearchCriteria<Long> sc = VpnUserCount.create();
sc.setParameters("accountId", accountId);
List<Long> rs = searchIncludingRemoved(sc, null);
if (rs.size() == 0) {
return 0;
}
return rs.get(0);
}
}

View File

@ -28,6 +28,7 @@ import com.cloud.api.Parameter;
import com.cloud.api.ServerApiException;
import com.cloud.api.response.VpnUsersResponse;
import com.cloud.event.EventTypes;
import com.cloud.exception.AccountLimitException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.network.VpnUserVO;
import com.cloud.user.Account;
@ -146,6 +147,6 @@ public class AddVpnUserCmd extends BaseAsyncCmd {
}
} catch (ConcurrentOperationException ex) {
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage());
}
}
}
}

View File

@ -62,6 +62,8 @@ public enum Config {
//VPN
RemoteAccessVpnPskLength("Network", AgentManager.class, Integer.class, "remote.access.vpn.psk.length", "24", "The length of the ipsec preshared key (minimum 8, maximum 256)", null),
RemoteAccessVpnClientIpRange("Network", AgentManager.class, String.class, "remote.access.vpn.client.iprange", "10.1.2.1-10.1.2.8", "The range of ips to be allocated to remote access vpn clients. The first ip in the range is used by the VPN server", null),
RemoteAccessVpnUserLimit("Network", AgentManager.class, String.class, "remote.access.vpn.user.limit", "8", "The maximum number of VPN users that can be created per account", null),
// Usage

View File

@ -40,6 +40,7 @@ import com.cloud.dc.HostPodVO;
import com.cloud.dc.VlanVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.exception.AccountLimitException;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
@ -324,7 +325,7 @@ public interface NetworkManager {
*/
public boolean destroyRemoteAccessVpn(DeleteRemoteAccessVpnCmd cmd) throws ConcurrentOperationException;
VpnUserVO addVpnUser(AddVpnUserCmd cmd) throws ConcurrentOperationException;
VpnUserVO addVpnUser(AddVpnUserCmd cmd) throws ConcurrentOperationException, AccountLimitException;
boolean removeVpnUser(RemoveVpnUserCmd cmd) throws ConcurrentOperationException;

View File

@ -1650,12 +1650,12 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
}
private Integer getIntegerConfigValue(String configKey) {
private Integer getIntegerConfigValue(String configKey, Integer dflt) {
String value = _configs.get(configKey);
if (value != null) {
return Integer.parseInt(value);
}
return null;
return dflt;
}
private void validateRemoteAccessVpnConfiguration() throws ConfigurationException {
@ -1664,7 +1664,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
s_logger.warn("Remote Access VPN configuration missing client ip range -- ignoring");
return;
}
Integer pskLength = getIntegerConfigValue(Config.RemoteAccessVpnPskLength.key());
Integer pskLength = getIntegerConfigValue(Config.RemoteAccessVpnPskLength.key(), 24);
if (pskLength != null && (pskLength < 8 || pskLength > 256)) {
throw new ConfigurationException("Remote Access VPN: IPSec preshared key length should be between 8 and 256");
} else if (pskLength == null) {
@ -1694,8 +1694,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
_configs = _configDao.getConfiguration("AgentManager", params);
validateRemoteAccessVpnConfiguration();
Integer rateMbps = getIntegerConfigValue(Config.NetworkThrottlingRate.key());
Integer multicastRateMbps = getIntegerConfigValue(Config.MulticastThrottlingRate.key());
Integer rateMbps = getIntegerConfigValue(Config.NetworkThrottlingRate.key(), null);
Integer multicastRateMbps = getIntegerConfigValue(Config.MulticastThrottlingRate.key(), null);
NetworkOfferingVO publicNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemVmPublicNetwork, TrafficType.Public, null);
@ -2749,7 +2749,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
long startIp = NetUtils.ip2Long(range[0]);
String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1];
String sharedSecret = PasswordGenerator.generatePresharedKey(getIntegerConfigValue(Config.RemoteAccessVpnPskLength.key()));
String sharedSecret = PasswordGenerator.generatePresharedKey(getIntegerConfigValue(Config.RemoteAccessVpnPskLength.key(), 24));
Transaction txn = Transaction.currentTxn();
txn.start();
boolean locked = false;
@ -2874,7 +2874,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
public VpnUserVO addVpnUser(AddVpnUserCmd cmd) throws ConcurrentOperationException, InvalidParameterValueException {
@DB
public VpnUserVO addVpnUser(AddVpnUserCmd cmd) throws ConcurrentOperationException, InvalidParameterValueException, AccountLimitException {
Long userId = UserContext.current().getUserId();
Account account = getAccountForApiCommand(cmd.getAccountName(), cmd.getDomainId());
EventUtils.saveStartedEvent(userId, account.getId(), EventTypes.EVENT_VPN_USER_ADD, "Add VPN user for account: " + account.getAccountName(), cmd.getStartEventId());
@ -2885,14 +2886,29 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
if (!cmd.getPassword().matches("^[a-zA-Z0-9][a-zA-Z0-9@#+=._-]{2,31}$")) {
throw new InvalidParameterValueException("Password has to be 3-32 characters including alphabets, numbers and the set '@#+=.-_'");
}
VpnUserVO user = addRemoveVpnUser(account, cmd.getUserName(), cmd.getPassword(), true);
if (user != null) {
EventUtils.saveEvent(userId, account.getId(), EventTypes.EVENT_VPN_USER_ADD, "Added a VPN user for account: " + account.getAccountName() + " username= " + cmd.getUserName());
} else {
EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VPN_USER_ADD, "Unable to add VPN user for account: ", account.getAccountName() + " username= " + cmd.getUserName());
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to add VPN user for account: "+ account.getAccountName() + " username= " + cmd.getUserName());
account = _accountDao.acquireInLockTable(account.getId());
if (account == null) {
throw new ConcurrentOperationException("Unable to add vpn user: Another operation active");
}
return user;
try {
long userCount = _vpnUsersDao.getVpnUserCount(account.getId());
Integer userLimit = getIntegerConfigValue(Config.RemoteAccessVpnUserLimit.key(), 8);
if (userCount >= userLimit) {
throw new AccountLimitException("Cannot add more than " + userLimit + " remote access vpn users");
}
VpnUserVO user = addRemoveVpnUser(account, cmd.getUserName(), cmd.getPassword(), true);
if (user != null) {
EventUtils.saveEvent(userId, account.getId(), EventTypes.EVENT_VPN_USER_ADD, "Added a VPN user for account: " + account.getAccountName() + " username= " + cmd.getUserName());
return user;
} else {
EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_VPN_USER_ADD, "Unable to add VPN user for account: ", account.getAccountName() + " username= " + cmd.getUserName());
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to add VPN user for account: "+ account.getAccountName() + " username= " + cmd.getUserName());
}
} finally {
if (account != null)
_accountDao.releaseFromLockTable(account.getId());
}
}
@ -2931,6 +2947,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
List<VpnUserVO> addVpnUsers = new ArrayList<VpnUserVO>();
List<VpnUserVO> removeVpnUsers = new ArrayList<VpnUserVO>();
if (add) {
user = _vpnUsersDao.persist(new VpnUserVO(account.getId(), username, password));
addVpnUsers.add(user);