summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/dhcp_server.py4
-rwxr-xr-xsrc/conf_mode/firewall.py35
-rwxr-xr-xsrc/conf_mode/interfaces-macsec.py74
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py26
-rwxr-xr-xsrc/conf_mode/interfaces-wireguard.py6
-rwxr-xr-xsrc/conf_mode/interfaces-wireless.py2
6 files changed, 85 insertions, 62 deletions
diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py
index 280057f04..c4c72aae9 100755
--- a/src/conf_mode/dhcp_server.py
+++ b/src/conf_mode/dhcp_server.py
@@ -296,6 +296,10 @@ def generate(dhcp):
render(config_file, 'dhcp-server/dhcpd.conf.j2', dhcp,
formater=lambda _: _.replace(""", '"'))
+ # Clean up configuration test file
+ if os.path.exists(tmp_file):
+ os.unlink(tmp_file)
+
return None
def apply(dhcp):
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index e946704b3..8ad3f27fc 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -351,39 +351,6 @@ def apply_sysfs(firewall):
with open(path, 'w') as f:
f.write(value)
-def post_apply_trap(firewall):
- if 'first_install' in firewall:
- return None
-
- if not process_named_running('snmpd'):
- return None
-
- trap_username = os.getlogin()
-
- for host, target_conf in firewall['trap_targets'].items():
- community = target_conf['community'] if 'community' in target_conf else 'public'
- port = int(target_conf['port']) if 'port' in target_conf else 162
-
- base_cmd = f'snmptrap -v2c -c {community} {host}:{port} 0 {snmp_trap_mib}::{snmp_trap_name} '
-
- for change_type, changes in firewall['trap_diff'].items():
- for path_str, value in changes.items():
- objects = [
- f'mgmtEventUser s "{trap_username}"',
- f'mgmtEventSource i {snmp_event_source}',
- f'mgmtEventType i {snmp_change_type[change_type]}'
- ]
-
- if change_type == 'add':
- objects.append(f'mgmtEventCurrCfg s "{path_str} {value}"')
- elif change_type == 'delete':
- objects.append(f'mgmtEventPrevCfg s "{path_str} {value}"')
- elif change_type == 'change':
- objects.append(f'mgmtEventPrevCfg s "{path_str} {value[0]}"')
- objects.append(f'mgmtEventCurrCfg s "{path_str} {value[1]}"')
-
- cmd(base_cmd + ' '.join(objects))
-
def apply(firewall):
install_result, output = rc_cmd(f'nft -f {nftables_conf}')
if install_result == 1:
@@ -408,8 +375,6 @@ def apply(firewall):
print('Updating GeoIP. Please wait...')
geoip_update(firewall)
- post_apply_trap(firewall)
-
return None
if __name__ == '__main__':
diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py
index 3f86e2638..0a927ac88 100755
--- a/src/conf_mode/interfaces-macsec.py
+++ b/src/conf_mode/interfaces-macsec.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2022 VyOS maintainers and contributors
+# Copyright (C) 2020-2023 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -43,6 +43,14 @@ airbag.enable()
# XXX: wpa_supplicant works on the source interface
wpa_suppl_conf = '/run/wpa_supplicant/{source_interface}.conf'
+# Constants
+## gcm-aes-128 requires a 128bit long key - 32 characters (string) = 16byte = 128bit
+GCM_AES_128_LEN: int = 32
+GCM_128_KEY_ERROR = 'gcm-aes-128 requires a 128bit long key!'
+## gcm-aes-256 requires a 256bit long key - 64 characters (string) = 32byte = 256bit
+GCM_AES_256_LEN: int = 64
+GCM_256_KEY_ERROR = 'gcm-aes-256 requires a 256bit long key!'
+
def get_config(config=None):
"""
Retrive CLI config as dictionary. Dictionary can never be empty, as at least the
@@ -89,18 +97,54 @@ def verify(macsec):
raise ConfigError('Cipher suite must be set for MACsec "{ifname}"'.format(**macsec))
if dict_search('security.encrypt', macsec) != None:
- if dict_search('security.mka.cak', macsec) == None or dict_search('security.mka.ckn', macsec) == None:
- raise ConfigError('Missing mandatory MACsec security keys as encryption is enabled!')
+ # Check that only static or MKA config is present
+ if dict_search('security.static', macsec) != None and (dict_search('security.mka.cak', macsec) != None or dict_search('security.mka.ckn', macsec) != None):
+ raise ConfigError('Only static or MKA can be used!')
+
+ # Logic to check static configuration
+ if dict_search('security.static', macsec) != None:
+ # tx-key must be defined
+ if dict_search('security.static.key', macsec) == None:
+ raise ConfigError('Static MACsec tx-key must be defined.')
+
+ tx_len = len(dict_search('security.static.key', macsec))
+
+ if dict_search('security.cipher', macsec) == 'gcm-aes-128' and tx_len != GCM_AES_128_LEN:
+ raise ConfigError(GCM_128_KEY_ERROR)
+
+ if dict_search('security.cipher', macsec) == 'gcm-aes-256' and tx_len != GCM_AES_256_LEN:
+ raise ConfigError(GCM_256_KEY_ERROR)
+
+ # Make sure at least one peer is defined
+ if 'peer' not in macsec['security']['static']:
+ raise ConfigError('Must have at least one peer defined for static MACsec')
+
+ # For every enabled peer, make sure a MAC and rx-key is defined
+ for peer, peer_config in macsec['security']['static']['peer'].items():
+ if 'disable' not in peer_config and ('mac' not in peer_config or 'key' not in peer_config):
+ raise ConfigError('Every enabled MACsec static peer must have a MAC address and rx-key defined.')
+
+ # check rx-key length against cipher suite
+ rx_len = len(peer_config['key'])
+
+ if dict_search('security.cipher', macsec) == 'gcm-aes-128' and rx_len != GCM_AES_128_LEN:
+ raise ConfigError(GCM_128_KEY_ERROR)
+
+ if dict_search('security.cipher', macsec) == 'gcm-aes-256' and rx_len != GCM_AES_256_LEN:
+ raise ConfigError(GCM_256_KEY_ERROR)
+
+ # Logic to check MKA configuration
+ else:
+ if dict_search('security.mka.cak', macsec) == None or dict_search('security.mka.ckn', macsec) == None:
+ raise ConfigError('Missing mandatory MACsec security keys as encryption is enabled!')
- cak_len = len(dict_search('security.mka.cak', macsec))
+ cak_len = len(dict_search('security.mka.cak', macsec))
- if dict_search('security.cipher', macsec) == 'gcm-aes-128' and cak_len != 32:
- # gcm-aes-128 requires a 128bit long key - 32 characters (string) = 16byte = 128bit
- raise ConfigError('gcm-aes-128 requires a 128bit long key!')
+ if dict_search('security.cipher', macsec) == 'gcm-aes-128' and cak_len != GCM_AES_128_LEN:
+ raise ConfigError(GCM_128_KEY_ERROR)
- elif dict_search('security.cipher', macsec) == 'gcm-aes-256' and cak_len != 64:
- # gcm-aes-128 requires a 128bit long key - 64 characters (string) = 32byte = 256bit
- raise ConfigError('gcm-aes-128 requires a 256bit long key!')
+ elif dict_search('security.cipher', macsec) == 'gcm-aes-256' and cak_len != GCM_AES_256_LEN:
+ raise ConfigError(GCM_256_KEY_ERROR)
if 'source_interface' in macsec:
# MACsec adds a 40 byte overhead (32 byte MACsec + 8 bytes VLAN 802.1ad
@@ -115,7 +159,9 @@ def verify(macsec):
def generate(macsec):
- render(wpa_suppl_conf.format(**macsec), 'macsec/wpa_supplicant.conf.j2', macsec)
+ # Only generate wpa_supplicant config if using MKA
+ if dict_search('security.mka.cak', macsec):
+ render(wpa_suppl_conf.format(**macsec), 'macsec/wpa_supplicant.conf.j2', macsec)
return None
@@ -142,8 +188,10 @@ def apply(macsec):
i = MACsecIf(**macsec)
i.update(macsec)
- if not is_systemd_service_running(systemd_service) or 'shutdown_required' in macsec:
- call(f'systemctl reload-or-restart {systemd_service}')
+ # Only reload/restart if using MKA
+ if dict_search('security.mka.cak', macsec):
+ if not is_systemd_service_running(systemd_service) or 'shutdown_required' in macsec:
+ call(f'systemctl reload-or-restart {systemd_service}')
return None
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 26b217d98..1d0feb56f 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -166,17 +166,23 @@ def verify_pki(openvpn):
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}')
-
- for ca_name in tls['ca_certificate']:
- if ca_name not in pki['ca']:
- raise ConfigError(f'Invalid CA certificate on openvpn interface {interface}')
+ if (mode in ['server', 'client']) and ('ca_certificate' not in tls):
+ raise ConfigError(f'Must specify "tls ca-certificate" on openvpn interface {interface},\
+ it is required in server and client modes')
+ else:
+ if ('ca_certificate' not in tls) and ('peer_fingerprint' not in tls):
+ raise ConfigError('Either "tls ca-certificate" or "tls peer-fingerprint" is required\
+ on openvpn interface {interface} in site-to-site mode')
- if len(tls['ca_certificate']) > 1:
- sorted_chain = sort_ca_chain(tls['ca_certificate'], pki['ca'])
- if not verify_ca_chain(sorted_chain, pki['ca']):
- raise ConfigError(f'CA certificates are not a valid chain')
+ if 'ca_certificate' in tls:
+ for ca_name in tls['ca_certificate']:
+ if ca_name not in pki['ca']:
+ raise ConfigError(f'Invalid CA certificate on openvpn interface {interface}')
+
+ if len(tls['ca_certificate']) > 1:
+ sorted_chain = sort_ca_chain(tls['ca_certificate'], pki['ca'])
+ if not verify_ca_chain(sorted_chain, pki['ca']):
+ raise ConfigError(f'CA certificates are not a valid chain')
if mode != 'client' and 'auth_key' not in tls:
if 'certificate' not in tls:
diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py
index 446399255..122d9589a 100755
--- a/src/conf_mode/interfaces-wireguard.py
+++ b/src/conf_mode/interfaces-wireguard.py
@@ -90,7 +90,6 @@ def verify(wireguard):
# run checks on individual configured WireGuard peer
public_keys = []
-
for tmp in wireguard['peer']:
peer = wireguard['peer'][tmp]
@@ -107,8 +106,9 @@ def verify(wireguard):
if peer['public_key'] in public_keys:
raise ConfigError(f'Duplicate public-key defined on peer "{tmp}"')
- if 'disable' not in peer and is_wireguard_key_pair(wireguard['private_key'], peer['public_key']):
- raise ConfigError(f'Peer "{tmp}" has the same public key as the interface "{wireguard["ifname"]}"')
+ if 'disable' not in peer:
+ if is_wireguard_key_pair(wireguard['private_key'], peer['public_key']):
+ raise ConfigError(f'Peer "{tmp}" has the same public key as the interface "{wireguard["ifname"]}"')
public_keys.append(peer['public_key'])
diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py
index e49ad25ac..29ab9713f 100755
--- a/src/conf_mode/interfaces-wireless.py
+++ b/src/conf_mode/interfaces-wireless.py
@@ -116,7 +116,7 @@ def verify(wifi):
raise ConfigError('You must specify a WiFi mode')
if 'ssid' not in wifi and wifi['type'] != 'monitor':
- raise ConfigError('SSID must be configured')
+ raise ConfigError('SSID must be configured unless type is set to "monitor"!')
if wifi['type'] == 'access-point':
if 'country_code' not in wifi: