Skip to content

Commit

Permalink
[openvpn] Added generate_client class method
Browse files Browse the repository at this point in the history
  • Loading branch information
nemesifier committed Sep 7, 2016
1 parent fee8423 commit dc9666b
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 1 deletion.
42 changes: 42 additions & 0 deletions docs/source/backends/openvpn.rst
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,45 @@ For a list of all the OpenVPN configuration settings, refer to the `OpenVPN 2.3

.. _auth property source code: https://github.com/openwisp/netjsonconfig/blob/master/netjsonconfig/backends/openvpn/schema.py#L79-L89
.. _cipher property source code: https://github.com/openwisp/netjsonconfig/blob/master/netjsonconfig/backends/openvpn/schema.py#L90-L103

Automatic generation of clients
-------------------------------

.. automethod:: netjsonconfig.OpenVpn.generate_client

Example:

.. code-block:: python
from netjsonconfig import OpenVpn
client_config = OpenVpn.generate_client('vpn1.test.com', {
"ca": "ca.pem",
"cert": "cert.pem",
"dev": "tap0",
"dev_type": "tap",
"dh": "dh.pem",
"key": "key.pem",
"mode": "server",
"name": "example-vpn",
"proto": "udp",
"tls_server": True
})
client = OpenVpn({"openvpn": [client_config]})
print(client.render())
Will be rendered as::

# openvpn config: example-vpn

ca ca.pem
cert cert.pem
dev tap0
dev-type tap
key key.pem
mode client
nobind
proto udp
remote vpn1.test.com 1195
resolv-retry
tls-client
2 changes: 1 addition & 1 deletion netjsonconfig/backends/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

class BaseBackend(object):
"""
TODO: explain
Base Backend class
"""
schema = None
env_path = 'netjsonconfig.backends.base'
Expand Down
42 changes: 42 additions & 0 deletions netjsonconfig/backends/openvpn/openvpn.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,45 @@ def _generate_contents(self, tar):
self._add_file(tar=tar,
name='{0}.conf'.format(vpn_name),
contents=text_contents)

@classmethod
def generate_client(self, host, server):
"""
Generates an OpenVPN client configuration
from an existing server configuration.
:param server: dictionary representing a single OpenVPN server configuration
:returns: dictionary representing a single OpenVPN client configuration
"""
# client defaults
c = {
"mode": "client",
"nobind": True,
"resolv_retry": True,
"tls_client": True
}
# remote
port = server.get('port') or 1195
c['remote'] = [{'host': host, 'port': port}]
# proto
if server.get('proto') == 'tcp-server':
c['proto'] = 'tcp-client'
else:
c['proto'] = 'udp'
# tls_client
if 'tls_server' not in server or not server['tls_server']:
c['tls_client'] = False
# ns_cert_type
if not server.get('ns_cert_type'):
c['ns_cert_type'] = ''
elif server.get('ns_cert_type') == 'client':
c['ns_cert_type'] = 'server'
copy_keys = ['name', 'dev_type', 'dev', 'comp_lzo', 'auth',
'cipher', 'ca', 'cert', 'key', 'mtu_disc', 'mtu_test',
'fragment', 'mssfix', 'keepalive', 'persist_tun', 'mute',
'persist_key', 'script_security', 'user', 'group', 'log',
'mute_replay_warnings', 'secret', 'fast_io', 'verb']
for key in copy_keys:
if key in server:
c[key] = server[key]
return c
130 changes: 130 additions & 0 deletions tests/openvpn/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,133 @@ def test_generate(self):
tls-server
"""
self.assertEqual(contents, expected)

def test_generate_client_simple(self):
client_config = OpenVpn.generate_client('vpn1.test.com', {
"ca": "ca.pem",
"cert": "cert.pem",
"dev": "tap0",
"dev_type": "tap",
"dh": "dh.pem",
"key": "key.pem",
"mode": "server",
"name": "example-vpn",
"proto": "udp",
})
o = OpenVpn({"openvpn": [client_config]})
expected = """# openvpn config: example-vpn
ca ca.pem
cert cert.pem
dev tap0
dev-type tap
key key.pem
mode client
nobind
proto udp
remote vpn1.test.com 1195
resolv-retry
"""
self.assertEqual(o.render(), expected)

def test_generate_client_tls(self):
client_config = OpenVpn.generate_client('vpn2.test.com', {
"ca": "ca.pem",
"cert": "cert.pem",
"dev": "tap0",
"dev_type": "tap",
"dh": "dh.pem",
"key": "key.pem",
"mode": "server",
"name": "example-vpn",
"port": 1196,
"proto": "tcp-server",
"tls_server": True
})
o = OpenVpn({"openvpn": [client_config]})
expected = """# openvpn config: example-vpn
ca ca.pem
cert cert.pem
dev tap0
dev-type tap
key key.pem
mode client
nobind
proto tcp-client
remote vpn2.test.com 1196
resolv-retry
tls-client
"""
self.assertEqual(o.render(), expected)

def test_generate_client_complex(self):
client_config = OpenVpn.generate_client('vpn1.test.com', {
"ca": "ca.pem",
"cert": "cert.pem",
"dev": "tap0",
"dev_type": "tap",
"dh": "dh.pem",
"key": "key.pem",
"mode": "server",
"name": "example-vpn",
"proto": "tcp-server",
"tls_server": True,
"comp_lzo": "yes",
"auth": "RSA-SHA1",
"cipher": "AES-128-CFB",
"engine": "dynamic",
"ns_cert_type": "client",

})
o = OpenVpn({"openvpn": [client_config]})
expected = """# openvpn config: example-vpn
auth RSA-SHA1
ca ca.pem
cert cert.pem
cipher AES-128-CFB
comp-lzo yes
dev tap0
dev-type tap
key key.pem
mode client
nobind
ns-cert-type server
proto tcp-client
remote vpn1.test.com 1195
resolv-retry
tls-client
"""
self.assertEqual(o.render(), expected)

def test_generate_client_ns_cert_type_empty(self):
client_config = OpenVpn.generate_client('vpn1.test.com', {
"ca": "ca.pem",
"cert": "cert.pem",
"dev": "tap0",
"dev_type": "tap",
"dh": "dh.pem",
"key": "key.pem",
"mode": "server",
"name": "example-vpn",
"proto": "udp",
"tls_server": True,
"ns_cert_type": "",
})
o = OpenVpn({"openvpn": [client_config]})
expected = """# openvpn config: example-vpn
ca ca.pem
cert cert.pem
dev tap0
dev-type tap
key key.pem
mode client
nobind
proto udp
remote vpn1.test.com 1195
resolv-retry
tls-client
"""
self.assertEqual(o.render(), expected)

0 comments on commit dc9666b

Please sign in to comment.