summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/configd-include.json4
-rw-r--r--interface-definitions/include/accel-ppp/client-ip-pool.xml.i4
-rw-r--r--interface-definitions/include/accel-ppp/default-pool.xml.i2
-rw-r--r--interface-definitions/include/bgp/afi-route-map-export-import.xml.i4
-rw-r--r--interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i8
-rw-r--r--interface-definitions/include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i3
-rw-r--r--interface-definitions/include/route-map.xml.i2
-rw-r--r--interface-definitions/interfaces_wireguard.xml.in12
-rw-r--r--interface-definitions/pki.xml.in41
-rw-r--r--interface-definitions/policy.xml.in2
-rw-r--r--interface-definitions/service_dhcp-server.xml.in6
-rw-r--r--interface-definitions/service_dhcpv6-server.xml.in6
-rwxr-xr-xop-mode-definitions/generate-system-login-user.xml.in12
-rw-r--r--op-mode-definitions/generate-wireguard.xml.in2
-rw-r--r--python/vyos/config.py14
-rw-r--r--python/vyos/configdict.py13
-rw-r--r--python/vyos/nat.py10
-rw-r--r--python/vyos/system/image.py2
-rwxr-xr-xsmoketest/scripts/cli/test_nat.py20
-rwxr-xr-xsmoketest/scripts/cli/test_pki.py26
-rwxr-xr-xsmoketest/scripts/cli/test_service_https.py3
-rwxr-xr-xsrc/conf_mode/interfaces_ethernet.py15
-rwxr-xr-xsrc/conf_mode/interfaces_openvpn.py16
-rwxr-xr-xsrc/conf_mode/interfaces_sstpc.py6
-rwxr-xr-xsrc/conf_mode/load-balancing_reverse-proxy.py15
-rwxr-xr-xsrc/conf_mode/nat.py5
-rwxr-xr-xsrc/conf_mode/service_https.py11
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py8
-rwxr-xr-xsrc/conf_mode/vpn_openconnect.py8
-rwxr-xr-xsrc/conf_mode/vpn_sstp.py9
-rw-r--r--src/etc/systemd/system/frr.service.d/override.conf3
-rwxr-xr-xsrc/migration-scripts/firewall/6-to-79
32 files changed, 168 insertions, 133 deletions
diff --git a/data/configd-include.json b/data/configd-include.json
index d1f9db796..dc00f0698 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -54,6 +54,7 @@
"protocols_static_multicast.py",
"protocols_static_neighbor-proxy.py",
"qos.py",
+"service_aws_glb.py",
"service_broadcast-relay.py",
"service_config-sync.py",
"service_conntrack-sync.py",
@@ -77,10 +78,13 @@
"service_pppoe-server.py",
"service_router-advert.py",
"service_salt-minion.py",
+"service_sla.py",
"service_ssh.py",
"service_tftp-server.py",
"service_upnp.py",
+"service_webproxy.py",
"system_acceleration.py",
+"system_config-management.py",
"system_conntrack.py",
"system_console.py",
"system_flow-accounting.py",
diff --git a/interface-definitions/include/accel-ppp/client-ip-pool.xml.i b/interface-definitions/include/accel-ppp/client-ip-pool.xml.i
index dff574e6c..71fe69f8d 100644
--- a/interface-definitions/include/accel-ppp/client-ip-pool.xml.i
+++ b/interface-definitions/include/accel-ppp/client-ip-pool.xml.i
@@ -7,7 +7,7 @@
<description>Name of IP pool</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
</properties>
<children>
@@ -37,7 +37,7 @@
<description>Name of IP pool</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/include/accel-ppp/default-pool.xml.i b/interface-definitions/include/accel-ppp/default-pool.xml.i
index 832594c12..a08b066b1 100644
--- a/interface-definitions/include/accel-ppp/default-pool.xml.i
+++ b/interface-definitions/include/accel-ppp/default-pool.xml.i
@@ -7,7 +7,7 @@
<description>Default IP pool</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/include/bgp/afi-route-map-export-import.xml.i b/interface-definitions/include/bgp/afi-route-map-export-import.xml.i
index c218937c8..388991241 100644
--- a/interface-definitions/include/bgp/afi-route-map-export-import.xml.i
+++ b/interface-definitions/include/bgp/afi-route-map-export-import.xml.i
@@ -10,7 +10,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
@@ -26,7 +26,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i
index 9ec513da9..c8ad68700 100644
--- a/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i
+++ b/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i
@@ -28,7 +28,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
@@ -44,7 +44,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
@@ -60,7 +60,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
@@ -185,7 +185,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
diff --git a/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i b/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i
new file mode 100644
index 000000000..7aeb85260
--- /dev/null
+++ b/interface-definitions/include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i
@@ -0,0 +1,3 @@
+<!-- include start from constraint/alpha-numeric-hyphen-underscore-dot.xml.i -->
+<regex>[-_a-zA-Z0-9.]+</regex>
+<!-- include end -->
diff --git a/interface-definitions/include/route-map.xml.i b/interface-definitions/include/route-map.xml.i
index 019868373..e49c388d6 100644
--- a/interface-definitions/include/route-map.xml.i
+++ b/interface-definitions/include/route-map.xml.i
@@ -10,7 +10,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
diff --git a/interface-definitions/interfaces_wireguard.xml.in b/interface-definitions/interfaces_wireguard.xml.in
index f3fe0f1da..fba1064ef 100644
--- a/interface-definitions/interfaces_wireguard.xml.in
+++ b/interface-definitions/interfaces_wireguard.xml.in
@@ -44,9 +44,9 @@
<properties>
<help>Base64 encoded private key</help>
<constraint>
- <regex>[0-9a-zA-Z\+/]{43}=</regex>
+ <validator name="base64"/>
</constraint>
- <constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage>
+ <constraintErrorMessage>Key is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
<tagNode name="peer">
@@ -64,18 +64,18 @@
<properties>
<help>base64 encoded public key</help>
<constraint>
- <regex>[0-9a-zA-Z\+/]{43}=</regex>
+ <validator name="base64"/>
</constraint>
- <constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage>
+ <constraintErrorMessage>Key is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="preshared-key">
<properties>
<help>base64 encoded preshared key</help>
<constraint>
- <regex>[0-9a-zA-Z\+/]{43}=</regex>
+ <validator name="base64"/>
</constraint>
- <constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage>
+ <constraintErrorMessage>Key is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="allowed-ips">
diff --git a/interface-definitions/pki.xml.in b/interface-definitions/pki.xml.in
index a13a357fd..097c541ac 100644
--- a/interface-definitions/pki.xml.in
+++ b/interface-definitions/pki.xml.in
@@ -9,11 +9,18 @@
<tagNode name="ca">
<properties>
<help>Certificate Authority</help>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
</properties>
<children>
<leafNode name="certificate">
<properties>
<help>CA certificate in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>CA certificate is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
#include <include/generic-description.xml.i>
@@ -25,6 +32,10 @@
<leafNode name="key">
<properties>
<help>CA private key in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>CA private key is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="password-protected">
@@ -38,6 +49,10 @@
<leafNode name="crl">
<properties>
<help>Certificate revocation list in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>CRL is not base64-encoded</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
@@ -52,11 +67,18 @@
<tagNode name="certificate">
<properties>
<help>Certificate</help>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
</properties>
<children>
<leafNode name="certificate">
<properties>
<help>Certificate in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>Certificate is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
#include <include/generic-description.xml.i>
@@ -68,6 +90,10 @@
<leafNode name="key">
<properties>
<help>Certificate private key in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>Certificate private key is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="password-protected">
@@ -89,11 +115,18 @@
<tagNode name="dh">
<properties>
<help>Diffie-Hellman parameters</help>
+ <constraint>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
+ </constraint>
</properties>
<children>
<leafNode name="parameters">
<properties>
<help>DH parameters in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>DH parameters are not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
</children>
@@ -111,6 +144,10 @@
<leafNode name="key">
<properties>
<help>Public key in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>Public key is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
</children>
@@ -123,6 +160,10 @@
<leafNode name="key">
<properties>
<help>Private key in PEM format</help>
+ <constraint>
+ <validator name="base64"/>
+ </constraint>
+ <constraintErrorMessage>Private key is not base64-encoded</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="password-protected">
diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in
index 0d2ed9746..0d82cd3f8 100644
--- a/interface-definitions/policy.xml.in
+++ b/interface-definitions/policy.xml.in
@@ -476,7 +476,7 @@
<description>Route map name</description>
</valueHelp>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
</properties>
diff --git a/interface-definitions/service_dhcp-server.xml.in b/interface-definitions/service_dhcp-server.xml.in
index e35d845f1..8e13f9372 100644
--- a/interface-definitions/service_dhcp-server.xml.in
+++ b/interface-definitions/service_dhcp-server.xml.in
@@ -38,7 +38,7 @@
<properties>
<help>Peer name used to identify connection</help>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Invalid failover peer name. May only contain letters, numbers and .-_</constraintErrorMessage>
</properties>
@@ -78,7 +78,7 @@
<properties>
<help>Name of DHCP shared network</help>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Invalid shared network name. May only contain letters, numbers and .-_</constraintErrorMessage>
</properties>
@@ -251,7 +251,7 @@
<properties>
<help>DHCP lease range</help>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Invalid range name, may only be alphanumeric, dot and hyphen</constraintErrorMessage>
</properties>
diff --git a/interface-definitions/service_dhcpv6-server.xml.in b/interface-definitions/service_dhcpv6-server.xml.in
index 102c164a6..6f7f3c1da 100644
--- a/interface-definitions/service_dhcpv6-server.xml.in
+++ b/interface-definitions/service_dhcpv6-server.xml.in
@@ -34,7 +34,7 @@
<properties>
<help>DHCPv6 shared network name</help>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Invalid DHCPv6 shared network name. May only contain letters, numbers and .-_</constraintErrorMessage>
</properties>
@@ -185,7 +185,7 @@
<properties>
<help>NIS domain name for client to use</help>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Invalid NIS domain name</constraintErrorMessage>
</properties>
@@ -207,7 +207,7 @@
<properties>
<help>NIS+ domain name for client to use</help>
<constraint>
- <regex>[-_a-zA-Z0-9.]+</regex>
+ #include <include/constraint/alpha-numeric-hyphen-underscore-dot.xml.i>
</constraint>
<constraintErrorMessage>Invalid NIS+ domain name. May only contain letters, numbers and .-_</constraintErrorMessage>
</properties>
diff --git a/op-mode-definitions/generate-system-login-user.xml.in b/op-mode-definitions/generate-system-login-user.xml.in
index bd80840df..6f65c12b3 100755
--- a/op-mode-definitions/generate-system-login-user.xml.in
+++ b/op-mode-definitions/generate-system-login-user.xml.in
@@ -35,19 +35,19 @@
<properties>
<help>Duration of single time interval</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "$9"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "$9"</command>
<children>
<tagNode name="rate-time">
<properties>
<help>The number of digits in the one-time password</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "$9" --rate-time "${11}" </command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "$9" --rate_time "${11}" </command>
<children>
<tagNode name="window-size">
<properties>
<help>The number of digits in the one-time password</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "$9" --rate-time "${11}" --window-size "${13}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "$9" --rate_time "${11}" --window_size "${13}"</command>
</tagNode>
</children>
</tagNode>
@@ -57,19 +57,19 @@
<properties>
<help>The number of digits in the one-time password</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --window-size "${9}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --window_size "${9}"</command>
<children>
<tagNode name="rate-limit">
<properties>
<help>Duration of single time interval</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "${11}" --window-size "${9}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "${11}" --window_size "${9}"</command>
<children>
<tagNode name="rate-time">
<properties>
<help>Duration of single time interval</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "${11}" --rate-time "${13}" --window-size "${9}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "${11}" --rate_time "${13}" --window_size "${9}"</command>
</tagNode>
</children>
</tagNode>
diff --git a/op-mode-definitions/generate-wireguard.xml.in b/op-mode-definitions/generate-wireguard.xml.in
index 1dcafcd8b..5f2463d1a 100644
--- a/op-mode-definitions/generate-wireguard.xml.in
+++ b/op-mode-definitions/generate-wireguard.xml.in
@@ -4,7 +4,7 @@
<children>
<node name="wireguard">
<properties>
- <help>Generate WireGuard keys</help>
+ <help>Generate WireGuard client config QR code</help>
</properties>
<children>
<tagNode name="client-config">
diff --git a/python/vyos/config.py b/python/vyos/config.py
index 0ca41718f..ca7b035e5 100644
--- a/python/vyos/config.py
+++ b/python/vyos/config.py
@@ -29,7 +29,7 @@ There are multiple types of config tree nodes in VyOS, each requires
its own set of operations.
*Leaf nodes* (such as "address" in interfaces) can have values, but cannot
-have children.
+have children.
Leaf nodes can have one value, multiple values, or no values at all.
For example, "system host-name" is a single-value leaf node,
@@ -258,7 +258,9 @@ class Config(object):
def get_config_dict(self, path=[], effective=False, key_mangling=None,
get_first_key=False, no_multi_convert=False,
no_tag_node_value_mangle=False,
- with_defaults=False, with_recursive_defaults=False):
+ with_defaults=False,
+ with_recursive_defaults=False,
+ with_pki=False):
"""
Args:
path (str list): Configuration tree path, can be empty
@@ -274,6 +276,7 @@ class Config(object):
del kwargs['no_multi_convert']
del kwargs['with_defaults']
del kwargs['with_recursive_defaults']
+ del kwargs['with_pki']
lpath = self._make_path(path)
root_dict = self.get_cached_root_dict(effective)
@@ -298,6 +301,13 @@ class Config(object):
else:
conf_dict = ConfigDict(conf_dict)
+ if with_pki and conf_dict:
+ pki_dict = self.get_config_dict(['pki'], key_mangling=('-', '_'),
+ no_tag_node_value_mangle=True,
+ get_first_key=True)
+ if pki_dict:
+ conf_dict['pki'] = pki_dict
+
# save optional args for a call to get_config_defaults
setattr(conf_dict, '_dict_kwargs', kwargs)
diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py
index 6a421485f..4111d7271 100644
--- a/python/vyos/configdict.py
+++ b/python/vyos/configdict.py
@@ -163,6 +163,9 @@ def node_changed(conf, path, key_mangling=None, recursive=False, expand_nodes=No
output.extend(list(tmp['delete'].keys()))
if expand_nodes & Diff.ADD:
output.extend(list(tmp['add'].keys()))
+
+ # remove duplicate keys from list, this happens when a node (e.g. description) is altered
+ output = list(dict.fromkeys(output))
return output
def get_removed_vlans(conf, path, dict):
@@ -424,7 +427,7 @@ def get_pppoe_interfaces(conf, vrf=None):
return pppoe_interfaces
-def get_interface_dict(config, base, ifname='', recursive_defaults=True):
+def get_interface_dict(config, base, ifname='', recursive_defaults=True, with_pki=False):
"""
Common utility function to retrieve and mangle the interfaces configuration
from the CLI input nodes. All interfaces have a common base where value
@@ -456,7 +459,8 @@ def get_interface_dict(config, base, ifname='', recursive_defaults=True):
get_first_key=True,
no_tag_node_value_mangle=True,
with_defaults=True,
- with_recursive_defaults=recursive_defaults)
+ with_recursive_defaults=recursive_defaults,
+ with_pki=with_pki)
# If interface does not request an IPv4 DHCP address there is no need
# to keep the dhcp-options key
@@ -620,7 +624,7 @@ def get_vlan_ids(interface):
return vlan_ids
-def get_accel_dict(config, base, chap_secrets):
+def get_accel_dict(config, base, chap_secrets, with_pki=False):
"""
Common utility function to retrieve and mangle the Accel-PPP configuration
from different CLI input nodes. All Accel-PPP services have a common base
@@ -635,7 +639,8 @@ def get_accel_dict(config, base, chap_secrets):
dict = config.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True,
- with_recursive_defaults=True)
+ with_recursive_defaults=True,
+ with_pki=with_pki)
# set CPUs cores to process requests
dict.update({'thread_count' : get_half_cpus()})
diff --git a/python/vyos/nat.py b/python/vyos/nat.py
index 392d38772..7215aac88 100644
--- a/python/vyos/nat.py
+++ b/python/vyos/nat.py
@@ -89,7 +89,10 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
if addr and is_ip_network(addr):
if not ipv6:
map_addr = dict_search_args(rule_conf, nat_type, 'address')
- translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ {map_addr} : {addr} }}')
+ if port:
+ translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ {map_addr} : {addr} . {port} }}')
+ else:
+ translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ {map_addr} : {addr} }}')
ignore_type_addr = True
else:
translation_output.append(f'prefix to {addr}')
@@ -112,7 +115,10 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
if port_mapping and port_mapping != 'none':
options.append(port_mapping)
- translation_str = " ".join(translation_output) + (f':{port}' if port else '')
+ if ((not addr) or (addr and not is_ip_network(addr))) and port:
+ translation_str = " ".join(translation_output) + (f':{port}')
+ else:
+ translation_str = " ".join(translation_output)
if options:
translation_str += f' {",".join(options)}'
diff --git a/python/vyos/system/image.py b/python/vyos/system/image.py
index c03ce02d5..514275654 100644
--- a/python/vyos/system/image.py
+++ b/python/vyos/system/image.py
@@ -241,7 +241,7 @@ def validate_name(image_name: str) -> bool:
Returns:
bool: validation result
"""
- regex_filter = re_compile(r'^[\w\.+-]{1,32}$')
+ regex_filter = re_compile(r'^[\w\.+-]{1,64}$')
if regex_filter.match(image_name):
return True
return False
diff --git a/smoketest/scripts/cli/test_nat.py b/smoketest/scripts/cli/test_nat.py
index 682fc141d..1e6435df8 100755
--- a/smoketest/scripts/cli/test_nat.py
+++ b/smoketest/scripts/cli/test_nat.py
@@ -292,5 +292,25 @@ class TestNAT(VyOSUnitTestSHIM.TestCase):
self.verify_nftables(nftables_search, 'ip vyos_nat')
+ def test_snat_net_port_map(self):
+ self.cli_set(src_path + ['rule', '10', 'protocol', 'tcp_udp'])
+ self.cli_set(src_path + ['rule', '10', 'source', 'address', '100.64.0.0/25'])
+ self.cli_set(src_path + ['rule', '10', 'translation', 'address', '203.0.113.0/25'])
+ self.cli_set(src_path + ['rule', '10', 'translation', 'port', '1025-3072'])
+
+ self.cli_set(src_path + ['rule', '20', 'protocol', 'tcp_udp'])
+ self.cli_set(src_path + ['rule', '20', 'source', 'address', '100.64.0.128/25'])
+ self.cli_set(src_path + ['rule', '20', 'translation', 'address', '203.0.113.128/25'])
+ self.cli_set(src_path + ['rule', '20', 'translation', 'port', '1025-3072'])
+
+ self.cli_commit()
+
+ nftables_search = [
+ ['meta l4proto { tcp, udp }', 'snat ip prefix to ip saddr map { 100.64.0.0/25 : 203.0.113.0/25 . 1025-3072 }', 'comment "SRC-NAT-10"'],
+ ['meta l4proto { tcp, udp }', 'snat ip prefix to ip saddr map { 100.64.0.128/25 : 203.0.113.128/25 . 1025-3072 }', 'comment "SRC-NAT-20"']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip vyos_nat')
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_pki.py b/smoketest/scripts/cli/test_pki.py
index b18b0b039..2ccc63b2c 100755
--- a/smoketest/scripts/cli/test_pki.py
+++ b/smoketest/scripts/cli/test_pki.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021 VyOS maintainers and contributors
+# Copyright (C) 2021-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
@@ -186,30 +186,6 @@ class TestPKI(VyOSUnitTestSHIM.TestCase):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- def test_invalid_certificate(self):
- self.cli_set(base_path + ['certificate', 'smoketest', 'certificate', 'invalidcertdata'])
-
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
-
- def test_invalid_public_key(self):
- self.cli_set(base_path + ['key-pair', 'smoketest', 'public', 'key', 'invalidkeydata'])
-
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
-
- def test_invalid_private_key(self):
- self.cli_set(base_path + ['key-pair', 'smoketest', 'private', 'key', 'invalidkeydata'])
-
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
-
- def test_invalid_dh_parameters(self):
- self.cli_set(base_path + ['dh', 'smoketest', 'parameters', 'thisisinvalid'])
-
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
-
def test_certificate_in_use(self):
self.cli_set(base_path + ['certificate', 'smoketest', 'certificate', valid_ca_cert.replace('\n','')])
self.cli_set(base_path + ['certificate', 'smoketest', 'private', 'key', valid_ca_private_key.replace('\n','')])
diff --git a/smoketest/scripts/cli/test_service_https.py b/smoketest/scripts/cli/test_service_https.py
index 703e3e8c4..280932fd7 100755
--- a/smoketest/scripts/cli/test_service_https.py
+++ b/smoketest/scripts/cli/test_service_https.py
@@ -395,8 +395,7 @@ class TestHTTPSService(VyOSUnitTestSHIM.TestCase):
@ignore_warning(InsecureRequestWarning)
def test_api_config_file_load_http(self):
- """Test load config from HTTP URL
- """
+ # Test load config from HTTP URL
address = '127.0.0.1'
key = 'VyOS-key'
url = f'https://{address}/config-file'
diff --git a/src/conf_mode/interfaces_ethernet.py b/src/conf_mode/interfaces_ethernet.py
index 7374a29f7..2c0f846c3 100755
--- a/src/conf_mode/interfaces_ethernet.py
+++ b/src/conf_mode/interfaces_ethernet.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2021 VyOS maintainers and contributors
+# Copyright (C) 2019-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
@@ -150,19 +150,12 @@ def get_config(config=None):
else:
conf = Config()
- # This must be called prior to get_interface_dict(), as this function will
- # alter the config level (config.set_level())
- pki = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
-
base = ['interfaces', 'ethernet']
- ifname, ethernet = get_interface_dict(conf, base)
+ ifname, ethernet = get_interface_dict(conf, base, with_pki=True)
+
if 'is_bond_member' in ethernet:
update_bond_options(conf, ethernet)
- if 'deleted' not in ethernet:
- if pki: ethernet['pki'] = pki
-
tmp = is_node_changed(conf, base + [ifname, 'speed'])
if tmp: ethernet.update({'speed_duplex_changed': {}})
@@ -171,8 +164,6 @@ def get_config(config=None):
return ethernet
-
-
def verify_speed_duplex(ethernet: dict, ethtool: Ethtool):
"""
Verify speed and duplex
diff --git a/src/conf_mode/interfaces_openvpn.py b/src/conf_mode/interfaces_openvpn.py
index bdeb44837..45569dd21 100755
--- a/src/conf_mode/interfaces_openvpn.py
+++ b/src/conf_mode/interfaces_openvpn.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2023 VyOS maintainers and contributors
+# Copyright (C) 2019-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
@@ -89,16 +89,12 @@ def get_config(config=None):
conf = Config()
base = ['interfaces', 'openvpn']
- ifname, openvpn = get_interface_dict(conf, base)
+ ifname, openvpn = get_interface_dict(conf, base, with_pki=True)
openvpn['auth_user_pass_file'] = '/run/openvpn/{ifname}.pw'.format(**openvpn)
if 'deleted' in openvpn:
return openvpn
- openvpn['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- get_first_key=True,
- no_tag_node_value_mangle=True)
-
if is_node_changed(conf, base + [ifname, 'openvpn-option']):
openvpn.update({'restart_required': {}})
if is_node_changed(conf, base + [ifname, 'enable-dco']):
@@ -167,9 +163,10 @@ def verify_pki(openvpn):
raise ConfigError(f'Invalid shared-secret on openvpn interface {interface}')
# If PSK settings are correct, warn about its deprecation
- DeprecationWarning("OpenVPN shared-secret support will be removed in future VyOS versions.\n\
- Please migrate your site-to-site tunnels to TLS.\n\
- You can use self-signed certificates with peer fingerprint verification, consult the documentation for details.")
+ DeprecationWarning('OpenVPN shared-secret support will be removed in future '\
+ 'VyOS versions. Please migrate your site-to-site tunnels to '\
+ 'TLS. You can use self-signed certificates with peer fingerprint '\
+ 'verification, consult the documentation for details.')
if tls:
if (mode in ['server', 'client']) and ('ca_certificate' not in tls):
@@ -729,4 +726,3 @@ if __name__ == '__main__':
except ConfigError as e:
print(e)
exit(1)
-
diff --git a/src/conf_mode/interfaces_sstpc.py b/src/conf_mode/interfaces_sstpc.py
index b588910dc..b9d7a74fb 100755
--- a/src/conf_mode/interfaces_sstpc.py
+++ b/src/conf_mode/interfaces_sstpc.py
@@ -45,7 +45,7 @@ def get_config(config=None):
else:
conf = Config()
base = ['interfaces', 'sstpc']
- ifname, sstpc = get_interface_dict(conf, base)
+ ifname, sstpc = get_interface_dict(conf, base, with_pki=True)
# We should only terminate the SSTP client session if critical parameters
# change. All parameters that can be changed on-the-fly (like interface
@@ -57,10 +57,6 @@ def get_config(config=None):
# bail out early - no need to further process other nodes
break
- # Load PKI certificates for later processing
- sstpc['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- get_first_key=True,
- no_tag_node_value_mangle=True)
return sstpc
def verify(sstpc):
diff --git a/src/conf_mode/load-balancing_reverse-proxy.py b/src/conf_mode/load-balancing_reverse-proxy.py
index 333ebc66c..7338fe573 100755
--- a/src/conf_mode/load-balancing_reverse-proxy.py
+++ b/src/conf_mode/load-balancing_reverse-proxy.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2023 VyOS maintainers and contributors
+# Copyright (C) 2023-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
@@ -43,17 +43,14 @@ def get_config(config=None):
conf = Config()
base = ['load-balancing', 'reverse-proxy']
+ if not conf.exists(base):
+ return None
lb = conf.get_config_dict(base,
get_first_key=True,
key_mangling=('-', '_'),
- no_tag_node_value_mangle=True)
-
- if lb:
- lb['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
-
- if lb:
- lb = conf.merge_defaults(lb, recursive=True)
+ no_tag_node_value_mangle=True,
+ with_recursive_defaults=True,
+ with_pki=True)
return lb
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index 20570da62..bd9b5162c 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -83,11 +83,6 @@ def verify_rule(config, err_msg, groups_dict):
raise ConfigError(f'{err_msg} ports can only be specified when '\
'protocol is either tcp, udp or tcp_udp!')
- if is_ip_network(dict_search('translation.address', config)):
- raise ConfigError(f'{err_msg} cannot use ports with an IPv4 network as '\
- 'translation address as it statically maps a whole network '\
- 'of addresses onto another network of addresses!')
-
for side in ['destination', 'source']:
if side in config:
side_conf = config[side]
diff --git a/src/conf_mode/service_https.py b/src/conf_mode/service_https.py
index 3dc5dfc01..cb40acc9f 100755
--- a/src/conf_mode/service_https.py
+++ b/src/conf_mode/service_https.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2023 VyOS maintainers and contributors
+# Copyright (C) 2019-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
@@ -78,12 +78,7 @@ def get_config(config=None):
diff = get_config_diff(conf)
- https = conf.get_config_dict(base, get_first_key=True)
-
- if https:
- https['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- no_tag_node_value_mangle=True,
- get_first_key=True)
+ https = conf.get_config_dict(base, get_first_key=True, with_pki=True)
https['children_changed'] = diff.node_changed_children(base)
https['api_add_or_delete'] = diff.node_changed_presence(base + ['api'])
@@ -119,7 +114,7 @@ def verify(https):
if 'certificate' in certificates:
if not https['pki']:
- raise ConfigError("PKI is not configured")
+ raise ConfigError('PKI is not configured')
cert_name = certificates['certificate']
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index 9e9385ddb..7fd32c230 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021-2023 VyOS maintainers and contributors
+# Copyright (C) 2021-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
@@ -87,15 +87,13 @@ 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_recursive_defaults=True,
+ with_pki=True)
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'])
ipsec['nhrp_exists'] = conf.exists(['protocols', 'nhrp', 'tunnel'])
- ipsec['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- no_tag_node_value_mangle=True,
- get_first_key=True)
tmp = conf.get_config_dict(l2tp_base, key_mangling=('-', '_'),
no_tag_node_value_mangle=True,
diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py
index a039172c4..421ac6997 100755
--- a/src/conf_mode/vpn_openconnect.py
+++ b/src/conf_mode/vpn_openconnect.py
@@ -56,12 +56,8 @@ def get_config(config=None):
ocserv = conf.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True,
- with_recursive_defaults=True)
-
- if ocserv:
- ocserv['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- no_tag_node_value_mangle=True,
- get_first_key=True)
+ with_recursive_defaults=True,
+ with_pki=True)
return ocserv
diff --git a/src/conf_mode/vpn_sstp.py b/src/conf_mode/vpn_sstp.py
index ac053cc76..6bf9307e1 100755
--- a/src/conf_mode/vpn_sstp.py
+++ b/src/conf_mode/vpn_sstp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2023 VyOS maintainers and contributors
+# Copyright (C) 2018-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
@@ -54,14 +54,11 @@ def get_config(config=None):
return None
# retrieve common dictionary keys
- sstp = get_accel_dict(conf, base, sstp_chap_secrets)
+ sstp = get_accel_dict(conf, base, sstp_chap_secrets, with_pki=True)
if dict_search('client_ip_pool', sstp):
# Multiple named pools require ordered values T5099
sstp['ordered_named_pools'] = get_pools_in_order(dict_search('client_ip_pool', sstp))
- if sstp:
- sstp['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
- get_first_key=True,
- no_tag_node_value_mangle=True)
+
sstp['server_type'] = 'sstp'
return sstp
diff --git a/src/etc/systemd/system/frr.service.d/override.conf b/src/etc/systemd/system/frr.service.d/override.conf
index 094f83551..614b4f7ed 100644
--- a/src/etc/systemd/system/frr.service.d/override.conf
+++ b/src/etc/systemd/system/frr.service.d/override.conf
@@ -1,3 +1,6 @@
+[Unit]
+After=vyos-router.service
+
[Service]
LimitNOFILE=4096
ExecStartPre=/bin/bash -c 'mkdir -p /run/frr/config; \
diff --git a/src/migration-scripts/firewall/6-to-7 b/src/migration-scripts/firewall/6-to-7
index 9ad887acc..b918833e9 100755
--- a/src/migration-scripts/firewall/6-to-7
+++ b/src/migration-scripts/firewall/6-to-7
@@ -73,6 +73,7 @@ icmp_translations = {
# Time Exceeded
'ttl-zero-during-transit': [11, 0],
'ttl-zero-during-reassembly': [11, 1],
+ 'ttl-exceeded': 'time-exceeded',
# Parameter Problem
'ip-header-bad': [12, 0],
'required-option-missing': [12, 1]
@@ -87,8 +88,14 @@ icmpv6_translations = {
'communication-prohibited': [1, 1],
'address-unreachble': [1, 3],
'port-unreachable': [1, 4],
- # Redirect
+ # nd
'redirect': 'nd-redirect',
+ 'router-solicitation': 'nd-router-solicit',
+ 'router-advertisement': 'nd-router-advert',
+ 'neighbour-solicitation': 'nd-neighbor-solicit',
+ 'neighbor-solicitation': 'nd-neighbor-solicit',
+ 'neighbour-advertisement': 'nd-neighbor-advert',
+ 'neighbor-advertisement': 'nd-neighbor-advert',
# Time Exceeded
'ttl-zero-during-transit': [3, 0],
'ttl-zero-during-reassembly': [3, 1],