summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--data/templates/container/registries.conf.j210
-rw-r--r--data/templates/rsyslog/rsyslog.conf.j22
-rw-r--r--interface-definitions/container.xml.in48
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_vxlan.py27
-rwxr-xr-xsmoketest/scripts/cli/test_system_syslog.py25
-rwxr-xr-xsrc/conf_mode/container.py7
-rwxr-xr-xsrc/conf_mode/interfaces_vxlan.py2
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py27
9 files changed, 146 insertions, 5 deletions
diff --git a/Makefile b/Makefile
index e194b6d2c..3f3ba5ba7 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,8 @@ op_xml_obj = $(op_xml_src:.xml.in=.xml)
.ONESHELL:
libvyosconfig:
if ! [ -f $(LIBVYOSCONFIG_BUILD_PATH) ]; then
- git clone https://github.com/vyos/libvyosconfig.git /tmp/libvyosconfig || exit 1
+ rm -rf /tmp/libvyosconfig && \
+ git clone https://github.com/vyos/libvyosconfig.git /tmp/libvyosconfig || exit 1
cd /tmp/libvyosconfig && \
git checkout 677d1e2bf8109b9fd4da60e20376f992b747e384 || exit 1
./build.sh
diff --git a/data/templates/container/registries.conf.j2 b/data/templates/container/registries.conf.j2
index eb7ff8775..b5c7eed9b 100644
--- a/data/templates/container/registries.conf.j2
+++ b/data/templates/container/registries.conf.j2
@@ -28,4 +28,14 @@
{% set _ = registry_list.append(r) %}
{% endfor %}
unqualified-search-registries = {{ registry_list }}
+{% for r, r_options in registry.items() if r_options.disable is not vyos_defined %}
+[[registry]]
+{% if r_options.mirror is vyos_defined %}
+location = "{{ r_options.mirror.host_name if r_options.mirror.host_name is vyos_defined else r_options.mirror.address }}{{ ":" + r_options.mirror.port if r_options.mirror.port is vyos_defined }}{{ r_options.mirror.path if r_options.mirror.path is vyos_defined }}"
+{% else %}
+location = "{{ r }}"
+{% endif %}
+insecure = {{ 'true' if r_options.insecure is vyos_defined else 'false' }}
+prefix = "{{ r }}"
+{% endfor %}
{% endif %}
diff --git a/data/templates/rsyslog/rsyslog.conf.j2 b/data/templates/rsyslog/rsyslog.conf.j2
index e2ff334ff..68e34f3f8 100644
--- a/data/templates/rsyslog/rsyslog.conf.j2
+++ b/data/templates/rsyslog/rsyslog.conf.j2
@@ -98,7 +98,7 @@ if prifilt("{{ tmp | join(',') }}") then {
action(
type="omfwd"
# Remote syslog server where we send our logs to
- target="{{ remote_name | bracketize_ipv6 }}"
+ target="{{ remote_name }}"
# Port on the remote syslog server
port="{{ remote_options.port }}"
protocol="{{ remote_options.protocol }}"
diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in
index 5c320e8c6..3a5cfbaa6 100644
--- a/interface-definitions/container.xml.in
+++ b/interface-definitions/container.xml.in
@@ -571,6 +571,54 @@
<children>
#include <include/interface/authentication.xml.i>
#include <include/generic-disable-node.xml.i>
+ <leafNode name="insecure">
+ <properties>
+ <help>Allow registry access over unencrypted HTTP or TLS connections with untrusted certificates</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="mirror">
+ <properties>
+ <help>Registry mirror, use host-name|address[:port][/path]</help>
+ </properties>
+ <children>
+ <leafNode name="address">
+ <properties>
+ <help>IP address of container registry mirror</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IPv4 address of container registry mirror</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address of container registry mirror</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ip-address"/>
+ <validator name="ipv6-link-local"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="host-name">
+ <properties>
+ <help>Hostname of container registry mirror</help>
+ <valueHelp>
+ <format>hostname</format>
+ <description>FQDN of container registry mirror</description>
+ </valueHelp>
+ <constraint>
+ <validator name="fqdn"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ #include <include/port-number.xml.i>
+ <leafNode name="path">
+ <properties>
+ <help>Path of container registry mirror, optional, must be start with '/' if not empty</help>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
</children>
</tagNode>
</children>
diff --git a/smoketest/scripts/cli/test_interfaces_vxlan.py b/smoketest/scripts/cli/test_interfaces_vxlan.py
index b2076b43b..05900a4ba 100755
--- a/smoketest/scripts/cli/test_interfaces_vxlan.py
+++ b/smoketest/scripts/cli/test_interfaces_vxlan.py
@@ -25,6 +25,7 @@ from vyos.utils.network import interface_exists
from vyos.utils.network import get_vxlan_vlan_tunnels
from vyos.utils.network import get_vxlan_vni_filter
from vyos.template import is_ipv6
+from vyos import ConfigError
from base_interfaces_test import BasicInterfaceTest
def convert_to_list(ranges_to_convert):
@@ -114,6 +115,32 @@ class VXLANInterfaceTest(BasicInterfaceTest.TestCase):
self.assertEqual(Interface(interface).get_admin_state(), 'up')
ttl += 10
+
+ def test_vxlan_group_remote_error(self):
+ intf = 'vxlan60'
+ options = [
+ 'group 239.4.4.5',
+ 'mtu 1420',
+ 'remote 192.168.0.254',
+ 'source-address 192.168.0.1',
+ 'source-interface eth0',
+ 'vni 60'
+ ]
+ params = []
+ for option in options:
+ opts = option.split()
+ params.append(opts[0])
+ self.cli_set(self._base_path + [ intf ] + opts)
+
+ with self.assertRaises(ConfigSessionError) as cm:
+ self.cli_commit()
+
+ exception = cm.exception
+ self.assertIn('Both group and remote cannot be specified', str(exception))
+ for param in params:
+ self.cli_delete(self._base_path + [intf, param])
+
+
def test_vxlan_external(self):
interface = 'vxlan0'
source_address = '192.0.2.1'
diff --git a/smoketest/scripts/cli/test_system_syslog.py b/smoketest/scripts/cli/test_system_syslog.py
index e642b5660..ba325ced8 100755
--- a/smoketest/scripts/cli/test_system_syslog.py
+++ b/smoketest/scripts/cli/test_system_syslog.py
@@ -18,6 +18,7 @@ import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.configsession import ConfigSessionError
from vyos.utils.file import read_file
from vyos.utils.process import cmd
from vyos.utils.process import process_named_running
@@ -28,6 +29,8 @@ RSYSLOG_CONF = '/run/rsyslog/rsyslog.conf'
base_path = ['system', 'syslog']
+dummy_interface = 'dum372874'
+
def get_config(string=''):
"""
Retrieve current "running configuration" from FRR
@@ -127,15 +130,22 @@ class TestRSYSLOGService(VyOSUnitTestSHIM.TestCase):
self.assertNotIn('module(load="immark"', config)
def test_remote(self):
+ dummy_if_path = ['interfaces', 'dummy', dummy_interface]
rhosts = {
'169.254.0.1': {
'facility': {'auth' : {'level': 'info'}},
'protocol': 'udp',
},
- '169.254.0.2': {
+ '2001:db8::1': {
+ 'facility': {'all' : {'level': 'debug'}},
'port': '1514',
'protocol': 'udp',
},
+ 'syslog.vyos.net': {
+ 'facility': {'all' : {'level': 'debug'}},
+ 'port': '1515',
+ 'protocol': 'tcp',
+ },
'169.254.0.3': {
'facility': {'auth' : {'level': 'info'},
'kern' : {'level': 'debug'},
@@ -169,6 +179,15 @@ class TestRSYSLOGService(VyOSUnitTestSHIM.TestCase):
protocol = remote_options['protocol']
self.cli_set(remote_base + ['protocol'], value=protocol)
+ if 'source_address' in remote_options:
+ source_address = remote_options['source_address']
+ self.cli_set(remote_base + ['source-address', source_address])
+
+ # check validate() - source address does not exist
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_set(dummy_if_path + ['address', f'{source_address}/32'])
+
self.cli_commit()
config = read_file(RSYSLOG_CONF)
@@ -211,6 +230,9 @@ class TestRSYSLOGService(VyOSUnitTestSHIM.TestCase):
else:
self.assertIn( ' TCP_Framing="traditional"', config)
+ # cleanup dummy interface
+ self.cli_delete(dummy_if_path)
+
def test_vrf_source_address(self):
rhosts = {
'169.254.0.10': { },
@@ -252,7 +274,6 @@ class TestRSYSLOGService(VyOSUnitTestSHIM.TestCase):
value=vrf)
self.cli_commit()
- config = read_file(RSYSLOG_CONF)
for remote, remote_options in rhosts.items():
config = get_config(f'# Remote syslog to {remote}')
diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py
index 3636b0871..18d660a4e 100755
--- a/src/conf_mode/container.py
+++ b/src/conf_mode/container.py
@@ -289,6 +289,13 @@ def verify(container):
if 'registry' in container:
for registry, registry_config in container['registry'].items():
+ if 'mirror' in registry_config:
+ if 'host_name' in registry_config['mirror'] and 'address' in registry_config['mirror']:
+ raise ConfigError(f'Container registry mirror address/host-name are mutually exclusive!')
+
+ if 'path' in registry_config['mirror'] and not registry_config['mirror']['path'].startswith('/'):
+ raise ConfigError('Container registry mirror path must start with "/"!')
+
if 'authentication' not in registry_config:
continue
if not {'username', 'password'} <= set(registry_config['authentication']):
diff --git a/src/conf_mode/interfaces_vxlan.py b/src/conf_mode/interfaces_vxlan.py
index 68646e8ff..256b65708 100755
--- a/src/conf_mode/interfaces_vxlan.py
+++ b/src/conf_mode/interfaces_vxlan.py
@@ -95,6 +95,8 @@ def verify(vxlan):
if 'group' in vxlan:
if 'source_interface' not in vxlan:
raise ConfigError('Multicast VXLAN requires an underlaying interface')
+ if 'remote' in vxlan:
+ raise ConfigError('Both group and remote cannot be specified')
verify_source_interface(vxlan)
if not any(tmp in ['group', 'remote', 'source_address', 'source_interface'] for tmp in vxlan):
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index 25604d2a2..71a503e61 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -156,6 +156,8 @@ def get_config(config=None):
_, vti = get_interface_dict(conf, ['interfaces', 'vti'], vti_interface)
ipsec['vti_interface_dicts'][vti_interface] = vti
+ ipsec['vpp_ipsec_exists'] = conf.exists(['vpp', 'settings', 'ipsec'])
+
return ipsec
def get_dhcp_address(iface):
@@ -484,6 +486,17 @@ def verify(ipsec):
else:
raise ConfigError(f"Missing ike-group on site-to-site peer {peer}")
+ # verify encryption algorithm compatibility for IKE with VPP
+ if ipsec['vpp_ipsec_exists']:
+ ike_group = ipsec['ike_group'][peer_conf['ike_group']]
+ for proposal, proposal_config in ike_group.get('proposal', {}).items():
+ algs = ['gmac', 'serpent', 'twofish']
+ if any(alg in proposal_config['encryption'] for alg in algs):
+ raise ConfigError(
+ f'Encryption algorithm {proposal_config["encryption"]} cannot be used '
+ f'for IKE proposal {proposal} for site-to-site peer {peer} with VPP'
+ )
+
if 'authentication' not in peer_conf or 'mode' not in peer_conf['authentication']:
raise ConfigError(f"Missing authentication on site-to-site peer {peer}")
@@ -562,7 +575,7 @@ def verify(ipsec):
esp_group_name = tunnel_conf['esp_group'] if 'esp_group' in tunnel_conf else peer_conf['default_esp_group']
- if esp_group_name not in ipsec['esp_group']:
+ if esp_group_name not in ipsec.get('esp_group'):
raise ConfigError(f"Invalid esp-group on tunnel {tunnel} for site-to-site peer {peer}")
esp_group = ipsec['esp_group'][esp_group_name]
@@ -574,6 +587,18 @@ def verify(ipsec):
if ('local' in tunnel_conf and 'prefix' in tunnel_conf['local']) or ('remote' in tunnel_conf and 'prefix' in tunnel_conf['remote']):
raise ConfigError(f"Local/remote prefix cannot be used with ESP transport mode on tunnel {tunnel} for site-to-site peer {peer}")
+ # verify ESP encryption algorithm compatibility with VPP
+ # because Marvel plugin for VPP doesn't support all algorithms that Strongswan does
+ if ipsec['vpp_ipsec_exists']:
+ for proposal, proposal_config in esp_group.get('proposal', {}).items():
+ algs = ['aes128', 'aes192', 'aes256', 'aes128gcm128', 'aes192gcm128', 'aes256gcm128']
+ if proposal_config['encryption'] not in algs:
+ raise ConfigError(
+ f'Encryption algorithm {proposal_config["encryption"]} cannot be used '
+ f'for ESP proposal {proposal} on tunnel {tunnel} for site-to-site peer {peer} with VPP'
+ )
+
+
def cleanup_pki_files():
for path in [CERT_PATH, CA_PATH, CRL_PATH, KEY_PATH, PUBKEY_PATH]:
if not os.path.exists(path):