Add VPN apis, some systemvm changes for vpn

This commit is contained in:
Chiradeep Vittal 2010-11-01 10:26:40 -07:00
parent 71f37ff1c7
commit 1e0eb04442
36 changed files with 1731 additions and 13 deletions

View File

@ -215,4 +215,9 @@ listInstanceGroups=com.cloud.api.commands.ListVMGroupsCmd;15
uploadCustomCertificate=com.cloud.api.commands.UploadCustomCertificateCmd;15
### other commands
listHypervisors=com.cloud.api.commands.ListHypervisorsCmd;15
listHypervisors=com.cloud.api.commands.ListHypervisorsCmd;15
### VPN
createRemoteAccessVpn=com.cloud.api.commands.CreateRemoteAccessVpnCmd;15
deleteRemoteAccessVpn=com.cloud.api.commands.DeleteRemoteAccessVpnCmd;15
listRemoteAccessVpns=com.cloud.api.commands.ListRemoteAccessVpnsCmd;15

View File

@ -114,7 +114,8 @@
<dao name="NicDao" class="com.cloud.vm.dao.NicDaoImpl"/>
<dao name="InstanceGroupDao" class="com.cloud.vm.dao.InstanceGroupDaoImpl"/>
<dao name="Instance Group to VM Mapping" class="com.cloud.vm.dao.InstanceGroupVMMapDaoImpl"/>
<dao name="Remote Access VPN" class="com.cloud.network.dao.RemoteAccessVpnDaoImpl"/>
<adapters key="com.cloud.agent.manager.allocator.HostAllocator">
<adapter name="FirstFitRouting" class="com.cloud.agent.manager.allocator.impl.RecreateHostAllocator"/>
<!--adapter name="FirstFit" class="com.cloud.agent.manager.allocator.impl.FirstFitAllocator"/-->

View File

@ -0,0 +1,90 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.agent.api.routing;
public class RemoteAccessVpnCfgCommand extends RoutingCommand {
String vpnAppliancePrivateIpAddress; //router private ip address typically
boolean create;
String vpnServerIp;
String ipRange;
String presharedKey;
String localIp;
protected RemoteAccessVpnCfgCommand() {
this.create = false;
}
public boolean isCreate() {
return create;
}
@Override
public boolean executeInSequence() {
return true;
}
public RemoteAccessVpnCfgCommand(boolean create, String routerPrivateIp, String vpnServerAddress, String localIp, String ipRange, String ipsecPresharedKey) {
this.vpnAppliancePrivateIpAddress = routerPrivateIp;
this.vpnServerIp = vpnServerAddress;
this.ipRange = ipRange;
this.presharedKey = ipsecPresharedKey;
this.localIp = localIp;
this.create = create;
}
public String getVpnServerIp() {
return vpnServerIp;
}
public void setVpnServerIp(String vpnServerIp) {
this.vpnServerIp = vpnServerIp;
}
public String getIpRange() {
return ipRange;
}
public void setIpRange(String ipRange) {
this.ipRange = ipRange;
}
public String getPresharedKey() {
return presharedKey;
}
public void setPresharedKey(String presharedKey) {
this.presharedKey = presharedKey;
}
public String getLocalIp() {
return localIp;
}
public String getVpnAppliancePrivateIpAddress() {
return vpnAppliancePrivateIpAddress;
}
public String getRouterPrivateIpAddress() {
return vpnAppliancePrivateIpAddress;
}
}

View File

@ -162,4 +162,8 @@ public class EventTypes {
public static final String EVENT_MAINTENANCE_CANCEL_PRIMARY_STORAGE = "MAINT.CANCEL.PS";
public static final String EVENT_MAINTENANCE_PREPARE = "MAINT.PREPARE";
public static final String EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE = "MAINT.PREPARE.PS";
//VPN
public static final String EVENT_REMOTE_ACCESS_VPN_CREATE = "VPN.REMOTE.ACCESS.CREATE";
public static final String EVENT_REMOTE_ACCESS_VPN_DESTROY = "VPN.REMOTE.ACCESS.DESTROY";
}

View File

@ -131,6 +131,7 @@ import com.cloud.agent.api.routing.IPAssocCommand;
import com.cloud.agent.api.routing.LoadBalancerCfgCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.SetFirewallRuleCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
@ -642,6 +643,8 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
return execute((PoolEjectCommand) cmd);
} else if (cmd instanceof Start2Command) {
return execute((Start2Command)cmd);
} else if (cmd instanceof RemoteAccessVpnCfgCommand) {
return execute((RemoteAccessVpnCfgCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -1204,6 +1207,25 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR
}
return new Answer(cmd);
}
protected synchronized Answer execute(final RemoteAccessVpnCfgCommand cmd) {
String args = cmd.getRouterPrivateIpAddress();
if (cmd.isCreate()) {
args += " -r " + cmd.getIpRange();
args += " -p " + cmd.getPresharedKey();
args += " -s " + cmd.getVpnServerIp();
args += " -l " + cmd.getLocalIp();
args += " -c";
} else {
args += " -d";
}
String result = callHostPlugin("vmops", "lt2p_vpn", "args", args);
if (result == null || result.isEmpty()) {
return new Answer(cmd, false, "Configure VPN failed");
}
return new Answer(cmd);
}
protected Answer execute(final VmDataCommand cmd) {
String routerPrivateIpAddress = cmd.getRouterPrivateIpAddress();

View File

@ -0,0 +1,135 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
@Entity
@Table(name=("remote_access_vpn"))
@SecondaryTable(name="account",
pkJoinColumns={@PrimaryKeyJoinColumn(name="account_id", referencedColumnName="id")})
public class RemoteAccessVpnVO {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@Column(name="account_id")
private long accountId;
@Column(name="zone_id")
private long zoneId;
@Column(name="account_name", table="account", insertable=false, updatable=false)
private String accountName = null;
@Column(name="domain_id", table="account", insertable=false, updatable=false)
private long domainId;
@Column(name="vpn_server_addr")
private String vpnServerAddress;
@Column(name="local_ip")
private String localIp;
@Column(name="ip_range")
private String ipRange;
@Column(name="ipsec_psk")
private String ipsecPresharedKey;
public RemoteAccessVpnVO() { }
public RemoteAccessVpnVO(long accountId, long zoneId, String publicIp, String localIp, String ipRange, String presharedKey) {
this.accountId = accountId;
this.vpnServerAddress = publicIp;
this.ipRange = ipRange;
this.ipsecPresharedKey = presharedKey;
this.zoneId = zoneId;
this.localIp = localIp;
}
public Long getId() {
return id;
}
public long getAccountId() {
return accountId;
}
public String getAccountName() {
return accountName;
}
public String getVpnServerAddress() {
return vpnServerAddress;
}
public void setVpnServerAddress(String vpnServerAddress) {
this.vpnServerAddress = vpnServerAddress;
}
public String getIpRange() {
return ipRange;
}
public void setIpRange(String ipRange) {
this.ipRange = ipRange;
}
public String getIpsecPresharedKey() {
return ipsecPresharedKey;
}
public void setIpsecPresharedKey(String ipsecPresharedKey) {
this.ipsecPresharedKey = ipsecPresharedKey;
}
public void setId(Long id) {
this.id = id;
}
public void setZoneId(long zoneId) {
this.zoneId = zoneId;
}
public long getZoneId() {
return zoneId;
}
public String getLocalIp() {
return localIp;
}
public long getDomainId() {
return domainId;
}
}

View File

@ -0,0 +1,27 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.dao;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.utils.db.GenericDao;
public interface RemoteAccessVpnDao extends GenericDao<RemoteAccessVpnVO, Long> {
RemoteAccessVpnVO findByPublicIpAddress(String ipAddress);
RemoteAccessVpnVO findByAccountAndZone(Long accountId, Long zoneId);
}

View File

@ -0,0 +1,62 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.network.dao;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@Local(value={RemoteAccessVpnDao.class})
public class RemoteAccessVpnDaoImpl extends GenericDaoBase<RemoteAccessVpnVO, Long> implements RemoteAccessVpnDao {
private static final Logger s_logger = Logger.getLogger(RemoteAccessVpnDaoImpl.class);
private final SearchBuilder<RemoteAccessVpnVO> ListByIp;
private final SearchBuilder<RemoteAccessVpnVO> AccountAndZoneSearch;
protected RemoteAccessVpnDaoImpl() {
ListByIp = createSearchBuilder();
ListByIp.and("ipAddress", ListByIp.entity().getVpnServerAddress(), SearchCriteria.Op.EQ);
ListByIp.done();
AccountAndZoneSearch = createSearchBuilder();
AccountAndZoneSearch.and("accountId", AccountAndZoneSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountAndZoneSearch.and("zoneId", AccountAndZoneSearch.entity().getZoneId(), SearchCriteria.Op.EQ);
AccountAndZoneSearch.done();
}
@Override
public RemoteAccessVpnVO findByPublicIpAddress(String ipAddress) {
SearchCriteria<RemoteAccessVpnVO> sc = ListByIp.create();
sc.setParameters("ipAddress", ipAddress);
return findOneBy(sc);
}
@Override
public RemoteAccessVpnVO findByAccountAndZone(Long accountId, Long zoneId) {
SearchCriteria<RemoteAccessVpnVO> sc = AccountAndZoneSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("zoneId", zoneId);
return findOneBy(sc);
}
}

View File

@ -335,10 +335,14 @@ xenstore_utils() {
for f in $(find ${scriptdir}/xe/ -name xe-*)
do
cp $f ./usr/sbin/
chmod a+x /usr/sbin/xe-*
chmod a+x ./usr/sbin/xe-*
done
}
vpn_config() {
cp -r ${scriptdir}/vpn/* ./
}
packages() {
DEBIAN_FRONTEND=noninteractive
DEBIAN_PRIORITY=critical
@ -346,7 +350,7 @@ packages() {
export DEBIAN_FRONTEND DEBIAN_PRIORITY DEBCONF_DB_OVERRIDE
#basic stuff
chroot . apt-get --no-install-recommends -q -y --force-yes install rsyslog logrotate cron chkconfig insserv net-tools ifupdown vim-tiny netbase iptables openssh-server grub e2fsprogs dhcp3-client dnsmasq tcpdump socat wget python bzip2 sed gawk diff grep gzip less tar telnet traceroute psmisc procps monit inetutils-ping iputils-arping httping dnsutils zip unzip ethtool uuid file iproute acpid iptables-persistent sysstat
chroot . apt-get --no-install-recommends -q -y --force-yes install rsyslog logrotate cron chkconfig insserv net-tools ifupdown vim-tiny netbase iptables openssh-server grub e2fsprogs dhcp3-client dnsmasq tcpdump socat wget python bzip2 sed gawk diff grep gzip less tar telnet traceroute psmisc lsof procps monit inetutils-ping iputils-arping httping dnsutils zip unzip ethtool uuid file iproute acpid iptables-persistent sysstat
#apache
chroot . apt-get --no-install-recommends -q -y --force-yes install apache2 ssl-cert
#haproxy
@ -422,6 +426,7 @@ cleanup() {
signature() {
(cd ${scriptdir}/config; tar czf ${MOUNTPOINT}/usr/share/cloud/cloud-scripts.tgz *)
md5sum ${MOUNTPOINT}/usr/share/cloud/cloud-scripts.tgz |awk '{print $1}' > ${MOUNTPOINT}/var/cache/cloud/cloud-scripts-signature
echo "Cloudstack Release 2.2 $(date)" > ${MOUNTPOUNT}/etc/cloudstack-release
}
mkdir -p $IMAGENAME
@ -487,6 +492,9 @@ services
echo "*************CONFIGURING APACHE********************"
apache2
echo "*************CONFIGURING VPN********************"
vpn_config
echo "*************CLEANING UP********************"
cleanup

View File

@ -0,0 +1,4 @@
if [ "`id -u`" -eq 0 ]; then
PATH=${PATH}:/opt/cloud/bin
fi
export PATH

View File

@ -0,0 +1,50 @@
# /etc/ipsec.conf - Openswan IPsec configuration file
# This file: /usr/share/doc/openswan/ipsec.conf-sample
#
# Manual: ipsec.conf.5
version 2.0 # conforms to second version of ipsec.conf specification
# basic configuration
config setup
# Do not set debug options to debug configuration issues!
# plutodebug / klipsdebug = "all", "none" or a combation from below:
# "raw crypt parsing emitting control klips pfkey natt x509 dpd private"
# eg:
# plutodebug="control parsing"
#
# enable to get logs per-peer
# plutoopts="--perpeerlog"
#
# Again: only enable plutodebug or klipsdebug when asked by a developer
#
# NAT-TRAVERSAL support, see README.NAT-Traversal
nat_traversal=yes
# exclude networks used on server side by adding %v4:!a.b.c.0/24
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
# OE is now off by default. Uncomment and change to on, to enable.
oe=off
# which IPsec stack to use. auto will try netkey, then klips then mast
protostack=auto
# Add connections here
# sample VPN connection
# for more examples, see /etc/ipsec.d/examples/
#conn sample
# # Left security gateway, subnet behind it, nexthop toward right.
# left=10.0.0.1
# leftsubnet=172.16.0.0/24
# leftnexthop=10.22.33.44
# # Right security gateway, subnet behind it, nexthop toward left.
# right=10.12.12.1
# rightsubnet=192.168.0.0/24
# rightnexthop=10.101.102.103
# # To authorize this connection, but not actually start it,
# # at startup, uncomment this.
# #auto=add
include /etc/ipsec.d/*.conf

View File

@ -0,0 +1,48 @@
# /etc/ipsec.conf - Openswan IPsec configuration file
# This file: /usr/share/doc/openswan/ipsec.conf-sample
#
# Manual: ipsec.conf.5
version 2.0 # conforms to second version of ipsec.conf specification
# basic configuration
config setup
# Do not set debug options to debug configuration issues!
# plutodebug / klipsdebug = "all", "none" or a combation from below:
# "raw crypt parsing emitting control klips pfkey natt x509 dpd private"
# eg:
# plutodebug="control parsing"
#
# enable to get logs per-peer
# plutoopts="--perpeerlog"
#
# Again: only enable plutodebug or klipsdebug when asked by a developer
#
# NAT-TRAVERSAL support, see README.NAT-Traversal
nat_traversal=yes
# exclude networks used on server side by adding %v4:!a.b.c.0/24
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
# OE is now off by default. Uncomment and change to on, to enable.
oe=off
# which IPsec stack to use. auto will try netkey, then klips then mast
protostack=auto
# Add connections here
# sample VPN connection
# for more examples, see /etc/ipsec.d/examples/
#conn sample
# # Left security gateway, subnet behind it, nexthop toward right.
# left=10.0.0.1
# leftsubnet=172.16.0.0/24
# leftnexthop=10.22.33.44
# # Right security gateway, subnet behind it, nexthop toward left.
# right=10.12.12.1
# rightsubnet=192.168.0.0/24
# rightnexthop=10.101.102.103
# # To authorize this connection, but not actually start it,
# # at startup, uncomment this.
# #auto=add

View File

@ -0,0 +1,33 @@
conn L2TP-PSK
authby=secret
pfs=no
rekey=no
keyingtries=3
#
# ----------------------------------------------------------
# The VPN server.
#
# Allow incoming connections on the external network interface.
# If you want to use a different interface or if there is no
# defaultroute, you can use: left=your.ip.addr.ess
#
left=172.26.0.151
#
leftprotoport=17/1701
# If you insist on supporting non-updated Windows clients,
# you can use: leftprotoport=17/%any
#
# ----------------------------------------------------------
# The remote user(s).
#
# Allow incoming connections only from this IP address.
right=%any
# If you want to allow multiple connections from any IP address,
# you can use: right=%any
#
rightprotoport=17/%any
#
# ----------------------------------------------------------
# Change 'ignore' to 'add' to enable this configuration.
#
auto=add

View File

@ -0,0 +1,12 @@
# RCSID $Id: ipsec.secrets.proto,v 1.3.6.1 2005/09/28 13:59:14 paul Exp $
# This file holds shared secrets or RSA private keys for inter-Pluto
# authentication. See ipsec_pluto(8) manpage, and HTML documentation.
# RSA private key for this host, authenticating it to any other host
# which knows the public part. Suitable public keys, for ipsec.conf, DNS,
# or configuration of other implementations, can be extracted conveniently
# with "ipsec showhostkey".
# this file is managed with debconf and will contain the automatically created RSA keys
include /var/lib/openswan/ipsec.secrets.inc
include /etc/ipsec.d/ipsec.*.secrets

View File

@ -0,0 +1,11 @@
# RCSID $Id: ipsec.secrets.proto,v 1.3.6.1 2005/09/28 13:59:14 paul Exp $
# This file holds shared secrets or RSA private keys for inter-Pluto
# authentication. See ipsec_pluto(8) manpage, and HTML documentation.
# RSA private key for this host, authenticating it to any other host
# which knows the public part. Suitable public keys, for ipsec.conf, DNS,
# or configuration of other implementations, can be extracted conveniently
# with "ipsec showhostkey".
# this file is managed with debconf and will contain the automatically created RSA keys
include /var/lib/openswan/ipsec.secrets.inc

View File

@ -0,0 +1,14 @@
proxyarp
ipcp-accept-local
ipcp-accept-remote
noccp
idle 1800
auth
crtscts
mtu 1410
mru 1410
nodefaultroute
debug
lock
connect-delay 5000
ms-dns 10.1.1.1

View File

@ -0,0 +1,6 @@
[lns default]
ip range = 10.1.9.2-10.1.9.8
local ip = 10.1.9.1
require chap = yes
refuse pap = yes
pppoptfile = /etc/ppp/options.xl2tpd

View File

@ -0,0 +1,76 @@
;
; Sample l2tpd configuration file
;
; This example file should give you some idea of how the options for l2tpd
; should work. The best place to look for a list of all options is in
; the source code itself, until I have the time to write better documetation :)
; Specifically, the file "file.c" contains a list of commands at the end.
;
; You most definitely don't have to spell out everything as it is done here
;
; [global] ; Global parameters:
; port = 1701 ; * Bind to port 1701
; auth file = /etc/l2tpd/l2tp-secrets ; * Where our challenge secrets are
; access control = yes ; * Refuse connections without IP match
; rand source = dev ; Source for entropy for random
; ; numbers, options are:
; ; dev - reads of /dev/urandom
; ; sys - uses rand()
; ; egd - reads from egd socket
; ; egd is not yet implemented
;
; [lns default] ; Our fallthrough LNS definition
; exclusive = no ; * Only permit one tunnel per host
; ip range = 192.168.0.1-192.168.0.20 ; * Allocate from this IP range
; no ip range = 192.168.0.3-192.168.0.9 ; * Except these hosts
; ip range = 192.168.0.5 ; * But this one is okay
; ip range = lac1-lac2 ; * And anything from lac1 to lac2's IP
; lac = 192.168.1.4 - 192.168.1.8 ; * These can connect as LAC's
; no lac = untrusted.marko.net ; * This guy can't connect
; hidden bit = no ; * Use hidden AVP's?
; local ip = 192.168.1.2 ; * Our local IP to use
; length bit = yes ; * Use length bit in payload?
; require chap = yes ; * Require CHAP auth. by peer
; refuse pap = yes ; * Refuse PAP authentication
; refuse chap = no ; * Refuse CHAP authentication
; refuse authentication = no ; * Refuse authentication altogether
; require authentication = yes ; * Require peer to authenticate
; unix authentication = no ; * Use /etc/passwd for auth.
; name = myhostname ; * Report this as our hostname
; ppp debug = no ; * Turn on PPP debugging
; pppoptfile = /etc/ppp/options.l2tpd.lns ; * ppp options file
; call rws = 10 ; * RWS for call (-1 is valid)
; tunnel rws = 4 ; * RWS for tunnel (must be > 0)
; flow bit = yes ; * Include sequence numbers
; challenge = yes ; * Challenge authenticate peer ;
; rx bps = 10000000 ; Receive tunnel speed
; tx bps = 10000000 ; Transmit tunnel speed
; bps = 100000 ; Define both receive and transmit speed in one option
; [lac marko] ; Example VPN LAC definition
; lns = lns.marko.net ; * Who is our LNS?
; lns = lns2.marko.net ; * A backup LNS (not yet used)
; redial = yes ; * Redial if disconnected?
; redial timeout = 15 ; * Wait n seconds between redials
; max redials = 5 ; * Give up after n consecutive failures
; hidden bit = yes ; * User hidden AVP's?
; local ip = 192.168.1.1 ; * Force peer to use this IP for us
; remote ip = 192.168.1.2 ; * Force peer to use this as their IP
; length bit = no ; * Use length bit in payload?
; require pap = no ; * Require PAP auth. by peer
; require chap = yes ; * Require CHAP auth. by peer
; refuse pap = yes ; * Refuse PAP authentication
; refuse chap = no ; * Refuse CHAP authentication
; refuse authentication = no ; * Refuse authentication altogether
; require authentication = yes ; * Require peer to authenticate
; name = marko ; * Report this as our hostname
; ppp debug = no ; * Turn on PPP debugging
; pppoptfile = /etc/ppp/options.l2tpd.marko ; * ppp options file for this lac
; call rws = 10 ; * RWS for call (-1 is valid)
; tunnel rws = 4 ; * RWS for tunnel (must be > 0)
; flow bit = yes ; * Include sequence numbers
; challenge = yes ; * Challenge authenticate peer
;
; [lac cisco] ; Another quick LAC
; lns = cisco.marko.net ; * Required, but can take from default
; require authentication = yes

View File

@ -0,0 +1,151 @@
#!/bin/bash
set -x
usage() {
printf "Usage: %s: \n" $(basename $0)
}
get_intf_ip() {
ip addr show $1 | grep -w inet | awk '{print $2}' | awk -F'/' '{print $1}'
}
iptables_() {
local op=$1
local public_if="eth2"
local subnet_if="eth0"
local subnet_ip=$(get_intf_ip $subnet_if)
iptables $op INPUT -i $public_if -p udp -m udp --dport 1701 -j ACCEPT
iptables $op INPUT -i $public_if -p udp -m udp --dport 500 -j ACCEPT
iptables $op INPUT -i $public_if -p udp -m udp --dport 4500 -j ACCEPT
iptables $op INPUT -i eth2 -p ah -j ACCEPT
iptables $op INPUT -i eth2 -p esp -j ACCEPT
iptables $op FORWARD -i ppp+ -o $subnet_if -j ACCEPT
iptables $op FORWARD -i $subnet_if -o ppp+ -j ACCEPT
iptables $op FORWARD -i ppp+ -o ppp+ -j ACCEPT
iptables $op INPUT -i ppp+ -m udp -p udp --dport 53 -j ACCEPT
iptables -t nat $op PREROUTING -i ppp+ -p udp -m udp --dport 53 -j DNAT --to-destination $subnet_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 server_ip=$2
local client_range=$3
local local_ip=$4
sed -i -e "s/left=.*$/left=$server_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"
iptables_ "-I"
ipsec_server "restart"
ipsec auto --rereadsecrets
ipsec auto --replace L2TP-PSK
}
destroy_l2tp_ipsec_vpn_server() {
ipsec auto --down L2TP-PSK
iptables_ "-D"
ipsec_server "stop"
}
remove_l2tp_ipsec_user() {
local u=$1
sed -i -e "/^$u .*$/d" /etc/ppp/chap-secrets
}
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:' 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"
;;
?) 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
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

@ -0,0 +1,10 @@
#!/bin/bash
#
# @VERSION@
cert="/root/.ssh/id_rsa.cloud"
domr=$1
shift
ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domr "/opt/cloud/bin/vpn_l2tp.sh $*" >/dev/null
exit $?

View File

@ -271,6 +271,21 @@ def saveDhcpEntry(session, args):
txt = ''
return txt
@echo
def lt2p_vpn(session, args):
sargs = args['args']
cmd = sargs.split(' ')
cmd.insert(0, "/opt/xensource/bin/l2tp_vpn.sh")
cmd.insert(0, "/bin/bash")
try:
txt = util.pread2(cmd)
txt = 'success'
except:
util.SMlog("l2tp vpn failed " )
txt = ''
return txt
@echo
def setLinkLocalIP(session, args):
@ -1088,5 +1103,5 @@ def network_rules(session, args):
if __name__ == "__main__":
XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "getnetwork": getnetwork, "preparemigration": preparemigration, "setIptables": setIptables, "patchdomr": patchdomr, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "checkMount": checkMount, "checkIscsi": checkIscsi, "networkUsage": networkUsage, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP})
XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "getnetwork": getnetwork, "preparemigration": preparemigration, "setIptables": setIptables, "patchdomr": patchdomr, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "checkMount": checkMount, "checkIscsi": checkIscsi, "networkUsage": networkUsage, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn})

View File

@ -36,3 +36,4 @@ save_password_to_domr.sh=../../../../network/domr/,0755,/opt/xensource/bin
networkUsage.sh=../../../../network/domr/,0755,/opt/xensource/bin
call_firewall.sh=../../../../network/domr/,0755,/opt/xensource/bin
call_loadbalancer.sh=../../../../network/domr/,0755,/opt/xensource/bin
l2tp_vpn.sh=../../../../network/domr/,0755,/opt/xensource/bin

View File

@ -0,0 +1,148 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCreateCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.event.EventTypes;
import com.cloud.network.NetworkManager;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
@Implementation(createMethod="createRemoteAccessVpn", method="startRemoteAccessVpn", manager=NetworkManager.class, description="Creates a l2tp/ipsec remote access vpn")
public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd {
public static final Logger s_logger = Logger.getLogger(CreateRemoteAccessVpnCmd.class.getName());
private static final String s_name = "createremoteaccessvpnresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name="zoneid", type=CommandType.LONG, required=true, description="zone id where the vpn server needs to be created")
private Long zoneId;
@Parameter(name="publicip", type=CommandType.STRING, required=false, description="public ip address of the vpn server")
private String publicIp;
@Parameter(name="iprange", type=CommandType.STRING, required=false, description="the range of ip addresses to allocate to vpn clients. The first ip in the range will be taken by the vpn server")
private String ipRange;
@Parameter(name="account", type=CommandType.STRING, description="an optional account for the virtual machine. Must be used with domainId.")
private String accountName;
@Parameter(name="domainid", type=CommandType.LONG, description="an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used.")
private Long domainId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getPublicIp() {
return publicIp;
}
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public void setPublicIp(String publicIp) {
this.publicIp = publicIp;
}
public String getIpRange() {
return ipRange;
}
public void setIpRange(String ipRange) {
this.ipRange = ipRange;
}
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public Long getZoneId() {
return zoneId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
public String getName() {
return s_name;
}
@Override @SuppressWarnings("unchecked")
public RemoteAccessVpnResponse getResponse() {
RemoteAccessVpnVO responseObj = (RemoteAccessVpnVO)getResponseObject();
RemoteAccessVpnResponse response = new RemoteAccessVpnResponse();
response.setId(responseObj.getId());
response.setPublicIp(responseObj.getVpnServerAddress());
response.setIpRange(responseObj.getIpRange());
response.setAccountName(responseObj.getAccountName());
response.setDomainId(responseObj.getDomainId());
response.setDomainName(ApiDBUtils.findDomainById(responseObj.getDomainId()).getName());
response.setResponseName(getName());
return response;
}
@Override
public long getAccountId() {
Account account = (Account)UserContext.current().getAccount();
if ((account == null) || isAdmin(account.getType())) {
if ((domainId != null) && (accountName != null)) {
Account userAccount = ApiDBUtils.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public String getEventDescription() {
return "Create Remote Access VPN for account " + getAccountId() + " in zone " + getZoneId();
}
@Override
public String getEventType() {
return EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE;
}
}

View File

@ -0,0 +1,120 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseAsyncCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.response.SuccessResponse;
import com.cloud.event.EventTypes;
import com.cloud.network.NetworkManager;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
@Implementation(method="destroyRemoteAccessVpn", manager=NetworkManager.class, description="Destroys a l2tp/ipsec remote access vpn")
public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeleteRemoteAccessVpnCmd.class.getName());
private static final String s_name = "deleteremoteaccessvpnresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name="zoneid", type=CommandType.LONG, required=true, description="zone id where the vpn server needs to be created")
private Long zoneId;
@Parameter(name="account", type=CommandType.STRING, description="an optional account for the virtual machine. Must be used with domainId.")
private String accountName;
@Parameter(name="domainid", type=CommandType.LONG, description="an optional domainId for the virtual machine. If the account parameter is used, domainId must also be used.")
private Long domainId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public Long getZoneId() {
return zoneId;
}
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
public String getName() {
return s_name;
}
@Override @SuppressWarnings("unchecked")
public SuccessResponse getResponse() {
Boolean success = (Boolean)getResponseObject();
SuccessResponse response = new SuccessResponse();
response.setSuccess(success);
response.setResponseName(getName());
return response;
}
@Override
public long getAccountId() {
Account account = (Account)UserContext.current().getAccount();
if ((account == null) || isAdmin(account.getType())) {
if ((domainId != null) && (accountName != null)) {
Account userAccount = ApiDBUtils.findAccountByNameDomain(accountName, domainId);
if (userAccount != null) {
return userAccount.getId();
}
}
}
if (account != null) {
return account.getId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public String getEventDescription() {
return "Delete Remote Access VPN for account " + getAccountId() + " in zone " + getZoneId();
}
@Override
public String getEventType() {
return EventTypes.EVENT_REMOTE_ACCESS_VPN_DESTROY;
}
}

View File

@ -0,0 +1,129 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.commands;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.BaseListCmd;
import com.cloud.api.Implementation;
import com.cloud.api.Parameter;
import com.cloud.api.response.RemoteAccessVpnResponse;
import com.cloud.api.response.ListResponse;
import com.cloud.api.response.LoadBalancerResponse;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.user.Account;
@Implementation(method="searchForRemoteAccessVpns", description="Lists remote access vpns")
public class ListRemoteAccessVpnsCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger (ListRemoteAccessVpnsCmd.class.getName());
private static final String s_name = "listremoteaccessvpnsresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name="account", type=CommandType.STRING, description="the account of the remote access vpn. Must be used with the domainId parameter.")
private String accountName;
@Parameter(name="domainid", type=CommandType.LONG, description="the domain ID of the remote access vpn rule. If used with the account parameter, lists remote access vpns for the account in the specified domain.")
private Long domainId;
@Parameter(name="id", type=CommandType.LONG, description="the ID of the remote access vpn")
private Long id;
@Parameter(name="zoneid", type=CommandType.LONG, description="the zone ID of the remote access vpn rule")
private Long zoneId;
@Parameter(name="publicip", type=CommandType.STRING, description="the public IP address of the remote access vpn ")
private String publicIp;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public Long getId() {
return id;
}
public void setZoneId(Long zoneId) {
this.zoneId = zoneId;
}
public Long getZoneId() {
return zoneId;
}
public String getPublicIp() {
return publicIp;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getName() {
return s_name;
}
@Override @SuppressWarnings("unchecked")
public ListResponse<RemoteAccessVpnResponse> getResponse() {
List<RemoteAccessVpnVO> vpns = (List<RemoteAccessVpnVO>)getResponseObject();
ListResponse<RemoteAccessVpnResponse> response = new ListResponse<RemoteAccessVpnResponse>();
List<RemoteAccessVpnResponse> vpnResponses = new ArrayList<RemoteAccessVpnResponse>();
for (RemoteAccessVpnVO vpn : vpns) {
RemoteAccessVpnResponse vpnResponse = new RemoteAccessVpnResponse();
vpnResponse.setId(vpn.getId());
vpnResponse.setPublicIp(vpn.getVpnServerAddress());
vpnResponse.setIpRange(vpn.getIpRange());
vpnResponse.setPresharedKey(vpn.getIpsecPresharedKey());
vpnResponse.setAccountName(vpn.getAccountName());
Account accountTemp = ApiDBUtils.findAccountById(vpn.getAccountId());
if (accountTemp != null) {
vpnResponse.setDomainId(accountTemp.getDomainId());
vpnResponse.setDomainName(ApiDBUtils.findDomainById(accountTemp.getDomainId()).getName());
}
vpnResponse.setResponseName("remoteaccessvpn");
vpnResponses.add(vpnResponse);
}
response.setResponses(vpnResponses);
response.setResponseName(getName());
return response;
}
}

View File

@ -0,0 +1,104 @@
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.api.response;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class RemoteAccessVpnResponse extends BaseResponse {
@SerializedName("id") @Param(description="the vpn ID")
private Long id;
@SerializedName("publicip") @Param(description="the public ip address of the vpn server")
private String publicIp;
@SerializedName("ipRange") @Param(description="the range of ips to allocate to the clients")
private String ipRange;
@SerializedName("presharedkey") @Param(description="the ipsec preshared key")
private String presharedKey;
@SerializedName("account") @Param(description="the account of the remote access vpn")
private String accountName;
@SerializedName("domainid") @Param(description="the domain id of the account of the remote access vpn")
private long domainId;
@SerializedName("domainname") @Param(description="the domain name of the account of the remote access vpn")
private String domainName;
public String getAccountName() {
return accountName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPublicIp() {
return publicIp;
}
public void setPublicIp(String publicIp) {
this.publicIp = publicIp;
}
public String getIpRange() {
return ipRange;
}
public void setIpRange(String ipRange) {
this.ipRange = ipRange;
}
public String getPresharedKey() {
return presharedKey;
}
public void setPresharedKey(String presharedKey) {
this.presharedKey = presharedKey;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public void setDomainId(long domainId) {
this.domainId = domainId;
}
public void setDomainName(String name) {
this.domainName = name;
}
public long getDomainId() {
return domainId;
}
public String getDomainName() {
return domainName;
}
}

View File

@ -25,8 +25,11 @@ import com.cloud.api.commands.AssignToLoadBalancerRuleCmd;
import com.cloud.api.commands.AssociateIPAddrCmd;
import com.cloud.api.commands.CreateIPForwardingRuleCmd;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.api.commands.CreateRemoteAccessVpnCmd;
import com.cloud.api.commands.DeleteIPForwardingRuleCmd;
import com.cloud.api.commands.DeleteLoadBalancerRuleCmd;
import com.cloud.api.commands.DeletePortForwardingServiceRuleCmd;
import com.cloud.api.commands.DeleteRemoteAccessVpnCmd;
import com.cloud.api.commands.DisassociateIPAddrCmd;
import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.api.commands.RebootRouterCmd;
@ -318,4 +321,29 @@ public interface NetworkManager extends Manager {
List<NetworkConfigurationVO> setupNetworkConfiguration(Account owner, ServiceOfferingVO offering, DeploymentPlan plan);
String assignSourceNatIpAddress(Account account, DataCenter dc) throws InsufficientAddressCapacityException;
/**
* Create a remote access vpn from the given public ip address and client ip range
* @param cmd the command specifying the ip address, ip range
* @return the newly created RemoteAccessVpnVO if successful, null otherwise
* @throws InvalidParameterValueException
* @throws PermissionDeniedException
* @throws ConcurrentOperationException
*/
public RemoteAccessVpnVO createRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, ConcurrentOperationException;
/**
* Start a remote access vpn for the given public ip address and client ip range
* @param cmd the command specifying the ip address, ip range
* @return the RemoteAccessVpnVO if successful, null otherwise
* @throws ConcurrentOperationException
*/
public RemoteAccessVpnVO startRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd) throws ConcurrentOperationException;
/**
* Destroy a previously created remote access VPN
* @param cmd the command specifying the account and zone
* @return success if successful, false otherwise
* @throws ConcurrentOperationException
*/
public boolean destroyRemoteAccessVpn(DeleteRemoteAccessVpnCmd cmd) throws ConcurrentOperationException;
}

View File

@ -47,8 +47,11 @@ import com.cloud.api.commands.AssignToLoadBalancerRuleCmd;
import com.cloud.api.commands.AssociateIPAddrCmd;
import com.cloud.api.commands.CreateIPForwardingRuleCmd;
import com.cloud.api.commands.CreateLoadBalancerRuleCmd;
import com.cloud.api.commands.CreateRemoteAccessVpnCmd;
import com.cloud.api.commands.DeleteIPForwardingRuleCmd;
import com.cloud.api.commands.DeleteLoadBalancerRuleCmd;
import com.cloud.api.commands.DeletePortForwardingServiceRuleCmd;
import com.cloud.api.commands.DeleteRemoteAccessVpnCmd;
import com.cloud.api.commands.DisassociateIPAddrCmd;
import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.api.commands.RebootRouterCmd;
@ -66,8 +69,8 @@ import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.dao.AccountVlanMapDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
@ -103,6 +106,9 @@ import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkConfigurationDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.router.DomainRouterManager;
import com.cloud.offering.NetworkOffering;
@ -131,16 +137,17 @@ import com.cloud.user.dao.UserDao;
import com.cloud.user.dao.UserStatisticsDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.StringUtils;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.JoinBuilder.JoinType;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.DomainRouter;
@ -200,6 +207,7 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService {
@Inject NetworkConfigurationDao _networkConfigDao = null;
@Inject NicDao _nicDao;
@Inject GuestOSDao _guestOSDao = null;
@Inject RemoteAccessVpnDao _remoteAccessVpnDao = null;
@Inject DomainRouterManager _routerMgr;
@Inject(adapter=NetworkGuru.class)
@ -588,6 +596,37 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService {
return true;
}
/** Returns the target account for an api command
* @param accountName - non-null if the account name was passed in in the command
* @param domainId - non-null if the domainId was passed in in the command.
* @return
*/
protected Account getAccountForApiCommand(String accountName, Long domainId) throws InvalidParameterValueException, PermissionDeniedException{
Account account = UserContext.current().getAccount();
if ((account == null) || isAdmin(account.getType())) {
//The admin is making the call, determine if it is for someone else or for himself
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, , permission denied");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
account = userAccount;
} else {
throw new PermissionDeniedException("Unable to find account " + accountName + " in domain " + domainId + ", permission denied");
}
}
} else if (account != null) {
// the admin is calling the api on his own behalf
return account;
} else {
throw new InvalidParameterValueException("Account information is not specified.");
}
}
return account;
}
@Override @DB
public IPAddressVO associateIP(AssociateIPAddrCmd cmd) throws ResourceAllocationException, InsufficientAddressCapacityException, InvalidParameterValueException, InternalErrorException, PermissionDeniedException {
@ -2547,5 +2586,187 @@ public class NetworkManagerImpl implements NetworkManager, DomainRouterService {
NetworkOfferingVO networkOffering = _networkOfferingDao.findByServiceOffering(offering);
return setupNetworkConfiguration(owner, networkOffering, plan);
}
@Override
@DB
public RemoteAccessVpnVO createRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd)
throws InvalidParameterValueException, PermissionDeniedException, ConcurrentOperationException {
String publicIp = cmd.getPublicIp();
IPAddressVO ipAddr = null;
Account account = getAccountForApiCommand(cmd.getAccountName(), cmd.getDomainId());
if (publicIp == null) {
List<IPAddressVO> accountAddrs = _ipAddressDao.listByAccount(account.getId());
for (IPAddressVO addr: accountAddrs){
if (addr.getSourceNat() && addr.getDataCenterId() == cmd.getZoneId()){
ipAddr = addr;
publicIp = ipAddr.getAddress();
break;
}
}
if (ipAddr == null) {
throw new InvalidParameterValueException("Account " + account.getAccountName() + " does not have any public ip addresses in zone " + cmd.getZoneId());
}
}
// make sure ip address exists
ipAddr = _ipAddressDao.findById(publicIp);
if (ipAddr == null) {
throw new InvalidParameterValueException("Unable to create remote access vpn, invalid public IP address " + publicIp);
}
VlanVO vlan = _vlanDao.findById(ipAddr.getVlanDbId());
if (vlan != null) {
if (!VlanType.VirtualNetwork.equals(vlan.getVlanType())) {
throw new InvalidParameterValueException("Unable to create VPN for IP address " + publicIp + ", only VirtualNetwork type IP addresses can be used for VPN.");
}
}
assert vlan != null:"Inconsistent DB state -- ip address does not belong to any vlan?";
if ((ipAddr.getAccountId() == null) || (ipAddr.getAllocated() == null)) {
throw new PermissionDeniedException("Unable to create VPN, permission denied for ip " + publicIp);
}
if (account != null) {
if ((account.getType() == Account.ACCOUNT_TYPE_ADMIN) || (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN)) {
if (!_domainDao.isChildDomain(account.getDomainId(), ipAddr.getDomainId())) {
throw new PermissionDeniedException("Unable to create VPN with public IP address " + publicIp + ", permission denied.");
}
} else if (account.getId() != ipAddr.getAccountId().longValue()) {
throw new PermissionDeniedException("Unable to create VPN for account " + account.getAccountName() + " doesn't own ip address " + publicIp);
}
}
RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIp);
if (vpnVO != null) {
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.findByAccountAndZone(account.getId(), cmd.getZoneId());
if (vpnVO != null) {
throw new InvalidParameterValueException("A Remote Access VPN already exists for this account");
}
String ipRange = cmd.getIpRange();
if (ipRange == null) {
//TODO: get default range from database
ipRange = "10.1.2.1-10.1.2.8";
}
String [] range = ipRange.split("-");
if (range.length != 2) {
throw new InvalidParameterValueException("Invalid ip range");
}
if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])){
throw new InvalidParameterValueException("Invalid ip range");
}
if (!NetUtils.validIpRange(range[0], range[1])){
throw new InvalidParameterValueException("Invalid ip range");
}
if (NetUtils.ipRangesOverlap(range[0], range[1], "10.1.1.1", "10.1.1.255")) {
throw new InvalidParameterValueException("Invalid ip range --- overlaps with guest ip range");
//TODO: get actual guest ip range from config db
}
//TODO: check sufficient range
//TODO: check overlap with private and public ip ranges in datacenter
//TODO: check overlap with port forwarding rules on this ip (udp ports 500, 4500, 1701)
long startIp = NetUtils.ip2Long(range[0]);
String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1];
String sharedSecret = PasswordGenerator.generateRandomPassword(24);
//TODO: use SecureRandom in password generator
Transaction txn = Transaction.currentTxn();
txn.start();
boolean locked = false;
try {
ipAddr = _ipAddressDao.acquire(publicIp);
if (ipAddr == null) {
throw new ConcurrentOperationException("Another operation active, unable to create vpn");
}
locked = true;
vpnVO = new RemoteAccessVpnVO(account.getId(), cmd.getZoneId(), publicIp, range[0], newIpRange, sharedSecret);
_remoteAccessVpnDao.persist(vpnVO);
txn.commit();
return vpnVO;
} finally {
if (locked) {
_ipAddressDao.release(publicIp);
}
}
}
@Override
@DB
public RemoteAccessVpnVO startRemoteAccessVpn(CreateRemoteAccessVpnCmd cmd) throws ConcurrentOperationException {
Long userId = UserContext.current().getUserId();
Account account = getAccountForApiCommand(cmd.getAccountName(), cmd.getDomainId());
EventUtils.saveStartedEvent(userId, account.getId(), EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE, "Creating a Remote Access VPN for account: " + account.getAccountName() + " in zone " + cmd.getZoneId(), cmd.getStartEventId());
RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findById(cmd.getId());
String publicIp = vpnVO.getVpnServerAddress();
Long vpnId = vpnVO.getId();
Transaction txn = Transaction.currentTxn();
txn.start();
boolean locked = false;
boolean created = false;
try {
IPAddressVO ipAddr = _ipAddressDao.acquire(publicIp);
if (ipAddr == null) {
throw new ConcurrentOperationException("Another operation active, unable to create vpn");
}
locked = true;
vpnVO = _routerMgr.startRemoteAccessVpn(vpnVO);
created = (vpnVO != null);
return vpnVO;
} finally {
if (created) {
EventUtils.saveEvent(userId, account.getId(), EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE, "Created a Remote Access VPN for account: " + account.getAccountName() + " in zone " + cmd.getZoneId());
} else {
EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE, "Unable to create Remote Access VPN ", account.getAccountName() + " in zone " + cmd.getZoneId());
_remoteAccessVpnDao.remove(vpnId);
}
txn.commit();
if (locked) {
_ipAddressDao.release(publicIp);
}
}
}
@Override
@DB
public boolean destroyRemoteAccessVpn(DeleteRemoteAccessVpnCmd cmd) throws ConcurrentOperationException {
Long userId = UserContext.current().getUserId();
Account account = getAccountForApiCommand(cmd.getAccountName(), cmd.getDomainId());
//TODO: assumes one virtual network / domr per account per zone
RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByAccountAndZone(account.getId(), cmd.getZoneId());
if (vpnVO == null) {
throw new InvalidParameterValueException("No VPN found for account " + account.getAccountName() + " in zone " + cmd.getZoneId());
}
EventUtils.saveStartedEvent(userId, account.getId(), EventTypes.EVENT_REMOTE_ACCESS_VPN_DESTROY, "Deleting Remote Access VPN for account: " + account.getAccountName() + " in zone " + cmd.getZoneId(), cmd.getStartEventId());
String publicIp = vpnVO.getVpnServerAddress();
Long vpnId = vpnVO.getId();
Transaction txn = Transaction.currentTxn();
txn.start();
boolean locked = false;
boolean deleted = false;
try {
IPAddressVO ipAddr = _ipAddressDao.acquire(publicIp);
if (ipAddr == null) {
throw new ConcurrentOperationException("Another operation active, unable to create vpn");
}
locked = true;
deleted = _routerMgr.deleteRemoteAccessVpn(vpnVO);
return deleted;
} finally {
if (deleted) {
_remoteAccessVpnDao.remove(vpnId);
EventUtils.saveEvent(userId, account.getId(), EventTypes.EVENT_REMOTE_ACCESS_VPN_DESTROY, "Deleted Remote Access VPN for account: " + account.getAccountName() + " in zone " + cmd.getZoneId());
} else {
EventUtils.saveEvent(userId, account.getId(), EventVO.LEVEL_ERROR, EventTypes.EVENT_REMOTE_ACCESS_VPN_DESTROY, "Unable to delete Remote Access VPN ", account.getAccountName() + " in zone " + cmd.getZoneId());
}
txn.commit();
if (locked) {
_ipAddressDao.release(publicIp);
}
}
}
}

View File

@ -34,6 +34,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.NetworkConfiguration;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.offering.NetworkOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.user.Account;
@ -169,4 +170,8 @@ public interface DomainRouterManager extends Manager {
DomainRouterVO getRouter(String publicIpAddress);
DomainRouterVO deploy(NetworkConfiguration guestConfig, NetworkOffering offering, DeployDestination dest, Account owner) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException;
RemoteAccessVpnVO startRemoteAccessVpn(RemoteAccessVpnVO vpnVO);
boolean deleteRemoteAccessVpn(RemoteAccessVpnVO vpnVO);
}

View File

@ -52,6 +52,7 @@ import com.cloud.agent.api.StartRouterCommand;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.agent.api.routing.SavePasswordCommand;
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
@ -109,6 +110,7 @@ import com.cloud.network.Network.TrafficType;
import com.cloud.network.NetworkConfiguration;
import com.cloud.network.NetworkConfigurationVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.network.SshKeysDistriMonitor;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
@ -2105,4 +2107,60 @@ public class DomainRouterManagerImpl implements DomainRouterManager, VirtualMach
return true;
}
@Override
public RemoteAccessVpnVO startRemoteAccessVpn(RemoteAccessVpnVO vpnVO) {
DomainRouterVO router = getRouter(vpnVO.getAccountId(), vpnVO.getZoneId());
if (router == null) {
s_logger.warn("Failed to start remote access VPN: no router found for account and zone");
return null;
}
if (router.getState() != State.Running) {
s_logger.warn("Failed to start remote access VPN: router not in running state");
return null;
}
try {
Answer answer = _agentMgr.send(router.getHostId(), new RemoteAccessVpnCfgCommand(true, router.getPrivateIpAddress(), vpnVO.getVpnServerAddress(), vpnVO.getLocalIp(), vpnVO.getIpRange(), vpnVO.getIpsecPresharedKey()));
if (answer != null && answer.getResult()) {
return vpnVO;
} else {
s_logger.debug("Failed to start remote access VPN: " + answer.getDetails());
return null;
}
} catch (AgentUnavailableException e) {
s_logger.debug("Failed to start remote access VPN: ", e);
return null;
} catch (OperationTimedoutException e) {
s_logger.debug("Failed to start remote access VPN: ", e);
return null;
}
}
@Override
public boolean deleteRemoteAccessVpn(RemoteAccessVpnVO vpnVO) {
DomainRouterVO router = getRouter(vpnVO.getAccountId(), vpnVO.getZoneId());
if (router == null) {
s_logger.warn("Failed to delete remote access VPN: no router found for account and zone");
return false;
}
if (router.getState() != State.Running) {
s_logger.warn("Failed to delete remote access VPN: router not in running state");
return false;
}
try {
Answer answer = _agentMgr.send(router.getHostId(), new RemoteAccessVpnCfgCommand(false, router.getPrivateIpAddress(), vpnVO.getVpnServerAddress(), vpnVO.getLocalIp(), vpnVO.getIpRange(), vpnVO.getIpsecPresharedKey()));
if (answer != null && answer.getResult()) {
return true;
} else {
s_logger.debug("Failed to delete remote access VPN: " + answer.getDetails());
return false;
}
} catch (AgentUnavailableException e) {
s_logger.debug("Failed to delete remote access VPN: ", e);
return false;
} catch (OperationTimedoutException e) {
s_logger.debug("Failed to delete remote access VPN: ", e);
return false;
}
}
}

View File

@ -499,7 +499,7 @@ public class ConfigurationServerImpl implements ConfigurationServer {
if (already == null) {
s_logger.info("Need to store secondary storage vm copy password in the database");
String password = PasswordGenerator.generateRandomPassword();
String password = PasswordGenerator.generateRandomPassword(12);
String insertSql1 = "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " +
"VALUES ('Hidden','DEFAULT', 'management-server','secstorage.copy.password', '" + password + "','Password used to authenticate zone-to-zone template copy requests')";

View File

@ -58,6 +58,7 @@ import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRemoteAccessVpnsCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
@ -113,6 +114,9 @@ import com.cloud.info.ConsoleProxyInfo;
import com.cloud.network.FirewallRuleVO;
import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.NetworkRuleConfigVO;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.network.SecurityGroupVO;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.DiskOfferingVO;
@ -1125,4 +1129,6 @@ public interface ManagementServer {
* @throws ServerApiException -- even if one of the console proxy patching fails, we throw back this exception
*/
String uploadCertificate(UploadCustomCertificateCmd cmd) throws ServerApiException;
public List<RemoteAccessVpnVO> searchForRemoteAccessVpns(ListRemoteAccessVpnsCmd cmd) throws InvalidParameterValueException, PermissionDeniedException;
}

View File

@ -104,6 +104,7 @@ import com.cloud.api.commands.ListLoadBalancerRulesCmd;
import com.cloud.api.commands.ListPodsByCmd;
import com.cloud.api.commands.ListPreallocatedLunsCmd;
import com.cloud.api.commands.ListPublicIpAddressesCmd;
import com.cloud.api.commands.ListRemoteAccessVpnsCmd;
import com.cloud.api.commands.ListRoutersCmd;
import com.cloud.api.commands.ListServiceOfferingsCmd;
import com.cloud.api.commands.ListSnapshotsCmd;
@ -202,10 +203,18 @@ import com.cloud.network.IPAddressVO;
import com.cloud.network.LoadBalancerVMMapVO;
import com.cloud.network.LoadBalancerVO;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkRuleConfigVO;
import com.cloud.network.RemoteAccessVpnVO;
import com.cloud.network.SecurityGroupVMMapVO;
import com.cloud.network.SecurityGroupVO;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkRuleConfigDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.SecurityGroupDao;
import com.cloud.network.dao.SecurityGroupVMMapDao;
import com.cloud.network.security.NetworkGroupManager;
import com.cloud.network.security.NetworkGroupVO;
import com.cloud.network.security.dao.NetworkGroupDao;
@ -375,6 +384,7 @@ public class ManagementServerImpl implements ManagementServer {
private final UploadMonitor _uploadMonitor;
private final UploadDao _uploadDao;
private final CertificateDao _certDao;
private final RemoteAccessVpnDao _remoteAccessVpnDao;
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AccountChecker"));
private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker"));
@ -449,6 +459,7 @@ public class ManagementServerImpl implements ManagementServer {
_groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class);
_uploadDao = locator.getDao(UploadDao.class);
_certDao = locator.getDao(CertificateDao.class);
_remoteAccessVpnDao = locator.getDao(RemoteAccessVpnDao.class);
_configs = _configDao.getConfiguration();
_userStatsDao = locator.getDao(UserStatisticsDao.class);
_vmInstanceDao = locator.getDao(VMInstanceDao.class);
@ -1432,7 +1443,7 @@ public class ManagementServerImpl implements ManagementServer {
@Override
public String generateRandomPassword() {
return PasswordGenerator.generateRandomPassword();
return PasswordGenerator.generateRandomPassword(6);
}
@Override
@ -6048,4 +6059,96 @@ public class ManagementServerImpl implements ManagementServer {
return accountId;
}
@Override
public List<RemoteAccessVpnVO> searchForRemoteAccessVpns(ListRemoteAccessVpnsCmd cmd) throws InvalidParameterValueException,
PermissionDeniedException {
// do some parameter validation
Account account = UserContext.current().getAccount();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
Long accountId = null;
Account ipAddressOwner = null;
String ipAddress = cmd.getPublicIp();
if (ipAddress != null) {
IPAddressVO ipAddressVO = _publicIpAddressDao.findById(ipAddress);
if (ipAddressVO == null) {
throw new InvalidParameterValueException("Unable to list remote access vpns, IP address " + ipAddress + " not found.");
} else {
Long ipAddrAcctId = ipAddressVO.getAccountId();
if (ipAddrAcctId == null) {
throw new InvalidParameterValueException("Unable to list remote access vpns, IP address " + ipAddress + " is not associated with an account.");
}
ipAddressOwner = _accountDao.findById(ipAddrAcctId);
}
}
if ((account == null) || isAdmin(account.getType())) {
// validate domainId before proceeding
if (domainId != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) {
throw new PermissionDeniedException("Unable to list remote access vpns for domain id " + domainId + ", permission denied.");
}
if (accountName != null) {
Account userAccount = _accountDao.findActiveAccount(accountName, domainId);
if (userAccount != null) {
accountId = userAccount.getId();
} else {
throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
}
}
} else if (ipAddressOwner != null) {
if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), ipAddressOwner.getDomainId())) {
throw new PermissionDeniedException("Unable to list remote access vpn for IP address " + ipAddress + ", permission denied.");
}
} else {
domainId = ((account == null) ? DomainVO.ROOT_DOMAIN : account.getDomainId());
}
} else {
accountId = account.getId();
}
Filter searchFilter = new Filter(RemoteAccessVpnVO.class, "vpnServerAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Object id = cmd.getId();
Object zoneId = cmd.getZoneId();
SearchBuilder<RemoteAccessVpnVO> sb = _remoteAccessVpnDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ);
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
sb.and("ipAddress", sb.entity().getVpnServerAddress(), SearchCriteria.Op.EQ);
if ((accountId == null) && (domainId != null)) {
// if accountId isn't specified, we can do a domain match for the admin case
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE);
sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER);
}
SearchCriteria<RemoteAccessVpnVO> sc = sb.create();
if (id != null) {
sc.setParameters("id", id);
}
if (ipAddress != null) {
sc.setParameters("ipAddress", ipAddress);
}
if (zoneId != null) {
sc.setParameters("zoneId", zoneId);
}
if (accountId != null) {
sc.setParameters("accountId", accountId);
} else if (domainId != null) {
DomainVO domain = _domainDao.findById(domainId);
sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%");
}
return _remoteAccessVpnDao.search(sc, searchFilter);
}
}

View File

@ -322,7 +322,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM
VMTemplateVO template = _templateDao.findById(vmInstance.getTemplateId());
if (template.getEnablePassword()) {
password = PasswordGenerator.generateRandomPassword();;
password = PasswordGenerator.generateRandomPassword(6);;
} else {
password = "saved_password";
}
@ -3824,7 +3824,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM
}
// Check that the password was passed in and is valid
String password = PasswordGenerator.generateRandomPassword();
String password = PasswordGenerator.generateRandomPassword(6);
if (!template.getEnablePassword()) {
password = "saved_password";
}

View File

@ -952,6 +952,17 @@ CREATE TABLE `cloud`.`load_balancer` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`remote_access_vpn` (
`id` bigint unsigned NOT NULL auto_increment,
`account_id` bigint unsigned NOT NULL,
`zone_id` bigint unsigned NOT NULL,
`vpn_server_addr` varchar(15) NOT NULL,
`local_ip` varchar(15) NOT NULL,
`ip_range` varchar(32) NOT NULL,
`ipsec_psk` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`storage_pool` (
`id` bigint unsigned UNIQUE NOT NULL,
`name` varchar(255) COMMENT 'should be NOT NULL',

View File

@ -25,7 +25,7 @@ import java.util.Random;
*
*/
public class PasswordGenerator {
public static String generateRandomPassword() {
public static String generateRandomPassword(int num) {
Random r = new Random();
StringBuffer password = new StringBuffer();
@ -46,7 +46,7 @@ public class PasswordGenerator {
// Generate a random 6-character string with only lowercase
// characters
for (int i = 0; i < 6; i++) {
for (int i = 0; i < num; i++) {
// Generate a random lowercase character (don't allow lowercase
// "l" or lowercase "o")
lowercase = generateLowercaseChar(r);