summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/interfaces_openvpn.py7
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py16
-rwxr-xr-xsrc/conf_mode/vrf.py5
-rw-r--r--src/migration-scripts/openvpn/2-to-343
-rwxr-xr-xsrc/op_mode/bridge.py2
-rwxr-xr-xsrc/op_mode/dhcp.py2
-rwxr-xr-xsrc/op_mode/openconnect.py6
-rwxr-xr-xsrc/op_mode/ssh.py2
-rw-r--r--src/op_mode/zone.py4
-rw-r--r--src/services/api/graphql/session/errors/op_mode_errors.py2
10 files changed, 79 insertions, 10 deletions
diff --git a/src/conf_mode/interfaces_openvpn.py b/src/conf_mode/interfaces_openvpn.py
index 017010a61..0dc76b39a 100755
--- a/src/conf_mode/interfaces_openvpn.py
+++ b/src/conf_mode/interfaces_openvpn.py
@@ -432,6 +432,13 @@ def verify(openvpn):
if IPv6Address(client['ipv6_ip'][0]) in v6PoolNet:
print(f'Warning: Client "{client["name"]}" IP {client["ipv6_ip"][0]} is in server IP pool, it is not reserved for this client.')
+ if 'topology' in openvpn['server']:
+ if openvpn['server']['topology'] == 'net30':
+ DeprecationWarning('Topology net30 is deprecated '\
+ 'and will be removed in future VyOS versions. '\
+ 'Switch to "subnet" or "p2p"'
+ )
+
# add mfa users to the file the mfa plugin uses
if dict_search('server.mfa.totp', openvpn):
user_data = ''
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index dc78c755e..cf82b767f 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -24,6 +24,7 @@ from time import sleep
from vyos.base import Warning
from vyos.config import Config
+from vyos.config import config_dict_merge
from vyos.configdep import set_dependents
from vyos.configdep import call_dependents
from vyos.configdict import leaf_node_changed
@@ -86,9 +87,22 @@ def get_config(config=None):
ipsec = conf.get_config_dict(base, key_mangling=('-', '_'),
no_tag_node_value_mangle=True,
get_first_key=True,
- with_recursive_defaults=True,
with_pki=True)
+ # We have to cleanup the default dict, as default values could
+ # enable features which are not explicitly enabled on the
+ # CLI. E.g. dead-peer-detection defaults should not be injected
+ # unless the feature is explicitly opted in to by setting the
+ # top-level node
+ default_values = conf.get_config_defaults(**ipsec.kwargs, recursive=True)
+
+ if 'ike_group' in ipsec:
+ for name, ike in ipsec['ike_group'].items():
+ if 'dead_peer_detection' not in ike:
+ del default_values['ike_group'][name]['dead_peer_detection']
+
+ ipsec = config_dict_merge(default_values, ipsec)
+
ipsec['dhcp_interfaces'] = set()
ipsec['dhcp_no_address'] = {}
ipsec['install_routes'] = 'no' if conf.exists(base + ["options", "disable-route-autoinstall"]) else default_install_routes
diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py
index 8d8c234c0..12edb7d02 100755
--- a/src/conf_mode/vrf.py
+++ b/src/conf_mode/vrf.py
@@ -27,6 +27,7 @@ from vyos.template import render
from vyos.template import render_to_string
from vyos.utils.dict import dict_search
from vyos.utils.network import get_interface_config
+from vyos.utils.network import get_vrf_tableid
from vyos.utils.network import get_vrf_members
from vyos.utils.network import interface_exists
from vyos.utils.process import call
@@ -160,8 +161,8 @@ def verify(vrf):
# routing table id can't be changed - OS restriction
if interface_exists(name):
- tmp = str(dict_search('linkinfo.info_data.table', get_interface_config(name)))
- if tmp and tmp != vrf_config['table']:
+ tmp = get_vrf_tableid(name)
+ if tmp and tmp != int(vrf_config['table']):
raise ConfigError(f'VRF "{name}" table id modification not possible!')
# VRF routing table ID must be unique on the system
diff --git a/src/migration-scripts/openvpn/2-to-3 b/src/migration-scripts/openvpn/2-to-3
new file mode 100644
index 000000000..0b9073ae6
--- /dev/null
+++ b/src/migration-scripts/openvpn/2-to-3
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Adds an explicit old default for 'server topology'
+# to keep old configs working as before even though the default has changed.
+
+from vyos.configtree import ConfigTree
+
+def migrate(config: ConfigTree) -> None:
+ if not config.exists(['interfaces', 'openvpn']):
+ # Nothing to do
+ return
+
+ ovpn_intfs = config.list_nodes(['interfaces', 'openvpn'])
+ for i in ovpn_intfs:
+ mode = config.return_value(['interfaces', 'openvpn', i, 'mode'])
+ if mode != 'server':
+ # If it's a client or a site-to-site OpenVPN interface,
+ # the topology setting is not applicable
+ # and will cause commit errors on load,
+ # so we must not change such interfaces.
+ continue
+ else:
+ # The default OpenVPN server topology was changed from net30 to subnet
+ # because net30 is deprecated and causes problems with Windows clients.
+ # We add 'net30' to old configs if topology is not set there
+ # to ensure that if anyone relies on net30, their configs work as before.
+ topology_path = ['interfaces', 'openvpn', i, 'server', 'topology']
+ if not config.exists(topology_path):
+ config.set(topology_path, value='net30', replace=False)
diff --git a/src/op_mode/bridge.py b/src/op_mode/bridge.py
index d04f1541f..e80b1c21d 100755
--- a/src/op_mode/bridge.py
+++ b/src/op_mode/bridge.py
@@ -70,7 +70,7 @@ def _get_raw_data_fdb(bridge):
# From iproute2 fdb.c, fdb_show() will only exit(-1) in case of
# non-existent bridge device; raise error.
if code == 255:
- raise vyos.opmode.UnconfiguredSubsystem(f"no such bridge device {bridge}")
+ raise vyos.opmode.UnconfiguredObject(f"bridge {bridge} does not exist in the system")
data_dict = json.loads(json_data)
return data_dict
diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py
index 6f57f22a5..e5455c8af 100755
--- a/src/op_mode/dhcp.py
+++ b/src/op_mode/dhcp.py
@@ -332,7 +332,7 @@ def _verify_client(func):
# Check if config does not exist
if not config.exists(f'interfaces {interface_path} address dhcp{v}'):
- raise vyos.opmode.UnconfiguredSubsystem(unconf_message)
+ raise vyos.opmode.UnconfiguredObject(unconf_message)
return func(*args, **kwargs)
return _wrapper
diff --git a/src/op_mode/openconnect.py b/src/op_mode/openconnect.py
index cfa0678a7..62c683ebb 100755
--- a/src/op_mode/openconnect.py
+++ b/src/op_mode/openconnect.py
@@ -42,8 +42,10 @@ def _get_formatted_sessions(data):
ses_list = []
for ses in data:
ses_list.append([
- ses["Device"], ses["Username"], ses["IPv4"], ses["Remote IP"],
- ses["_RX"], ses["_TX"], ses["State"], ses["_Connected at"]
+ ses.get("Device", '(none)'), ses.get("Username", '(none)'),
+ ses.get("IPv4", '(none)'), ses.get("Remote IP", '(none)'),
+ ses.get("_RX", '(none)'), ses.get("_TX", '(none)'),
+ ses.get("State", '(none)'), ses.get("_Connected at", '(none)')
])
if len(ses_list) > 0:
output = tabulate(ses_list, headers)
diff --git a/src/op_mode/ssh.py b/src/op_mode/ssh.py
index 102becc55..0c51576b0 100755
--- a/src/op_mode/ssh.py
+++ b/src/op_mode/ssh.py
@@ -65,7 +65,7 @@ def show_fingerprints(raw: bool, ascii: bool):
def show_dynamic_protection(raw: bool):
config = ConfigTreeQuery()
if not config.exists(['service', 'ssh', 'dynamic-protection']):
- raise vyos.opmode.UnconfiguredSubsystem("SSH server dynamic-protection is not enabled.")
+ raise vyos.opmode.UnconfiguredObject("SSH server dynamic-protection is not enabled.")
attackers = []
try:
diff --git a/src/op_mode/zone.py b/src/op_mode/zone.py
index d24b1065b..49fecdf28 100644
--- a/src/op_mode/zone.py
+++ b/src/op_mode/zone.py
@@ -104,7 +104,7 @@ def _convert_config(zones_config: dict, zone: str = None) -> list:
if zones_config:
output = [_convert_one_zone_data(zone, zones_config)]
else:
- raise vyos.opmode.DataUnavailable(f'Zone {zone} not found')
+ raise vyos.opmode.UnconfiguredObject(f'Zone {zone} not found')
else:
if zones_config:
output = _convert_zones_data(zones_config)
@@ -212,4 +212,4 @@ if __name__ == '__main__':
print(res)
except (ValueError, vyos.opmode.Error) as e:
print(e)
- sys.exit(1) \ No newline at end of file
+ sys.exit(1)
diff --git a/src/services/api/graphql/session/errors/op_mode_errors.py b/src/services/api/graphql/session/errors/op_mode_errors.py
index 18d555f2d..800767219 100644
--- a/src/services/api/graphql/session/errors/op_mode_errors.py
+++ b/src/services/api/graphql/session/errors/op_mode_errors.py
@@ -1,5 +1,6 @@
op_mode_err_msg = {
"UnconfiguredSubsystem": "subsystem is not configured or not running",
+ "UnconfiguredObject": "object does not exist in the system configuration",
"DataUnavailable": "data currently unavailable",
"PermissionDenied": "client does not have permission",
"InsufficientResources": "insufficient system resources",
@@ -9,6 +10,7 @@ op_mode_err_msg = {
op_mode_err_code = {
"UnconfiguredSubsystem": 2000,
+ "UnconfiguredObject": 2003,
"DataUnavailable": 2001,
"InsufficientResources": 2002,
"PermissionDenied": 1003,