summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/interfaces-loopback.py4
-rwxr-xr-xsrc/conf_mode/le_cert.py4
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py10
-rwxr-xr-xsrc/conf_mode/system-option.py3
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py42
5 files changed, 49 insertions, 14 deletions
diff --git a/src/conf_mode/interfaces-loopback.py b/src/conf_mode/interfaces-loopback.py
index 30a27abb4..193334443 100755
--- a/src/conf_mode/interfaces-loopback.py
+++ b/src/conf_mode/interfaces-loopback.py
@@ -45,8 +45,8 @@ def generate(loopback):
return None
def apply(loopback):
- l = LoopbackIf(loopback['ifname'])
- if 'deleted' in loopback.keys():
+ l = LoopbackIf(**loopback)
+ if 'deleted' in loopback:
l.remove()
else:
l.update(loopback)
diff --git a/src/conf_mode/le_cert.py b/src/conf_mode/le_cert.py
index 755c89966..6e169a3d5 100755
--- a/src/conf_mode/le_cert.py
+++ b/src/conf_mode/le_cert.py
@@ -22,6 +22,7 @@ from vyos.config import Config
from vyos import ConfigError
from vyos.util import cmd
from vyos.util import call
+from vyos.util import is_systemd_service_running
from vyos import airbag
airbag.enable()
@@ -87,8 +88,7 @@ def generate(cert):
# certbot will attempt to reload nginx, even with 'certonly';
# start nginx if not active
- ret = call('systemctl is-active --quiet nginx.service')
- if ret:
+ if not is_systemd_service_running('nginx.service'):
call('systemctl start nginx.service')
request_certbot(cert)
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 1a2fabded..9ecfd07fe 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -57,6 +57,11 @@ def get_config(config=None):
if not conf.exists(base):
bgp.update({'deleted' : ''})
+ if not vrf:
+ # We are running in the default VRF context, thus we can not delete
+ # our main BGP instance if there are dependent BGP VRF instances.
+ bgp['dependent_vrfs'] = conf.get_config_dict(['vrf', 'name'],
+ key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True)
return bgp
# We also need some additional information from the config, prefix-lists
@@ -96,6 +101,11 @@ def verify_remote_as(peer_config, bgp_config):
def verify(bgp):
if not bgp or 'deleted' in bgp:
+ if 'dependent_vrfs' in bgp:
+ for vrf, vrf_options in bgp['dependent_vrfs'].items():
+ if dict_search('protocols.bgp', vrf_options) != None:
+ raise ConfigError('Cannot delete default BGP instance, ' \
+ 'dependent VRF instance(s) exist!')
return None
if 'local_as' not in bgp:
diff --git a/src/conf_mode/system-option.py b/src/conf_mode/system-option.py
index 454611c55..55cf6b142 100755
--- a/src/conf_mode/system-option.py
+++ b/src/conf_mode/system-option.py
@@ -24,6 +24,7 @@ from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.template import render
from vyos.util import cmd
+from vyos.util import is_systemd_service_running
from vyos.validate import is_addr_assigned
from vyos.xml import defaults
from vyos import ConfigError
@@ -114,7 +115,7 @@ def apply(options):
if 'performance' in options:
cmd('systemctl restart tuned.service')
# wait until daemon has started before sending configuration
- while (int(os.system('systemctl is-active --quiet tuned.service')) != 0):
+ while (not is_systemd_service_running('tuned.service')):
sleep(0.250)
cmd('tuned-adm profile network-{performance}'.format(**options))
else:
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index f1c6b216b..11ff12e94 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -49,13 +49,14 @@ airbag.enable()
dhcp_wait_attempts = 2
dhcp_wait_sleep = 1
-swanctl_dir = '/etc/swanctl'
-ipsec_conf = '/etc/ipsec.conf'
-ipsec_secrets = '/etc/ipsec.secrets'
-charon_conf = '/etc/strongswan.d/charon.conf'
-charon_dhcp_conf = '/etc/strongswan.d/charon/dhcp.conf'
-interface_conf = '/etc/strongswan.d/interfaces_use.conf'
-swanctl_conf = f'{swanctl_dir}/swanctl.conf'
+swanctl_dir = '/etc/swanctl'
+ipsec_conf = '/etc/ipsec.conf'
+ipsec_secrets = '/etc/ipsec.secrets'
+charon_conf = '/etc/strongswan.d/charon.conf'
+charon_dhcp_conf = '/etc/strongswan.d/charon/dhcp.conf'
+charon_radius_conf = '/etc/strongswan.d/charon/eap-radius.conf'
+interface_conf = '/etc/strongswan.d/interfaces_use.conf'
+swanctl_conf = f'{swanctl_dir}/swanctl.conf'
default_install_routes = 'yes'
@@ -110,6 +111,12 @@ def get_config(config=None):
ipsec['remote_access']['connection'][rw] = dict_merge(default_values,
ipsec['remote_access']['connection'][rw])
+ if 'remote_access' in ipsec and 'radius' in ipsec['remote_access'] and 'server' in ipsec['remote_access']['radius']:
+ default_values = defaults(base + ['remote-access', 'radius', 'server'])
+ for server in ipsec['remote_access']['radius']['server']:
+ ipsec['remote_access']['radius']['server'][server] = dict_merge(default_values,
+ ipsec['remote_access']['radius']['server'][server])
+
ipsec['dhcp_no_address'] = {}
ipsec['install_routes'] = 'no' if conf.exists(base + ["options", "disable-route-autoinstall"]) else default_install_routes
ipsec['interface_change'] = leaf_node_changed(conf, base + ['interface'])
@@ -243,6 +250,11 @@ def verify(ipsec):
if 'ike_group' in ra_conf:
if 'ike_group' not in ipsec or ra_conf['ike_group'] not in ipsec['ike_group']:
raise ConfigError(f"Invalid ike-group on {name} remote-access config")
+
+ ike = ra_conf['ike_group']
+ if dict_search(f'ike_group.{ike}.key_exchange', ipsec) != 'ikev2':
+ raise ConfigError('IPSec remote-access connections requires IKEv2!')
+
else:
raise ConfigError(f"Missing ike-group on {name} remote-access config")
@@ -263,13 +275,19 @@ def verify(ipsec):
if 'pre_shared_secret' not in ra_conf['authentication']:
raise ConfigError(f"Missing pre-shared-key on {name} remote-access config")
+
+ if 'client_mode' in ra_conf['authentication']:
+ if ra_conf['authentication']['client_mode'] == 'eap-radius':
+ if 'radius' not in ipsec['remote_access'] or 'server' not in ipsec['remote_access']['radius'] or len(ipsec['remote_access']['radius']['server']) == 0:
+ raise ConfigError('RADIUS authentication requires at least one server')
+
if 'pool' in ra_conf:
if 'dhcp' in ra_conf['pool'] and len(ra_conf['pool']) > 1:
raise ConfigError(f'Can not use both DHCP and a predefined address pool for "{name}"!')
for pool in ra_conf['pool']:
if pool == 'dhcp':
- if dict_search('options.remote_access.dhcp.server', ipsec) == None:
+ if dict_search('remote_access.dhcp.server', ipsec) == None:
raise ConfigError('IPSec DHCP server is not configured!')
elif 'pool' not in ipsec['remote_access'] or pool not in ipsec['remote_access']['pool']:
@@ -297,6 +315,10 @@ def verify(ipsec):
if v4_addr_and_exclude or v6_addr_and_exclude:
raise ConfigError('Must use both IPv4 or IPv6 addresses for pool prefix and exclude prefixes!')
+ if 'radius' in ipsec['remote_access'] and 'server' in ipsec['remote_access']['radius']:
+ for server, server_config in ipsec['remote_access']['radius']['server'].items():
+ if 'key' not in server_config:
+ raise ConfigError(f'Missing RADIUS secret key for server "{server}"')
if 'site_to_site' in ipsec and 'peer' in ipsec['site_to_site']:
for peer, peer_conf in ipsec['site_to_site']['peer'].items():
@@ -449,7 +471,8 @@ def generate(ipsec):
cleanup_pki_files()
if not ipsec:
- for config_file in [ipsec_conf, ipsec_secrets, charon_dhcp_conf, interface_conf, swanctl_conf]:
+ for config_file in [ipsec_conf, ipsec_secrets, charon_dhcp_conf,
+ charon_radius_conf, interface_conf, swanctl_conf]:
if os.path.isfile(config_file):
os.unlink(config_file)
render(charon_conf, 'ipsec/charon.tmpl', {'install_routes': default_install_routes})
@@ -518,6 +541,7 @@ def generate(ipsec):
render(ipsec_secrets, 'ipsec/ipsec.secrets.tmpl', ipsec)
render(charon_conf, 'ipsec/charon.tmpl', ipsec)
render(charon_dhcp_conf, 'ipsec/charon/dhcp.conf.tmpl', ipsec)
+ render(charon_radius_conf, 'ipsec/charon/eap-radius.conf.tmpl', ipsec)
render(interface_conf, 'ipsec/interfaces_use.conf.tmpl', ipsec)
render(swanctl_conf, 'ipsec/swanctl.conf.tmpl', ipsec)