summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/openvpn/server.conf.tmpl2
-rw-r--r--op-mode-definitions/generate-wireguard.xml.in26
-rw-r--r--op-mode-definitions/pki.xml.in82
-rw-r--r--python/vyos/configdict.py4
-rw-r--r--python/vyos/ethtool.py19
-rw-r--r--python/vyos/ifconfig/ethernet.py42
-rw-r--r--python/vyos/util.py4
-rwxr-xr-xsrc/conf_mode/interfaces-ethernet.py2
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py81
-rwxr-xr-xsrc/conf_mode/policy.py1
-rw-r--r--src/etc/systemd/system/openvpn@.service.d/override.conf4
-rwxr-xr-xsrc/op_mode/pki.py142
12 files changed, 194 insertions, 215 deletions
diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl
index 9b07a9ba2..9e4cc6813 100644
--- a/data/templates/openvpn/server.conf.tmpl
+++ b/data/templates/openvpn/server.conf.tmpl
@@ -7,8 +7,6 @@
#
verb 3
-user {{ daemon_user }}
-group {{ daemon_group }}
dev-type {{ device_type }}
dev {{ ifname }}
persist-key
diff --git a/op-mode-definitions/generate-wireguard.xml.in b/op-mode-definitions/generate-wireguard.xml.in
index 6557b463b..259c9a898 100644
--- a/op-mode-definitions/generate-wireguard.xml.in
+++ b/op-mode-definitions/generate-wireguard.xml.in
@@ -4,9 +4,27 @@
<children>
<node name="wireguard">
<properties>
- <help>Generate Wireguard keys</help>
+ <help>Generate WireGuard keys</help>
</properties>
<children>
+ <leafNode name="default-keypair">
+ <properties>
+ <help>generates the wireguard default-keypair</help>
+ </properties>
+ <command>echo "This command is deprecated. Please use: \"generate pki wireguard key-pair\""</command>
+ </leafNode>
+ <leafNode name="preshared-key">
+ <properties>
+ <help>generate a wireguard preshared key</help>
+ </properties>
+ <command>echo "This command is deprecated. Please use: \"generate pki wireguard pre-shared-key\""</command>
+ </leafNode>
+ <tagNode name="named-keypairs">
+ <properties>
+ <help>Generates named wireguard keypairs</help>
+ </properties>
+ <command>echo "This command is deprecated. Please use: \"generate pki wireguard key-pair install wgN\""</command>
+ </tagNode>
<tagNode name="client-config">
<properties>
<help>Generate Client config QR code</help>
@@ -59,12 +77,6 @@
</tagNode>
</children>
</tagNode>
- <leafNode name="key-pair">
- <properties>
- <help>Generate Wireguard key pair for use with server or peer</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --key "noname"</command>
- </leafNode>
</children>
</node>
</children>
diff --git a/op-mode-definitions/pki.xml.in b/op-mode-definitions/pki.xml.in
index a11814c8a..6b9b0d3f6 100644
--- a/op-mode-definitions/pki.xml.in
+++ b/op-mode-definitions/pki.xml.in
@@ -282,60 +282,66 @@
</node>
<node name="wireguard">
<properties>
- <help>Generate Wireguard keys</help>
+ <help>Generate WireGuard keys</help>
</properties>
<children>
<node name="key-pair">
<properties>
- <help>Generate Wireguard key pair for use with server or peer</help>
+ <help>Generate WireGuard public/private key-pair</help>
</properties>
<children>
- <tagNode name="file">
+ <node name="install">
<properties>
- <help>Write generated Wireguard keys into the specified filename</help>
- <completionHelp>
- <list>&lt;filename&gt;</list>
- </completionHelp>
+ <help>Generate CLI commands to install WireGuard key to configuration</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --key "$6" --file</command>
- </tagNode>
- <tagNode name="install">
- <properties>
- <help>Commands for installing generated Wireguard key into running configuration</help>
- <completionHelp>
- <list>&lt;interface&gt; &lt;peer&gt;</list>
- </completionHelp>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --key "$6" --install</command>
- </tagNode>
+ <children>
+ <tagNode name="interface">
+ <properties>
+ <help>WireGuard Interface used in install command</help>
+ <completionHelp>
+ <path>interfaces wireguard</path>
+ </completionHelp>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --key --interface "$7" --install</command>
+ </tagNode>
+ </children>
+ </node>
</children>
- <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --key "noname"</command>
+ <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --key</command>
</node>
- <node name="pre-shared-key">
+ <node name="preshared-key">
<properties>
- <help>Generate pre-shared key for use with a Wireguard peer</help>
+ <help>Generate WireGuard pre-shared key</help>
</properties>
<children>
- <tagNode name="file">
+ <node name="install">
<properties>
- <help>Write generated Wireguard PSK into the specified filename</help>
- <completionHelp>
- <list>&lt;filename&gt;</list>
- </completionHelp>
+ <help>Generate CLI commands to install WireGuard key to configuration</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --psk "$6" --file</command>
- </tagNode>
- <tagNode name="install">
- <properties>
- <help>Commands for installing generated Wireguard PSK on specified peer into running configuration</help>
- <completionHelp>
- <list>&lt;peer&gt;</list>
- </completionHelp>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --psk "$6" --install</command>
- </tagNode>
+ <children>
+ <tagNode name="interface">
+ <properties>
+ <help>WireGuard Interface used in install command</help>
+ <completionHelp>
+ <path>interfaces wireguard</path>
+ </completionHelp>
+ </properties>
+ <children>
+ <tagNode name="peer">
+ <properties>
+ <help>Interface used for install command</help>
+ <completionHelp>
+ <path>interfaces wireguard ${COMP_WORDS[COMP_CWORD-2]} peer</path>
+ </completionHelp>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --psk --interface "$7" --peer "$9" --install</command>
+ </tagNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
</children>
- <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --psk "noname"</command>
+ <command>sudo ${vyos_op_scripts_dir}/pki.py --action generate --wireguard --psk</command>
</node>
</children>
</node>
diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py
index e15579b95..24b76fb0b 100644
--- a/python/vyos/configdict.py
+++ b/python/vyos/configdict.py
@@ -347,8 +347,8 @@ def get_interface_dict(config, base, ifname=''):
# setup config level which is extracted in get_removed_vlans()
config.set_level(base + [ifname])
- dict = config.get_config_dict([], key_mangling=('-', '_'),
- get_first_key=True)
+ dict = config.get_config_dict([], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True)
# Check if interface has been removed. We must use exists() as
# get_config_dict() will always return {} - even when an empty interface
diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py
index 609d83b5e..bc95767b1 100644
--- a/python/vyos/ethtool.py
+++ b/python/vyos/ethtool.py
@@ -46,7 +46,7 @@ class Ethtool:
_ring_buffers_max = { }
_driver_name = None
_auto_negotiation = None
- _flow_control = None
+ _flow_control = False
_flow_control_enabled = None
def __init__(self, ifname):
@@ -134,6 +134,12 @@ class Ethtool:
# ['Autonegotiate:', 'on']
self._flow_control_enabled = out.splitlines()[1].split()[-1]
+ def get_auto_negotiation(self):
+ return self._auto_negotiation
+
+ def get_driver_name(self):
+ return self._driver_name
+
def _get_generic(self, feature):
"""
Generic method to read self._features and return a tuple for feature
@@ -184,12 +190,12 @@ class Ethtool:
the underlaying network adapter. """
if isinstance(speed, int):
speed = str(speed)
- if not speed.isdigit():
+ if speed != 'auto' and not speed.isdigit():
raise ValueError(f'Value "{speed}" for speed is invalid!')
- if duplex not in ['full', 'half']:
+ if duplex not in ['auto', 'full', 'half']:
raise ValueError(f'Value "{duplex}" for duplex is invalid!')
- if self._driver_name in ['vmxnet3', 'virtio_net', 'xen_netfront']:
+ if self.get_driver_name() in ['vmxnet3', 'virtio_net', 'xen_netfront']:
return False
if speed in self._speed_duplex:
@@ -199,7 +205,7 @@ class Ethtool:
def check_flow_control(self):
""" Check if the NIC supports flow-control """
- if self._driver_name in ['vmxnet3', 'virtio_net', 'xen_netfront']:
+ if self.get_driver_name() in ['vmxnet3', 'virtio_net', 'xen_netfront']:
return False
return self._flow_control
@@ -208,6 +214,3 @@ class Ethtool:
raise ValueError('Interface does not support changing '\
'flow-control settings!')
return self._flow_control_enabled
-
- def get_auto_negotiation(self):
- return self._auto_negotiation
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index 7bd269491..2e59a7afc 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -80,25 +80,6 @@ class EthernetIf(Interface):
super().__init__(ifname, **kargs)
self.ethtool = Ethtool(ifname)
- def get_driver_name(self):
- """
- Return the driver name used by NIC. Some NICs don't support all
- features e.g. changing link-speed, duplex
-
- Example:
- >>> from vyos.ifconfig import EthernetIf
- >>> i = EthernetIf('eth0')
- >>> i.get_driver_name()
- 'vmxnet3'
- """
- ifname = self.config['ifname']
- sysfs_file = f'/sys/class/net/{ifname}/device/driver/module'
- if os.path.exists(sysfs_file):
- link = os.readlink(sysfs_file)
- return os.path.basename(link)
- else:
- return None
-
def set_flow_control(self, enable):
"""
Changes the pause parameters of the specified Ethernet device.
@@ -115,11 +96,9 @@ class EthernetIf(Interface):
if enable not in ['on', 'off']:
raise ValueError("Value out of range")
- driver_name = self.get_driver_name()
- if driver_name in ['vmxnet3', 'virtio_net', 'xen_netfront']:
- self._debug_msg(f'{driver_name} driver does not support changing '\
- 'flow control settings!')
- return
+ if not self.ethtool.check_flow_control():
+ self._debug_msg(f'NIC driver does not support changing flow control settings!')
+ return False
current = self.ethtool.get_flow_control()
if current != enable:
@@ -152,10 +131,8 @@ class EthernetIf(Interface):
if duplex not in ['auto', 'full', 'half']:
raise ValueError("Value out of range (duplex)")
- driver_name = self.get_driver_name()
- if driver_name in ['vmxnet3', 'virtio_net', 'xen_netfront']:
- self._debug_msg(f'{driver_name} driver does not support changing '\
- 'speed/duplex settings!')
+ if not self.ethtool.check_speed_duplex(speed, duplex):
+ self._debug_msg(f'NIC driver does not support changing speed/duplex settings!')
return
# Get current speed and duplex settings:
@@ -165,9 +142,12 @@ class EthernetIf(Interface):
# bail out early as nothing is to change
return
else:
- # read in current speed and duplex settings
- cur_speed = read_file(f'/sys/class/net/{ifname}/speed')
- cur_duplex = read_file(f'/sys/class/net/{ifname}/duplex')
+ # XXX: read in current speed and duplex settings
+ # There are some "nice" NICs like AX88179 which do not support
+ # reading the speed thus we simply fallback to the supplied speed
+ # to not cause any change here and raise an exception.
+ cur_speed = read_file(f'/sys/class/net/{ifname}/speed', speed)
+ cur_duplex = read_file(f'/sys/class/net/{ifname}/duplex', duplex)
if (cur_speed == speed) and (cur_duplex == duplex):
# bail out early as nothing is to change
return
diff --git a/python/vyos/util.py b/python/vyos/util.py
index b41c5b346..849b27d3b 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -197,7 +197,7 @@ def read_file(fname, defaultonfailure=None):
return defaultonfailure
raise e
-def write_file(fname, data, defaultonfailure=None, user=None, group=None):
+def write_file(fname, data, defaultonfailure=None, user=None, group=None, mode=None):
"""
Write content of data to given fname, should defaultonfailure be not None,
it is returned on failure to read.
@@ -215,6 +215,7 @@ def write_file(fname, data, defaultonfailure=None, user=None, group=None):
with open(fname, 'w') as f:
bytes = f.write(data)
chown(fname, user, group)
+ chmod(fname, mode)
return bytes
except Exception as e:
if defaultonfailure is not None:
@@ -295,7 +296,6 @@ def makedir(path, user=None, group=None):
os.makedirs(path, mode=0o755)
chown(path, user, group)
-
def colon_separated_to_dict(data_string, uniquekeys=False):
""" Converts a string containing newline-separated entries
of colon-separated key-value pairs into a dict.
diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py
index 21a04f954..e7250fb49 100755
--- a/src/conf_mode/interfaces-ethernet.py
+++ b/src/conf_mode/interfaces-ethernet.py
@@ -126,7 +126,7 @@ def verify(ethernet):
if not os.path.exists(f'/sys/class/net/{ifname}/queues/rx-0/rps_cpus'):
raise ConfigError('Interface does not suport RPS!')
- driver = EthernetIf(ifname).get_driver_name()
+ driver = ethtool.get_driver_name()
# T3342 - Xen driver requires special treatment
if driver == 'vif':
if int(ethernet['mtu']) > 1500 and dict_search('offload.sg', ethernet) == None:
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 6be4e918b..02b7f83bf 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -45,9 +45,10 @@ from vyos.template import is_ipv4
from vyos.template import is_ipv6
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.util import makedir
+from vyos.util import write_file
from vyos.validate import is_addr_assigned
from vyos import ConfigError
@@ -80,9 +81,6 @@ def get_config(config=None):
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):
@@ -128,7 +126,7 @@ def verify_pki(openvpn):
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 mode != 'client' and 'auth_key' not in tls:
if 'certificate' not in tls:
raise ConfigError(f'Missing "tls certificate" on openvpn interface {interface}')
@@ -449,7 +447,6 @@ def verify(openvpn):
def generate_pki_files(openvpn):
pki = openvpn['pki']
-
if not pki:
return None
@@ -457,16 +454,11 @@ def generate_pki_files(openvpn):
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)
+ write_file(key_path, wrap_openvpn_key(pki_key['key']),
+ user=user, group=group)
if tls:
if 'ca_certificate' in tls:
@@ -475,20 +467,15 @@ def generate_pki_files(openvpn):
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)
+ write_file(cert_path, wrap_certificate(pki_ca['certificate']),
+ user=user, group=group, mode=0o600)
if 'crl' in pki_ca:
for crl in pki_ca['crl']:
crl_path = os.path.join(cfg_dir, f'{interface}_crl.pem')
+ write_file(crl_path, wrap_crl(crl), user=user, group=group,
+ mode=0o600)
- with open(crl_path, 'w') as f:
- f.write(wrap_crl(crl))
-
- files.append(crl_path)
openvpn['tls']['crl'] = True
if 'certificate' in tls:
@@ -497,19 +484,14 @@ def generate_pki_files(openvpn):
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)
+ write_file(cert_path, wrap_certificate(pki_cert['certificate']),
+ user=user, group=group, mode=0o600)
if 'private' in pki_cert and 'key' in pki_cert['private']:
key_path = os.path.join(cfg_dir, f'{interface}_cert.key')
+ write_file(key_path, wrap_private_key(pki_cert['private']['key']),
+ user=user, group=group, mode=0o600)
- 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:
@@ -518,11 +500,8 @@ def generate_pki_files(openvpn):
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)
+ write_file(dh_path, wrap_dh_parameters(pki_dh['parameters']),
+ user=user, group=group, mode=0o600)
if 'auth_key' in tls:
key_name = tls['auth_key']
@@ -530,11 +509,8 @@ def generate_pki_files(openvpn):
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)
+ write_file(key_path, wrap_openvpn_key(pki_key['key']),
+ user=user, group=group, mode=0o600)
if 'crypt_key' in tls:
key_name = tls['crypt_key']
@@ -542,18 +518,17 @@ def generate_pki_files(openvpn):
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
+ write_file(key_path, wrap_openvpn_key(pki_key['key']),
+ user=user, group=group, mode=0o600)
def generate(openvpn):
interface = openvpn['ifname']
directory = os.path.dirname(cfg_file.format(**openvpn))
+ # create base config directory on demand
+ makedir(directory, user, group)
+ # enforce proper permissions on /run/openvpn
+ chown(directory, user, group)
# we can't know in advance which clients have been removed,
# thus all client configs will be removed and re-added on demand
@@ -565,12 +540,10 @@ def generate(openvpn):
return None
# create client config directory on demand
- if not os.path.exists(ccd_dir):
- os.makedirs(ccd_dir, 0o755)
- chown(ccd_dir, user, group)
+ makedir(ccd_dir, user, group)
# Fix file permissons for keys
- fix_permissions = generate_pki_files(openvpn)
+ generate_pki_files(openvpn)
# Generate User/Password authentication file
if 'authentication' in openvpn:
@@ -598,10 +571,6 @@ def generate(openvpn):
render(cfg_file.format(**openvpn), 'openvpn/server.conf.tmpl', openvpn,
formater=lambda _: _.replace("&quot;", '"'), user=user, group=group)
- # Fixup file permissions
- for file in fix_permissions:
- chmod_600(file)
-
return None
def apply(openvpn):
diff --git a/src/conf_mode/policy.py b/src/conf_mode/policy.py
index d56bae9e9..1a03d520b 100755
--- a/src/conf_mode/policy.py
+++ b/src/conf_mode/policy.py
@@ -190,6 +190,7 @@ def apply(policy):
frr_cfg.modify_section(r'^bgp community-list .*')
frr_cfg.modify_section(r'^bgp extcommunity-list .*')
frr_cfg.modify_section(r'^bgp large-community-list .*')
+ frr_cfg.modify_section(r'^route-map .*')
frr_cfg.add_before('^line vty', policy['new_frr_config'])
frr_cfg.commit_configuration(bgp_daemon)
diff --git a/src/etc/systemd/system/openvpn@.service.d/override.conf b/src/etc/systemd/system/openvpn@.service.d/override.conf
index 7946484a3..03fe6b587 100644
--- a/src/etc/systemd/system/openvpn@.service.d/override.conf
+++ b/src/etc/systemd/system/openvpn@.service.d/override.conf
@@ -7,3 +7,7 @@ WorkingDirectory=
WorkingDirectory=/run/openvpn
ExecStart=
ExecStart=/usr/sbin/openvpn --daemon openvpn-%i --config %i.conf --status %i.status 30 --writepid %i.pid
+User=openvpn
+Group=openvpn
+AmbientCapabilities=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
+CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
diff --git a/src/op_mode/pki.py b/src/op_mode/pki.py
index 36891d080..d28cee5d0 100755
--- a/src/op_mode/pki.py
+++ b/src/op_mode/pki.py
@@ -17,7 +17,6 @@
import argparse
import ipaddress
import os
-import re
import sys
import tabulate
@@ -44,12 +43,14 @@ auth_dir = '/config/auth'
conf = ConfigTreeQuery()
def get_default_values():
# Fetch default x509 values
-
base = ['pki', 'x509', 'default']
x509_defaults = conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
+ get_first_key=True,
+ no_tag_node_value_mangle=True)
default_values = defaults(base)
- return dict_merge(default_values, x509_defaults)
+ x509_defaults = dict_merge(default_values, x509_defaults)
+
+ return x509_defaults
def get_config_ca_certificate(name=None):
# Fetch ca certificates from config
@@ -63,7 +64,8 @@ def get_config_ca_certificate(name=None):
return False
return conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
+ get_first_key=True,
+ no_tag_node_value_mangle=True)
def get_config_certificate(name=None):
# Get certificates from config
@@ -77,7 +79,8 @@ def get_config_certificate(name=None):
return False
return conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
+ get_first_key=True,
+ no_tag_node_value_mangle=True)
def get_certificate_ca(cert, ca_certs):
# Find CA certificate for given certificate
@@ -103,12 +106,14 @@ def get_config_revoked_certificates():
if conf.exists(ca_base):
ca_certificates = conf.get_config_dict(ca_base, key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
+ get_first_key=True,
+ no_tag_node_value_mangle=True)
certs.extend(ca_certificates.values())
if conf.exists(cert_base):
certificates = conf.get_config_dict(cert_base, key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
+ get_first_key=True,
+ no_tag_node_value_mangle=True)
certs.extend(certificates.values())
return [cert_dict for cert_dict in certs if 'revoke' in cert_dict]
@@ -139,39 +144,41 @@ def get_revoked_by_serial_numbers(serial_numbers=[]):
def install_certificate(name, cert='', private_key=None, key_type=None, key_passphrase=None, is_ca=False):
# Show conf commands for installing certificate
prefix = 'ca' if is_ca else 'certificate'
- print("Configure mode commands to install:")
+ print('Configure mode commands to install:')
+ base = f"set pki {prefix} {name}"
if cert:
cert_pem = "".join(encode_certificate(cert).strip().split("\n")[1:-1])
- print("set pki %s %s certificate '%s'" % (prefix, name, cert_pem))
+ print(f"{base} certificate '{cert_pem}'")
if private_key:
key_pem = "".join(encode_private_key(private_key, passphrase=key_passphrase).strip().split("\n")[1:-1])
- print("set pki %s %s private key '%s'" % (prefix, name, key_pem))
+ print(f"{base} private key '{key_pem}'")
if key_passphrase:
- print("set pki %s %s private password-protected" % (prefix, name))
+ print(f"{base} private password-protected")
def install_crl(ca_name, crl):
# Show conf commands for installing crl
print("Configure mode commands to install CRL:")
crl_pem = "".join(encode_certificate(crl).strip().split("\n")[1:-1])
- print("set pki ca %s crl '%s'" % (ca_name, crl_pem))
+ print(f"set pki ca {ca_name} crl '{crl_pem}'")
def install_dh_parameters(name, params):
# Show conf commands for installing dh params
print("Configure mode commands to install DH parameters:")
dh_pem = "".join(encode_dh_parameters(params).strip().split("\n")[1:-1])
- print("set pki dh %s parameters '%s'" % (name, dh_pem))
+ print(f"set pki dh {name} parameters '{dh_pem}'")
def install_ssh_key(name, public_key, private_key, passphrase=None):
# Show conf commands for installing ssh key
key_openssh = encode_public_key(public_key, encoding='OpenSSH', key_format='OpenSSH')
username = os.getlogin()
type_key_split = key_openssh.split(" ")
+
+ base = f"set system login user {username} authentication public-keys {name}"
print("Configure mode commands to install SSH key:")
- print("set system login user %s authentication public-keys %s key '%s'" % (username, name, type_key_split[1]))
- print("set system login user %s authentication public-keys %s type '%s'" % (username, name, type_key_split[0]))
- print("")
+ print(f"{base} key '{type_key_split[1]}'")
+ print(f"{base} type '{type_key_split[0]}'", end="\n\n")
print(encode_private_key(private_key, encoding='PEM', key_format='OpenSSH', passphrase=passphrase))
def install_keypair(name, key_type, private_key=None, public_key=None, passphrase=None):
@@ -184,7 +191,7 @@ def install_keypair(name, key_type, private_key=None, public_key=None, passphras
if install_public_key:
install_public_pem = "".join(public_key_pem.strip().split("\n")[1:-1])
- print("set pki key-pair %s public key '%s'" % (name, install_public_pem))
+ print(f"set pki key-pair {name} public key '{install_public_pem}'")
else:
print("Public key:")
print(public_key_pem)
@@ -195,30 +202,31 @@ def install_keypair(name, key_type, private_key=None, public_key=None, passphras
if install_private_key:
install_private_pem = "".join(private_key_pem.strip().split("\n")[1:-1])
- print("set pki key-pair %s private key '%s'" % (name, install_private_pem))
+ print(f"set pki key-pair {name} private key '{install_private_pem}'")
if passphrase:
- print("set pki key-pair %s private password-protected" % (name,))
+ print(f"set pki key-pair {name} private password-protected")
else:
print("Private key:")
print(private_key_pem)
-def install_wireguard_key(name, private_key, public_key):
+def install_wireguard_key(interface, private_key, public_key):
# Show conf commands for installing wireguard key pairs
- is_interface = re.match(r'^wg[\d]+$', name)
-
- print("Configure mode commands to install key:")
- if is_interface:
- print("set interfaces wireguard %s private-key '%s'" % (name, private_key))
- print("")
- print("Public key for use on peer configuration: " + public_key)
- else:
- print("set interfaces wireguard [INTERFACE] peer %s public-key '%s'" % (name, public_key))
- print("")
- print("Private key for use on peer configuration: " + private_key)
-
-def install_wireguard_psk(name, psk):
+ from vyos.ifconfig import Section
+ if Section.section(interface) != 'wireguard':
+ print(f'"{interface}" is not a WireGuard interface name!')
+ exit(1)
+
+ print("Configure mode commands to install key:", end="\n\n")
+ print(f"set interfaces wireguard {interface} private-key '{private_key}'", end="\n\n")
+ print(f"Public key to use on peer system: '{public_key}'")
+
+def install_wireguard_psk(interface, peer, psk):
+ from vyos.ifconfig import Section
+ if Section.section(interface) != 'wireguard':
+ print(f'"{interface}" is not a WireGuard interface name!')
+ exit(1)
# Show conf commands for installing wireguard psk
- print("set interfaces wireguard [INTERFACE] peer %s preshared-key '%s'" % (name, psk))
+ print(f"set interfaces wireguard {interface} peer {peer} preshared-key '{psk}'")
def ask_passphrase():
passphrase = None
@@ -625,49 +633,37 @@ def generate_openvpn_key(name, install=False, file=False):
key_data = "".join(key_lines[1:-1]) # Remove wrapper tags and line endings
key_version = '1'
+ import re
version_search = re.search(r'BEGIN OpenVPN Static key V(\d+)', result) # Future-proofing (hopefully)
if version_search:
key_version = version_search[1]
+ base = f"set pki openvpn shared-secret {name}"
print("Configure mode commands to install OpenVPN key:")
- print("set pki openvpn shared-secret %s key '%s'" % (name, key_data))
- print("set pki openvpn shared-secret %s version '%s'" % (name, key_version))
+ print(f"{base} key '{key_data}'")
+ print(f"{base} version '{key_version}'")
if file:
write_file(f'{name}.key', result)
-def generate_wireguard_key(name, install=False, file=False):
+def generate_wireguard_key(interface=None, install=False):
private_key = cmd('wg genkey')
public_key = cmd('wg pubkey', input=private_key)
- if not install:
- print("Private key: " + private_key)
- print("Public key: " + public_key)
- return None
-
- if install:
- install_wireguard_key(name, private_key, public_key)
-
- if file:
- write_file(f'{name}_public.key', public_key)
- write_file(f'{name}_private.key', private_key)
+ if interface and install:
+ install_wireguard_key(interface, private_key, public_key)
+ else:
+ print(f'Private key: {private_key}')
+ print(f'Public key: {public_key}', end='\n\n')
-def generate_wireguard_psk(name, install=False, file=False):
+def generate_wireguard_psk(interface=None, peer=None, install=False):
psk = cmd('wg genpsk')
-
- if not install and not file:
- print("Pre-shared key:")
- print(psk)
- return None
-
- if install:
- install_wireguard_psk(name, psk)
-
- if file:
- write_file(f'{name}.key', psk)
+ if interface and peer and install:
+ install_wireguard_psk(interface, peer, psk)
+ else:
+ print(f'Pre-shared key: {psk}')
# Show functions
-
def show_certificate_authority(name=None):
headers = ['Name', 'Subject', 'Issuer CN', 'Issued', 'Expiry', 'Private Key', 'Parent']
data = []
@@ -784,10 +780,13 @@ if __name__ == '__main__':
# OpenVPN
parser.add_argument('--openvpn', help='OpenVPN TLS key', required=False)
- # Wireguard
+ # WireGuard
parser.add_argument('--wireguard', help='Wireguard', action='store_true')
- parser.add_argument('--key', help='Wireguard key pair', required=False)
- parser.add_argument('--psk', help='Wireguard pre shared key', required=False)
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument('--key', help='Wireguard key pair', action='store_true', required=False)
+ group.add_argument('--psk', help='Wireguard pre shared key', action='store_true', required=False)
+ parser.add_argument('--interface', help='Install generated keys into running-config for named interface', action='store')
+ parser.add_argument('--peer', help='Install generated keys into running-config for peer', action='store')
# Global
parser.add_argument('--file', help='Write generated keys into specified filename', action='store_true')
@@ -809,21 +808,28 @@ if __name__ == '__main__':
generate_certificate_selfsign(args.certificate, install=args.install, file=args.file)
else:
generate_certificate_request(name=args.certificate, install=args.install, file=args.file)
+
elif args.crl:
generate_certificate_revocation_list(args.crl, install=args.install, file=args.file)
+
elif args.ssh:
generate_ssh_keypair(args.ssh, install=args.install, file=args.file)
+
elif args.dh:
generate_dh_parameters(args.dh, install=args.install, file=args.file)
+
elif args.keypair:
generate_keypair(args.keypair, install=args.install, file=args.file)
+
elif args.openvpn:
generate_openvpn_key(args.openvpn, install=args.install, file=args.file)
+
elif args.wireguard:
if args.key:
- generate_wireguard_key(args.key, install=args.install, file=args.file)
- elif args.psk:
- generate_wireguard_psk(args.psk, install=args.install, file=args.file)
+ generate_wireguard_key(args.interface, install=args.install)
+ if args.psk:
+ generate_wireguard_psk(args.interface, peer=args.peer, install=args.install)
+
elif args.action == 'show':
if args.ca:
show_certificate_authority(None if args.ca == 'all' else args.ca)