Use a better way of obtaining the VPN files
diff --git a/xos/services/vpn/models.py b/xos/services/vpn/models.py
index a9390ff..8586eb8 100644
--- a/xos/services/vpn/models.py
+++ b/xos/services/vpn/models.py
@@ -11,6 +11,7 @@
"""Defines the Service for creating VPN servers."""
KIND = VPN_KIND
OPENVPN_PREFIX = "/opt/openvpn/"
+ SERVER_PREFIX = OPENVPN_PREFIX + "server-"
VARS = OPENVPN_PREFIX + "vars"
EASYRSA_LOC = OPENVPN_PREFIX + "easyrsa3/easyrsa"
EASYRSA_COMMAND = EASYRSA_LOC + " --vars=" + VARS
@@ -29,6 +30,10 @@
full_command + " failed with standard out:" + str(stdout) +
" and stderr: " + str(stderr))
+ @classmethod
+ def get_pki_dir(cls, tenant):
+ return VPNService.SERVER_PREFIX + str(tenant.id)
+
class Meta:
proxy = True
# The name used to find this service, all directories are named this
@@ -89,10 +94,7 @@
'server_network': None,
'clients_can_see_each_other': True,
'is_persistent': True,
- 'ca_crt': None,
'port': None,
- 'script_text': None,
- 'pki_dir': None,
'use_ca_from_id': None,
'failover_server_ids': list(),
'protocol': None}
@@ -131,15 +133,6 @@
self.set_attribute("use_ca_from_id", value)
@property
- def pki_dir(self):
- return self.get_attribute(
- "pki_dir", self.default_attributes["pki_dir"])
-
- @pki_dir.setter
- def pki_dir(self, value):
- self.set_attribute("pki_dir", value)
-
- @property
def addresses(self):
"""Mapping[str, str]: The ip, mac address, and subnet of the NAT
network of this Tenant."""
@@ -222,15 +215,6 @@
self.set_attribute("clients_can_see_each_other", value)
@property
- def ca_crt(self):
- """str: the string for the ca certificate"""
- return self.get_attribute("ca_crt", self.default_attributes['ca_crt'])
-
- @ca_crt.setter
- def ca_crt(self, value):
- self.set_attribute("ca_crt", value)
-
- @property
def port_number(self):
"""int: the integer representing the port number for this server"""
return self.get_attribute("port", self.default_attributes['port'])
@@ -240,21 +224,22 @@
self.set_attribute("port", value)
def create_client_script(self, client_name):
+ pki_dir = VPNService.get_pki_dir(self)
script = ""
# write the configuration portion
script += ("printf \"%b\" \"")
script += self.generate_client_conf(client_name)
script += ("\" > client.conf\n")
script += ("printf \"%b\" \"")
- for line in self.ca_crt:
+ for line in self.get_ca_crt(pki_dir):
script += (line.rstrip() + r"\n")
script += ("\" > ca.crt\n")
script += ("printf \"%b\" \"")
- for line in self.get_client_cert(client_name):
+ for line in self.get_client_cert(client_name, pki_dir):
script += (line.rstrip() + r"\n")
script += ("\" > " + client_name + ".crt\n")
script += ("printf \"%b\" \"")
- for line in self.get_client_key(client_name):
+ for line in self.get_client_key(client_name, pki_dir):
script += (line.rstrip() + r"\n")
script += ("\" > " + client_name + ".key\n")
# make sure openvpn is installed
@@ -264,12 +249,16 @@
# close the script
return script
- def get_client_cert(self, client_name):
- with open(self.pki_dir + "/issued/" + client_name + ".crt", 'r') as f:
+ def get_ca_crt(self, pki_dir):
+ with open(pki_dir + "/ca.crt", 'r') as f:
return f.readlines()
- def get_client_key(self, client_name):
- with open(self.pki_dir + "/private/" + client_name + ".key", 'r') as f:
+ def get_client_cert(self, client_name, pki_dir):
+ with open(pki_dir + "/issued/" + client_name + ".crt", 'r') as f:
+ return f.readlines()
+
+ def get_client_key(self, client_name, pki_dir):
+ with open(pki_dir + "/private/" + client_name + ".key", 'r') as f:
return f.readlines()
def generate_client_conf(self, client_name):
diff --git a/xos/synchronizers/vpn/steps/sync_tenantprivilege.py b/xos/synchronizers/vpn/steps/sync_tenantprivilege.py
index 65baeda..9b10192 100644
--- a/xos/synchronizers/vpn/steps/sync_tenantprivilege.py
+++ b/xos/synchronizers/vpn/steps/sync_tenantprivilege.py
@@ -3,7 +3,7 @@
from core.models import TenantPrivilege
from services.vpn.models import VPN_KIND, VPNService, VPNTenant
-from synchronizers.base.syncstep import SyncStep
+from synchronizers.base.syncstep import DeferredException, SyncStep
parentdir = os.path.join(os.path.dirname(__file__), "..")
sys.path.insert(0, parentdir)
@@ -22,28 +22,38 @@
return privs
def sync_record(self, record):
+ if (not record.tenant.id):
+ raise DeferredException("Privilege waiting on VPN Tenant ID")
certificate = self.get_certificate_name(record)
tenant = VPNTenant.get_tenant_objects().filter(pk=record.tenant.id)[0]
+ if (not tenant):
+ raise DeferredException("Privilege waiting on VPN Tenant")
# Only add a certificate if ones does not yet exist
- if (not os.path.isfile(tenant.pki_dir + "/issued/" + certificate + ".crt")):
+ pki_dir = VPNService.get_pki_dir(tenant)
+ if (not os.path.isfile(pki_dir + "/issued/" + certificate + ".crt")):
VPNService.execute_easyrsa_command(
- tenant.pki_dir, "build-client-full " + certificate + " nopass")
+ pki_dir, "build-client-full " + certificate + " nopass")
tenant.save()
record.save()
def delete_record(self, record):
+ if (not record.tenant.id):
+ return
certificate = self.get_certificate_name(record)
tenant = VPNTenant.get_tenant_objects().filter(pk=record.tenant.id)[0]
+ if (not tenant):
+ return
# If the client has already been reovked don't do it again
- if (os.path.isfile(tenant.pki_dir + "/issued/" + certificate + ".crt")):
+ pki_dir = VPNService.get_pki_dir(tenant)
+ if (os.path.isfile(pki_dir + "/issued/" + certificate + ".crt")):
VPNService.execute_easyrsa_command(
- tenant.pki_dir, "revoke " + certificate)
+ pki_dir, "revoke " + certificate)
# Revoking a client cert does not delete any of the files
# to make sure that we can add this user again we need to
# delete all of the files created by easyrsa
- os.remove(tenant.pki_dir + "/issued/" + certificate + ".crt")
- os.remove(tenant.pki_dir + "/private/" + certificate + ".key")
- os.remove(tenant.pki_dir + "/reqs/" + certificate + ".req")
+ os.remove(pki_dir + "/issued/" + certificate + ".crt")
+ os.remove(pki_dir + "/private/" + certificate + ".key")
+ os.remove(pki_dir + "/reqs/" + certificate + ".req")
tenant.save()
record.delete()
diff --git a/xos/synchronizers/vpn/steps/sync_vpntenant.py b/xos/synchronizers/vpn/steps/sync_vpntenant.py
index 977825d..640b6a7 100644
--- a/xos/synchronizers/vpn/steps/sync_vpntenant.py
+++ b/xos/synchronizers/vpn/steps/sync_vpntenant.py
@@ -3,7 +3,6 @@
import sys
from django.db.models import F, Q
-
from services.vpn.models import VPNService, VPNTenant
from synchronizers.base.SyncInstanceUsingAnsible import \
SyncInstanceUsingAnsible
@@ -38,40 +37,34 @@
tenant.clients_can_see_each_other),
"port_number": tenant.port_number,
"protocol": tenant.protocol,
- "pki_dir": tenant.pki_dir
+ "pki_dir": VPNService.get_pki_dir(tenant)
}
def sync_fields(self, o, fields):
- o.pki_dir = (VPNService.OPENVPN_PREFIX + "server-" + str(o.id))
+ pki_dir = VPNService.get_pki_dir(o)
- if (not os.path.isdir(o.pki_dir)):
- VPNService.execute_easyrsa_command(o.pki_dir, "init-pki")
+ if (not os.path.isdir(pki_dir)):
+ VPNService.execute_easyrsa_command(pki_dir, "init-pki")
VPNService.execute_easyrsa_command(
- o.pki_dir, "--req-cn=XOS build-ca nopass")
+ pki_dir, "--req-cn=XOS build-ca nopass")
# Very hacky way to handle VPNs that need to share CAs
if (o.use_ca_from_id):
tenant = VPNTenant.get_tenant_objects().filter(
pk=o.use_ca_from_id)[0]
- shutil.copy2(tenant.pki_dir + "/ca.crt", o.pki_dir)
- shutil.copy2(tenant.pki_dir + "/private/ca.key",
- o.pki_dir + "/private")
-
- o.ca_crt = self.get_ca_crt(o)
+ other_pki_dir = VPNService.get_pki_dir(tenant)
+ shutil.copy2(other_pki_dir + "/ca.crt", pki_dir)
+ shutil.copy2(other_pki_dir + "/private/ca.key",
+ pki_dir + "/private")
# If the server has to be built then we need to build it
- if (not os.path.isfile(o.pki_dir + "/issued/server.crt")):
+ if (not os.path.isfile(pki_dir + "/issued/server.crt")):
VPNService.execute_easyrsa_command(
- o.pki_dir, "build-server-full server nopass")
- VPNService.execute_easyrsa_command(o.pki_dir, "gen-dh")
+ pki_dir, "build-server-full server nopass")
+ VPNService.execute_easyrsa_command(pki_dir, "gen-dh")
# Get the most recent list of revoked clients
- VPNService.execute_easyrsa_command(o.pki_dir, "gen-crl")
+ VPNService.execute_easyrsa_command(pki_dir, "gen-crl")
# Super runs the playbook
super(SyncVPNTenant, self).sync_fields(o, fields)
-
- def get_ca_crt(self, tenant):
- """str: Generates the ca cert by reading from the ca file"""
- with open(tenant.pki_dir + "/ca.crt") as crt:
- return crt.readlines()