summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/rsyslog/rsyslog.conf.j210
-rw-r--r--interface-definitions/system_syslog.xml.in14
-rw-r--r--smoketest/config-tests/basic-syslog25
-rw-r--r--smoketest/configs/basic-syslog70
-rwxr-xr-xsmoketest/scripts/cli/test_system_syslog.py65
-rwxr-xr-xsrc/conf_mode/system_syslog.py46
-rw-r--r--src/migration-scripts/system/28-to-297
7 files changed, 201 insertions, 36 deletions
diff --git a/data/templates/rsyslog/rsyslog.conf.j2 b/data/templates/rsyslog/rsyslog.conf.j2
index daaafa6d1..45742b073 100644
--- a/data/templates/rsyslog/rsyslog.conf.j2
+++ b/data/templates/rsyslog/rsyslog.conf.j2
@@ -106,12 +106,11 @@ if prifilt("{{ tmp | join(',') }}") then {
template="SyslogProtocol23Format"
{% endif %}
TCP_Framing="{{ 'octed-counted' if remote_options.format.octet_counted is vyos_defined else 'traditional' }}"
-{% if source_address is vyos_defined %}
- # Sender IP address
- Address="{{ source_address }}"
+{% if remote_options.source_address is vyos_defined %}
+ Address="{{ remote_options.source_address }}"
{% endif %}
-{% if vrf is vyos_defined %}
- Device="{{ vrf }}"
+{% if remote_options.vrf is vyos_defined %}
+ Device="{{ remote_options.vrf }}"
{% endif %}
)
}
@@ -121,3 +120,4 @@ if prifilt("{{ tmp | join(',') }}") then {
# Include all configuration files in /etc/rsyslog.d/
include(file="/etc/rsyslog.d/*.conf")
+
diff --git a/interface-definitions/system_syslog.xml.in b/interface-definitions/system_syslog.xml.in
index 0dbf5d497..91fb680e0 100644
--- a/interface-definitions/system_syslog.xml.in
+++ b/interface-definitions/system_syslog.xml.in
@@ -38,11 +38,6 @@
</valueHelp>
</properties>
<children>
- #include <include/port-number.xml.i>
- <leafNode name="port">
- <defaultValue>514</defaultValue>
- </leafNode>
- #include <include/protocol-tcp-udp.xml.i>
#include <include/syslog-facility.xml.i>
<node name="format">
<properties>
@@ -63,6 +58,13 @@
</leafNode>
</children>
</node>
+ #include <include/port-number.xml.i>
+ <leafNode name="port">
+ <defaultValue>514</defaultValue>
+ </leafNode>
+ #include <include/protocol-tcp-udp.xml.i>
+ #include <include/source-address-ipv4-ipv6.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
<node name="local">
@@ -100,8 +102,6 @@
<valueless/>
</properties>
</leafNode>
- #include <include/source-address-ipv4-ipv6.xml.i>
- #include <include/interface/vrf.xml.i>
</children>
</node>
</children>
diff --git a/smoketest/config-tests/basic-syslog b/smoketest/config-tests/basic-syslog
new file mode 100644
index 000000000..349d642fd
--- /dev/null
+++ b/smoketest/config-tests/basic-syslog
@@ -0,0 +1,25 @@
+set interfaces ethernet eth0 duplex 'auto'
+set interfaces ethernet eth0 speed 'auto'
+set interfaces ethernet eth1 address '172.16.33.154/24'
+set interfaces ethernet eth1 duplex 'auto'
+set interfaces ethernet eth1 speed 'auto'
+set interfaces ethernet eth1 vrf 'red'
+set system console device ttyS0 speed '115200'
+set system domain-name 'vyos-ci-test.net'
+set system host-name 'vyos'
+set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0'
+set system login user vyos authentication plaintext-password ''
+set system syslog local facility all level 'info'
+set system syslog local facility local7 level 'debug'
+set system syslog marker interval '999'
+set system syslog preserve-fqdn
+set system syslog remote syslog01.vyos.net facility local7 level 'notice'
+set system syslog remote syslog01.vyos.net port '8000'
+set system syslog remote syslog01.vyos.net vrf 'red'
+set system syslog remote syslog02.vyos.net facility all level 'debug'
+set system syslog remote syslog02.vyos.net format include-timezone
+set system syslog remote syslog02.vyos.net format octet-counted
+set system syslog remote syslog02.vyos.net port '8001'
+set system syslog remote syslog02.vyos.net protocol 'tcp'
+set system syslog remote syslog02.vyos.net vrf 'red'
+set vrf name red table '12321'
diff --git a/smoketest/configs/basic-syslog b/smoketest/configs/basic-syslog
new file mode 100644
index 000000000..9336b73bc
--- /dev/null
+++ b/smoketest/configs/basic-syslog
@@ -0,0 +1,70 @@
+interfaces {
+ ethernet eth0 {
+ duplex "auto"
+ speed "auto"
+ }
+ ethernet eth1 {
+ address 172.16.33.154/24
+ duplex auto
+ speed auto
+ vrf red
+ }
+}
+system {
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ domain-name vyos-ci-test.net
+ host-name vyos
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
+ plaintext-password ""
+ }
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level info
+ }
+ facility local7 {
+ level debug
+ }
+ marker {
+ interval 999
+ }
+ preserve-fqdn
+ }
+ host syslog01.vyos.net {
+ facility local7 {
+ level notice
+ }
+ port 8000
+ }
+ host syslog02.vyos.net {
+ facility all {
+ level debug
+ }
+ format {
+ include-timezone
+ octet-counted
+ }
+ protocol tcp
+ port 8001
+ }
+ vrf red
+ }
+}
+vrf {
+ name red {
+ table 12321
+ }
+}
+
+// Warning: Do not remove the following line.
+// vyos-config-version: "bgp@5:broadcast-relay@1:cluster@2:config-management@1:conntrack@5:conntrack-sync@2:container@2:dhcp-relay@2:dhcp-server@8:dhcpv6-server@1:dns-dynamic@4:dns-forwarding@4:firewall@15:flow-accounting@1:https@6:ids@1:interfaces@32:ipoe-server@3:ipsec@13:isis@3:l2tp@9:lldp@2:mdns@1:monitoring@1:nat@8:nat66@3:ntp@3:openconnect@3:ospf@2:pim@1:policy@8:pppoe-server@10:pptp@5:qos@2:quagga@11:reverse-proxy@1:rip@1:rpki@2:salt@1:snmp@3:ssh@2:sstp@6:system@27:vrf@3:vrrp@4:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2"
+// Release version: 1.4.0
diff --git a/smoketest/scripts/cli/test_system_syslog.py b/smoketest/scripts/cli/test_system_syslog.py
index 5a09fab18..bf6d3134d 100755
--- a/smoketest/scripts/cli/test_system_syslog.py
+++ b/smoketest/scripts/cli/test_system_syslog.py
@@ -14,7 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import re
import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
@@ -47,6 +46,7 @@ class TestRSYSLOGService(VyOSUnitTestSHIM.TestCase):
# ensure we can also run this test on a live system - so lets clean
# out the current configuration :)
cls.cli_delete(cls, base_path)
+ cls.cli_delete(cls, ['vrf'])
def tearDown(self):
# Check for running process
@@ -204,5 +204,68 @@ class TestRSYSLOGService(VyOSUnitTestSHIM.TestCase):
else:
self.assertIn( ' TCP_Framing="traditional"', config)
+ def test_vrf_source_address(self):
+ rhosts = {
+ '169.254.0.10': { },
+ '169.254.0.11': {
+ 'vrf': {'name' : 'red', 'table' : '12321'},
+ 'source_address' : '169.254.0.11',
+ },
+ '169.254.0.12': {
+ 'vrf': {'name' : 'green', 'table' : '12322'},
+ 'source_address' : '169.254.0.12',
+ },
+ '169.254.0.13': {
+ 'vrf': {'name' : 'blue', 'table' : '12323'},
+ 'source_address' : '169.254.0.13',
+ },
+ }
+
+ for remote, remote_options in rhosts.items():
+ remote_base = base_path + ['remote', remote]
+ self.cli_set(remote_base + ['facility', 'all'])
+
+ vrf = None
+ if 'vrf' in remote_options:
+ vrf = remote_options['vrf']['name']
+ self.cli_set(['vrf', 'name', vrf, 'table', remote_options['vrf']['table']])
+ self.cli_set(remote_base + ['vrf', vrf])
+
+ if 'source_address' in remote_options:
+ source_address = remote_options['source_address']
+ self.cli_set(remote_base + ['source-address', source_address])
+
+ idx = source_address.split('.')[-1]
+ self.cli_set(['interfaces', 'dummy', f'dum{idx}', 'address', f'{source_address}/32'])
+ if vrf:
+ self.cli_set(['interfaces', 'dummy', f'dum{idx}', 'vrf', vrf])
+
+
+ self.cli_commit()
+ config = read_file(RSYSLOG_CONF)
+
+ for remote, remote_options in rhosts.items():
+ config = get_config(f'# Remote syslog to {remote}')
+
+ self.assertIn(f'target="{remote}"', config)
+ if 'vrf' in remote_options:
+ vrf = remote_options['vrf']['name']
+ self.assertIn(f'Device="{vrf}"', config)
+
+ if 'source_address' in remote_options:
+ source_address = remote_options['source_address']
+ self.assertIn(f'Address="{source_address}"', config)
+
+ # Cleanup VRF/Dummy interfaces
+ for remote, remote_options in rhosts.items():
+ if 'vrf' in remote_options:
+ vrf = remote_options['vrf']['name']
+ self.cli_delete(['vrf', 'name', vrf])
+
+ if 'source_address' in remote_options:
+ source_address = remote_options['source_address']
+ idx = source_address.split('.')[-1]
+ self.cli_delete(['interfaces', 'dummy', f'dum{idx}'])
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/system_syslog.py b/src/conf_mode/system_syslog.py
index f27c27e0b..00c571ea9 100755
--- a/src/conf_mode/system_syslog.py
+++ b/src/conf_mode/system_syslog.py
@@ -20,11 +20,12 @@ from sys import exit
from vyos.base import Warning
from vyos.config import Config
-from vyos.configdict import is_node_changed
from vyos.configverify import verify_vrf
from vyos.utils.network import is_addr_assigned
from vyos.utils.process import call
from vyos.template import render
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -46,9 +47,6 @@ def get_config(config=None):
syslog.update({ 'logrotate' : logrotate_conf })
- tmp = is_node_changed(conf, base + ['vrf'])
- if tmp: syslog.update({'restart_required': {}})
-
syslog = conf.merge_defaults(syslog, recursive=True)
if syslog.from_defaults(['local']):
del syslog['local']
@@ -74,19 +72,26 @@ def verify(syslog):
Warning('No "system domain-name" defined - cannot set syslog FQDN!')
if 'remote' in syslog:
- for host, host_options in syslog['remote'].items():
- if 'protocol' in host_options and host_options['protocol'] == 'udp':
- if 'format' in host_options and 'octet_counted' in host_options['format']:
- Warning(f'Syslog UDP transport for "{host}" should not use octet-counted format!')
-
- verify_vrf(syslog)
-
- if 'source_address' in syslog:
- syslog_vrf = None
- if 'vrf' in syslog:
- syslog_vrf = syslog['vrf']
- if not is_addr_assigned(syslog['source_address'], syslog_vrf):
- raise ConfigError('No interface with given address specified!')
+ for remote, remote_options in syslog['remote'].items():
+ if 'protocol' in remote_options and remote_options['protocol'] == 'udp':
+ if 'format' in remote_options and 'octet_counted' in remote_options['format']:
+ Warning(f'Syslog UDP transport for "{remote}" should not use octet-counted format!')
+
+ if 'vrf' in remote_options:
+ verify_vrf(remote_options)
+
+ if 'source_address' in remote_options:
+ vrf = None
+ if 'vrf' in remote_options:
+ vrf = remote_options['vrf']
+ if not is_addr_assigned(remote_options['source_address'], vrf):
+ raise ConfigError('No interface with given address specified!')
+
+ source_address = remote_options['source_address']
+ if ((is_ipv4(remote) and is_ipv6(source_address)) or
+ (is_ipv6(remote) and is_ipv4(source_address))):
+ raise ConfigError(f'Source-address "{source_address}" does not match '\
+ f'address-family of remote "{remote}"!')
def generate(syslog):
if not syslog:
@@ -108,12 +113,7 @@ def apply(syslog):
call(f'systemctl stop {systemd_service} {systemd_socket}')
return None
- # we need to restart the service if e.g. the VRF name changed
- systemd_action = 'reload-or-restart'
- if 'restart_required' in syslog:
- systemd_action = 'restart'
-
- call(f'systemctl {systemd_action} {systemd_service}')
+ call(f'systemctl reload-or-restart {systemd_service}')
return None
if __name__ == '__main__':
diff --git a/src/migration-scripts/system/28-to-29 b/src/migration-scripts/system/28-to-29
index 2ccd4b9c0..ccf7056c4 100644
--- a/src/migration-scripts/system/28-to-29
+++ b/src/migration-scripts/system/28-to-29
@@ -54,6 +54,11 @@ def migrate(config: ConfigTree) -> None:
if config.exists(base + ['global']):
config.rename(base + ['global'], 'local')
+ vrf = ''
+ if config.exists(base + ['vrf']):
+ vrf = config.return_value(base + ['vrf'])
+ config.delete(base + ['vrf'])
+
# Rename host x.x.x.x -> remote x.x.x.x
if config.exists(base + ['host']):
config.set(base + ['remote'])
@@ -61,4 +66,6 @@ def migrate(config: ConfigTree) -> None:
for remote in config.list_nodes(base + ['host']):
config.copy(base + ['host', remote], base + ['remote', remote])
config.set_tag(base + ['remote'])
+ if vrf:
+ config.set(base + ['remote', remote, 'vrf'], value=vrf)
config.delete(base + ['host'])