diff options
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], |