Move to better way of handling multiple pkis
diff --git a/containers/xos/Dockerfile.devel b/containers/xos/Dockerfile.devel
index f1c1c26..832fa3c 100644
--- a/containers/xos/Dockerfile.devel
+++ b/containers/xos/Dockerfile.devel
@@ -98,9 +98,8 @@
RUN chmod 777 /opt/openvpn
RUN git clone https://github.com/OpenVPN/easy-rsa.git /opt/openvpn
RUN git -C /opt/openvpn pull origin master
-RUN echo 'set_var EASYRSA "/opt/openvpn/easyrsa3"' | tee /opt/openvpn/init_vars
-RUN echo 'set_var EASYRSA_PKI "/opt/openvpn/init_pki"' | tee -a /opt/openvpn/init_vars
-RUN echo 'set_var EASYRSA_BATCH "true"' | tee -a /opt/openvpn/init_vars
-RUN /opt/openvpn/easyrsa3/easyrsa --vars=/opt/openvpn/init_vars init-pki
-RUN /opt/openvpn/easyrsa3/easyrsa --vars=/opt/openvpn/init_vars gen-dh
+RUN echo 'set_var EASYRSA "/opt/openvpn/easyrsa3"' | tee /opt/openvpn/vars
+RUN echo 'set_var EASYRSA_BATCH "true"' | tee -a /opt/openvpn/vars
+RUN /opt/openvpn/easyrsa3/easyrsa --pki-dir="/opt/openvpn/init_pki" --vars=/opt/openvpn/vars init-pki
+RUN /opt/openvpn/easyrsa3/easyrsa --pki-dir="/opt/openvpn/init_pki" --vars=/opt/openvpn/vars gen-dh
RUN chmod 777 /opt/openvpn/init_pki/dh.pem
diff --git a/xos/services/vpn/admin.py b/xos/services/vpn/admin.py
index c38721a..9567377 100644
--- a/xos/services/vpn/admin.py
+++ b/xos/services/vpn/admin.py
@@ -1,5 +1,4 @@
import os
-import shutil
from core.admin import ReadOnlyAwareAdmin, SliceInline, TenantPrivilegeInline
from core.middleware import get_request
@@ -8,8 +7,7 @@
from django.contrib import admin
from django.core import serializers
from services.vpn.models import VPN_KIND, VPNService, VPNTenant
-from subprocess import Popen, PIPE
-from xos.exceptions import XOSConfigurationError, XOSValidationError
+from xos.exceptions import XOSValidationError
class VPNServiceForm(forms.ModelForm):
@@ -185,39 +183,18 @@
result = super(VPNTenantForm, self).save(commit=commit)
result.save()
- pki_dir = "/opt/openvpn/easyrsa3/server-" + str(result.id)
+ pki_dir = VPNService.OPENVPN_PREFIX + "server-" + str(result.id)
if (not os.path.isdir(pki_dir)):
- os.makedirs(pki_dir)
- shutil.copy2("/opt/openvpn/easyrsa3/openssl-1.0.cnf", pki_dir)
- shutil.copy2("/opt/openvpn/easyrsa3/easyrsa", pki_dir)
- shutil.copytree("/opt/openvpn/easyrsa3/x509-types",
- pki_dir + "/x509-types")
- (stdout, stderr) = Popen(
- pki_dir + "/easyrsa --batch init-pki nopass",
- shell=True,
- stdout=PIPE,
- stderr=PIPE).communicate()
- if (stderr):
- raise XOSConfigurationError(
- "init-pki failed with standard out:" + str(stdout) +
- " and stderr: " + str(stderr))
- (stdout, stderr) = Popen(
- pki_dir + "/easyrsa --batch --req-cn=XOS build-ca nopass",
- shell=True,
- stdout=PIPE,
- stderr=PIPE).communicate()
- if (stderr):
- raise XOSConfigurationError(
- "build-ca failed with standard out:" + str(stdout) +
- " and stderr: " + str(stderr))
- result.ca_crt = self.generate_ca_crt(result.id)
+ VPNService.execute_easyrsa_command(pki_dir, "init-pki")
+ VPNService.execute_easyrsa_command(
+ pki_dir, "--req-cn=XOS build-ca nopass")
+ result.ca_crt = self.generate_ca_crt(pki_dir)
+ result.save()
return result
- def generate_ca_crt(self, server_id):
+ def generate_ca_crt(self, pki_dir):
"""str: Generates the ca cert by reading from the ca file"""
- with open(
- "/opt/openvpn/easyrsa3/server-" + server_id + "/pki/ca.crt"
- ) as crt:
+ with open(pki_dir + "/ca.crt") as crt:
return crt.readlines()
class Meta:
@@ -259,16 +236,10 @@
# certificate
if type(obj) is TenantPrivilege:
certificate = self.certificate_name(obj)
- (stdout, stderr) = Popen(
- "/opt/openvpn/easyrsa3/server-" + obj.tenant.id +
- "/easyrsa --batch revoke " + certificate,
- shell=True,
- stdout=PIPE,
- stderr=PIPE).communicate()
- if (stderr):
- raise XOSConfigurationError(
- "revoke failed with standard out:" + str(stdout) +
- " and stderr: " + str(stderr))
+ pki_dir = (
+ VPNService.OPENVPN_PREFIX + "server-" + str(obj.id))
+ VPNService.execute_easyrsa_command(
+ pki_dir, "revoke " + certificate)
# TODO(jermowery): determine if this is necessary.
# if type(obj) is VPNTenant:
# if the tenant was deleted revoke all certs assoicated
@@ -278,17 +249,10 @@
# If there were any new TenantPrivlege objects then create certs
if type(obj) is TenantPrivilege:
certificate = self.certificate_name(obj)
- (stdout, stderr) = Popen(
- "/opt/openvpn/easyrsa3/server-" + obj.tenant.id +
- "/easyrsa --batch build-client-full " + certificate +
- " nopass",
- shell=True,
- stdout=PIPE,
- stderr=PIPE).communicate()
- if (stderr):
- raise XOSConfigurationError(
- "build-client-full failed with standard out:" +
- str(stdout) + " and stderr: " + str(stderr))
+ pki_dir = (
+ VPNService.OPENVPN_PREFIX + "server-" + str(obj.id))
+ VPNService.execute_easyrsa_command(
+ pki_dir, "build-client-full " + certificate + " nopass")
# Associate the admin forms with the models.
admin.site.register(VPNService, VPNServiceAdmin)
diff --git a/xos/services/vpn/models.py b/xos/services/vpn/models.py
index 76bc516..3996605 100644
--- a/xos/services/vpn/models.py
+++ b/xos/services/vpn/models.py
@@ -1,6 +1,7 @@
from core.models import Service, TenantWithContainer
from django.db import transaction
-from xos.exceptions import XOSValidationError
+from subprocess import Popen, PIPE
+from xos.exceptions import XOSConfigurationError, XOSValidationError
VPN_KIND = "vpn"
@@ -8,6 +9,25 @@
class VPNService(Service):
"""Defines the Service for creating VPN servers."""
KIND = VPN_KIND
+ OPENVPN_PREFIX = "/opt/openvpn/"
+ VARS = OPENVPN_PREFIX + "vars"
+ EASYRSA_LOC = OPENVPN_PREFIX + "easyrsa3/easyrsa"
+ EASYRSA_COMMAND = EASYRSA_LOC + " --vars=" + VARS
+
+ @classmethod
+ def execute_easyrsa_command(pki_dir, command):
+ full_command = (
+ VPNService.EASYRSA_COMMAND + " --pki-dir=" +
+ pki_dir + " " + command)
+ (stdout, stderr) = (
+ Popen(
+ full_command, shell=True, stdout=PIPE, stderr=PIPE
+ ).communicate()
+ )
+ if (stderr):
+ raise XOSConfigurationError(
+ full_command + " failed with standard out:" + str(stdout) +
+ " and stderr: " + str(stderr))
class Meta:
proxy = True
@@ -234,12 +254,12 @@
def get_client_cert(self, client_name):
return open(
- "/opt/openvpn/easyrsa3/server-" + self.id + "/pki/issued/" +
+ VPNService.OPENVPN_PREFIX + "server-" + self.id + "/issued/" +
client_name + ".crt").readlines()
def get_client_key(self, client_name):
return open(
- "/opt/openvpn/easyrsa3/server-" + self.id + "/pki/private/" +
+ VPNService.OPENVPN_PREFIX + "server-" + self.id + "/private/" +
client_name + ".key").readlines()
def generate_client_conf(self, client_name):
diff --git a/xos/synchronizers/vpn/steps/sync_vpntenant.py b/xos/synchronizers/vpn/steps/sync_vpntenant.py
index 90c46a3..8e9005f 100644
--- a/xos/synchronizers/vpn/steps/sync_vpntenant.py
+++ b/xos/synchronizers/vpn/steps/sync_vpntenant.py
@@ -2,11 +2,9 @@
import sys
from django.db.models import F, Q
-from services.vpn.models import VPNTenant
-from subprocess import Popen, PIPE
+from services.vpn.models import VPNService, VPNTenant
from synchronizers.base.SyncInstanceUsingAnsible import \
SyncInstanceUsingAnsible
-from xos.exceptions import XOSConfigurationError
parentdir = os.path.join(os.path.dirname(__file__), "..")
sys.path.insert(0, parentdir)
@@ -26,7 +24,8 @@
def fetch_pending(self, deleted):
if (not deleted):
objs = VPNTenant.get_tenant_objects().filter(
- Q(enacted__lt=F('updated')) | Q(enacted=None), Q(lazy_blocked=False))
+ Q(enacted__lt=F('updated')) |
+ Q(enacted=None), Q(lazy_blocked=False))
else:
objs = VPNTenant.get_deleted_tenant_objects()
@@ -36,18 +35,19 @@
return {"is_persistent": tenant.is_persistent,
"vpn_subnet": tenant.vpn_subnet,
"server_network": tenant.server_network,
- "clients_can_see_each_other": tenant.clients_can_see_each_other,
+ "clients_can_see_each_other": (
+ tenant.clients_can_see_each_other),
"tenant_id": tenant.id,
"port_number": tenant.port_number,
- "protocol": tenant.protocol
+ "protocol": tenant.protocol,
+ "pki_dir": (
+ VPNService.OPENVPN_PREFIX + "server-" + str(tenant.id))
}
def run_playbook(self, o, fields):
# Generate the server files
- (stdout, stderr) = Popen("/opt/openvpn/easyrsa3/server-" + o.id + "/easyrsa --batch build-server-full server nopass", shell=True, stdout=PIPE, stderr=PIPE).communicate()
- if (stderr):
- raise XOSConfigurationError("build-server-full failed with standard out:" + str(stdout) + " and stderr: " + str(stderr))
- (stdout, stderr) = Popen("/opt/openvpn/easyrsa3/server-" + o.id + "/easyrsa --batch gen-crl", shell=True, stdout=PIPE, stderr=PIPE).communicate()
- if (stderr):
- raise XOSConfigurationError("gen-crl failed with standard out:" + str(stdout) + " and stderr: " + str(stderr))
+ pki_dir = VPNService.OPENVPN_PREFIX + "server-" + str(o.id)
+ VPNService.execute_easyrsa_command(
+ pki_dir, "build-server-full server nopass")
+ VPNService.execute_easyrsa_command(pki_dir, "gen-crl")
super(SyncVPNTenant, self).run_playbook(o, fields)
diff --git a/xos/synchronizers/vpn/steps/sync_vpntenant.yaml b/xos/synchronizers/vpn/steps/sync_vpntenant.yaml
index 256dd63..d72b465 100644
--- a/xos/synchronizers/vpn/steps/sync_vpntenant.yaml
+++ b/xos/synchronizers/vpn/steps/sync_vpntenant.yaml
@@ -12,46 +12,38 @@
tenant_id: {{ tenant_id }}
port_number: {{ port_number }}
protocol: {{ protocol }}
+ pki_dir: {{ pki_dir }}
tasks:
- name: install openvpn
apt: name=openvpn state=present update_cache=yes
- name: stop openvpn
- shell: kill -9 $(cat /opt/openvpn/server-{{ tenant_id }}/pid) || true
+ shell: kill -9 $(cat {{ pki_dir }}/pid) || true
- name: make sure /opt/openvpn exists
file: path=/opt/openvpn state=directory
- name: make sure directory for this server exists
- file: path=/opt/openvpn/server-{{ tenant_id }} state=directory
+ file: path={{ pki_dir }} state=directory
- name: get server key
- copy: src=/opt/openvpn/easyrsa3/server-{{ tenant_id }}/pki/private/server.key dest=/opt/openvpn/server-{{ tenant_id }}/server.key
+ copy: src={{ pki_dir }}/private/server.key dest={{ pki_dir }}/server.key
- name: get server crt
- copy: src=/opt/openvpn/easyrsa3/server-{{ tenant_id }}/pki/issued/server.crt dest=/opt/openvpn/server-{{ tenant_id }}/server.crt
+ copy: src={{ pki_dir }}/issued/server.crt dest={{ pki_dir }}/server.crt
- name: get ca crt
- copy: src=/opt/openvpn/easyrsa3/server-{{ tenant_id }}/pki/ca.crt dest=/opt/openvpn/ca.crt
+ copy: src={{ pki_dir }}/ca.crt dest={{ pki_dir }}/ca.crt
- name: get crl
- copy: src=/opt/openvpn/easyrsa3/server-{{ tenant_id }}/pki/crl.pem dest=/opt/openvpn/crl.pem
+ copy: src={{ pki_dir }}/crl.pem dest={{ pki_dir }}/crl.pem
- name: get dh
- copy: src=/opt/openvpn/easyrsa3/pki/dh.pem dest=/opt/openvpn/dh.pem
+ copy: src=/opt/openvpn/init_pki/dh.pem dest={{ pki_dir }}/dh.pem
- name: erase config
- shell: rm -f /opt/openvpn/server-{{ tenant_id }}/server.conf
-
- - name: erase auth script
- shell: rm -f /opt/openvpn/server-{{ tenant_id }}/auth.sh
-
- - name: write auth script
- shell: printf "%b" "#!/bin/bash\nexit 0" > /opt/openvpn/server-{{ tenant_id }}/auth.sh
-
- - name: make auth script executable
- shell: chmod 777 /opt/openvpn/server-{{ tenant_id }}/auth.sh
+ shell: rm -f {{ pki_dir }}/server.conf
- name: write base config
shell:
@@ -60,17 +52,17 @@
port {{ port_number }}
proto {{ protocol }}
dev tun
- ca /opt/openvpn/ca.crt
- cert /opt/openvpn/server-{{ tenant_id }}/server.crt
- key /opt/openvpn/server-{{ tenant_id }}/server.key
- dh /opt/openvpn/server-{{ tenant_id }}/dh.pem
- crl-verify /opt/openvpn/server-{{ tenant_id }}/crl.pem
+ ca {{ pki_dir }}/ca.crt
+ cert {{ pki_dir }}/server.crt
+ key {{ pki_dir }}/server.key
+ dh {{ pki_dir }}/dh.pem
+ crl-verify {{ pki_dir }}/crl.pem
server {{ server_network }} {{ vpn_subnet }}
- ifconfig-pool-persist /opt/openvpn/server-{{ tenant_id }}/ipp.txt
+ ifconfig-pool-persist {{ pki_dir }}/ipp.txt
comp-lzo
- status /opt/openvpn/server-{{ tenant_id }}/openvpn-status.log
+ status {{ pki_dir }}/openvpn-status.log
verb 3
- " > /opt/openvpn/server-{{ tenant_id }}/server.conf
+ " > {{ pki_dir }}/server.conf
- name: write persistent config
shell:
@@ -78,12 +70,12 @@
printf "keepalive 10 60
persist-tun
persist-key
- " >> /opt/openvpn/server-{{ tenant_id }}/server.conf
+ " >> {{ pki_dir }}/server.conf
when: {{ is_persistent }}
- name: write client-to-client config
- shell: printf "client-to-client\n" >> /opt/openvpn/server{{ tenant_id }}/server.conf
+ shell: printf "client-to-client\n" >> {{ pki_dir }}/server.conf
when: {{ clients_can_see_each_other }}
- name: start openvpn
- shell: openvpn --writepid /opt/openvpn/server{{ tenant_id }}/pid /opt/openvpn/server{{ tenant_id }}/server.conf &
+ shell: openvpn --writepid {{ pki_dir }}/pid {{ pki_dir }}/server.conf &