Skip to content

Commit 1840d1d

Browse files
committed
syslog: T6989: add possibility to define VRF per remote
Rsyslog supports individual VRFs per omfwd remote entry - so we should support this, too.
1 parent e2944c1 commit 1840d1d

File tree

7 files changed

+200
-25
lines changed

7 files changed

+200
-25
lines changed

data/templates/rsyslog/rsyslog.conf.j2

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,11 @@ if prifilt("{{ tmp | join(',') }}") then {
106106
template="SyslogProtocol23Format"
107107
{% endif %}
108108
TCP_Framing="{{ 'octed-counted' if remote_options.format.octet_counted is vyos_defined else 'traditional' }}"
109-
{% if source_address is vyos_defined %}
110-
# Sender IP address
111-
Address="{{ source_address }}"
109+
{% if remote_options.source_address is vyos_defined %}
110+
Address="{{ remote_options.source_address }}"
112111
{% endif %}
113-
{% if vrf is vyos_defined %}
114-
Device="{{ vrf }}"
112+
{% if remote_options.vrf is vyos_defined %}
113+
Device="{{ remote_options.vrf }}"
115114
{% endif %}
116115
)
117116
}
@@ -121,3 +120,4 @@ if prifilt("{{ tmp | join(',') }}") then {
121120

122121
# Include all configuration files in /etc/rsyslog.d/
123122
include(file="/etc/rsyslog.d/*.conf")
123+

interface-definitions/system_syslog.xml.in

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@
3838
</valueHelp>
3939
</properties>
4040
<children>
41-
#include <include/port-number.xml.i>
42-
<leafNode name="port">
43-
<defaultValue>514</defaultValue>
44-
</leafNode>
45-
#include <include/protocol-tcp-udp.xml.i>
4641
#include <include/syslog-facility.xml.i>
4742
<node name="format">
4843
<properties>
@@ -63,6 +58,13 @@
6358
</leafNode>
6459
</children>
6560
</node>
61+
#include <include/port-number.xml.i>
62+
<leafNode name="port">
63+
<defaultValue>514</defaultValue>
64+
</leafNode>
65+
#include <include/protocol-tcp-udp.xml.i>
66+
#include <include/source-address-ipv4-ipv6.xml.i>
67+
#include <include/interface/vrf.xml.i>
6668
</children>
6769
</tagNode>
6870
<node name="local">
@@ -100,8 +102,6 @@
100102
<valueless/>
101103
</properties>
102104
</leafNode>
103-
#include <include/source-address-ipv4-ipv6.xml.i>
104-
#include <include/interface/vrf.xml.i>
105105
</children>
106106
</node>
107107
</children>

smoketest/config-tests/basic-syslog

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
set interfaces ethernet eth0 duplex 'auto'
2+
set interfaces ethernet eth0 speed 'auto'
3+
set interfaces ethernet eth1 address '172.16.33.154/24'
4+
set interfaces ethernet eth1 duplex 'auto'
5+
set interfaces ethernet eth1 speed 'auto'
6+
set interfaces ethernet eth1 vrf 'red'
7+
set system console device ttyS0 speed '115200'
8+
set system domain-name 'vyos-ci-test.net'
9+
set system host-name 'vyos'
10+
set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0'
11+
set system login user vyos authentication plaintext-password ''
12+
set system syslog local facility all level 'info'
13+
set system syslog local facility local7 level 'debug'
14+
set system syslog marker interval '999'
15+
set system syslog preserve-fqdn
16+
set system syslog remote syslog01.vyos.net facility local7 level 'notice'
17+
set system syslog remote syslog01.vyos.net port '8000'
18+
set system syslog remote syslog01.vyos.net vrf 'red'
19+
set system syslog remote syslog02.vyos.net facility all level 'debug'
20+
set system syslog remote syslog02.vyos.net format include-timezone
21+
set system syslog remote syslog02.vyos.net format octet-counted
22+
set system syslog remote syslog02.vyos.net port '8001'
23+
set system syslog remote syslog02.vyos.net protocol 'tcp'
24+
set system syslog remote syslog02.vyos.net vrf 'red'
25+
set vrf name red table '12321'

smoketest/configs/basic-syslog

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
interfaces {
2+
ethernet eth0 {
3+
duplex "auto"
4+
speed "auto"
5+
}
6+
ethernet eth1 {
7+
address 172.16.33.154/24
8+
duplex auto
9+
speed auto
10+
vrf red
11+
}
12+
}
13+
system {
14+
console {
15+
device ttyS0 {
16+
speed 115200
17+
}
18+
}
19+
domain-name vyos-ci-test.net
20+
host-name vyos
21+
login {
22+
user vyos {
23+
authentication {
24+
encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
25+
plaintext-password ""
26+
}
27+
}
28+
}
29+
syslog {
30+
global {
31+
facility all {
32+
level info
33+
}
34+
facility local7 {
35+
level debug
36+
}
37+
marker {
38+
interval 999
39+
}
40+
preserve-fqdn
41+
}
42+
host syslog01.vyos.net {
43+
facility local7 {
44+
level notice
45+
}
46+
port 8000
47+
}
48+
host syslog02.vyos.net {
49+
facility all {
50+
level debug
51+
}
52+
format {
53+
include-timezone
54+
octet-counted
55+
}
56+
protocol tcp
57+
port 8001
58+
}
59+
vrf red
60+
}
61+
}
62+
vrf {
63+
name red {
64+
table 12321
65+
}
66+
}
67+
68+
// Warning: Do not remove the following line.
69+
// 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"
70+
// Release version: 1.4.0

smoketest/scripts/cli/test_system_syslog.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def setUpClass(cls):
4747
# ensure we can also run this test on a live system - so lets clean
4848
# out the current configuration :)
4949
cls.cli_delete(cls, base_path)
50+
cls.cli_delete(cls, ['vrf'])
5051

5152
def tearDown(self):
5253
# Check for running process
@@ -204,5 +205,68 @@ def test_remote(self):
204205
else:
205206
self.assertIn( ' TCP_Framing="traditional"', config)
206207

208+
def test_vrf_source_address(self):
209+
rhosts = {
210+
'169.254.0.10': { },
211+
'169.254.0.11': {
212+
'vrf': {'name' : 'red', 'table' : '12321'},
213+
'source_address' : '169.254.0.11',
214+
},
215+
'169.254.0.12': {
216+
'vrf': {'name' : 'green', 'table' : '12322'},
217+
'source_address' : '169.254.0.12',
218+
},
219+
'169.254.0.13': {
220+
'vrf': {'name' : 'blue', 'table' : '12323'},
221+
'source_address' : '169.254.0.13',
222+
},
223+
}
224+
225+
for remote, remote_options in rhosts.items():
226+
remote_base = base_path + ['remote', remote]
227+
self.cli_set(remote_base + ['facility', 'all'])
228+
229+
vrf = None
230+
if 'vrf' in remote_options:
231+
vrf = remote_options['vrf']['name']
232+
self.cli_set(['vrf', 'name', vrf, 'table', remote_options['vrf']['table']])
233+
self.cli_set(remote_base + ['vrf', vrf])
234+
235+
if 'source_address' in remote_options:
236+
source_address = remote_options['source_address']
237+
self.cli_set(remote_base + ['source-address', source_address])
238+
239+
idx = source_address.split('.')[-1]
240+
self.cli_set(['interfaces', 'dummy', f'dum{idx}', 'address', f'{source_address}/32'])
241+
if vrf:
242+
self.cli_set(['interfaces', 'dummy', f'dum{idx}', 'vrf', vrf])
243+
244+
245+
self.cli_commit()
246+
config = read_file(RSYSLOG_CONF)
247+
248+
for remote, remote_options in rhosts.items():
249+
config = get_config(f'# Remote syslog to {remote}')
250+
251+
self.assertIn(f'target="{remote}"', config)
252+
if 'vrf' in remote_options:
253+
vrf = remote_options['vrf']['name']
254+
self.assertIn(f'Device="{vrf}"', config)
255+
256+
if 'source_address' in remote_options:
257+
source_address = remote_options['source_address']
258+
self.assertIn(f'Address="{source_address}"', config)
259+
260+
# Cleanup VRF/Dummy interfaces
261+
for remote, remote_options in rhosts.items():
262+
if 'vrf' in remote_options:
263+
vrf = remote_options['vrf']['name']
264+
self.cli_delete(['vrf', 'name', vrf])
265+
266+
if 'source_address' in remote_options:
267+
source_address = remote_options['source_address']
268+
idx = source_address.split('.')[-1]
269+
self.cli_delete(['interfaces', 'dummy', f'dum{idx}'])
270+
207271
if __name__ == '__main__':
208272
unittest.main(verbosity=2)

src/conf_mode/system_syslog.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
from vyos.utils.network import is_addr_assigned
2626
from vyos.utils.process import call
2727
from vyos.template import render
28+
from vyos.template import is_ipv4
29+
from vyos.template import is_ipv6
2830
from vyos import ConfigError
2931
from vyos import airbag
3032
airbag.enable()
@@ -74,19 +76,26 @@ def verify(syslog):
7476
Warning('No "system domain-name" defined - cannot set syslog FQDN!')
7577

7678
if 'remote' in syslog:
77-
for host, host_options in syslog['remote'].items():
78-
if 'protocol' in host_options and host_options['protocol'] == 'udp':
79-
if 'format' in host_options and 'octet_counted' in host_options['format']:
80-
Warning(f'Syslog UDP transport for "{host}" should not use octet-counted format!')
81-
82-
verify_vrf(syslog)
83-
84-
if 'source_address' in syslog:
85-
syslog_vrf = None
86-
if 'vrf' in syslog:
87-
syslog_vrf = syslog['vrf']
88-
if not is_addr_assigned(syslog['source_address'], syslog_vrf):
89-
raise ConfigError('No interface with given address specified!')
79+
for remote, remote_options in syslog['remote'].items():
80+
if 'protocol' in remote_options and remote_options['protocol'] == 'udp':
81+
if 'format' in remote_options and 'octet_counted' in remote_options['format']:
82+
Warning(f'Syslog UDP transport for "{remote}" should not use octet-counted format!')
83+
84+
if 'vrf' in remote_options:
85+
verify_vrf(remote_options)
86+
87+
if 'source_address' in remote_options:
88+
vrf = None
89+
if 'vrf' in remote_options:
90+
vrf = remote_options['vrf']
91+
if not is_addr_assigned(remote_options['source_address'], vrf):
92+
raise ConfigError('No interface with given address specified!')
93+
94+
source_address = remote_options['source_address']
95+
if ((is_ipv4(remote) and is_ipv6(source_address)) or
96+
(is_ipv6(remote) and is_ipv4(source_address))):
97+
raise ConfigError(f'Source-address "{source_address}" does not match '\
98+
f'address-family of remote "{remote}"!')
9099

91100
def generate(syslog):
92101
if not syslog:

src/migration-scripts/system/28-to-29

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,18 @@ def migrate(config: ConfigTree) -> None:
5454
if config.exists(base + ['global']):
5555
config.rename(base + ['global'], 'local')
5656

57+
vrf = ''
58+
if config.exists(base + ['vrf']):
59+
vrf = config.return_value(base + ['vrf'])
60+
config.delete(base + ['vrf'])
61+
5762
# Rename host x.x.x.x -> remote x.x.x.x
5863
if config.exists(base + ['host']):
5964
config.set(base + ['remote'])
6065
config.set_tag(base + ['remote'])
6166
for remote in config.list_nodes(base + ['host']):
6267
config.copy(base + ['host', remote], base + ['remote', remote])
6368
config.set_tag(base + ['remote'])
69+
if vrf:
70+
config.set(base + ['remote', remote, 'vrf'], value=vrf)
6471
config.delete(base + ['host'])

0 commit comments

Comments
 (0)