Commit 2962db81 authored by David Johnson's avatar David Johnson

Add support for building the routed-privaddr POWDER VPN case mockup.

parent 074913fd
#! /usr/bin/env python
#
# Copyright (c) 2008-2009, 2015 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
# GENI Public License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#
# }}}
#
#
#
import sys
import pwd
import getopt
import os
import re
import xmlrpclib
from M2Crypto import X509
import os.path
dirname = os.path.abspath(os.path.dirname(sys.argv[0]))
execfile("%s/test-common.py" % (dirname,))
#
# Convert the certificate into a credential.
#
params = {}
rval,response = do_method("", "GetCredential", params)
if rval:
Fatal("Could not get my credential")
pass
mycredential = response["value"]
params["credential"] = mycredential
rval,response = do_method("", "GetManifests", params)
if rval:
Fatal("Could not get manifests")
pass
if len(sys.argv) < 2:
print response["value"]
else:
f = open("%s.xml" % (sys.argv[1],),'w')
value = response["value"]["manifests"]
i = 0
for key in value.keys():
f2 = open("%s.%d.xml" % (sys.argv[1],i,),'w')
f2.write(value[key])
f2.close()
i += 1
f.write(value[key])
pass
f.close()
pass
#!/usr/bin/env python2
import sys
import lxml.etree
iface_link_map = {}
link_members = {}
node_ifaces = {}
link_netmasks = {}
allifaces = {}
f = open(sys.argv[1],'r')
contents = f.read()
f.close()
root = lxml.etree.fromstring(contents)
# Find all the links:
for elm in root.getchildren():
if not elm.tag.endswith("}link"):
continue
name = elm.get("client_id")
ifacerefs = []
for elm2 in elm.getchildren():
if not elm2.tag.endswith("}interface_ref"):
continue
ifacename = elm2.get("client_id")
ifacerefs.append(ifacename)
iface_link_map[ifacename] = name
link_members[name] = ifacerefs
# Find all the node interfaces
for elm in root.getchildren():
if not elm.tag.endswith("}node"):
continue
name = elm.get("client_id")
ifaces = {}
for elm2 in elm.getchildren():
if not elm2.tag.endswith("}interface"):
continue
ifacename = elm2.get("client_id")
for elm3 in elm2.getchildren():
if not elm3.tag.endswith("}ip"):
continue
if not elm3.get("type") == 'ipv4':
continue
addrtuple = (elm3.get("address"),elm3.get("netmask"))
ifaces[ifacename] = addrtuple
allifaces[ifacename] = addrtuple
break
node_ifaces[name] = ifaces
# Dump the nodes a la topomap
print "# nodes: vname,links"
for n in node_ifaces.keys():
for (i,(addr,mask)) in node_ifaces[n].iteritems():
print "%s,%s:%s" % (n,iface_link_map[i],addr)
# Dump the links a la topomap -- but with fixed cost of 1
print "# lans: vname,mask,cost"
for m in link_members.keys():
ifref = link_members[m][0]
(ip,mask) = allifaces[ifref]
print "%s,%s,1" % (m,mask)
sys.exit(0)
#!/bin/sh
set -x
DIRNAME=`dirname $0`
# Gotta know the rules!
if [ `id -u` -ne 0 ] ; then
echo "This script must be run as root" 1>&2
exit 1
fi
# Grab our libs
. "$DIRNAME/setup-lib.sh"
# Don't run setup-driver.sh twice
if [ -f $OURDIR/setup-driver-done ]; then
echo "setup-driver already ran; not running again"
exit 0
fi
logtstart "driver"
echo "*** Setting up root ssh pubkey access across all nodes..."
# All nodes need to publish public keys, and acquire others'
mkdir -p $OURDIR
$DIRNAME/setup-root-ssh.sh 1> $OURDIR/setup-root-ssh.log 2>&1
if [ -f $SETTINGS ]; then
. $SETTINGS
fi
if [ "$HOSTNAME" = "$CONCENTRATOR" ]; then
echo "*** Waiting for ssh access to all nodes..."
for node in $NODES ; do
[ "$node" = "$CONCENTRATOR" ] && continue
SUCCESS=1
fqdn=`getfqdn $node`
while [ $SUCCESS -ne 0 ] ; do
sleep 1
ssh -o ConnectTimeout=1 -o PasswordAuthentication=No \
-o NumberOfPasswordPrompts=0 -o StrictHostKeyChecking=No \
$fqdn /bin/ls > /dev/null
SUCCESS=$?
done
echo "*** $node is up!"
done
echo "*** Setting up the VPNs"
$DIRNAME/setup-vpn.sh 1> $OURDIR/setup-vpn.log 2>&1
# Give the VPN a chance to settle down
PINGED=0
while [ $PINGED -eq 0 ]; do
sleep 2
ping -c 1 $CONTROLLER
if [ $? -eq 0 ]; then
PINGED=1
fi
done
fi
# Mark things as done right here, it's safe.
touch $OURDIR/setup-driver-done
logtend "driver"
exit 0
This diff is collapsed.
#!/bin/sh
##
## Setup a root ssh key on the calling node, and broadcast it to all the
## other nodes' authorized_keys2 file.
##
set -x
# Grab our libs
. "`dirname $0`/setup-lib.sh"
logtstart "root-ssh"
KEYNAME=id_rsa
# Remove it if it exists...
rm -f /root/.ssh/${KEYNAME} /root/.ssh/${KEYNAME}.pub
##
## Figure out our strategy. Are we using the new geni_certificate and
## geni_key support to generate the same keypair on each host, or not.
##
geni-get key > $OURDIR/$KEYNAME
chmod 600 $OURDIR/${KEYNAME}
if [ -s $OURDIR/${KEYNAME} ] ; then
ssh-keygen -f $OURDIR/${KEYNAME} -y > $OURDIR/${KEYNAME}.pub
chmod 600 $OURDIR/${KEYNAME}.pub
mkdir -p /root/.ssh
chmod 600 /root/.ssh
cp -p $OURDIR/${KEYNAME} $OURDIR/${KEYNAME}.pub /root/.ssh/
ps axwww > $OURDIR/ps.txt
touch /root/.ssh/authorized_keys2
cat $OURDIR/${KEYNAME}.pub >> /root/.ssh/authorized_keys2
chmod 600 /root/.ssh/authorized_keys2
logtend "root-ssh"
exit 0
fi
##
## If geni calls are not available, make ourself a keypair; this gets copied
## to other roots' authorized_keys2.
##
if [ ! -f /root/.ssh/${KEYNAME} ]; then
ssh-keygen -t rsa -f /root/.ssh/${KEYNAME} -N ''
fi
if [ -f $SETTINGS ]; then
. $SETTINGS
fi
if [ $GENIUSER -eq 1 ]; then
SHAREDIR=/proj/$EPID/exp/$EEID/tmp
cp /root/.ssh/${KEYNAME}.pub $SHAREDIR/$HOSTNAME
for node in $NODES ; do
while [ ! -f $SHAREDIR/$node ]; do
sleep 1
done
echo $node is up
cat $SHAREDIR/$node >> /root/.ssh/authorized_keys2
chmod 600 /root/.ssh/authorized_keys2
done
else
for node in $NODES ; do
if [ "$node" != "$HOSTNAME" ]; then
fqdn=`getfqdn $node`
SUCCESS=1
while [ $SUCCESS -ne 0 ]; do
su -c "$SSH -l $SWAPPER $fqdn sudo tee -a /root/.ssh/authorized_keys2" $SWAPPER < /root/.ssh/${KEYNAME}.pub
su -c "$SSH -l $SWAPPER $fqdn sudo chmod 600 /root/.ssh/authorized_keys2"
SUCCESS=$?
sleep 1
done
fi
done
fi
logtend "root-ssh"
exit 0
#!/bin/sh
##
## Setup an OpenVPN client for the management network. Just saves
## a couple SSH connections from the server driving the setup.
##
set -x
# Gotta know the rules!
if [ `id -u` -ne 0 ] ; then
echo "This script must be run as root" 1>&2
exit 1
fi
# Grab our libs
. "`dirname $0`/setup-lib.sh"
logtstart "vpn-client"
maybe_install_packages openvpn
#
# For each aggregate hosted on this ctlnuc host, setup a VPN, using the
# keys/crts/conf files pushed from the server. They are already in
# $OURDIR; see setup-vpn.sh .
#
eval "varname=${HOSTNAME}_AGGREGATES ; AGGREGATES=\$$varname"
for aggname in $AGGREGATES ; do
node="${HOSTNAME}${aggname}"
cp -pv $OURDIR/${node}* /etc/openvpn/
cp -pv $OURDIR/ca.crt /etc/openvpn
#
# Get the server up
#
systemctl enable openvpn@${node}.service
systemctl restart openvpn@${node}.service
done
logtend "vpn-client"
exit 0
#!/bin/sh
##
## Setup OpenVPN to create the OpenStack management network.
## This script only runs on the "network" node.
##
set -x
DIRNAME=`dirname $0`
# Grab our libs
. "$DIRNAME/setup-lib.sh"
if [ "$HOSTNAME" != "$CONCENTRATOR" ]; then
exit 0;
fi
logtstart "vpn"
if [ ! -f $OURDIR/vpn-server-done ]; then
maybe_install_packages openvpn easy-rsa
fi
# Only initiate client setup scripts on vpn client hosts.
VPNHOSTS=""
#
# Get our server CA config set up.
#
export EASY_RSA="/etc/openvpn/easy-rsa"
if [ ! -f $OURDIR/vpn-server-done ]; then
mkdir -p $EASY_RSA
cp -r /usr/share/easy-rsa/* $EASY_RSA
cd $EASY_RSA
# Batch mode
sed -i -e s/--interact/--batch/ $EASY_RSA/build-ca
sed -i -e s/--interact/--batch/ $EASY_RSA/build-key-server
sed -i -e s/--interact/--batch/ $EASY_RSA/build-key
sed -i -e s/DEBUG=0/DEBUG=1/ $EASY_RSA/pkitool
fi
export OPENSSL="openssl"
export PKCS11TOOL="pkcs11-tool"
export GREP="grep"
export KEY_CONFIG="`$EASY_RSA/whichopensslcnf $EASY_RSA`"
export KEY_DIR="$EASY_RSA/keys"
export PKCS11_MODULE_PATH="dummy"
export PKCS11_PIN="dummy"
export KEY_SIZE=2048
export CA_EXPIRE=3650
export KEY_EXPIRE=3650
export KEY_COUNTRY="US"
export KEY_PROVINCE="UT"
export KEY_CITY="Salt Lake City"
export KEY_ORG="$EPID-$EEID"
TRUNCATED_EMAIL=`echo ${SWAPPER_EMAIL} | cut -c 1-40`
export KEY_EMAIL="${TRUNCATED_EMAIL}"
export KEY_CN="POWDERAggVPNCon"
export KEY_NAME=$KEY_CN
export KEY_OU=$KEY_CN
# --batch mode is unhappy if it's not this
export KEY_ALTNAMES="DNS:$CONCENTRATOR"
mkdir -p $KEY_DIR
cd $EASY_RSA
if [ ! -f $OURDIR/vpn-server-done ]; then
# Handle the case on Ubuntu18 where easy-rsa is broken for openssl 1.1.0
# (https://github.com/OpenVPN/easy-rsa/issues/159)
openssl version | grep -iq '^openssl 1\.1\.'
if [ $? -eq 0 -a -n "$KEY_CONFIG" -a ! -e $KEY_CONFIG -a -e openssl-1.0.0.cnf ]; then
cp -p openssl-1.0.0.cnf $KEY_CONFIG
echo '# For use with easy-rsa version 2.x and OpenSSL 1.1.0*' >> $KEY_CONFIG
echo '# For use with easy-rsa version 2.0 and OpenSSL 1.1.0*' >> $KEY_CONFIG
fi
# Fixup the openssl.cnf files
for file in `ls -1 /etc/openvpn/easy-rsa/openssl*.cnf | xargs` ; do
sed -i -e 's/^\(subjectAltName=.*\)$/#\1/' $file
done
export KEY_CN="POWDERAggVPNCon"
./clean-all
./build-ca
# We needed a CN for the CA build -- but now we have to drop it cause
# the build-key* scripts don't want it set -- they set it to the first arg,
# and behave badly if it IS set.
unset KEY_CN
./build-key-server $CONCENTRATOR
cp -p $KEY_DIR/$CONCENTRATOR.crt $KEY_DIR/$CONCENTRATOR.key $KEY_DIR/ca.crt \
/etc/openvpn/
if [ -f $DIRNAME/etc/dh2048.pem ]; then
cp $DIRNAME/etc/dh2048.pem /etc/openvpn
else
./build-dh
cp -p $KEY_DIR/dh2048.pem /etc/openvpn/
fi
#
# Get openvpn setup and restarted.
#
if [ $VPNTYPE -eq 'routed-privaddr' ]; then
cat <<EOF > /etc/openvpn/server.conf
local $con_conlink_IP
port 1194
proto udp
dev tun
topology subnet
ca ca.crt
cert $CONCENTRATOR.crt
key $CONCENTRATOR.key
dh dh2048.pem
server $VPN_NETWORK $VPN_MASK
client-config-dir /etc/openvpn/ccd
;client-to-client
;duplicate-cn
keepalive 10 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
verb 3
push "route $MLAN_NETWORK $MLAN_MASK"
EOF
elif [ $VPNTYPE -eq 'bridged' ]; then
echo "bridged VPNTYPE not yet supported!"
exit 1
elif [ $VPNTYPE -eq 'routed-pubaddr' ]; then
echo "routed-pubaddr VPNTYPE not yet supported!"
exit 1
fi
mkdir -p /etc/openvpn/ccd
#
# Get the server up
#
if [ ${HAVE_SYSTEMD} -eq 1 ]; then
# Make sure we don't start the VPN until our network is up.
# This is sort of magical, but it works.
mkdir /etc/systemd/system/openvpn@.service.d
systemctl list-units | grep -q networking\.service
if [ $? -eq 0 ]; then
cat <<EOF >/etc/systemd/system/openvpn@.service.d/local-ifup.conf
[Unit]
Requires=networking.service
After=networking.service
EOF
else
systemctl list-units | grep -q network-online\.target
if [ $? -eq 0 ]; then
cat <<EOF >/etc/systemd/system/openvpn@.service.d/local-ifup.conf
[Unit]
Requires=network-online.target
After=network-online.target
EOF
fi
fi
systemctl daemon-reload
systemctl enable openvpn@server.service
systemctl start openvpn@server.service
else
service openvpn restart
fi
touch $OURDIR/vpn-server-done
fi
#
# Now build keys and set static IPs for the aggregate VPNs. We also
# generate config files for the aggregate VPNs.
#
mkdir -p /etc/openvpn/clients
for aggprefix in $AGGREGATES ; do
agglan="${aggprefix}lan"
eval "varname=${aggprefix}_HOST ; agghost=\$$varname"
eval "varname=${aggprefix}_GW ; agg_gw=\$$varname"
eval "varname=$agglan_NETWORK ; agg_net=\$$varname"
eval "varname=$agglan_MASK ; agg_mask=\$$varname"
eval "varname=$agglan_CIDR ; agg_cidr=\$$varname"
aggnum=`echo $aggprefix | sed -n -r -e 's/^agg([0-9]+)$/\1/p'`
node="${agghost}${aggprefix}"
if [ -f /etc/openvpn/ccd/$node ]; then
continue
fi
fqdn=`getfqdn $agghost`
echo $VPNHOSTS | grep -q $fqdn
if [ ! $? -eq 0 ]; then
VPNHOSTS="${VPNHOSTS} $fqdn"
fi
export KEY_CN="$node"
./build-key $node
#
# Write its server-side client config bits.
#
#echo "ifconfig-push $NMIP 255.255.0.0" \
# > /etc/openvpn/ccd/$node
echo "iroute $agg_net $agg_mask" >> /etc/openvpn/ccd/$node
#
# Write a client configuration, complete with up/down scripts.
#
cat <<EOF > /etc/openvpn/clients/$node.conf
client
dev tun-$aggprefix
proto udp
remote $con_conlink_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert $node.crt
key $node.key
ns-cert-type server
comp-lzo
verb 3
route-up "/etc/openvpn/$node-route-up.sh"
route-down "/etc/openvpn/$node-route-down.sh"
EOF
#
# Note that because we have to pack multiple aggregates onto ctlnuc
# vhosts, we also need per-agg-subnet route tables that we use
# source routing to feed. Real aggregate control NUCs would not
# need this, of course.
#
cat <<EOF > /etc/openvpn/clients/$node-route-up.sh
#!/bin/sh
VNODES=`/usr/local/etc/emulab/tmcc vnodelist | sed -nre 's/^VNODEID=(pcvm[0-9]*-[0-9]*) .*$/\1/p' | xargs`
for vnode in $VNODES ; do
VTAG=`/usr/local/etc/emulab/tmcc -n $vnode ifconfig | sed -nre 's/^.* LAN=$agglan .*VTAG=([0-9]*).*$/\1/p'`
if [ -n "$VTAG" ]; then
break;
fi
done
if [ -z "$VTAG" ]; then
echo "ERROR: fatal: could not find bridge for $agglan"
exit 1
fi
mkdir -p /etc/iproute2
echo $aggnum $aggprefix >> /etc/iproute2/rt_tables
ip rule add from $agg_cidr table $aggprefix
ip rule add iif tun-$aggprefix to $agg_cidr table $aggprefix
ip route add $mlan_CIDR via $VPN_SERVER dev tun-$aggprefix table $aggprefix
ip route add 192.168.0.0/16 via $VPN_SERVER dev tun-$aggprefix table $aggprefix
ifconfig br$VTAG $agg_gw netmask $agg_mask up
ip route add $agg_cidr dev br$VTAG table $aggprefix
EOF
chmod 755 /etc/openvpn/clients/$node-route-up.sh
cat <<EOF > /etc/openvpn/clients/$node-route-down.sh
#!/bin/sh
ip rule del from $agg_cidr table $aggprefix
ip rule del iif tun-$aggprefix to $agg_cidr table $aggprefix
ip route flush table $aggprefix
ifconfig br$VTAG 0 up
EOF
chmod 755 /etc/openvpn/clients/$node-route-down.sh
#
# Ok, copy the key/crts/conf files to the agg host
#
rsync -avz -o StrictHostKeyChecking=no \
/etc/openvpn/ca.crt $KEY_DIR/$node* $fqdn:$OURDIR
rsync -avz -o StrictHostKeyChecking=no \
/etc/openvpn/clients/$node* $fqdn:$OURDIR
done
unset KEY_COUNTRY
unset KEY_PROVINCE
unset KEY_CITY
unset KEY_ORG
unset KEY_EMAIL
unset KEY_NAME
unset KEY_OU
unset KEY_ALTNAMES
unset EASY_RSA
unset OPENSSL
unset PKCS11TOOL
unset GREP
unset KEY_CONFIG
unset PKCS11_MODULE_PATH
unset PKCS11_PIN
unset KEY_SIZE
unset CA_EXPIRE
unset KEY_EXPIRE
#
# Get the hosts files setup to point to the new management network
# and setup the VPN on the clients.
#
maybe_install_packages pssh
PSSH='/usr/bin/parallel-ssh -t 0 -O StrictHostKeyChecking=no '
PHOSTS=""
mkdir -p $OURDIR/pssh.setup-vpn.stdout $OURDIR/pssh.setup-vpn.stderr
for fqdn in $VPNHOSTS ; do
PHOSTS="$PHOSTS -H $fqdn"
done
$PSSH -o $OURDIR/pssh.setup-vpn.stdout -e $OURDIR/pssh.setup-vpn.stderr \
$PHOSTS $DIRNAME/setup-vpn-client.sh
logtend "vpn"
exit 0
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment