Add RFC5424 syslog protocol support (VPP-1139)
[vpp.git] / test / test_syslog.py
1 #!/usr/bin/env python
2
3 from framework import VppTestCase, VppTestRunner
4 from util import ppp
5 from scapy.packet import Raw
6 from scapy.layers.inet import IP, UDP
7 from vpp_papi_provider import SYSLOG_SEVERITY
8 from syslog_rfc5424_parser import SyslogMessage, ParseError
9 from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
10
11
12 class TestSyslog(VppTestCase):
13     """ Syslog Protocol Test Cases """
14
15     @classmethod
16     def setUpClass(cls):
17         super(TestSyslog, cls).setUpClass()
18
19         try:
20             cls.create_pg_interfaces(range(1))
21             cls.pg0.admin_up()
22             cls.pg0.config_ip4()
23             cls.pg0.resolve_arp()
24
25         except Exception:
26             super(TestSyslog, cls).tearDownClass()
27             raise
28
29     def syslog_generate(self, facility, severity, appname, msgid, sd=None,
30                         msg=None):
31         """
32         Generate syslog message
33
34         :param facility: facility value
35         :param severity: severity level
36         :param appname: application name that originate message
37         :param msgid: message indetifier
38         :param sd: structured data (optional)
39         :param msg: free-form message (optional)
40         """
41         facility_str = ['kernel', 'user-level', 'mail-system',
42                         'system-daemons', 'security-authorization', 'syslogd',
43                         'line-printer', 'network-news', 'uucp', 'clock-daemon',
44                         '', 'ftp-daemon', 'ntp-subsystem', 'log-audit',
45                         'log-alert', '', 'local0', 'local1', 'local2',
46                         'local3', 'local4', 'local5', 'local6', 'local7']
47
48         severity_str = ['emergency', 'alert', 'critical', 'error', 'warning',
49                         'notice', 'informational', 'debug']
50
51         cli_str = "test syslog %s %s %s %s" % (facility_str[facility],
52                                                severity_str[severity],
53                                                appname,
54                                                msgid)
55         if sd is not None:
56             for sd_id, sd_params in sd.items():
57                 cli_str += " sd-id %s" % (sd_id)
58                 for name, value in sd_params.items():
59                     cli_str += " sd-param %s %s" % (name, value)
60         if msg is not None:
61             cli_str += " %s" % (msg)
62         self.vapi.cli(cli_str)
63
64     def syslog_verify(self, data, facility, severity, appname, msgid, sd=None,
65                       msg=None):
66         """
67         Verify syslog message
68
69         :param data: syslog message
70         :param facility: facility value
71         :param severity: severity level
72         :param appname: application name that originate message
73         :param msgid: message indetifier
74         :param sd: structured data (optional)
75         :param msg: free-form message (optional)
76         """
77         message = data.decode('utf-8')
78         if sd is None:
79             sd = {}
80         try:
81             message = SyslogMessage.parse(message)
82             self.assertEqual(message.facility, facility)
83             self.assertEqual(message.severity, severity)
84             self.assertEqual(message.appname, appname)
85             self.assertEqual(message.msgid, msgid)
86             self.assertEqual(message.msg, msg)
87             self.assertEqual(message.sd, sd)
88             self.assertEqual(message.version, 1)
89             self.assertEqual(message.hostname, self.pg0.local_ip4)
90         except ParseError as e:
91             self.logger.error(e)
92
93     def test_syslog(self):
94         """ Syslog Protocol test """
95         self.vapi.syslog_set_sender(self.pg0.remote_ip4n, self.pg0.local_ip4n)
96         config = self.vapi.syslog_get_sender()
97         self.assertEqual(config.collector_address.address,
98                          self.pg0.remote_ip4n)
99         self.assertEqual(config.collector_port, 514)
100         self.assertEqual(config.src_address.address, self.pg0.local_ip4n)
101         self.assertEqual(config.vrf_id, 0)
102         self.assertEqual(config.max_msg_size, 480)
103
104         appname = 'test'
105         msgid = 'testMsg'
106         msg = 'this is message'
107         sd1 = {'exampleSDID@32473': {'iut': '3',
108                                      'eventSource': 'App',
109                                      'eventID': '1011'}}
110         sd2 = {'exampleSDID@32473': {'iut': '3',
111                                      'eventSource': 'App',
112                                      'eventID': '1011'},
113                'examplePriority@32473': {'class': 'high'}}
114
115         self.pg_enable_capture(self.pg_interfaces)
116         self.syslog_generate(SyslogFacility.local7,
117                              SyslogSeverity.info,
118                              appname,
119                              msgid,
120                              None,
121                              msg)
122         capture = self.pg0.get_capture(1)
123         try:
124             self.assertEqual(capture[0][IP].src, self.pg0.local_ip4)
125             self.assertEqual(capture[0][IP].dst, self.pg0.remote_ip4)
126             self.assertEqual(capture[0][UDP].dport, 514)
127             self.assert_packet_checksums_valid(capture[0], False)
128         except:
129                 self.logger.error(ppp("invalid packet:", capture[0]))
130                 raise
131         self.syslog_verify(capture[0][Raw].load,
132                            SyslogFacility.local7,
133                            SyslogSeverity.info,
134                            appname,
135                            msgid,
136                            None,
137                            msg)
138
139         self.pg_enable_capture(self.pg_interfaces)
140         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.WARN)
141         filter = self.vapi.syslog_get_filter()
142         self.assertEqual(filter.severity, SYSLOG_SEVERITY.WARN)
143         self.syslog_generate(SyslogFacility.local7,
144                              SyslogSeverity.info,
145                              appname,
146                              msgid,
147                              None,
148                              msg)
149         self.pg0.assert_nothing_captured()
150
151         self.pg_enable_capture(self.pg_interfaces)
152         self.syslog_generate(SyslogFacility.local6,
153                              SyslogSeverity.warning,
154                              appname,
155                              msgid,
156                              sd1,
157                              msg)
158         capture = self.pg0.get_capture(1)
159         self.syslog_verify(capture[0][Raw].load,
160                            SyslogFacility.local6,
161                            SyslogSeverity.warning,
162                            appname,
163                            msgid,
164                            sd1,
165                            msg)
166
167         self.vapi.syslog_set_sender(self.pg0.remote_ip4n,
168                                     self.pg0.local_ip4n,
169                                     collector_port=12345)
170         config = self.vapi.syslog_get_sender()
171         self.assertEqual(config.collector_port, 12345)
172
173         self.pg_enable_capture(self.pg_interfaces)
174         self.syslog_generate(SyslogFacility.local5,
175                              SyslogSeverity.err,
176                              appname,
177                              msgid,
178                              sd2,
179                              None)
180         capture = self.pg0.get_capture(1)
181         try:
182             self.assertEqual(capture[0][UDP].dport, 12345)
183         except:
184                 self.logger.error(ppp("invalid packet:", capture[0]))
185                 raise
186         self.syslog_verify(capture[0][Raw].load,
187                            SyslogFacility.local5,
188                            SyslogSeverity.err,
189                            appname,
190                            msgid,
191                            sd2,
192                            None)
193
194
195 if __name__ == '__main__':
196     unittest.main(testRunner=VppTestRunner)