X-Git-Url: https://git.llucax.com/software/pymin.git/blobdiff_plain/12b7d86229346c68e653a51d1e6598a5973901ba..b53a45e7e79b31d0b6b44df0405366cc8a2fd016:/services/vpn/__init__.py?ds=sidebyside diff --git a/services/vpn/__init__.py b/services/vpn/__init__.py index ebfa0ab..5071c7e 100644 --- a/services/vpn/__init__.py +++ b/services/vpn/__init__.py @@ -1,205 +1,17 @@ # vim: set encoding=utf-8 et sw=4 sts=4 : -import os -import errno -import signal -from os import path -import logging ; log = logging.getLogger('pymin.services.vpn') - - -from pymin.seqtools import Sequence -from pymin.dispatcher import Handler, handler, HandlerError -from pymin.service.util import Restorable, ConfigWriter, InitdHandler, \ - TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError - -__all__ = ('VpnHandler', 'get_service') - +from formencode import validators as V +from pymin.config import Option +from handler import VpnHandler + +def setup_service(options, config): + options.add_group('vpn', 'Virtual Private Networking service', [ + Option('pickle_dir', V.String, metavar='DIR', + help='store persistent data in DIR directory'), + Option('config_dir', V.String, metavar='DIR', + help='write config file in DIR directory'), + ]) def get_service(config): return VpnHandler(config.vpn.pickle_dir, config.vpn.config_dir) - -class Host(Sequence): - def __init__(self, vpn_src, ip, vpn_src_net, key): - self.name = vpn_src - self.ip = ip - self.src_net = vpn_src_net - self.pub_key = key - self._delete = False - - def as_tuple(self): - return(self.name, self.ip, self.src_net, self.pub_key) - -class HostHandler(DictComposedSubHandler): - - handler_help = u"Manage hosts for a vpn" - _comp_subhandler_cont = 'vpns' - _comp_subhandler_attr = 'hosts' - _comp_subhandler_class = Host - - -class Vpn(Sequence): - def __init__(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask, - pub_key=None, priv_key=None): - self.vpn_src = vpn_src - self.vpn_dst = vpn_dst - self.vpn_src_ip = vpn_src_ip - self.vpn_src_mask = vpn_src_mask - self.pub_key = pub_key - self.priv_key = priv_key - self.hosts = dict() - self._delete = False - - def as_tuple(self): - return(self.vpn_src, self.vpn_dst, self.vpn_src_ip, self.vpn_src_mask, self.pub_key, self.priv_key) - - def update(self, vpn_dst=None, vpn_src_ip=None, vpn_src_mask=None): - if vpn_dst is not None: - self.vpn_dst = vpn_dst - if vpn_src_ip is not None: - self.vpn_src_ip = vpn_src_ip - if vpn_src_mask is not None: - self.vpn_src_mask = vpn_src_mask - - -class VpnHandler(Restorable, ConfigWriter, - TransactionalHandler, DictSubHandler): - - handler_help = u"Manage vpn service" - - _cont_subhandler_attr = 'vpns' - _cont_subhandler_class = Vpn - - _persistent_attrs = ('vpns','hosts') - - _restorable_defaults = dict( - vpns = dict(), - hosts = dict(), - ) - - _config_writer_files = ('tinc.conf','tinc-up','host') - _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates') - - def __init__(self, pickle_dir='.', config_dir='/etc/tinc'): - log.debug(u'VpnHandler(%r, %r)', pickle_dir, config_dir) - DictSubHandler.__init__(self, self) - self._config_writer_cfg_dir = config_dir - self._persistent_dir = pickle_dir - self._config_build_templates() - self._restore() - self.host = HostHandler(self) - - @handler('usage: start ') - def start(self, vpn_src): - log.debug(u'VpnHandler.start(%r)', vpn_src) - if vpn_src in self.vpns: - call(('tincd','--net='+ vpn_src)) - - @handler('usage: stop ') - def stop(self, vpn_src): - log.debug(u'VpnHandler.stop(%r)', vpn_src) - if vpn_src in self.vpns: - pid_file = '/var/run/tinc.' + vpn_src + '.pid' - log.debug(u'VpnHandler.stop: getting pid from %r', pid_file) - if path.exists(pid_file): - pid = file(pid_file).readline() - pid = int(pid.strip()) - try: - log.debug(u'VpnHandler.stop: killing pid %r', pid) - os.kill(pid, signal.SIGTERM) - except OSError: - log.debug(u'VpnHandler.stop: error killing: %r', e) - else: - log.debug(u'VpnHandler.stop: pid file not found') - - def _write_config(self): - log.debug(u'VpnHandler._write_config()') - for v in self.vpns.values(): - log.debug(u'VpnHandler._write_config: processing %r', v) - #chek whether it's been created or not. - if not v._delete: - if v.pub_key is None: - log.debug(u'VpnHandler._write_config: new VPN, generating ' - 'key...') - try: - log.debug(u'VpnHandler._write_config: creating dir %r', - path.join(self._config_writer_cfg_dir, - v.vpn_src ,'hosts')) - #first create the directory for the vpn - try: - os.makedirs(path.join(self._config_writer_cfg_dir, - v.vpn_src, 'hosts')) - except (IOError, OSError), e: - if e.errno != errno.EEXIST: - raise HandlerError(u"Can't create VPN config " - "directory '%s' (%s)'" - % (e.filename, e.strerror)) - #this command should generate 2 files inside the vpn - #dir, one rsa_key.priv and one rsa_key.pub - #for some reason debian does not work like this - # FIXME if the < /dev/null works, is magic! - log.debug(u'VpnHandler._write_config: creating key...') - call(('tincd', '-n', v.vpn_src, '-K', '<', '/dev/null')) - #open the created files and load the keys - try: - f = file(path.join(self._config_writer_cfg_dir, - v.vpn_src, 'rsa_key.pub'), - 'r') - pub = f.read() - f.close() - except (IOError, OSError), e: - raise HandlerError(u"Can't read VPN key '%s' (%s)'" - % (e.filename, e.strerror)) - - v.pub_key = pub - v.priv_key = priv - except ExecutionError, e: - log.debug(u'VpnHandler._write_config: error executing ' - 'the command: %r', e) - - vars = dict( - vpn = v, - ) - self._write_single_config('tinc.conf', - path.join(v.vpn_src, 'tinc.conf'), vars) - self._write_single_config('tinc-up', - path.join(v.vpn_src, 'tinc-up'), vars) - for h in v.hosts.values(): - if not h._delete: - vars = dict( - host = h, - ) - self._write_single_config('host', - path.join(v.vpn_src, 'hosts', h.name), vars) - else: - log.debug(u'VpnHandler._write_config: removing...') - try: - # FIXME use os.unlink() - call(('rm','-f', - path.join(v.vpn_src, 'hosts', h.name))) - del v.hosts[h.name] - except ExecutionError, e: - log.debug(u'VpnHandler._write_config: error ' - 'removing files: %r', e) - else: - #delete the vpn root at tinc dir - if path.exists('/etc/tinc/' + v.vpn_src): - self.stop(v.vpn_src) - call(('rm','-rf','/etc/tinc/' + v.vpn_src)) - del self.vpns[v.vpn_src] - - -if __name__ == '__main__': - - logging.basicConfig( - level = logging.DEBUG, - format = '%(asctime)s %(levelname)-8s %(message)s', - datefmt = '%H:%M:%S', - ) - - v = VpnHandler() - v.add('prueba','sarasa','192.168.0.188','255.255.255.0') - v.host.add('prueba', 'azazel' ,'192.168.0.77', '192.168.0.0', - 'kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb') - v.commit() -