summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-07-22 09:16:30 +0200
committerGitHub <noreply@github.com>2021-07-22 09:16:30 +0200
commite09dd24cd1d7c1076dca2b30b224e17b9ae28e3a (patch)
treef42f7d9f65cdbf0b832373e68fd71e253a69f452 /src
parent936b36fdf180fce830dbc388ec5e8fc35feb9474 (diff)
parenta9e9c4acfa90fc15a8a4b6b5ea6e1c2814ce940e (diff)
downloadvyos-1x-e09dd24cd1d7c1076dca2b30b224e17b9ae28e3a.tar.gz
vyos-1x-e09dd24cd1d7c1076dca2b30b224e17b9ae28e3a.zip
Merge pull request #934 from sarthurdev/pki_openvpn
pki: openvpn: T3642: Migrate OpenVPN to PKI and refactor
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py326
-rwxr-xr-xsrc/migration-scripts/interfaces/22-to-23219
2 files changed, 440 insertions, 105 deletions
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 0256ad62a..74e29ed82 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -17,6 +17,7 @@
import os
import re
+from cryptography.hazmat.primitives.asymmetric import ec
from glob import glob
from sys import exit
from ipaddress import IPv4Address
@@ -31,8 +32,14 @@ from vyos.config import Config
from vyos.configdict import get_interface_dict
from vyos.configverify import verify_vrf
from vyos.configverify import verify_bridge_delete
-from vyos.configverify import verify_diffie_hellman_length
from vyos.ifconfig import VTunIf
+from vyos.pki import load_dh_parameters
+from vyos.pki import load_private_key
+from vyos.pki import wrap_certificate
+from vyos.pki import wrap_crl
+from vyos.pki import wrap_dh_parameters
+from vyos.pki import wrap_openvpn_key
+from vyos.pki import wrap_private_key
from vyos.template import render
from vyos.template import is_ipv4
from vyos.template import is_ipv6
@@ -40,6 +47,7 @@ from vyos.util import call
from vyos.util import chown
from vyos.util import chmod_600
from vyos.util import dict_search
+from vyos.util import dict_search_args
from vyos.validate import is_addr_assigned
from vyos import ConfigError
@@ -49,23 +57,9 @@ airbag.enable()
user = 'openvpn'
group = 'openvpn'
+cfg_dir = '/run/openvpn'
cfg_file = '/run/openvpn/{ifname}.conf'
-def checkCertHeader(header, filename):
- """
- Verify if filename contains specified header.
- Returns True if match is found, False if no match or file is not found
- """
- if not os.path.isfile(filename):
- return False
-
- with open(filename, 'r') as f:
- for line in f:
- if re.match(header, line):
- return True
-
- return False
-
def get_config(config=None):
"""
Retrive CLI config as dictionary. Dictionary can never be empty, as at least the
@@ -76,14 +70,105 @@ def get_config(config=None):
else:
conf = Config()
base = ['interfaces', 'openvpn']
+
+ tmp_pki = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
+ get_first_key=True, no_tag_node_value_mangle=True)
+
openvpn = get_interface_dict(conf, base)
+ if 'deleted' not in openvpn:
+ openvpn['pki'] = tmp_pki
+
openvpn['auth_user_pass_file'] = '/run/openvpn/{ifname}.pw'.format(**openvpn)
openvpn['daemon_user'] = user
openvpn['daemon_group'] = group
return openvpn
+def is_ec_private_key(pki, cert_name):
+ if not pki or 'certificate' not in pki:
+ return False
+ if cert_name not in pki['certificate']:
+ return False
+
+ pki_cert = pki['certificate'][cert_name]
+ if 'private' not in pki_cert or 'key' not in pki_cert['private']:
+ return False
+
+ key = load_private_key(pki_cert['private']['key'])
+ return isinstance(key, ec.EllipticCurvePrivateKey)
+
+def verify_pki(openvpn):
+ pki = openvpn['pki']
+ interface = openvpn['ifname']
+ mode = openvpn['mode']
+ shared_secret_key = dict_search_args(openvpn, 'shared_secret_key')
+ tls = dict_search_args(openvpn, 'tls')
+
+ if not bool(shared_secret_key) ^ bool(tls): # xor check if only one is set
+ raise ConfigError('Must specify only one of "shared-secret-key" and "tls"')
+
+ if mode in ['server', 'client'] and not tls:
+ raise ConfigError('Must specify "tls" for server and client modes')
+
+ if not pki:
+ raise ConfigError('PKI is not configured')
+
+ if shared_secret_key:
+ if not dict_search_args(pki, 'openvpn', 'shared_secret'):
+ raise ConfigError('There are no openvpn shared-secrets in PKI configuration')
+
+ if shared_secret_key not in pki['openvpn']['shared_secret']:
+ raise ConfigError(f'Invalid shared-secret on openvpn interface {interface}')
+
+ if tls:
+ if 'ca_certificate' not in tls:
+ raise ConfigError(f'Must specify "tls ca-certificate" on openvpn interface {interface}')
+
+ if tls['ca_certificate'] not in pki['ca']:
+ raise ConfigError(f'Invalid CA certificate on openvpn interface {interface}')
+
+ if not (mode == 'client' and 'auth_key' in tls):
+ if 'certificate' not in tls:
+ raise ConfigError(f'Missing "tls certificate" on openvpn interface {interface}')
+
+ if 'certificate' in tls:
+ if tls['certificate'] not in pki['certificate']:
+ raise ConfigError(f'Invalid certificate on openvpn interface {interface}')
+
+ if dict_search_args(pki, 'certificate', tls['certificate'], 'private', 'password_protected'):
+ raise ConfigError(f'Cannot use encrypted private key on openvpn interface {interface}')
+
+ if mode == 'server' and 'dh_params' not in tls and not is_ec_private_key(pki, tls['certificate']):
+ raise ConfigError('Must specify "tls dh-params" when not using EC keys in server mode')
+
+ if 'dh_params' in tls:
+ if 'dh' not in pki:
+ raise ConfigError('There are no DH parameters in PKI configuration')
+
+ if tls['dh_params'] not in pki['dh']:
+ raise ConfigError(f'Invalid dh-params on openvpn interface {interface}')
+
+ pki_dh = pki['dh'][tls['dh_params']]
+ dh_params = load_dh_parameters(pki_dh['parameters'])
+ dh_numbers = dh_params.parameter_numbers()
+ dh_bits = dh_numbers.p.bit_length()
+
+ if dh_bits < 2048:
+ raise ConfigError(f'Minimum DH key-size is 2048 bits')
+
+ if 'auth_key' in tls or 'crypt_key' in tls:
+ if not dict_search_args(pki, 'openvpn', 'shared_secret'):
+ raise ConfigError('There are no openvpn shared-secrets in PKI configuration')
+
+ if 'auth_key' in tls:
+ if tls['auth_key'] not in pki['openvpn']['shared_secret']:
+ raise ConfigError(f'Invalid auth-key on openvpn interface {interface}')
+
+ if 'crypt_key' in tls:
+ if tls['crypt_key'] not in pki['openvpn']['shared_secret']:
+ raise ConfigError(f'Invalid crypt-key on openvpn interface {interface}')
+
def verify(openvpn):
if 'deleted' in openvpn:
verify_bridge_delete(openvpn)
@@ -108,8 +193,8 @@ def verify(openvpn):
if openvpn['protocol'] == 'tcp-passive':
raise ConfigError('Protocol "tcp-passive" is not valid in client mode')
- if dict_search('tls.dh_file', openvpn):
- raise ConfigError('Cannot specify "tls dh-file" in client mode')
+ if dict_search('tls.dh_params', openvpn):
+ raise ConfigError('Cannot specify "tls dh-params" in client mode')
#
# OpenVPN site-to-site - VERIFY
@@ -194,11 +279,6 @@ def verify(openvpn):
if 'remote_host' in openvpn:
raise ConfigError('Cannot specify "remote-host" in server mode')
- if 'tls' in openvpn:
- if 'dh_file' not in openvpn['tls']:
- if 'key_file' in openvpn['tls'] and not checkCertHeader('-----BEGIN EC PRIVATE KEY-----', openvpn['tls']['key_file']):
- raise ConfigError('Must specify "tls dh-file" when not using EC keys in server mode')
-
tmp = dict_search('server.subnet', openvpn)
if tmp:
v4_subnets = len([subnet for subnet in tmp if is_ipv4(subnet)])
@@ -306,97 +386,40 @@ def verify(openvpn):
if 'remote_host' not in openvpn:
raise ConfigError('Must specify "remote-host" with "tcp-active"')
- # shared secret and TLS
- if not ('shared_secret_key_file' in openvpn or 'tls' in openvpn):
- raise ConfigError('Must specify one of "shared-secret-key-file" and "tls"')
-
- if {'shared_secret_key_file', 'tls'} <= set(openvpn):
- raise ConfigError('Can only specify one of "shared-secret-key-file" and "tls"')
-
- if openvpn['mode'] in ['client', 'server']:
- if 'tls' not in openvpn:
- raise ConfigError('Must specify "tls" for server and client mode')
-
#
# TLS/encryption
#
- if 'shared_secret_key_file' in openvpn:
+ if 'shared_secret_key' in openvpn:
if dict_search('encryption.cipher', openvpn) in ['aes128gcm', 'aes192gcm', 'aes256gcm']:
- raise ConfigError('GCM encryption with shared-secret-key-file not supported')
-
- file = dict_search('shared_secret_key_file', openvpn)
- if file and not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', file):
- raise ConfigError(f'Specified shared-secret-key-file "{file}" is not valid')
+ raise ConfigError('GCM encryption with shared-secret-key not supported')
if 'tls' in openvpn:
- if 'ca_cert_file' not in openvpn['tls']:
- raise ConfigError('Must specify "tls ca-cert-file"')
-
- if not (openvpn['mode'] == 'client' and 'auth_file' in openvpn['tls']):
- if 'cert_file' not in openvpn['tls']:
- raise ConfigError('Missing "tls cert-file"')
-
- if 'key_file' not in openvpn['tls']:
- raise ConfigError('Missing "tls key-file"')
-
- if {'auth_file', 'crypt_file'} <= set(openvpn['tls']):
- raise ConfigError('TLS auth and crypt are mutually exclusive')
-
- file = dict_search('tls.ca_cert_file', openvpn)
- if file and not checkCertHeader('-----BEGIN CERTIFICATE-----', file):
- raise ConfigError(f'Specified ca-cert-file "{file}" is invalid')
-
- file = dict_search('tls.auth_file', openvpn)
- if file and not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', file):
- raise ConfigError(f'Specified auth-file "{file}" is invalid')
-
- file = dict_search('tls.cert_file', openvpn)
- if file and not checkCertHeader('-----BEGIN CERTIFICATE-----', file):
- raise ConfigError(f'Specified cert-file "{file}" is invalid')
-
- file = dict_search('tls.key_file', openvpn)
- if file and not checkCertHeader('-----BEGIN (?:RSA |EC )?PRIVATE KEY-----', file):
- raise ConfigError(f'Specified key-file "{file}" is not valid')
-
- file = dict_search('tls.crypt_file', openvpn)
- if file and not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', file):
- raise ConfigError(f'Specified TLS crypt-file "{file}" is invalid')
-
- file = dict_search('tls.crl_file', openvpn)
- if file and not checkCertHeader('-----BEGIN X509 CRL-----', file):
- raise ConfigError(f'Specified crl-file "{file} not valid')
-
- file = dict_search('tls.dh_file', openvpn)
- if file and not checkCertHeader('-----BEGIN DH PARAMETERS-----', file):
- raise ConfigError(f'Specified dh-file "{file}" is not valid')
-
- if file and not verify_diffie_hellman_length(file, 2048):
- raise ConfigError(f'Minimum DH key-size is 2048 bits')
+ if {'auth_key', 'crypt_key'} <= set(openvpn['tls']):
+ raise ConfigError('TLS auth and crypt keys are mutually exclusive')
tmp = dict_search('tls.role', openvpn)
if tmp:
if openvpn['mode'] in ['client', 'server']:
- if not dict_search('tls.auth_file', openvpn):
+ if not dict_search('tls.auth_key', openvpn):
raise ConfigError('Cannot specify "tls role" in client-server mode')
if tmp == 'active':
if openvpn['protocol'] == 'tcp-passive':
raise ConfigError('Cannot specify "tcp-passive" when "tls role" is "active"')
- if dict_search('tls.dh_file', openvpn):
- raise ConfigError('Cannot specify "tls dh-file" when "tls role" is "active"')
+ if dict_search('tls.dh_params', openvpn):
+ raise ConfigError('Cannot specify "tls dh-params" when "tls role" is "active"')
elif tmp == 'passive':
if openvpn['protocol'] == 'tcp-active':
raise ConfigError('Cannot specify "tcp-active" when "tls role" is "passive"')
- if not dict_search('tls.dh_file', openvpn):
- raise ConfigError('Must specify "tls dh-file" when "tls role" is "passive"')
+ if not dict_search('tls.dh_params', openvpn):
+ raise ConfigError('Must specify "tls dh-params" when "tls role" is "passive"')
- file = dict_search('tls.key_file', openvpn)
- if file and checkCertHeader('-----BEGIN EC PRIVATE KEY-----', file):
- if dict_search('tls.dh_file', openvpn):
- print('Warning: using dh-file and EC keys simultaneously will ' \
+ if 'certificate' in openvpn['tls'] and is_ec_private_key(openvpn['pki'], openvpn['tls']['certificate']):
+ if 'dh_params' in openvpn['tls']:
+ print('Warning: using dh-params and EC keys simultaneously will ' \
'lead to DH ciphers being used instead of ECDH')
if dict_search('encryption.cipher', openvpn) == 'none':
@@ -404,6 +427,8 @@ def verify(openvpn):
print('No encryption will be performed and data is transmitted in ' \
'plain text over the network!')
+ verify_pki(openvpn)
+
#
# Auth user/pass
#
@@ -419,6 +444,110 @@ def verify(openvpn):
return None
+def generate_pki_files(openvpn):
+ pki = openvpn['pki']
+
+ if not pki:
+ return None
+
+ interface = openvpn['ifname']
+ shared_secret_key = dict_search_args(openvpn, 'shared_secret_key')
+ tls = dict_search_args(openvpn, 'tls')
+
+ files = []
+
+ if shared_secret_key:
+ pki_key = pki['openvpn']['shared_secret'][shared_secret_key]
+ key_path = os.path.join(cfg_dir, f'{interface}_shared.key')
+
+ with open(key_path, 'w') as f:
+ f.write(wrap_openvpn_key(pki_key['key']))
+
+ files.append(key_path)
+
+ if tls:
+ if 'ca_certificate' in tls:
+ cert_name = tls['ca_certificate']
+ pki_ca = pki['ca'][cert_name]
+
+ if 'certificate' in pki_ca:
+ cert_path = os.path.join(cfg_dir, f'{interface}_ca.pem')
+
+ with open(cert_path, 'w') as f:
+ f.write(wrap_certificate(pki_ca['certificate']))
+
+ files.append(cert_path)
+
+ if 'crl' in pki_ca:
+ for crl in pki_ca['crl']:
+ crl_path = os.path.join(cfg_dir, f'{interface}_crl.pem')
+
+ with open(crl_path, 'w') as f:
+ f.write(wrap_crl(crl))
+
+ files.append(crl_path)
+ openvpn['tls']['crl'] = True
+
+ if 'certificate' in tls:
+ cert_name = tls['certificate']
+ pki_cert = pki['certificate'][cert_name]
+
+ if 'certificate' in pki_cert:
+ cert_path = os.path.join(cfg_dir, f'{interface}_cert.pem')
+
+ with open(cert_path, 'w') as f:
+ f.write(wrap_certificate(pki_cert['certificate']))
+
+ files.append(cert_path)
+
+ if 'private' in pki_cert and 'key' in pki_cert['private']:
+ key_path = os.path.join(cfg_dir, f'{interface}_cert.key')
+
+ with open(key_path, 'w') as f:
+ f.write(wrap_private_key(pki_cert['private']['key']))
+
+ files.append(key_path)
+ openvpn['tls']['private_key'] = True
+
+ if 'dh_params' in tls:
+ dh_name = tls['dh_params']
+ pki_dh = pki['dh'][dh_name]
+
+ if 'parameters' in pki_dh:
+ dh_path = os.path.join(cfg_dir, f'{interface}_dh.pem')
+
+ with open(dh_path, 'w') as f:
+ f.write(wrap_dh_parameters(pki_dh['parameters']))
+
+ files.append(dh_path)
+
+ if 'auth_key' in tls:
+ key_name = tls['auth_key']
+ pki_key = pki['openvpn']['shared_secret'][key_name]
+
+ if 'key' in pki_key:
+ key_path = os.path.join(cfg_dir, f'{interface}_auth.key')
+
+ with open(key_path, 'w') as f:
+ f.write(wrap_openvpn_key(pki_key['key']))
+
+ files.append(key_path)
+
+ if 'crypt_key' in tls:
+ key_name = tls['crypt_key']
+ pki_key = pki['openvpn']['shared_secret'][key_name]
+
+ if 'key' in pki_key:
+ key_path = os.path.join(cfg_dir, f'{interface}_crypt.key')
+
+ with open(key_path, 'w') as f:
+ f.write(wrap_openvpn_key(pki_key['key']))
+
+ files.append(key_path)
+
+ return files
+
+
def generate(openvpn):
interface = openvpn['ifname']
directory = os.path.dirname(cfg_file.format(**openvpn))
@@ -438,13 +567,7 @@ def generate(openvpn):
chown(ccd_dir, user, group)
# Fix file permissons for keys
- fix_permissions = []
-
- tmp = dict_search('shared_secret_key_file', openvpn)
- if tmp: fix_permissions.append(openvpn['shared_secret_key_file'])
-
- tmp = dict_search('tls.key_file', openvpn)
- if tmp: fix_permissions.append(tmp)
+ fix_permissions = generate_pki_files(openvpn)
# Generate User/Password authentication file
if 'authentication' in openvpn:
@@ -456,8 +579,9 @@ def generate(openvpn):
os.remove(openvpn['auth_user_pass_file'])
# Generate client specific configuration
- if dict_search('server.client', openvpn):
- for client, client_config in dict_search('server.client', openvpn).items():
+ server_client = dict_search_args(openvpn, 'server', 'client')
+ if server_client:
+ for client, client_config in server_client.items():
client_file = os.path.join(ccd_dir, client)
# Our client need's to know its subnet mask ...
diff --git a/src/migration-scripts/interfaces/22-to-23 b/src/migration-scripts/interfaces/22-to-23
index 3fd5998a0..93ce9215f 100755
--- a/src/migration-scripts/interfaces/22-to-23
+++ b/src/migration-scripts/interfaces/22-to-23
@@ -21,12 +21,34 @@ import os
import sys
from vyos.configtree import ConfigTree
from vyos.pki import load_certificate
+from vyos.pki import load_crl
+from vyos.pki import load_dh_parameters
from vyos.pki import load_private_key
from vyos.pki import encode_certificate
+from vyos.pki import encode_dh_parameters
from vyos.pki import encode_private_key
+from vyos.util import run
def wrapped_pem_to_config_value(pem):
- return "".join(pem.strip().split("\n")[1:-1])
+ out = []
+ for line in pem.strip().split("\n"):
+ if not line or line.startswith("-----") or line[0] == '#':
+ continue
+ out.append(line)
+ return "".join(out)
+
+def read_file_for_pki(config_auth_path):
+ full_path = os.path.join(AUTH_DIR, config_auth_path)
+ output = None
+
+ if os.path.isfile(full_path):
+ if not os.access(full_path, os.R_OK):
+ run(f'sudo chmod 644 {full_path}')
+
+ with open(full_path, 'r') as f:
+ output = f.read()
+
+ return output
if (len(sys.argv) < 1):
print("Must specify file name!")
@@ -39,6 +61,198 @@ with open(file_name, 'r') as f:
config = ConfigTree(config_file)
+AUTH_DIR = '/config/auth'
+pki_base = ['pki']
+
+# OpenVPN
+base = ['interfaces', 'openvpn']
+
+if config.exists(base):
+ for interface in config.list_nodes(base):
+ x509_base = base + [interface, 'tls']
+ pki_name = f'openvpn_{interface}'
+
+ if config.exists(base + [interface, 'shared-secret-key-file']):
+ if not config.exists(pki_base + ['openvpn', 'shared-secret']):
+ config.set(pki_base + ['openvpn', 'shared-secret'])
+ config.set_tag(pki_base + ['openvpn', 'shared-secret'])
+
+ key_file = config.return_value(base + [interface, 'shared-secret-key-file'])
+ key = read_file_for_pki(key_file)
+ key_pki_name = f'{pki_name}_shared'
+
+ if key:
+ config.set(pki_base + ['openvpn', 'shared-secret', key_pki_name, 'key'], value=wrapped_pem_to_config_value(key))
+ config.set(pki_base + ['openvpn', 'shared-secret', key_pki_name, 'version'], value='1')
+ config.set(base + [interface, 'shared-secret-key'], value=key_pki_name)
+ else:
+ print(f'Failed to migrate shared-secret-key on openvpn interface {interface}')
+
+ config.delete(base + [interface, 'shared-secret-key-file'])
+
+ if not config.exists(base + [interface, 'tls']):
+ continue
+
+ if config.exists(base + [interface, 'tls', 'auth-file']):
+ if not config.exists(pki_base + ['openvpn', 'shared-secret']):
+ config.set(pki_base + ['openvpn', 'shared-secret'])
+ config.set_tag(pki_base + ['openvpn', 'shared-secret'])
+
+ key_file = config.return_value(base + [interface, 'tls', 'auth-file'])
+ key = read_file_for_pki(key_file)
+ key_pki_name = f'{pki_name}_auth'
+
+ if key:
+ config.set(pki_base + ['openvpn', 'shared-secret', key_pki_name, 'key'], value=wrapped_pem_to_config_value(key))
+ config.set(pki_base + ['openvpn', 'shared-secret', key_pki_name, 'version'], value='1')
+ config.set(base + [interface, 'tls', 'auth-key'], value=key_pki_name)
+ else:
+ print(f'Failed to migrate auth-key on openvpn interface {interface}')
+
+ config.delete(base + [interface, 'tls', 'auth-file'])
+
+ if config.exists(base + [interface, 'tls', 'crypt-file']):
+ if not config.exists(pki_base + ['openvpn', 'shared-secret']):
+ config.set(pki_base + ['openvpn', 'shared-secret'])
+ config.set_tag(pki_base + ['openvpn', 'shared-secret'])
+
+ key_file = config.return_value(base + [interface, 'tls', 'crypt-file'])
+ key = read_file_for_pki(key_file)
+ key_pki_name = f'{pki_name}_crypt'
+
+ if key:
+ config.set(pki_base + ['openvpn', 'shared-secret', key_pki_name, 'key'], value=wrapped_pem_to_config_value(key))
+ config.set(pki_base + ['openvpn', 'shared-secret', key_pki_name, 'version'], value='1')
+ config.set(base + [interface, 'tls', 'crypt-key'], value=key_pki_name)
+ else:
+ print(f'Failed to migrate crypt-key on openvpn interface {interface}')
+
+ config.delete(base + [interface, 'tls', 'crypt-file'])
+
+ if config.exists(x509_base + ['ca-cert-file']):
+ if not config.exists(pki_base + ['ca']):
+ config.set(pki_base + ['ca'])
+ config.set_tag(pki_base + ['ca'])
+
+ cert_file = config.return_value(x509_base + ['ca-cert-file'])
+ cert_path = os.path.join(AUTH_DIR, cert_file)
+ cert = None
+
+ if os.path.isfile(cert_path):
+ if not os.access(cert_path, os.R_OK):
+ run(f'sudo chmod 644 {cert_path}')
+
+ with open(cert_path, 'r') as f:
+ cert_data = f.read()
+ cert = load_certificate(cert_data, wrap_tags=False)
+
+ if cert:
+ cert_pem = encode_certificate(cert)
+ config.set(pki_base + ['ca', pki_name, 'certificate'], value=wrapped_pem_to_config_value(cert_pem))
+ config.set(x509_base + ['ca-certificate'], value=pki_name)
+ else:
+ print(f'Failed to migrate CA certificate on openvpn interface {interface}')
+
+ config.delete(x509_base + ['ca-cert-file'])
+
+ if config.exists(x509_base + ['crl-file']):
+ if not config.exists(pki_base + ['ca']):
+ config.set(pki_base + ['ca'])
+ config.set_tag(pki_base + ['ca'])
+
+ crl_file = config.return_value(x509_base + ['crl-file'])
+ crl_path = os.path.join(AUTH_DIR, crl_file)
+ crl = None
+
+ if os.path.isfile(crl_path):
+ if not os.access(crl_path, os.R_OK):
+ run(f'sudo chmod 644 {crl_path}')
+
+ with open(crl_path, 'r') as f:
+ crl_data = f.read()
+ crl = load_crl(crl_data, wrap_tags=False)
+
+ if crl:
+ crl_pem = encode_certificate(crl)
+ config.set(pki_base + ['ca', pki_name, 'crl'], value=wrapped_pem_to_config_value(crl_pem))
+ else:
+ print(f'Failed to migrate CRL on openvpn interface {interface}')
+
+ config.delete(x509_base + ['crl-file'])
+
+ if config.exists(x509_base + ['cert-file']):
+ if not config.exists(pki_base + ['certificate']):
+ config.set(pki_base + ['certificate'])
+ config.set_tag(pki_base + ['certificate'])
+
+ cert_file = config.return_value(x509_base + ['cert-file'])
+ cert_path = os.path.join(AUTH_DIR, cert_file)
+ cert = None
+
+ if os.path.isfile(cert_path):
+ if not os.access(cert_path, os.R_OK):
+ run(f'sudo chmod 644 {cert_path}')
+
+ with open(cert_path, 'r') as f:
+ cert_data = f.read()
+ cert = load_certificate(cert_data, wrap_tags=False)
+
+ if cert:
+ cert_pem = encode_certificate(cert)
+ config.set(pki_base + ['certificate', pki_name, 'certificate'], value=wrapped_pem_to_config_value(cert_pem))
+ config.set(x509_base + ['certificate'], value=pki_name)
+ else:
+ print(f'Failed to migrate certificate on openvpn interface {interface}')
+
+ config.delete(x509_base + ['cert-file'])
+
+ if config.exists(x509_base + ['key-file']):
+ key_file = config.return_value(x509_base + ['key-file'])
+ key_path = os.path.join(AUTH_DIR, key_file)
+ key = None
+
+ if os.path.isfile(key_path):
+ if not os.access(key_path, os.R_OK):
+ run(f'sudo chmod 644 {key_path}')
+
+ with open(key_path, 'r') as f:
+ key_data = f.read()
+ key = load_private_key(key_data, passphrase=None, wrap_tags=False)
+
+ if key:
+ key_pem = encode_private_key(key, passphrase=None)
+ config.set(pki_base + ['certificate', pki_name, 'private', 'key'], value=wrapped_pem_to_config_value(key_pem))
+ else:
+ print(f'Failed to migrate private key on openvpn interface {interface}')
+
+ config.delete(x509_base + ['key-file'])
+
+ if config.exists(x509_base + ['dh-file']):
+ if not config.exists(pki_base + ['dh']):
+ config.set(pki_base + ['dh'])
+ config.set_tag(pki_base + ['dh'])
+
+ dh_file = config.return_value(x509_base + ['dh-file'])
+ dh_path = os.path.join(AUTH_DIR, dh_file)
+ dh = None
+
+ if os.path.isfile(dh_path):
+ if not os.access(dh_path, os.R_OK):
+ run(f'sudo chmod 644 {dh_path}')
+
+ with open(dh_path, 'r') as f:
+ dh_data = f.read()
+ dh = load_dh_parameters(dh_data, wrap_tags=False)
+
+ if dh:
+ dh_pem = encode_dh_parameters(dh)
+ config.set(pki_base + ['dh', pki_name, 'parameters'], value=wrapped_pem_to_config_value(dh_pem))
+ config.set(x509_base + ['dh-params'], value=pki_name)
+ else:
+ print(f'Failed to migrate DH parameters on openvpn interface {interface}')
+
+ config.delete(x509_base + ['dh-file'])
+
# Wireguard
base = ['interfaces', 'wireguard']
@@ -67,9 +281,6 @@ if config.exists(base):
base = ['interfaces', 'ethernet']
if config.exists(base):
- AUTH_DIR = '/config/auth'
- pki_base = ['pki']
-
for interface in config.list_nodes(base):
if not config.exists(base + [interface, 'eapol']):
continue