CLOUDSTACK-754: Enable Remote Access VPN for VPC

With integration smoke test case.
This commit is contained in:
Sheng Yang 2013-10-24 17:33:46 -07:00
parent d63a08d0a3
commit 1528725949
20 changed files with 613 additions and 264 deletions

View File

@ -31,6 +31,7 @@ public interface RemoteAccessVpn extends ControlledEntity, InternalIdentity, Ide
String getIpRange(); String getIpRange();
String getIpsecPresharedKey(); String getIpsecPresharedKey();
String getLocalIp(); String getLocalIp();
long getNetworkId(); Long getNetworkId();
Long getVpcId();
State getState(); State getState();
} }

View File

@ -31,7 +31,7 @@ import com.cloud.utils.Pair;
public interface RemoteAccessVpnService { public interface RemoteAccessVpnService {
static final String RemoteAccessVpnClientIpRangeCK = "remote.access.vpn.client.iprange"; static final String RemoteAccessVpnClientIpRangeCK = "remote.access.vpn.client.iprange";
RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, long networkId) RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall)
throws NetworkRuleConflictException; throws NetworkRuleConflictException;
void destroyRemoteAccessVpnForIp(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; void destroyRemoteAccessVpnForIp(long vpnServerAddressId, Account caller) throws ResourceUnavailableException;
RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException; RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException;
@ -47,5 +47,4 @@ public interface RemoteAccessVpnService {
List<? extends RemoteAccessVpn> listRemoteAccessVpns(long networkId); List<? extends RemoteAccessVpn> listRemoteAccessVpns(long networkId);
RemoteAccessVpn getRemoteAccessVpn(long vpnAddrId); RemoteAccessVpn getRemoteAccessVpn(long vpnAddrId);
} }

View File

@ -126,25 +126,10 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
return EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE; return EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE;
} }
public long getNetworkId() {
IpAddress ip = _entityMgr.findById(IpAddress.class, getPublicIpId());
Long ntwkId = null;
if (ip.getAssociatedWithNetworkId() != null) {
ntwkId = ip.getAssociatedWithNetworkId();
}
if (ntwkId == null) {
throw new InvalidParameterValueException("Unable to create remote access vpn for the ipAddress id=" + getPublicIpId() +
" as ip is not associated with any network and no networkId is passed in");
}
return ntwkId;
}
@Override @Override
public void create() { public void create() {
try { try {
RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall(), getNetworkId()); RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall());
if (vpn != null) { if (vpn != null) {
this.setEntityId(vpn.getServerAddressId()); this.setEntityId(vpn.getServerAddressId());
// find uuid for server ip address // find uuid for server ip address

View File

@ -20,10 +20,13 @@ package com.cloud.agent.api.routing;
public class RemoteAccessVpnCfgCommand extends NetworkElementCommand { public class RemoteAccessVpnCfgCommand extends NetworkElementCommand {
boolean create; boolean create;
private boolean vpcEnabled;
String vpnServerIp; String vpnServerIp;
String ipRange; String ipRange;
String presharedKey; String presharedKey;
String localIp; String localIp;
private String localCidr;
private String publicInterface;
protected RemoteAccessVpnCfgCommand() { protected RemoteAccessVpnCfgCommand() {
this.create = false; this.create = false;
@ -39,12 +42,18 @@ public class RemoteAccessVpnCfgCommand extends NetworkElementCommand {
} }
public RemoteAccessVpnCfgCommand(boolean create, String vpnServerAddress, String localIp, String ipRange, String ipsecPresharedKey) { public RemoteAccessVpnCfgCommand(boolean create, String vpnServerAddress, String localIp, String ipRange, String ipsecPresharedKey, boolean vpcEnabled) {
this.vpnServerIp = vpnServerAddress; this.vpnServerIp = vpnServerAddress;
this.ipRange = ipRange; this.ipRange = ipRange;
this.presharedKey = ipsecPresharedKey; this.presharedKey = ipsecPresharedKey;
this.localIp = localIp; this.localIp = localIp;
this.create = create; this.create = create;
this.vpcEnabled = vpcEnabled;
if (vpcEnabled) {
this.setPublicInterface("eth1");
} else {
this.setPublicInterface("eth2");
}
} }
public String getVpnServerIp() { public String getVpnServerIp() {
@ -75,4 +84,28 @@ public class RemoteAccessVpnCfgCommand extends NetworkElementCommand {
return localIp; return localIp;
} }
public boolean isVpcEnabled() {
return vpcEnabled;
}
public void setVpcEnabled(boolean vpcEnabled) {
this.vpcEnabled = vpcEnabled;
}
public String getLocalCidr() {
return localCidr;
}
public void setLocalCidr(String localCidr) {
this.localCidr = localCidr;
}
public String getPublicInterface() {
return publicInterface;
}
public void setPublicInterface(String publicInterface) {
this.publicInterface = publicInterface;
}
} }

View File

@ -24,7 +24,8 @@ import com.cloud.utils.db.GenericDao;
public interface RemoteAccessVpnDao extends GenericDao<RemoteAccessVpnVO, Long> { public interface RemoteAccessVpnDao extends GenericDao<RemoteAccessVpnVO, Long> {
RemoteAccessVpnVO findByPublicIpAddress(long ipAddressId); RemoteAccessVpnVO findByPublicIpAddress(long ipAddressId);
RemoteAccessVpnVO findByPublicIpAddressAndState(long ipAddressId, RemoteAccessVpn.State state); RemoteAccessVpnVO findByPublicIpAddressAndState(long ipAddressId, RemoteAccessVpn.State state);
RemoteAccessVpnVO findByAccountAndNetwork(Long accountId, Long zoneId); RemoteAccessVpnVO findByAccountAndNetwork(Long accountId, Long networkId);
RemoteAccessVpnVO findByAccountAndVpc(Long accountId, Long vpcId);
List<RemoteAccessVpnVO> findByAccount(Long accountId); List<RemoteAccessVpnVO> findByAccount(Long accountId);
List<RemoteAccessVpnVO> listByNetworkId(Long networkId); List<RemoteAccessVpnVO> listByNetworkId(Long networkId);
} }

View File

@ -40,6 +40,7 @@ public class RemoteAccessVpnDaoImpl extends GenericDaoBase<RemoteAccessVpnVO, Lo
AllFieldsSearch = createSearchBuilder(); AllFieldsSearch = createSearchBuilder();
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ); AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("networkId", AllFieldsSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); AllFieldsSearch.and("networkId", AllFieldsSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("ipAddress", AllFieldsSearch.entity().getServerAddressId(), SearchCriteria.Op.EQ); AllFieldsSearch.and("ipAddress", AllFieldsSearch.entity().getServerAddressId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ); AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
AllFieldsSearch.done(); AllFieldsSearch.done();
@ -60,6 +61,14 @@ public class RemoteAccessVpnDaoImpl extends GenericDaoBase<RemoteAccessVpnVO, Lo
return findOneBy(sc); return findOneBy(sc);
} }
@Override
public RemoteAccessVpnVO findByAccountAndVpc(Long accountId, Long vpcId) {
SearchCriteria<RemoteAccessVpnVO> sc = AllFieldsSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("vpcId", vpcId);
return findOneBy(sc);
}
@Override @Override
public List<RemoteAccessVpnVO> findByAccount(Long accountId) { public List<RemoteAccessVpnVO> findByAccount(Long accountId) {
SearchCriteria<RemoteAccessVpnVO> sc = AllFieldsSearch.create(); SearchCriteria<RemoteAccessVpnVO> sc = AllFieldsSearch.create();

View File

@ -34,7 +34,7 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn {
private long accountId; private long accountId;
@Column(name="network_id") @Column(name="network_id")
private long networkId; private Long networkId;
@Column(name="domain_id") @Column(name="domain_id")
private long domainId; private long domainId;
@ -62,11 +62,14 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn {
@Column(name="uuid") @Column(name="uuid")
private String uuid; private String uuid;
@Column(name="vpc_id")
private Long vpcId;
public RemoteAccessVpnVO() { public RemoteAccessVpnVO() {
this.uuid = UUID.randomUUID().toString(); this.uuid = UUID.randomUUID().toString();
} }
public RemoteAccessVpnVO(long accountId, long domainId, long networkId, long publicIpId, String localIp, String ipRange, String presharedKey) { public RemoteAccessVpnVO(long accountId, long domainId, Long networkId, long publicIpId, Long vpcId, String localIp, String ipRange, String presharedKey) {
this.accountId = accountId; this.accountId = accountId;
this.serverAddressId = publicIpId; this.serverAddressId = publicIpId;
this.ipRange = ipRange; this.ipRange = ipRange;
@ -76,6 +79,7 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn {
this.networkId = networkId; this.networkId = networkId;
this.state = State.Added; this.state = State.Added;
this.uuid = UUID.randomUUID().toString(); this.uuid = UUID.randomUUID().toString();
this.vpcId = vpcId;
} }
@Override @Override
@ -126,7 +130,7 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn {
} }
@Override @Override
public long getNetworkId() { public Long getNetworkId() {
return networkId; return networkId;
} }
@ -139,4 +143,9 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn {
public String getUuid() { public String getUuid() {
return uuid; return uuid;
} }
@Override
public Long getVpcId() {
return vpcId;
}
} }

View File

@ -2184,11 +2184,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
args += " -s " + cmd.getVpnServerIp(); args += " -s " + cmd.getVpnServerIp();
args += " -l " + cmd.getLocalIp(); args += " -l " + cmd.getLocalIp();
args += " -c "; args += " -c ";
} else { } else {
args += " -d "; args += " -d ";
args += " -s " + cmd.getVpnServerIp(); args += " -s " + cmd.getVpnServerIp();
} }
args += " -C " + cmd.getLocalCidr();
args += " -i " + cmd.getPublicInterface();
String result = callHostPlugin(conn, "vmops", "routerProxy", "args", args); String result = callHostPlugin(conn, "vmops", "routerProxy", "args", args);
if (result == null || result.isEmpty()) { if (result == null || result.isEmpty()) {
return new Answer(cmd, false, "Configure VPN failed"); return new Answer(cmd, false, "Configure VPN failed");

View File

@ -669,7 +669,7 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl
String maskedIpRange = ipRange[0] + "-" + ipRange[1]; String maskedIpRange = ipRange[0] + "-" + ipRange[1];
RemoteAccessVpnCfgCommand createVpnCmd = new RemoteAccessVpnCfgCommand(create, ip.getAddress().addr(), vpn.getLocalIp(), maskedIpRange, vpn.getIpsecPresharedKey()); RemoteAccessVpnCfgCommand createVpnCmd = new RemoteAccessVpnCfgCommand(create, ip.getAddress().addr(), vpn.getLocalIp(), maskedIpRange, vpn.getIpsecPresharedKey(), false);
createVpnCmd.setAccessDetail(NetworkElementCommand.ACCOUNT_ID, String.valueOf(network.getAccountId())); createVpnCmd.setAccessDetail(NetworkElementCommand.ACCOUNT_ID, String.valueOf(network.getAccountId()));
createVpnCmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); createVpnCmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr());
Answer answer = _agentMgr.easySend(externalFirewall.getId(), createVpnCmd); Answer answer = _agentMgr.easySend(externalFirewall.getId(), createVpnCmd);

View File

@ -387,8 +387,11 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
@Override @Override
public String[] applyVpnUsers(RemoteAccessVpn vpn, List<? extends VpnUser> users) throws ResourceUnavailableException { public String[] applyVpnUsers(RemoteAccessVpn vpn, List<? extends VpnUser> users) throws ResourceUnavailableException {
Network network = _networksDao.findById(vpn.getNetworkId()); if (vpn.getNetworkId() == null) {
return null;
}
Network network = _networksDao.findById(vpn.getNetworkId());
if (canHandle(network, Service.Vpn)) { if (canHandle(network, Service.Vpn)) {
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) { if (routers == null || routers.isEmpty()) {
@ -405,8 +408,11 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
@Override @Override
public boolean startVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException { public boolean startVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException {
Network network = _networksDao.findById(vpn.getNetworkId()); if (vpn.getNetworkId() == null) {
return false;
}
Network network = _networksDao.findById(vpn.getNetworkId());
if (canHandle(network, Service.Vpn)) { if (canHandle(network, Service.Vpn)) {
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) { if (routers == null || routers.isEmpty()) {
@ -423,8 +429,11 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
@Override @Override
public boolean stopVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException { public boolean stopVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException {
Network network = _networksDao.findById(vpn.getNetworkId()); if (vpn.getNetworkId() == null) {
return false;
}
Network network = _networksDao.findById(vpn.getNetworkId());
if (canHandle(network, Service.Vpn)) { if (canHandle(network, Service.Vpn)) {
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER);
if (routers == null || routers.isEmpty()) { if (routers == null || routers.isEmpty()) {

View File

@ -39,9 +39,11 @@ import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service; import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel; import com.cloud.network.NetworkModel;
import com.cloud.network.PublicIpAddress; import com.cloud.network.PublicIpAddress;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.Site2SiteVpnGateway; import com.cloud.network.Site2SiteVpnGateway;
import com.cloud.network.VirtualRouterProvider.Type; import com.cloud.network.VirtualRouterProvider.Type;
import com.cloud.network.VpnUser;
import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.Site2SiteVpnGatewayDao; import com.cloud.network.dao.Site2SiteVpnGatewayDao;
@ -531,4 +533,47 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc
return _vpcRouterMgr.stopSite2SiteVpn(conn, routers.get(0)); return _vpcRouterMgr.stopSite2SiteVpn(conn, routers.get(0));
} }
@Override
public String[] applyVpnUsers(RemoteAccessVpn vpn, List<? extends VpnUser> users) throws ResourceUnavailableException {
if (vpn.getVpcId() == null) {
return null;
}
List<DomainRouterVO> routers = _vpcRouterMgr.getVpcRouters(vpn.getVpcId());
if (routers == null || routers.size() != 1) {
s_logger.debug("Cannot apply vpn users on the backend; virtual router doesn't exist in the network " + vpn.getVpcId());
return null;
}
return _vpcRouterMgr.applyVpnUsers(vpn, users, routers.get(0));
}
@Override
public boolean startVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException {
if (vpn.getVpcId() == null) {
return false;
}
List<DomainRouterVO> routers = _vpcRouterMgr.getVpcRouters(vpn.getVpcId());
if (routers == null || routers.size() != 1) {
s_logger.debug("Cannot apply vpn users on the backend; virtual router doesn't exist in the network " + vpn.getVpcId());
return true;
}
return _vpcRouterMgr.startRemoteAccessVpn(vpn, routers.get(0));
}
@Override
public boolean stopVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException {
if (vpn.getVpcId() == null) {
return false;
}
List<DomainRouterVO> routers = _vpcRouterMgr.getVpcRouters(vpn.getVpcId());
if (routers == null || routers.size() != 1) {
s_logger.debug("Cannot apply vpn users on the backend; virtual router doesn't exist in the network " + vpn.getVpcId());
return true;
}
return _vpcRouterMgr.stopRemoteAccessVpn(vpn, routers.get(0));
}
} }

View File

@ -3342,6 +3342,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
} }
protected String getVpnCidr(RemoteAccessVpn vpn)
{
Network network = _networkDao.findById(vpn.getNetworkId());
return network.getCidr();
}
protected void createApplyVpnCommands(boolean isCreate, RemoteAccessVpn vpn, VirtualRouter router, Commands cmds) { protected void createApplyVpnCommands(boolean isCreate, RemoteAccessVpn vpn, VirtualRouter router, Commands cmds) {
List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); List<VpnUserVO> vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId());
@ -3349,8 +3355,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
IpAddress ip = _networkModel.getIp(vpn.getServerAddressId()); IpAddress ip = _networkModel.getIp(vpn.getServerAddressId());
String cidr = getVpnCidr(vpn);
RemoteAccessVpnCfgCommand startVpnCmd = new RemoteAccessVpnCfgCommand(isCreate, ip.getAddress().addr(), RemoteAccessVpnCfgCommand startVpnCmd = new RemoteAccessVpnCfgCommand(isCreate, ip.getAddress().addr(),
vpn.getLocalIp(), vpn.getIpRange(), vpn.getIpsecPresharedKey()); vpn.getLocalIp(), vpn.getIpRange(), vpn.getIpsecPresharedKey(), (vpn.getVpcId() != null));
startVpnCmd.setLocalCidr(cidr);
startVpnCmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); startVpnCmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId()));
startVpnCmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); startVpnCmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId());

View File

@ -23,8 +23,10 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network; import com.cloud.network.Network;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.VpcVirtualNetworkApplianceService;
import com.cloud.network.VpnUser;
import com.cloud.network.vpc.*; import com.cloud.network.vpc.*;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.vm.DomainRouterVO; import com.cloud.vm.DomainRouterVO;
@ -106,4 +108,31 @@ public interface VpcVirtualNetworkApplianceManager extends VirtualNetworkApplian
* @return * @return
*/ */
List<DomainRouterVO> getVpcRouters(long vpcId); List<DomainRouterVO> getVpcRouters(long vpcId);
/**
* @param vpn
* @param router
* @return
* @throws ResourceUnavailableException
*/
boolean startRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router)
throws ResourceUnavailableException;
/**
* @param vpn
* @param router
* @return
* @throws ResourceUnavailableException
*/
boolean stopRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router)
throws ResourceUnavailableException;
/**
* @param vpn
* @param users
* @param routers
* @return
* @throws ResourceUnavailableException
*/
String[] applyVpnUsers(RemoteAccessVpn vpn, List<? extends VpnUser> users, VirtualRouter router) throws ResourceUnavailableException;
} }

View File

@ -39,10 +39,12 @@ import com.cloud.agent.api.SetupGuestNetworkAnswer;
import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.SetupGuestNetworkCommand;
import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand;
import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.NetworkElementCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.SetNetworkACLCommand; import com.cloud.agent.api.routing.SetNetworkACLCommand;
import com.cloud.agent.api.routing.SetSourceNatCommand; import com.cloud.agent.api.routing.SetSourceNatCommand;
import com.cloud.agent.api.routing.SetStaticRouteCommand; import com.cloud.agent.api.routing.SetStaticRouteCommand;
import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand;
import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.NetworkACLTO; import com.cloud.agent.api.to.NetworkACLTO;
import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.NicTO;
@ -52,10 +54,12 @@ import com.cloud.dc.DataCenterVO;
import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlan;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.StorageUnavailableException; import com.cloud.exception.StorageUnavailableException;
import com.cloud.network.IpAddress; import com.cloud.network.IpAddress;
@ -70,15 +74,18 @@ import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetwork;
import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PublicIpAddress; import com.cloud.network.PublicIpAddress;
import com.cloud.network.RemoteAccessVpn;
import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.VirtualRouterProvider; import com.cloud.network.VirtualRouterProvider;
import com.cloud.network.VirtualRouterProvider.Type; import com.cloud.network.VirtualRouterProvider.Type;
import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.VpcVirtualNetworkApplianceService;
import com.cloud.network.VpnUser;
import com.cloud.network.addr.PublicIp; import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.RemoteAccessVpnVO;
import com.cloud.network.dao.Site2SiteCustomerGatewayVO; import com.cloud.network.dao.Site2SiteCustomerGatewayVO;
import com.cloud.network.dao.Site2SiteVpnConnectionDao; import com.cloud.network.dao.Site2SiteVpnConnectionDao;
import com.cloud.network.dao.Site2SiteVpnGatewayDao; import com.cloud.network.dao.Site2SiteVpnGatewayDao;
@ -839,7 +846,13 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
createStaticRouteCommands(staticRouteProfiles, router, cmds); createStaticRouteCommands(staticRouteProfiles, router, cmds);
} }
//5) REPROGRAM GUEST NETWORK //5) RE-APPLY ALL REMOTE ACCESS VPNs
RemoteAccessVpnVO vpn = _vpnDao.findByAccountAndVpc(router.getAccountId(), router.getVpcId());
if (vpn != null) {
createApplyVpnCommands(true, vpn, router, cmds);
}
//6) REPROGRAM GUEST NETWORK
boolean reprogramGuestNtwks = true; boolean reprogramGuestNtwks = true;
if (profile.getParameter(Param.ReProgramGuestNetworks) != null if (profile.getParameter(Param.ReProgramGuestNetworks) != null
&& (Boolean) profile.getParameter(Param.ReProgramGuestNetworks) == false) { && (Boolean) profile.getParameter(Param.ReProgramGuestNetworks) == false) {
@ -1342,4 +1355,100 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
return _routerDao.listByVpcId(vpcId); return _routerDao.listByVpcId(vpcId);
} }
@Override
public String[] applyVpnUsers(RemoteAccessVpn vpn, List<? extends VpnUser> users, VirtualRouter router) throws ResourceUnavailableException {
Vpc vpc = _vpcDao.findById(vpn.getVpcId());
if (router.getState() != State.Running) {
s_logger.warn("Failed to add/remove Remote Access VPN users: router not in running state");
throw new ResourceUnavailableException("Failed to add/remove Remote Access VPN users: router not in running state: " +
router.getState(), DataCenter.class, vpc.getZoneId());
}
Commands cmds = new Commands(Command.OnError.Continue);
createApplyVpnUsersCommand(users, router, cmds);
// Currently we receive just one answer from the agent. In the future we have to parse individual answers and set
// results accordingly
boolean agentResult = sendCommandsToRouter(router, cmds);
String[] result = new String[users.size()];
for (int i = 0; i < result.length; i++) {
if (agentResult) {
result[i] = null;
} else {
result[i] = String.valueOf(agentResult);
}
}
return result;
}
protected String getVpnCidr(RemoteAccessVpn vpn)
{
if (vpn.getVpcId() == null) {
return super.getVpnCidr(vpn);
}
Vpc vpc = _vpcDao.findById(vpn.getVpcId());
return vpc.getCidr();
}
@Override
public boolean startRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) throws ResourceUnavailableException {
if (router.getState() != State.Running) {
s_logger.warn("Unable to apply remote access VPN configuration, virtual router is not in the right state " + router.getState());
throw new ResourceUnavailableException("Unable to apply remote access VPN configuration," +
" virtual router is not in the right state", DataCenter.class, router.getDataCenterId());
}
Commands cmds = new Commands(Command.OnError.Stop);
createApplyVpnCommands(true, vpn, router, cmds);
try {
_agentMgr.send(router.getHostId(), cmds);
} catch (OperationTimedoutException e) {
s_logger.debug("Failed to start remote access VPN: ", e);
throw new AgentUnavailableException("Unable to send commands to virtual router ", router.getHostId(), e);
}
Answer answer = cmds.getAnswer("users");
if (!answer.getResult()) {
s_logger.error("Unable to start vpn: unable add users to vpn in zone " + router.getDataCenterId()
+ " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName()
+ " due to " + answer.getDetails());
throw new ResourceUnavailableException("Unable to start vpn: Unable to add users to vpn in zone " +
router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: "
+ router.getInstanceName() + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId());
}
answer = cmds.getAnswer("startVpn");
if (!answer.getResult()) {
s_logger.error("Unable to start vpn in zone " + router.getDataCenterId() + " for account " +
vpn.getAccountId() + " on domR: " + router.getInstanceName() + " due to "
+ answer.getDetails());
throw new ResourceUnavailableException("Unable to start vpn in zone " + router.getDataCenterId()
+ " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName()
+ " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId());
}
return true;
}
@Override
public boolean stopRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) throws ResourceUnavailableException {
boolean result = true;
if (router.getState() == State.Running) {
Commands cmds = new Commands(Command.OnError.Continue);
createApplyVpnCommands(false, vpn, router, cmds);
result = result && sendCommandsToRouter(router, cmds);
} else if (router.getState() == State.Stopped) {
s_logger.debug("Router " + router + " is in Stopped state, not sending deleteRemoteAccessVpn command to it");
} else {
s_logger.warn("Failed to delete remote access VPN: domR " + router + " is not in right state " + router.getState());
throw new ResourceUnavailableException("Failed to delete remote access VPN: domR is not in right state " +
router.getState(), DataCenter.class, router.getDataCenterId());
}
return true;
}
} }

View File

@ -63,6 +63,8 @@ import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.RulesManager; import com.cloud.network.rules.RulesManager;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.projects.Project.ListProjectResourcesCriteria;
import com.cloud.server.ConfigurationServer; import com.cloud.server.ConfigurationServer;
import com.cloud.user.Account; import com.cloud.user.Account;
@ -109,7 +111,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
@Inject ConfigurationDao _configDao; @Inject ConfigurationDao _configDao;
@Inject List<RemoteAccessVPNServiceProvider> _vpnServiceProviders; @Inject List<RemoteAccessVPNServiceProvider> _vpnServiceProviders;
@Inject ConfigurationServer _configServer; @Inject ConfigurationServer _configServer;
@Inject VpcDao _vpcDao;
int _userLimit; int _userLimit;
int _pskLength; int _pskLength;
@ -117,11 +119,13 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
@Override @Override
@DB @DB
public RemoteAccessVpn createRemoteAccessVpn(final long publicIpId, String ipRange, final boolean openFirewall, long networkId) public RemoteAccessVpn createRemoteAccessVpn(final long publicIpId, String ipRange, boolean openFirewall)
throws NetworkRuleConflictException { throws NetworkRuleConflictException {
CallContext ctx = CallContext.current(); CallContext ctx = CallContext.current();
final Account caller = ctx.getCallingAccount(); final Account caller = ctx.getCallingAccount();
Long networkId = null;
// make sure ip address exists // make sure ip address exists
final PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId); final PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId);
if (ipAddr == null) { if (ipAddr == null) {
@ -135,7 +139,26 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
} }
IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId); IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId);
_networkMgr.checkIpForService(ipAddress, Service.Vpn, null);
networkId = ipAddress.getAssociatedWithNetworkId();
if (networkId != null) {
_networkMgr.checkIpForService(ipAddress, Service.Vpn, null);
}
final Long vpcId = ipAddress.getVpcId();
/* IP Address used for VPC must be the source NAT IP of whole VPC */
if (vpcId != null && ipAddress.isSourceNat()) {
assert networkId == null;
// No firewall setting for VPC, it would be open internally
openFirewall = false;
}
final boolean openFirewallFinal = openFirewall;
if (networkId == null && vpcId == null) {
throw new InvalidParameterValueException("Unable to create remote access vpn for the ipAddress: " + ipAddr.getAddress().addr() +
" as ip is not associated with any network or VPC");
}
RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId); RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId);
@ -147,22 +170,6 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
throw new InvalidParameterValueException("A Remote Access VPN already exists for this public Ip address"); throw new InvalidParameterValueException("A Remote Access VPN already exists for this public Ip address");
} }
// TODO: assumes one virtual network / domr per account per zone
vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId);
if (vpnVO != null) {
//if vpn is in Added state, return it to the api
if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
return vpnVO;
}
throw new InvalidParameterValueException("A Remote Access VPN already exists for this account");
}
//Verify that vpn service is enabled for the network
Network network = _networkMgr.getNetwork(networkId);
if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) {
throw new InvalidParameterValueException("Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId());
}
if (ipRange == null) { if (ipRange == null) {
ipRange = RemoteAccessVpnClientIpRange.valueIn(ipAddr.getAccountId()); ipRange = RemoteAccessVpnClientIpRange.valueIn(ipAddr.getAccountId());
} }
@ -177,7 +184,28 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
throw new InvalidParameterValueException("Invalid ip range " + ipRange); throw new InvalidParameterValueException("Invalid ip range " + ipRange);
} }
Pair<String, Integer> cidr = NetUtils.getCidr(network.getCidr()); Pair<String, Integer> cidr = null;
// TODO: assumes one virtual network / domr per account per zone
if (networkId != null) {
vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId);
if (vpnVO != null) {
//if vpn is in Added state, return it to the api
if (vpnVO.getState() == RemoteAccessVpn.State.Added) {
return vpnVO;
}
throw new InvalidParameterValueException("A Remote Access VPN already exists for this account");
}
//Verify that vpn service is enabled for the network
Network network = _networkMgr.getNetwork(networkId);
if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) {
throw new InvalidParameterValueException("Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId());
}
cidr = NetUtils.getCidr(network.getCidr());
} else { // Don't need to check VPC because there is only one IP(source NAT IP) available for VPN
Vpc vpc = _vpcDao.findById(vpcId);
cidr = NetUtils.getCidr(vpc.getCidr());
}
// FIXME: This check won't work for the case where the guest ip range // FIXME: This check won't work for the case where the guest ip range
// changes depending on the vlan allocated. // changes depending on the vlan allocated.
@ -196,9 +224,11 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
return Transaction.execute(new TransactionCallbackWithException<RemoteAccessVpn, NetworkRuleConflictException>() { return Transaction.execute(new TransactionCallbackWithException<RemoteAccessVpn, NetworkRuleConflictException>() {
@Override @Override
public RemoteAccessVpn doInTransaction(TransactionStatus status) throws NetworkRuleConflictException { public RemoteAccessVpn doInTransaction(TransactionStatus status) throws NetworkRuleConflictException {
_rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewall, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT); if (vpcId == null) {
_rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewallFinal, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT);
}
RemoteAccessVpnVO vpnVO = new RemoteAccessVpnVO(ipAddr.getAccountId(), ipAddr.getDomainId(), ipAddr.getAssociatedWithNetworkId(), RemoteAccessVpnVO vpnVO = new RemoteAccessVpnVO(ipAddr.getAccountId(), ipAddr.getDomainId(), ipAddr.getAssociatedWithNetworkId(),
publicIpId, range[0], newIpRange, sharedSecret); publicIpId, vpcId, range[0], newIpRange, sharedSecret);
return _remoteAccessVpnDao.persist(vpnVO); return _remoteAccessVpnDao.persist(vpnVO);
} }
}); });
@ -240,12 +270,9 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
_accountMgr.checkAccess(caller, null, true, vpn); _accountMgr.checkAccess(caller, null, true, vpn);
Network network = _networkMgr.getNetwork(vpn.getNetworkId());
vpn.setState(RemoteAccessVpn.State.Removed); vpn.setState(RemoteAccessVpn.State.Removed);
_remoteAccessVpnDao.update(vpn.getId(), vpn); _remoteAccessVpnDao.update(vpn.getId(), vpn);
boolean success = false; boolean success = false;
try { try {
for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) { for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) {
@ -262,7 +289,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
boolean applyFirewall = false; boolean applyFirewall = false;
final List<FirewallRuleVO> fwRules = new ArrayList<FirewallRuleVO>(); final List<FirewallRuleVO> fwRules = new ArrayList<FirewallRuleVO>();
//if related firewall rule is created for the first vpn port, it would be created for the 2 other ports as well, so need to cleanup the backend //if related firewall rule is created for the first vpn port, it would be created for the 2 other ports as well, so need to cleanup the backend
if (_rulesDao.findByRelatedId(vpnFwRules.get(0).getId()) != null) { if (vpnFwRules.size() != 0 && _rulesDao.findByRelatedId(vpnFwRules.get(0).getId()) != null) {
applyFirewall = true; applyFirewall = true;
} }
@ -396,9 +423,11 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc
throw new InvalidParameterValueException("Unable to find your vpn: " + ipAddressId); throw new InvalidParameterValueException("Unable to find your vpn: " + ipAddressId);
} }
_accountMgr.checkAccess(caller, null, true, vpn); if (vpn.getVpcId() != null) {
openFirewall = false;
}
Network network = _networkMgr.getNetwork(vpn.getNetworkId()); _accountMgr.checkAccess(caller, null, true, vpn);
boolean started = false; boolean started = false;
try { try {

View File

@ -426,4 +426,26 @@ VpcVirtualNetworkApplianceService {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override
public boolean startRemoteAccessVpn(RemoteAccessVpn vpn,
VirtualRouter router) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean stopRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public String[] applyVpnUsers(RemoteAccessVpn vpn,
List<? extends VpnUser> users, VirtualRouter router)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -107,6 +107,9 @@ UPDATE `cloud`.`vm_template` SET `state`='Inactive' WHERE `removed` IS NOT NULL;
UPDATE `cloud`.`vm_template` SET `state`='Active' WHERE `removed` IS NULL; UPDATE `cloud`.`vm_template` SET `state`='Active' WHERE `removed` IS NULL;
UPDATE `cloud`.`vm_template` SET `removed`=NULL; UPDATE `cloud`.`vm_template` SET `removed`=NULL;
ALTER TABLE `cloud`.`remote_access_vpn` MODIFY COLUMN `network_id` bigint unsigned;
ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `vpc_id` bigint unsigned default NULL;
DROP VIEW IF EXISTS `cloud`.`disk_offering_view`; DROP VIEW IF EXISTS `cloud`.`disk_offering_view`;
CREATE VIEW `cloud`.`disk_offering_view` AS CREATE VIEW `cloud`.`disk_offering_view` AS
select select

View File

@ -1,178 +0,0 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#set -x
usage() {
printf "Usage:\n"
printf "Create VPN : %s -c -r <ip range for clients> -l <local ip> -p <ipsec psk> -s <public ip> -D <eth for public ip> -z < zone cidr> \n" $(basename $0)
printf "Delete VPN : %s -d -l <local ip> -s <public ip> -D <eth for public ip> -z < zone cidr> \n" $(basename $0)
printf "Add VPN User : %s -u <username,password> \n" $(basename $0)
printf "Remote VPN User: %s -U <username \n" $(basename $0)
}
iptables_() {
local op=$1
local public_ip=$2
sudo iptables $op INPUT -i $dev -d $public_ip -p udp --dport 500 -j ACCEPT
sudo iptables $op INPUT -i $dev -d $public_ip -p udp --dport 4500 -j ACCEPT
sudo iptables $op INPUT -i $dev -d $public_ip -p udp --dport 1701 -j ACCEPT
sudo iptables $op INPUT -i $dev -p ah -j ACCEPT
sudo iptables $op INPUT -i $dev -p esp -j ACCEPT
sudo iptables $op FORWARD -i ppp+ -d $zcidr -j ACCEPT
sudo iptables $op FORWARD -i ppp+ -o ppp+ -j ACCEPT
sudo iptables $op INPUT -i ppp+ -p udp --dport 53 -j ACCEPT
sudo iptables $op INPUT -i ppp+ -p tcp --dport 53 -j ACCEPT
sudo iptables -t nat $op PREROUTING -i ppp+ -p udp --dport 53 -j DNAT --to-destination $local_ip
sudo iptables -t nat $op PREROUTING -i ppp+ -p tcp --dport 53 -j DNAT --to-destination $local_ip
}
ipsec_server() {
local op=$1
if [ "$op" == "restart" ]
then
service ipsec stop
service xl2tpd stop
service ipsec start
service xl2tpd start
return $?
fi
service ipsec $op
service xl2tpd $op
}
create_l2tp_ipsec_vpn_server() {
local ipsec_psk=$1
local public_ip=$2
local client_range=$3
local local_ip=$4
sed -i -e "s/left=.*$/left=$public_ip/" /etc/ipsec.d/l2tp.conf
echo ": PSK \"$ipsec_psk\"" > /etc/ipsec.d/ipsec.any.secrets
sed -i -e "s/^ip range = .*$/ip range = $client_range/" /etc/xl2tpd/xl2tpd.conf
sed -i -e "s/^local ip = .*$/local ip = $local_ip/" /etc/xl2tpd/xl2tpd.conf
sed -i -e "s/^ms-dns.*$/ms-dns $local_ip/" /etc/ppp/options.xl2tpd
iptables_ "-D" $public_ip
iptables_ "-I" $public_ip
ipsec_server "restart"
ipsec auto --rereadsecrets
ipsec auto --replace L2TP-PSK
}
destroy_l2tp_ipsec_vpn_server() {
local public_ip=$1
ipsec auto --down L2TP-PSK
iptables_ "-D" $public_ip
ipsec_server "stop"
}
remove_l2tp_ipsec_user() {
local u=$1
sed -i -e "/^$u .*$/d" /etc/ppp/chap-secrets
if [ -x /usr/bin/tdbdump ]; then
pid=$(tdbdump /var/run/pppd2.tdb | grep -w $u | awk -F';' '{print $4}' | awk -F= '{print $2}')
[ "$pid" != "" ] && kill -9 $pid
fi
return 0
}
add_l2tp_ipsec_user() {
local u=$1
local passwd=$2
remove_l2tp_ipsec_user $u
echo "$u * $passwd *" >> /etc/ppp/chap-secrets
}
rflag=
pflag=
lflag=
sflag=
create=
destroy=
useradd=
userdel=
while getopts 'cdl:p:r:s:u:U:D:z' OPTION
do
case $OPTION in
c) create=1
;;
d) destroy=1
;;
u) useradd=1
user_pwd="$OPTARG"
;;
U) userdel=1
user="$OPTARG"
;;
r) rflag=1
client_range="$OPTARG"
;;
p) pflag=1
ipsec_psk="$OPTARG"
;;
l) lflag=1
local_ip="$OPTARG"
;;
s) sflag=1
server_ip="$OPTARG"
;;
D) dev="$OPTARG"
;;
z) zcidr="$OPTARG"
;;
?) usage
exit 2
;;
esac
done
[ "$create$destroy" == "11" ] || [ "$create$destroy$useradd$userdel" == "" ] && usage && exit 2
[ "$create" == "1" ] && [ "$lflag$pflag$rflag$sflag" != "1111" ] && usage && exit 2
if [ "$create" == "1" ]; then
create_l2tp_ipsec_vpn_server $ipsec_psk $server_ip $client_range $local_ip
exit $?
fi
if [ "$destroy" == "1" ]; then
destroy_l2tp_ipsec_vpn_server $server_ip
exit $?
fi
if [ "$useradd" == "1" ]; then
u=$(echo $user_pwd | awk -F',' '{print $1}')
pwd=$(echo $user_pwd | awk -F',' '{print $2}')
add_l2tp_ipsec_user $u $pwd
exit $?
fi
if [ "$userdel" == "1" ]; then
remove_l2tp_ipsec_user $user
exit $?
fi

View File

@ -22,8 +22,8 @@
#set -x #set -x
usage() { usage() {
printf "Usage:\n" printf "Usage:\n"
printf "Create VPN : %s -c -r <ip range for clients> -l <localip> -p <ipsec psk> -s <public ip> \n" $(basename $0) printf "Create VPN : %s -c -r <ip range for clients> -l <local ip> -p <ipsec psk> -s <public ip> -i <eth for public ip> \n" $(basename $0)
printf "Delete VPN : %s -d -s <public ip>\n" $(basename $0) printf "Delete VPN : %s -d -l <local ip> -s <public ip> -D <eth for public ip> -C < local cidr> \n" $(basename $0)
printf "Add VPN User : %s -u <username,password> \n" $(basename $0) printf "Add VPN User : %s -u <username,password> \n" $(basename $0)
printf "Remote VPN User: %s -U <username \n" $(basename $0) printf "Remote VPN User: %s -U <username \n" $(basename $0)
} }
@ -32,25 +32,27 @@ get_intf_ip() {
ip addr show $1 | grep -w inet | awk '{print $2}' | awk -F'/' '{print $1}' ip addr show $1 | grep -w inet | awk '{print $2}' | awk -F'/' '{print $1}'
} }
iptables_() { iptables_() {
local op=$1 local op=$1
local public_ip=$2 local public_ip=$2
local public_if="eth2"
local subnet_if="eth0"
local subnet_ip=$(get_intf_ip $subnet_if)
sudo iptables $op INPUT -i $public_if --dst $public_ip -p udp -m udp --dport 500 -j ACCEPT sudo iptables $op INPUT -i $dev --dst $public_ip -p udp -m udp --dport 500 -j ACCEPT
sudo iptables $op INPUT -i $public_if --dst $public_ip -p udp -m udp --dport 4500 -j ACCEPT sudo iptables $op INPUT -i $dev --dst $public_ip -p udp -m udp --dport 4500 -j ACCEPT
sudo iptables $op INPUT -i $public_if --dst $public_ip -p udp -m udp --dport 1701 -j ACCEPT sudo iptables $op INPUT -i $dev --dst $public_ip -p udp -m udp --dport 1701 -j ACCEPT
sudo iptables $op INPUT -i eth2 -p ah -j ACCEPT sudo iptables $op INPUT -i $dev -p ah -j ACCEPT
sudo iptables $op INPUT -i eth2 -p esp -j ACCEPT sudo iptables $op INPUT -i $dev -p esp -j ACCEPT
sudo iptables $op FORWARD -i ppp+ -o $subnet_if -j ACCEPT sudo iptables $op FORWARD -i ppp+ -d $cidr -j ACCEPT
sudo iptables $op FORWARD -i $subnet_if -o ppp+ -j ACCEPT sudo iptables $op FORWARD -s $cidr -o ppp+ -j ACCEPT
sudo iptables $op FORWARD -i ppp+ -o ppp+ -j ACCEPT sudo iptables $op FORWARD -i ppp+ -o ppp+ -j ACCEPT
sudo iptables $op INPUT -i ppp+ -m udp -p udp --dport 53 -j ACCEPT sudo iptables $op INPUT -i ppp+ -m udp -p udp --dport 53 -j ACCEPT
sudo iptables $op INPUT -i ppp+ -m tcp -p tcp --dport 53 -j ACCEPT sudo iptables $op INPUT -i ppp+ -m tcp -p tcp --dport 53 -j ACCEPT
sudo iptables -t nat $op PREROUTING -i ppp+ -p tcp -m tcp --dport 53 -j DNAT --to-destination $subnet_ip sudo iptables -t nat $op PREROUTING -i ppp+ -p tcp -m tcp --dport 53 -j DNAT --to-destination $local_ip
sudo iptables -t nat $op PREROUTING -i ppp+ -p udp -m udp --dport 53 -j DNAT --to-destination $local_ip
if grep "vpcrouter" /var/cache/cloud/cmdline &> /dev/null
then
return
fi
if sudo iptables -t mangle -N VPN_$public_ip &> /dev/null if sudo iptables -t mangle -N VPN_$public_ip &> /dev/null
then then
@ -64,17 +66,42 @@ iptables_() {
sudo iptables -t mangle $op VPN_$public_ip -p esp -j ACCEPT sudo iptables -t mangle $op VPN_$public_ip -p esp -j ACCEPT
} }
start_ipsec() {
service ipsec status > /dev/null
if [ $? -ne 0 ]
then
service ipsec start > /dev/null
#Wait until ipsec started, 5 seconds at most
for i in {1..5}
do
logger -t cloud "$(basename $0): waiting ipsec start..."
service ipsec status > /dev/null
result=$?
if [ $result -eq 0 ]
then
break
fi
sleep 1
done
fi
service ipsec status > /dev/null
return $?
}
ipsec_server() { ipsec_server() {
local op=$1 local op=$1
if [ "$op" == "restart" ]; then case $op in
service ipsec stop "start") start_ipsec
service xl2tpd stop sudo service xl2tpd start
service ipsec start ;;
service xl2tpd start "stop") sudo service xl2tpd stop
return $? ;;
fi "restart") start_ipsec
service ipsec $op sudo ipsec auto --rereadall
service xl2tpd $op service xl2tpd stop
service xl2tpd start
;;
esac
} }
create_l2tp_ipsec_vpn_server() { create_l2tp_ipsec_vpn_server() {
@ -135,8 +162,10 @@ create=
destroy= destroy=
useradd= useradd=
userdel= userdel=
dev=
cidr=
while getopts 'cdl:p:r:s:u:U:' OPTION while getopts 'cdl:p:r:s:u:U:i:C:' OPTION
do do
case $OPTION in case $OPTION in
c) create=1 c) create=1
@ -161,12 +190,26 @@ do
s) sflag=1 s) sflag=1
server_ip="$OPTARG" server_ip="$OPTARG"
;; ;;
i) dev="$OPTARG"
;;
C) cidr="$OPTARG"
;;
?) usage ?) usage
exit 2 exit 2
;; ;;
esac esac
done done
if [ "$dev" == "" ]
then
$dev="eth2"
fi
if [ "$cidr" == "" ]
then
$cidr=$(get_intf_ip "eth0")
fi
[ "$create$destroy" == "11" ] || [ "$create$destroy$useradd$userdel" == "" ] && usage && exit 2 [ "$create$destroy" == "11" ] || [ "$create$destroy$useradd$userdel" == "" ] && usage && exit 2
[ "$create" == "1" ] && [ "$lflag$pflag$rflag$sflag" != "1111" ] && usage && exit 2 [ "$create" == "1" ] && [ "$lflag$pflag$rflag$sflag" != "1111" ] && usage && exit 2

View File

@ -0,0 +1,192 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
""" Tests for VPN in VPC
"""
#Import Local Modules
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
from marvin.integration.lib.utils import *
from marvin.integration.lib.base import *
from marvin.integration.lib.common import *
from nose.plugins.attrib import attr
class Services:
def __init__(self):
self.services = {
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
"password": "password",
},
"virtual_machine": {
"displayname": "Test VM",
"username": "root",
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"ostype": 'CentOS 5.3 (64-bit)',
"service_offering": {
"name": "Tiny Instance",
"displaytext": "Tiny Instance",
"cpunumber": 1,
"cpuspeed": 100,
"memory": 256,
},
"network_offering": {
"name": "Network offering for internal vpc",
"displaytext": "Network offering for internal vpc",
"guestiptype": "Isolated",
"traffictype": "Guest",
"supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL",
"serviceProviderList": {
"Dhcp": "VpcVirtualRouter",
"Dns": "VpcVirtualRouter",
"Vpn": "VpcVirtualRouter",
"UserData": "VpcVirtualRouter",
"Lb": "InternalLbVM",
"SourceNat": "VpcVirtualRouter",
"StaticNat": "VpcVirtualRouter",
"PortForwarding": "VpcVirtualRouter",
"NetworkACL": "VpcVirtualRouter",
},
"serviceCapabilityList": {
"SourceNat": {"SupportedSourceNatTypes": "peraccount"},
"Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"}
}
},
"vpn_user": {
"username": "test",
"password": "password",
}
}
class TestVpcVpn(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.apiclient = super(TestVpcVpn, cls).getClsTestClient().getApiClient()
cls.services = Services().services
cls.zone = get_zone(cls.apiclient, cls.services)
cls.domain = get_domain(cls.apiclient)
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.services["service_offering"]
)
cls.account = Account.create(cls.apiclient, services=cls.services["account"])
cls.template = get_template(
cls.apiclient,
cls.zone.id,
cls.services["ostype"]
)
cls.cleanup = [cls.account]
@attr(tags=["advanced"])
def test_vpc_vpn(self):
"""Test VPN in VPC"""
# 0) Get the default network offering for VPC
networkOffering = NetworkOffering.list(self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks")
self.assert_(networkOffering is not None and len(networkOffering) > 0, "No VPC based network offering")
# 1) Create VPC
vpcOffering = VpcOffering.list(self.apiclient,isdefault=True)
self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found")
self.services["vpc"] = {}
self.services["vpc"]["name"] = "vpc-vpn"
self.services["vpc"]["displaytext"] = "vpc-vpn"
self.services["vpc"]["cidr"] = "10.1.1.0/24"
vpc = VPC.create(
apiclient=self.apiclient,
services=self.services["vpc"],
networkDomain="vpc.vpn",
vpcofferingid=vpcOffering[0].id,
zoneid=self.zone.id,
account=self.account.name,
domainid=self.domain.id
)
self.assert_(vpc is not None, "VPC creation failed")
# 2) Create network in VPC
self.services["vpcnetwork"] = {}
self.services["vpcnetwork"]["name"] = "vpcntwk"
self.services["vpcnetwork"]["displaytext"] = "vpcntwk"
ntwk = Network.create(
apiclient=self.apiclient,
services=self.services["vpcnetwork"],
accountid=self.account.name,
domainid=self.domain.id,
networkofferingid=networkOffering[0].id,
zoneid=self.zone.id,
vpcid=vpc.id,
gateway="10.1.1.1",
netmask="255.255.255.192"
)
self.assertIsNotNone(ntwk, "Network failed to create")
self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id))
# 3) Deploy a vm
self.services["virtual_machine"]["networkids"] = ntwk.id
vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
templateid=self.template.id,
zoneid=self.zone.id,
accountid=self.account.name,
domainid= self.domain.id,
serviceofferingid=self.service_offering.id,
)
self.assert_(vm is not None, "VM failed to deploy")
self.assert_(vm.state == 'Running', "VM is not running")
self.debug("VM %s deployed in VPC %s" %(vm.id, vpc.id))
# 4) Enable VPN for VPC
src_nat_list = PublicIPAddress.list(
self.apiclient,
account=self.account.name,
domainid=self.account.domainid,
listall=True,
issourcenat=True,
vpcid=vpc.id
)
ip = src_nat_list[0]
vpn = Vpn.create(self.apiclient,
publicipid=ip.id,
account=self.account.name,
domainid=self.account.domainid)
# 5) Add VPN user for VPC
vpnUser = VpnUser.create(self.apiclient,
account=self.account.name,
domainid=self.account.domainid,
username=self.services["vpn_user"]["username"],
password=self.services["vpn_user"]["password"])
# 6) Disable VPN for VPC
vpn.delete(self.apiclient)
@classmethod
def tearDownClass(cls):
try:
cleanup_resources(cls.apiclient, cls.cleanup)
except Exception, e:
raise Exception("Cleanup failed with %s" % e)