mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
CLOUDSTACK-8690:Added remote access vpn and vpn users configuration
This commit is contained in:
parent
76c81a7bd9
commit
f661ac0a2a
@ -28,6 +28,7 @@ import re
|
||||
import time
|
||||
import shutil
|
||||
import os.path
|
||||
import os
|
||||
from fcntl import flock, LOCK_EX, LOCK_UN
|
||||
|
||||
from cs.CsDatabag import CsDataBag, CsCmdLine
|
||||
@ -484,6 +485,170 @@ class CsSite2SiteVpn(CsDataBag):
|
||||
hrs = int(val) / 3600
|
||||
return "%sh" % hrs
|
||||
|
||||
class CsVpnUser(CsDataBag):
|
||||
PPP_CHAP='/etc/ppp/chap-secrets'
|
||||
|
||||
def process(self):
|
||||
for user in self.dbag:
|
||||
if user == 'id':
|
||||
continue
|
||||
|
||||
userconfig=self.dbag[user]
|
||||
if userconfig['add']:
|
||||
self.add_l2tp_ipsec_user(user, userconfig)
|
||||
else:
|
||||
self.del_l2tp_ipsec_user(user, userconfig)
|
||||
|
||||
def add_l2tp_ipsec_user(self, user, obj):
|
||||
userfound = False
|
||||
password = obj['password']
|
||||
|
||||
userSearchEntry = "%s \* %s \*"%(user,password)
|
||||
userAddEntry = "%s * %s *" %(user,password)
|
||||
logging.debug("Adding vpn user %s" %userSearchEntry)
|
||||
|
||||
file = CsFile(self.PPP_CHAP)
|
||||
userfound = file.searchString(userSearchEntry, '#')
|
||||
if not userfound:
|
||||
logging.debug("User is not there already, so adding user ")
|
||||
self.del_l2tp_ipsec_user(user, obj)
|
||||
file.add(userAddEntry)
|
||||
file.commit()
|
||||
|
||||
|
||||
def del_l2tp_ipsec_user(self, user, obj):
|
||||
userfound = False
|
||||
password = obj['password']
|
||||
userentry = "%s \* %s \*"%(user,password)
|
||||
|
||||
logging.debug("Deleting the user %s " % user)
|
||||
file = CsFile(self.PPP_CHAP)
|
||||
file.deleteLine(userentry)
|
||||
file.commit()
|
||||
|
||||
if not os.path.exists('/var/run/pppd2.tdb'):
|
||||
return
|
||||
|
||||
logging.debug("kiing the PPPD process for the user %s " % user)
|
||||
|
||||
fileContents = CsHelper.execute("tdbdump /var/run/pppd2.tdb")
|
||||
print fileContents
|
||||
|
||||
for line in fileContents:
|
||||
if user in line:
|
||||
contentlist = line.split(';')
|
||||
for str in contentlist:
|
||||
print 'in del_l2tp str = '+ str
|
||||
pppd = str.split('=')[0]
|
||||
if pppd == 'PPPD_PID':
|
||||
pid = str.split('=')[1]
|
||||
if pid:
|
||||
logging.debug("killing process %s" %pid)
|
||||
CsHelper.execute('kill -9 %s' % pid)
|
||||
|
||||
|
||||
|
||||
class CsRemoteAccessVpn(CsDataBag):
|
||||
VPNCONFDIR = "/etc/ipsec.d"
|
||||
|
||||
def process(self):
|
||||
self.confips = []
|
||||
|
||||
logging.debug(self.dbag)
|
||||
for public_ip in self.dbag:
|
||||
if public_ip == "id":
|
||||
continue
|
||||
vpnconfig=self.dbag[public_ip]
|
||||
|
||||
#Enable remote access vpn
|
||||
if vpnconfig['create']:
|
||||
logging.debug("Enabling remote access vpn on "+ public_ip)
|
||||
self.configure_l2tpIpsec(public_ip, self.dbag[public_ip])
|
||||
logging.debug("Remote accessvpn data bag %s", self.dbag)
|
||||
self.remoteaccessvpn_iptables(public_ip, self.dbag[public_ip])
|
||||
|
||||
CsHelper.execute("ipsec auto --rereadall")
|
||||
CsHelper.execute("service xl2tpd stop")
|
||||
CsHelper.execute("service xl2tpd start")
|
||||
CsHelper.execute("ipsec auto --rereadsecrets")
|
||||
CsHelper.execute("ipsec auto --replace L2TP-PSK")
|
||||
else:
|
||||
logging.debug("Disabling remote access vpn .....")
|
||||
#disable remote access vpn
|
||||
CsHelper.execute("ipsec auto --down L2TP-PSK")
|
||||
CsHelper.execute("service xl2tpd stop")
|
||||
|
||||
|
||||
def configure_l2tpIpsec(self, left, obj):
|
||||
vpnconffile="%s/l2tp.conf" % (self.VPNCONFDIR)
|
||||
vpnsecretfilte="%s/ipsec.any.secrets" % (self.VPNCONFDIR)
|
||||
xl2tpdconffile="/etc/xl2tpd/xl2tpd.conf"
|
||||
xl2tpoptionsfile='/etc/ppp/options.xl2tpd'
|
||||
|
||||
file = CsFile(vpnconffile)
|
||||
localip=obj['local_ip']
|
||||
localcidr=obj['local_cidr']
|
||||
publicIface=obj['public_interface']
|
||||
iprange=obj['ip_range']
|
||||
psk=obj['preshared_key']
|
||||
|
||||
#left
|
||||
file.addeq(" left=%s" % left)
|
||||
file.commit()
|
||||
|
||||
|
||||
secret = CsFile(vpnsecretfilte)
|
||||
secret.addeq(": PSK \"%s\"" %psk)
|
||||
secret.commit()
|
||||
|
||||
xl2tpdconf = CsFile(xl2tpdconffile)
|
||||
xl2tpdconf.addeq("ip range = %s" %iprange)
|
||||
xl2tpdconf.addeq("local ip = %s" %localip)
|
||||
xl2tpdconf.commit()
|
||||
|
||||
xl2tpoptions=CsFile(xl2tpoptionsfile)
|
||||
xl2tpoptions.search("ms-dns ", "ms-dns %s" %localip)
|
||||
xl2tpoptions.commit()
|
||||
|
||||
def remoteaccessvpn_iptables(self, publicip, obj):
|
||||
publicdev=obj['public_interface']
|
||||
localcidr=obj['local_cidr']
|
||||
local_ip=obj['local_ip']
|
||||
|
||||
|
||||
self.fw.append(["", "", "-A INPUT -i %s --dst %s -p udp -m udp --dport 500 -j ACCEPT" % (publicdev, publicip)])
|
||||
self.fw.append(["", "", "-A INPUT -i %s --dst %s -p udp -m udp --dport 4500 -j ACCEPT" % (publicdev, publicip)])
|
||||
self.fw.append(["", "", "-A INPUT -i %s --dst %s -p udp -m udp --dport 1701 -j ACCEPT" % (publicdev, publicip)])
|
||||
self.fw.append(["", "", "-A INPUT -i %s -p ah -j ACCEPT" % publicdev])
|
||||
self.fw.append(["", "", "-A INPUT -i %s -p esp -j ACCEPT" % publicdev])
|
||||
|
||||
if self.config.is_vpc():
|
||||
self.fw.append(["", ""," -N VPN_FORWARD"])
|
||||
self.fw.append(["", "","-I FORWARD -i ppp+ -j VPN_FORWARD"])
|
||||
self.fw.append(["", "","-I FORWARD -o ppp+ -j VPN_FORWARD"])
|
||||
self.fw.append(["", "","-I FORWARD -o ppp+ -j VPN_FORWARD"])
|
||||
self.fw.append(["", "","-A VPN_FORWARD -s %s -j RETURN" %localcidr])
|
||||
self.fw.append(["", "","-A VPN_FORWARD -i ppp+ -d %s -j RETURN" %localcidr])
|
||||
self.fw.append(["", "","-A VPN_FORWARD -i ppp+ -o ppp+ -j RETURN"])
|
||||
else:
|
||||
self.fw.append(["", "","-A FORWARD -i ppp+ -o ppp+ -j ACCEPT"])
|
||||
self.fw.append(["", "","-A FORWARD -s %s -o ppp+ -j ACCEPT" % localcidr])
|
||||
self.fw.append(["", "","-A FORWARD -i ppp+ -d %s -j ACCEPT" % localcidr])
|
||||
|
||||
|
||||
self.fw.append(["", "","-A INPUT -i ppp+ -m udp -p udp --dport 53 -j ACCEPT"])
|
||||
self.fw.append(["", "","-A INPUT -i ppp+ -m tcp -p tcp --dport 53 -j ACCEPT"])
|
||||
self.fw.append(["nat", "","-I PREROUTING -i ppp+ -m tcp --dport 53 -j DNAT --to-destination %s" % local_ip])
|
||||
|
||||
if self.config.is_vpc():
|
||||
return
|
||||
|
||||
self.fw.append(["mangle", "","-N VPN_%s " %publicip])
|
||||
self.fw.append(["mangle", "","-I PREROUTING -d %s -j VPN_%s " % (publicip, publicip)])
|
||||
self.fw.append(["mangle", "","-A VPN_%s -p ah -j ACCEPT " % publicip])
|
||||
self.fw.append(["mangle", "","-A VPN_%s -p esp -j ACCEPT " % publicip])
|
||||
self.fw.append(["mangle", "","-A VPN_%s -j RETURN " % publicip])
|
||||
|
||||
|
||||
class CsForwardingRules(CsDataBag):
|
||||
|
||||
@ -672,15 +837,20 @@ def main(argv):
|
||||
fwd = CsForwardingRules("forwardingrules", config)
|
||||
fwd.process()
|
||||
|
||||
nf = CsNetfilters()
|
||||
nf.compare(config.get_fw())
|
||||
|
||||
red = CsRedundant(config)
|
||||
red.set()
|
||||
|
||||
vpns = CsSite2SiteVpn("site2sitevpn", config)
|
||||
vpns.process()
|
||||
|
||||
#remote access vpn
|
||||
rvpn = CsRemoteAccessVpn("remoteaccessvpn", config)
|
||||
rvpn.process()
|
||||
|
||||
#remote access vpn users
|
||||
vpnuser = CsVpnUser("vpnuserlist", config)
|
||||
vpnuser.process()
|
||||
|
||||
dhcp = CsDhcp("dhcpentry", config)
|
||||
dhcp.process()
|
||||
|
||||
|
||||
@ -130,5 +130,34 @@ class CsFile:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def searchString(self, search, ignoreLinesStartWith):
|
||||
found = False
|
||||
logging.debug("Searching for %s string " % search)
|
||||
|
||||
for index, line in enumerate(self.new_config):
|
||||
print ' line = ' +line
|
||||
if line.lstrip().startswith(ignoreLinesStartWith):
|
||||
continue
|
||||
if re.search(search, line):
|
||||
found = True
|
||||
break
|
||||
|
||||
return found
|
||||
|
||||
|
||||
def deleteLine(self, search):
|
||||
found = False
|
||||
logging.debug("Searching for %s to remove the line " % search)
|
||||
temp_config = []
|
||||
for index, line in enumerate(self.new_config):
|
||||
if line.lstrip().startswith("#"):
|
||||
continue
|
||||
if not re.search(search, line):
|
||||
temp_config.append(line)
|
||||
|
||||
self.new_config = list(temp_config)
|
||||
|
||||
|
||||
def compare(self, o):
|
||||
return (isinstance(o, self.__class__) and set(self.config) == set(o.new_config))
|
||||
|
||||
@ -157,7 +157,7 @@ def get_hostname():
|
||||
|
||||
def execute(command):
|
||||
""" Execute command """
|
||||
logging.debug("Executing %s" % command)
|
||||
logging.debug("Executing: %s" % command)
|
||||
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
result = p.communicate()[0]
|
||||
return result.splitlines()
|
||||
@ -178,7 +178,7 @@ def save_iptables(command, iptables_file):
|
||||
|
||||
def execute2(command):
|
||||
""" Execute command """
|
||||
logging.debug("Executing %s" % command)
|
||||
logging.debug("Executing: %s" % command)
|
||||
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
p.wait()
|
||||
return p
|
||||
|
||||
28
systemvm/patches/debian/config/opt/cloud/bin/cs_remoteaccessvpn.py
Executable file
28
systemvm/patches/debian/config/opt/cloud/bin/cs_remoteaccessvpn.py
Executable file
@ -0,0 +1,28 @@
|
||||
# -- coding: utf-8 --
|
||||
# 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.
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
def merge(dbag, vpn):
|
||||
key = vpn['vpn_server_ip']
|
||||
op = vpn['create']
|
||||
if key in dbag.keys() and not op:
|
||||
del(dbag[key])
|
||||
else:
|
||||
dbag[key] = vpn
|
||||
return dbag
|
||||
48
systemvm/patches/debian/config/opt/cloud/bin/cs_vpnusers.py
Executable file
48
systemvm/patches/debian/config/opt/cloud/bin/cs_vpnusers.py
Executable file
@ -0,0 +1,48 @@
|
||||
# -- coding: utf-8 --
|
||||
# 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.
|
||||
from pprint import pprint
|
||||
|
||||
import copy
|
||||
|
||||
|
||||
def merge(dbag, data):
|
||||
dbagc = copy.deepcopy(dbag)
|
||||
|
||||
print dbag
|
||||
print data
|
||||
if "vpn_users" not in data:
|
||||
return dbagc
|
||||
|
||||
# remove previously deleted user from the dict
|
||||
for user in dbagc.keys():
|
||||
if user == 'id':
|
||||
continue
|
||||
userrec = dbagc[user]
|
||||
add = userrec['add']
|
||||
if not add:
|
||||
del(dbagc[user])
|
||||
|
||||
for user in data['vpn_users']:
|
||||
username=user['user']
|
||||
add=user['add']
|
||||
if username not in dbagc.keys():
|
||||
dbagc[username] = user
|
||||
elif username in dbagc.keys() and not add:
|
||||
dbagc[username] = user
|
||||
|
||||
return dbagc
|
||||
@ -32,6 +32,8 @@ import cs_vmdata
|
||||
import cs_dhcp
|
||||
import cs_forwardingrules
|
||||
import cs_site2sitevpn
|
||||
import cs_remoteaccessvpn
|
||||
import cs_vpnusers
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
@ -66,6 +68,7 @@ class DataBag:
|
||||
logging.error("Could not write data bag %s", self.key)
|
||||
else:
|
||||
logging.debug("Writing data bag type %s", self.key)
|
||||
logging.debug(dbag)
|
||||
jsono = json.dumps(dbag, indent=4, sort_keys=True)
|
||||
handle.write(jsono)
|
||||
|
||||
@ -119,6 +122,10 @@ class updateDataBag:
|
||||
dbag = self.processForwardingRules(self.db.getDataBag())
|
||||
elif self.qFile.type == 'site2sitevpn':
|
||||
dbag = self.process_site2sitevpn(self.db.getDataBag())
|
||||
elif self.qFile.type == 'remoteaccessvpn':
|
||||
dbag = self.process_remoteaccessvpn(self.db.getDataBag())
|
||||
elif self.qFile.type == 'vpnuserlist':
|
||||
dbag = self.process_vpnusers(self.db.getDataBag())
|
||||
else:
|
||||
logging.error("Error I do not know what to do with file of type %s", self.qFile.type)
|
||||
return
|
||||
@ -147,6 +154,12 @@ class updateDataBag:
|
||||
def process_site2sitevpn(self, dbag):
|
||||
return cs_site2sitevpn.merge(dbag, self.qFile.data)
|
||||
|
||||
def process_remoteaccessvpn(self, dbag):
|
||||
return cs_remoteaccessvpn.merge(dbag, self.qFile.data)
|
||||
|
||||
def process_vpnusers(self, dbag):
|
||||
return cs_vpnusers.merge(dbag, self.qFile.data)
|
||||
|
||||
def process_network_acl(self, dbag):
|
||||
return cs_network_acl.merge(dbag, self.qFile.data)
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ import os.path
|
||||
import configure
|
||||
import json
|
||||
|
||||
logging.basicConfig(filename='/var/log/cloud.log', level=logging.DEBUG, format='%(asctime)s %(message)s')
|
||||
logging.basicConfig(filename='/var/log/cloud.log', level=logging.DEBUG, format='%(asctime)s %(filename)s %(funcName)s:%(lineno)d %(message)s')
|
||||
|
||||
# first commandline argument should be the file to process
|
||||
if (len(sys.argv) != 2):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user