2727
2828PROCESS_NAME = 'rsyslogd'
2929RSYSLOG_CONF = '/run/rsyslog/rsyslog.conf'
30+ CERT_DIR = '/etc/rsyslog.d/certs'
3031
3132base_path = ['system' , 'syslog' ]
33+ pki_base = ['pki' ]
3234
3335dummy_interface = 'dum372874'
3436
37+ ca_cert_name = "syslog_ca_certificate"
38+ ca_cert = """
39+ MIIBrTCCAV+gAwIBAgIUdTEOleLyGTteZC+yEi252lRUq8EwBQYDK2VwMEsxCzAJ
40+ BgNVBAYTAlVTMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEMMAoGA1UE
41+ CgwDT3JnMQ8wDQYDVQQDDAZSb290Q0EwIBcNMjUwOTE1MTQxNDI4WhgPMjEyNTA4
42+ MjIxNDE0MjhaMEsxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UE
43+ BwwEQ2l0eTEMMAoGA1UECgwDT3JnMQ8wDQYDVQQDDAZSb290Q0EwKjAFBgMrZXAD
44+ IQCtTlgU+aqU/i6k6b318vebALk0zs9RvE96vw7taIt2iqNTMFEwHQYDVR0OBBYE
45+ FHl8GywRMCWSotNGmyjuvRbPqCq8MB8GA1UdIwQYMBaAFHl8GywRMCWSotNGmyju
46+ vRbPqCq8MA8GA1UdEwEB/wQFMAMBAf8wBQYDK2VwA0EAouZ4s+/ZeZxZxOZ7yFG0
47+ RQ9BfPWySrX4kgavyJJeg8LNCYUIRIP6iC41MTyHUVsWwar91xBT0DKBkpwrOQ0n
48+ Dg==
49+ """
50+
51+ client_cert_name = "syslog_client_certificate"
52+ client_cert = """
53+ MIIBVjCCAQgCFArrkIM+zg8luHbXwsS8cUB5xrh/MAUGAytlcDBLMQswCQYDVQQG
54+ EwJVUzEOMAwGA1UECAwFU3RhdGUxDTALBgNVBAcMBENpdHkxDDAKBgNVBAoMA09y
55+ ZzEPMA0GA1UEAwwGUm9vdENBMB4XDTI1MDkxNTE0MTUwN1oXDTM1MDkxMzE0MTUw
56+ N1owUDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5
57+ MQwwCgYDVQQKDANPcmcxFDASBgNVBAMMC2V4YW1wbGUuY29tMCowBQYDK2VwAyEA
58+ eZZRz7yVQ+exm6vyh/GdGZrTSEmtbvfafG0digqpfnUwBQYDK2VwA0EAU8/kw1i0
59+ s4j2fPQmU1q6Qql3xaxUlDyzhRPSIeH7ZhOlNg8R7gR1QnA7Rel6oU4EqJJHvz9l
60+ 83HQAy7ZcNIoBw==
61+ """
62+
63+ client_cert_key = """
64+ MC4CAQAwBQYDK2VwBCIEIG59XPVZoMCxBVD/eJVqJSmV+Uc0bUHjHS4bkfkjM6Jj
65+ """
66+
3567def get_config (string = '' ):
3668 """
3769 Retrieve current "running configuration" from FRR
@@ -51,11 +83,15 @@ def setUpClass(cls):
5183 # out the current configuration :)
5284 cls .cli_delete (cls , base_path )
5385 cls .cli_delete (cls , ['vrf' ])
86+ cls .cli_delete (cls , pki_base )
5487
5588 def tearDown (self ):
5689 # Check for running process
5790 self .assertTrue (process_named_running (PROCESS_NAME ))
5891
92+ # delete test certificates for syslog
93+ self .cli_delete (pki_base )
94+
5995 # delete testing SYSLOG config
6096 self .cli_delete (base_path )
6197 self .cli_commit ()
@@ -68,6 +104,30 @@ def tearDown(self):
68104 # Check for running process
69105 self .assertFalse (process_named_running (PROCESS_NAME ))
70106
107+ def _set_tls_certificates (self ):
108+ self .cli_set (
109+ pki_base + ['ca' , ca_cert_name , 'certificate' , ca_cert .replace ('\n ' , '' )]
110+ )
111+ self .cli_set (
112+ pki_base
113+ + [
114+ 'certificate' ,
115+ client_cert_name ,
116+ 'certificate' ,
117+ client_cert .replace ('\n ' , '' ),
118+ ]
119+ )
120+ self .cli_set (
121+ pki_base
122+ + [
123+ 'certificate' ,
124+ client_cert_name ,
125+ 'private' ,
126+ 'key' ,
127+ client_cert_key .replace ('\n ' , '' ),
128+ ]
129+ )
130+
71131 def test_console (self ):
72132 level = 'warning'
73133 self .cli_set (base_path + ['console' , 'facility' , 'all' , 'level' ], value = level )
@@ -239,6 +299,119 @@ def test_remote(self):
239299 # cleanup dummy interface
240300 self .cli_delete (dummy_if_path )
241301
302+ def test_remote_tls (self ):
303+ self ._set_tls_certificates ()
304+
305+ rhosts = {
306+ '172.10.0.2' : {
307+ 'facility' : {'all' : {'level' : 'debug' }},
308+ 'port' : '6514' ,
309+ 'protocol' : 'udp' ,
310+ 'tls' : {
311+ 'enable' : True ,
312+ 'auth-mode' : 'anon' ,
313+ },
314+ },
315+ '172.10.0.3' : {
316+ 'facility' : {'all' : {'level' : 'debug' }},
317+ 'port' : '6514' ,
318+ 'protocol' : 'tcp' ,
319+ 'tls' : {
320+ 'enable' : True ,
321+ 'ca-certificate' : ca_cert_name ,
322+ 'auth-mode' : 'certvalid' ,
323+ },
324+ },
325+ '172.10.0.4' : {
326+ 'facility' : {'all' : {'level' : 'debug' }},
327+ 'port' : '6514' ,
328+ 'protocol' : 'tcp' ,
329+ 'tls' : {
330+ 'enable' : True ,
331+ 'ca-certificate' : ca_cert_name ,
332+ 'certificate' : client_cert_name ,
333+ 'auth-mode' : 'fingerprint' ,
334+ 'permitted-peers' : 'SHA1:E1:DB:C4:FF:83:54:85:40:2D:56:E7:1A:C3:FF:70:22:0F:21:74:ED' ,
335+ },
336+ },
337+ '172.10.0.5' : {
338+ 'facility' : {'all' : {'level' : 'debug' }},
339+ 'port' : '6514' ,
340+ 'protocol' : 'tcp' ,
341+ 'tls' : {
342+ 'enable' : True ,
343+ 'ca-certificate' : ca_cert_name ,
344+ 'certificate' : client_cert_name ,
345+ 'auth-mode' : 'name' ,
346+ 'permitted-peers' : 'logs.example.com' ,
347+ },
348+ },
349+ }
350+
351+ for remote , remote_options in rhosts .items ():
352+ remote_base = base_path + ['remote' , remote ]
353+
354+ if 'port' in remote_options :
355+ self .cli_set (remote_base + ['port' ], value = remote_options ['port' ])
356+
357+ if 'facility' in remote_options :
358+ for facility , facility_options in remote_options ['facility' ].items ():
359+ level = facility_options ['level' ]
360+ self .cli_set (
361+ remote_base + ['facility' , facility , 'level' ], value = level
362+ )
363+
364+ if 'protocol' in remote_options :
365+ protocol = remote_options ['protocol' ]
366+ self .cli_set (remote_base + ['protocol' ], value = protocol )
367+
368+ tls = remote_options ['tls' ]
369+ for key , value in tls .items ():
370+ if key == 'enable' :
371+ self .cli_set (remote_base + ['tls' , 'enable' ])
372+ else :
373+ self .cli_set (remote_base + ['tls' , key ], value = value )
374+
375+ self .cli_commit ()
376+
377+ read_file (RSYSLOG_CONF )
378+ for remote , remote_options in rhosts .items ():
379+ with self .subTest (remote = remote ):
380+ config = get_config (f'# Remote syslog to { remote } ' )
381+
382+ if 'port' in remote_options :
383+ port = remote_options ['port' ]
384+ self .assertIn (f'port="{ port } "' , config )
385+
386+ self .assertIn ('protocol="tcp"' , config )
387+ self .assertIn ('StreamDriver="ossl"' , config )
388+ self .assertIn ('StreamDriverMode="1"' , config )
389+
390+ tls = remote_options ['tls' ]
391+ if 'ca-certificate' in tls :
392+ self .assertIn (
393+ f'StreamDriver.CAFile="{ CERT_DIR } /{ ca_cert_name } .pem"' , config
394+ )
395+
396+ if 'certificate' in tls :
397+ self .assertIn (
398+ f'StreamDriver.CertFile="{ CERT_DIR } /{ client_cert_name } .pem"' ,
399+ config ,
400+ )
401+ self .assertIn (
402+ f'StreamDriver.KeyFile="{ CERT_DIR } /{ client_cert_name } .key"' ,
403+ config ,
404+ )
405+
406+ if 'auth-mode' in tls :
407+ value = tls ['auth-mode' ]
408+ auth_mode = value if value == 'anon' else f'x509/{ value } '
409+ self .assertIn (f'StreamDriverAuthMode="{ auth_mode } "' , config )
410+
411+ if 'permitted-peers' in tls :
412+ value = tls ['permitted-peers' ]
413+ self .assertIn (f'StreamDriverPermittedPeers="{ value } "' , config )
414+
242415 def test_vrf_source_address (self ):
243416 rhosts = {
244417 '169.254.0.10' : { },
0 commit comments