logstash-input-syslog 3.4.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/LICENSE +199 -10
- data/README.md +1 -1
- data/docs/index.asciidoc +34 -5
- data/lib/logstash/inputs/syslog.rb +126 -77
- data/logstash-input-syslog.gemspec +3 -3
- data/spec/inputs/syslog_spec.rb +197 -96
- metadata +11 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6f54c37d7c50508f001a49df641a45df74cf61cf4c4a4fcebafef442e380df68
|
|
4
|
+
data.tar.gz: 8c269bbad63b3ee0b022e7e206fc0884ed213b38380b15bdda9ee421e7f8ebeb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c886952d2095e9cefddeaaebbefa8495b78732b74350a6579849dd22da8f85f3065a35b411ce8952cd2cb12a80d49468cb44eeabfac4d93d8610663f7536366
|
|
7
|
+
data.tar.gz: a254785ecca431fc409bd2ebd031a14b2901295f2293913c6d7f92629327e8694e1ee2e13e7e04898cdc7c1939f29b1a6bb674e5dbc183b7c5c1487146d47284
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 3.5.0
|
|
2
|
+
- Feat: ECS compatibility support [#63](https://github.com/logstash-plugins/logstash-input-syslog/pull/63)
|
|
3
|
+
|
|
4
|
+
## 3.4.5
|
|
5
|
+
- Added support for listening on IPv6 addresses
|
|
6
|
+
|
|
7
|
+
## 3.4.4
|
|
8
|
+
- Refactor: avoid global side-effect + cleanup [#62](https://github.com/logstash-plugins/logstash-input-syslog/pull/62)
|
|
9
|
+
* avoid setting `BasicSocket.do_not_reverse_lookup` as it has side effects for others
|
|
10
|
+
|
|
11
|
+
## 3.4.3
|
|
12
|
+
- [DOC] Added expanded descriptions and requirements for facility_labels and severity_labels. [#52](https://github.com/logstash-plugins/logstash-input-syslog/pull/52)
|
|
13
|
+
|
|
14
|
+
## 3.4.2
|
|
15
|
+
- Remove (deprecated) dependency on thread_safe gem.
|
|
16
|
+
- CI: upgrade testing [#58](https://github.com/logstash-plugins/logstash-input-syslog/pull/58)
|
|
17
|
+
- [DOC] Correct example for `timezone` option [#53](https://github.com/logstash-plugins/logstash-input-syslog/pull/53)
|
|
18
|
+
|
|
1
19
|
## 3.4.1
|
|
2
20
|
- Docs: Set the default_codec doc attribute.
|
|
3
21
|
|
data/LICENSE
CHANGED
|
@@ -1,13 +1,202 @@
|
|
|
1
|
-
Copyright (c) 2012-2018 Elasticsearch <http://www.elastic.co>
|
|
2
1
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright 2020 Elastic and contributors
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Logstash Plugin
|
|
2
2
|
|
|
3
|
-
[](https://travis-ci.com/logstash-plugins/logstash-input-syslog)
|
|
4
4
|
|
|
5
5
|
This is a plugin for [Logstash](https://github.com/elastic/logstash).
|
|
6
6
|
|
data/docs/index.asciidoc
CHANGED
|
@@ -47,6 +47,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
|
|
|
47
47
|
[cols="<,<,<",options="header",]
|
|
48
48
|
|=======================================================================
|
|
49
49
|
|Setting |Input type|Required
|
|
50
|
+
| <<plugins-{type}s-{plugin}-ecs_compatibility>> | <<string,string>>|No
|
|
50
51
|
| <<plugins-{type}s-{plugin}-facility_labels>> |<<array,array>>|No
|
|
51
52
|
| <<plugins-{type}s-{plugin}-grok_pattern>> |<<string,string>>|No
|
|
52
53
|
| <<plugins-{type}s-{plugin}-host>> |<<string,string>>|No
|
|
@@ -64,19 +65,43 @@ input plugins.
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
|
|
68
|
+
[id="plugins-{type}s-{plugin}-ecs_compatibility"]
|
|
69
|
+
===== `ecs_compatibility`
|
|
70
|
+
|
|
71
|
+
* Value type is <<string,string>>
|
|
72
|
+
* Supported values are:
|
|
73
|
+
** `disabled`: does not use ECS-compatible field names (for example, `priority` for syslog priority)
|
|
74
|
+
** `v1`: uses fields that are compatible with Elastic Common Schema (for example, `[log][syslog][priority]`)
|
|
75
|
+
* Default value depends on which version of Logstash is running:
|
|
76
|
+
** When Logstash provides a `pipeline.ecs_compatibility` setting, its value is used as the default
|
|
77
|
+
** Otherwise, the default value is `disabled`.
|
|
78
|
+
|
|
79
|
+
Controls this plugin's compatibility with the
|
|
80
|
+
{ecs-ref}[Elastic Common Schema (ECS)].
|
|
81
|
+
|
|
67
82
|
[id="plugins-{type}s-{plugin}-facility_labels"]
|
|
68
83
|
===== `facility_labels`
|
|
69
84
|
|
|
70
85
|
* Value type is <<array,array>>
|
|
71
86
|
* Default value is `["kernel", "user-level", "mail", "system", "security/authorization", "syslogd", "line printer", "network news", "UUCP", "clock", "security/authorization", "FTP", "NTP", "log audit", "log alert", "clock", "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"]`
|
|
72
87
|
|
|
73
|
-
Labels for facility levels
|
|
88
|
+
Labels for facility levels defined in RFC3164.
|
|
89
|
+
|
|
90
|
+
You can use this option to override the integer->label mapping for syslog inputs
|
|
91
|
+
that behave differently than the RFCs.
|
|
92
|
+
|
|
93
|
+
Provide a zero-indexed array with all of your facility labels _in order_.
|
|
94
|
+
If a log message contains a facility number with no corresponding entry,
|
|
95
|
+
the facility_label is not added to the event.
|
|
74
96
|
|
|
75
97
|
[id="plugins-{type}s-{plugin}-grok_pattern"]
|
|
76
98
|
===== `grok_pattern`
|
|
77
99
|
|
|
78
100
|
* Value type is <<string,string>>
|
|
79
101
|
* Default value is `"<%{POSINT:priority}>%{SYSLOGLINE}"`
|
|
102
|
+
* Default value depends on whether <<plugins-{type}s-{plugin}-ecs_compatibility>> is enabled:
|
|
103
|
+
** ECS Compatibility disabled: `"<%{POSINT:priority}>%{SYSLOGLINE}"`
|
|
104
|
+
** ECS Compatibility enabled: `"<%{POSINT:[log][syslog][priority]:int}>%{SYSLOGLINE}"`
|
|
80
105
|
|
|
81
106
|
The default value should read and properly parse syslog lines which are
|
|
82
107
|
fully compliant with http://www.ietf.org/rfc/rfc3164.txt[RFC3164].
|
|
@@ -136,7 +161,11 @@ http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
|
|
|
136
161
|
* Value type is <<array,array>>
|
|
137
162
|
* Default value is `["Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Informational", "Debug"]`
|
|
138
163
|
|
|
139
|
-
Labels for severity levels
|
|
164
|
+
Labels for severity levels defined in RFC3164.
|
|
165
|
+
|
|
166
|
+
Provide a zero-indexed array with all of your severity labels _in order_.
|
|
167
|
+
If a log message contains a severity label with no corresponding entry,
|
|
168
|
+
the severity_label is not added to the event.
|
|
140
169
|
|
|
141
170
|
[id="plugins-{type}s-{plugin}-syslog_field"]
|
|
142
171
|
===== `syslog_field`
|
|
@@ -172,8 +201,8 @@ The valid IDs are listed on the [Joda.org available time zones page](http://joda
|
|
|
172
201
|
This is useful in case the time zone cannot be extracted from the value,
|
|
173
202
|
and is not the platform default.
|
|
174
203
|
If this is not specified the platform default will be used.
|
|
175
|
-
Canonical ID is good as it takes care of daylight saving time for you
|
|
176
|
-
For example, `America/Los_Angeles` or `Europe/
|
|
204
|
+
Canonical ID is good as it takes care of daylight saving time for you.
|
|
205
|
+
For example, `America/Los_Angeles` or `Europe/Paris` are valid IDs.
|
|
177
206
|
|
|
178
207
|
[id="plugins-{type}s-{plugin}-use_labels"]
|
|
179
208
|
===== `use_labels`
|
|
@@ -188,4 +217,4 @@ Use label parsing for severity and facility levels.
|
|
|
188
217
|
[id="plugins-{type}s-{plugin}-common-options"]
|
|
189
218
|
include::{include_path}/{type}.asciidoc[]
|
|
190
219
|
|
|
191
|
-
:default_codec!:
|
|
220
|
+
:default_codec!:
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
require "date"
|
|
3
3
|
require "socket"
|
|
4
|
-
require "concurrent"
|
|
4
|
+
require "concurrent/array"
|
|
5
5
|
require "logstash/filters/grok"
|
|
6
6
|
require "logstash/filters/date"
|
|
7
7
|
require "logstash/inputs/base"
|
|
8
8
|
require "logstash/namespace"
|
|
9
|
+
require 'logstash/plugin_mixins/ecs_compatibility_support'
|
|
9
10
|
require "stud/interval"
|
|
10
11
|
|
|
11
12
|
# Read syslog messages as events over the network.
|
|
@@ -25,6 +26,8 @@ require "stud/interval"
|
|
|
25
26
|
# Note: This input will start listeners on both TCP and UDP.
|
|
26
27
|
#
|
|
27
28
|
class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
29
|
+
include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1)
|
|
30
|
+
|
|
28
31
|
config_name "syslog"
|
|
29
32
|
|
|
30
33
|
default :codec, "plain"
|
|
@@ -42,7 +45,7 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
42
45
|
|
|
43
46
|
# Set custom grok pattern to parse the syslog, in case the format differs
|
|
44
47
|
# from the defined standard. This is common in security and other appliances
|
|
45
|
-
config :grok_pattern, :validate => :string
|
|
48
|
+
config :grok_pattern, :validate => :string
|
|
46
49
|
|
|
47
50
|
# Proxy protocol support, only v1 is supported at this time
|
|
48
51
|
# http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
|
|
@@ -59,8 +62,7 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
59
62
|
|
|
60
63
|
# Specify a time zone canonical ID to be used for date parsing.
|
|
61
64
|
# The valid IDs are listed on the [Joda.org available time zones page](http://joda-time.sourceforge.net/timezones.html).
|
|
62
|
-
# This is useful in case the time zone cannot be extracted from the value,
|
|
63
|
-
# and is not the platform default.
|
|
65
|
+
# This is useful in case the time zone cannot be extracted from the value, and is not the platform default.
|
|
64
66
|
# If this is not specified the platform default will be used.
|
|
65
67
|
# Canonical ID is good as it takes care of daylight saving time for you
|
|
66
68
|
# For example, `America/Los_Angeles` or `Europe/France` are valid IDs.
|
|
@@ -75,36 +77,76 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
75
77
|
#
|
|
76
78
|
config :locale, :validate => :string
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
# ECS only option to configure [service][type] value in produced events.
|
|
81
|
+
#
|
|
82
|
+
# NOTE: for now, purposefully un-documented as there are other [service] fields we could support,
|
|
83
|
+
# assuming users would want that (they have specific use-case for LS as syslog server).
|
|
84
|
+
config :service_type, :validate => :string, :default => 'system'
|
|
85
|
+
|
|
86
|
+
def initialize(*params)
|
|
80
87
|
super
|
|
81
|
-
BasicSocket.do_not_reverse_lookup = true
|
|
82
|
-
end # def initialize
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@
|
|
87
|
-
|
|
89
|
+
@priority_key = ecs_select[disabled:'priority', v1:'[log][syslog][priority]']
|
|
90
|
+
@facility_key = ecs_select[disabled:'facility', v1:'[log][syslog][facility][code]']
|
|
91
|
+
@severity_key = ecs_select[disabled:'severity', v1:'[log][syslog][severity][code]']
|
|
92
|
+
|
|
93
|
+
@facility_label_key = ecs_select[disabled:'facility_label', v1:'[log][syslog][facility][name]']
|
|
94
|
+
@severity_label_key = ecs_select[disabled:'severity_label', v1:'[log][syslog][severity][name]']
|
|
95
|
+
|
|
96
|
+
@host_key = ecs_select[disabled:'host', v1:'[host][ip]']
|
|
97
|
+
|
|
98
|
+
@grok_pattern ||= ecs_select[
|
|
99
|
+
disabled:"<%{POSINT:#{@priority_key}}>%{SYSLOGLINE}",
|
|
100
|
+
v1:"<%{POSINT:#{@priority_key}:int}>%{SYSLOGLINE}"
|
|
101
|
+
]
|
|
102
|
+
|
|
88
103
|
@grok_filter = LogStash::Filters::Grok.new(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
"overwrite" => @syslog_field,
|
|
105
|
+
"match" => { @syslog_field => @grok_pattern },
|
|
106
|
+
"tag_on_failure" => ["_grokparsefailure_sysloginput"],
|
|
107
|
+
"ecs_compatibility" => ecs_compatibility # use ecs-compliant patterns
|
|
92
108
|
)
|
|
93
109
|
|
|
110
|
+
@grok_filter_exec = ecs_select[
|
|
111
|
+
disabled: -> (event) { @grok_filter.filter(event) },
|
|
112
|
+
v1: -> (event) {
|
|
113
|
+
event.set('[event][original]', event.get(@syslog_field))
|
|
114
|
+
@grok_filter.filter(event)
|
|
115
|
+
set_service_fields(event)
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
|
|
94
119
|
@date_filter = LogStash::Filters::Date.new(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
120
|
+
"match" => [ "timestamp", "MMM dd HH:mm:ss", "MMM d HH:mm:ss", "MMM d HH:mm:ss", "ISO8601"],
|
|
121
|
+
"locale" => @locale,
|
|
122
|
+
"timezone" => @timezone,
|
|
98
123
|
)
|
|
99
124
|
|
|
125
|
+
@date_filter_exec = ecs_select[
|
|
126
|
+
disabled: -> (event) {
|
|
127
|
+
# in legacy (non-ecs) mode we used to match (SYSLOGBASE2) timestamp into two fields
|
|
128
|
+
event.set("timestamp", event.get("timestamp8601")) if event.include?("timestamp8601")
|
|
129
|
+
@date_filter.filter(event)
|
|
130
|
+
},
|
|
131
|
+
v1: -> (event) {
|
|
132
|
+
@date_filter.filter(event)
|
|
133
|
+
event.remove('timestamp')
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def register
|
|
139
|
+
@metric_errors = metric.namespace(:errors)
|
|
140
|
+
|
|
100
141
|
@grok_filter.register
|
|
101
142
|
@date_filter.register
|
|
102
143
|
|
|
103
|
-
@tcp_sockets =
|
|
144
|
+
@tcp_sockets = Concurrent::Array.new
|
|
104
145
|
@tcp = @udp = nil
|
|
105
146
|
end # def register
|
|
106
147
|
|
|
107
|
-
|
|
148
|
+
private
|
|
149
|
+
|
|
108
150
|
def run(output_queue)
|
|
109
151
|
udp_thr = Thread.new(output_queue) do |output_queue|
|
|
110
152
|
server(:udp, output_queue)
|
|
@@ -119,8 +161,8 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
119
161
|
udp_thr.join
|
|
120
162
|
tcp_thr.join
|
|
121
163
|
end # def run
|
|
164
|
+
public :run
|
|
122
165
|
|
|
123
|
-
private
|
|
124
166
|
# server call the specified protocol listener and basically restarts on
|
|
125
167
|
# any listener uncatched exception
|
|
126
168
|
#
|
|
@@ -137,7 +179,6 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
137
179
|
end
|
|
138
180
|
end
|
|
139
181
|
|
|
140
|
-
private
|
|
141
182
|
# udp_listener creates the udp socket and continously read from it.
|
|
142
183
|
# upon exception the socket will be closed and the exception bubbled
|
|
143
184
|
# in the server which will restart the listener
|
|
@@ -145,7 +186,8 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
145
186
|
@logger.info("Starting syslog udp listener", :address => "#{@host}:#{@port}")
|
|
146
187
|
|
|
147
188
|
@udp.close if @udp
|
|
148
|
-
@udp = UDPSocket.new(Socket::AF_INET
|
|
189
|
+
@udp = UDPSocket.new (IPAddr.new(@host).ipv6? rescue nil) ? Socket::AF_INET6 : Socket::AF_INET
|
|
190
|
+
@udp.do_not_reverse_lookup = true
|
|
149
191
|
@udp.bind(@host, @port)
|
|
150
192
|
|
|
151
193
|
while !stop?
|
|
@@ -157,7 +199,6 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
157
199
|
close_udp
|
|
158
200
|
end # def udp_listener
|
|
159
201
|
|
|
160
|
-
private
|
|
161
202
|
# tcp_listener accepts tcp connections and creates a new tcp_receiver thread
|
|
162
203
|
# for each accepted socket.
|
|
163
204
|
# upon exception all tcp sockets will be closed and the exception bubbled
|
|
@@ -165,6 +206,7 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
165
206
|
def tcp_listener(output_queue)
|
|
166
207
|
@logger.info("Starting syslog tcp listener", :address => "#{@host}:#{@port}")
|
|
167
208
|
@tcp = TCPServer.new(@host, @port)
|
|
209
|
+
@tcp.do_not_reverse_lookup = true
|
|
168
210
|
|
|
169
211
|
while !stop?
|
|
170
212
|
socket = @tcp.accept
|
|
@@ -182,11 +224,14 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
182
224
|
# tcp_receiver is executed in a thread, any uncatched exception will be bubbled up to the
|
|
183
225
|
# tcp server thread and all tcp connections will be closed and the listener restarted.
|
|
184
226
|
def tcp_receiver(output_queue, socket)
|
|
185
|
-
|
|
186
|
-
|
|
227
|
+
peer_addr = socket.peeraddr
|
|
228
|
+
ip, port = peer_addr[3], peer_addr[1]
|
|
229
|
+
|
|
187
230
|
@logger.info("new connection", :client => "#{ip}:#{port}")
|
|
188
231
|
LogStash::Util::set_thread_name("input|syslog|tcp|#{ip}:#{port}}")
|
|
189
232
|
|
|
233
|
+
first_read = true
|
|
234
|
+
|
|
190
235
|
socket.each do |line|
|
|
191
236
|
metric.increment(:messages_received)
|
|
192
237
|
if @proxy_protocol && first_read
|
|
@@ -194,10 +239,10 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
194
239
|
pp_info = line.split(/\s/)
|
|
195
240
|
# PROXY proto clientip proxyip clientport proxyport
|
|
196
241
|
if pp_info[0] != "PROXY"
|
|
197
|
-
@logger.error("invalid proxy protocol header label", :
|
|
242
|
+
@logger.error("invalid proxy protocol header label", header: line)
|
|
198
243
|
raise IOError
|
|
199
244
|
else
|
|
200
|
-
|
|
245
|
+
@logger.debug("proxy protocol detected", header: line)
|
|
201
246
|
ip = pp_info[2]
|
|
202
247
|
port = pp_info[3]
|
|
203
248
|
next
|
|
@@ -211,49 +256,45 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
211
256
|
rescue Errno::EBADF
|
|
212
257
|
# swallow connection closed exceptions to avoid bubling up the tcp_listener & server
|
|
213
258
|
logger.info("connection closed", :client => "#{ip}:#{port}")
|
|
214
|
-
rescue IOError =>
|
|
259
|
+
rescue IOError => e
|
|
215
260
|
# swallow connection closed exceptions to avoid bubling up the tcp_listener & server
|
|
216
|
-
raise unless socket.closed? &&
|
|
217
|
-
logger.info("connection error:
|
|
261
|
+
raise(e) unless socket.closed? && e.message.to_s.include?("closed")
|
|
262
|
+
logger.info("connection error:", :exception => e.class, :message => e.message)
|
|
218
263
|
ensure
|
|
219
264
|
@tcp_sockets.delete(socket)
|
|
220
|
-
socket.close rescue log_and_squash
|
|
265
|
+
socket.close rescue log_and_squash(:close_tcp_receiver_socket)
|
|
221
266
|
end
|
|
222
267
|
|
|
223
|
-
|
|
224
|
-
def decode(host, output_queue, data)
|
|
268
|
+
def decode(ip, output_queue, data)
|
|
225
269
|
@codec.decode(data) do |event|
|
|
226
270
|
decorate(event)
|
|
227
|
-
event.set(
|
|
271
|
+
event.set(@host_key, ip)
|
|
228
272
|
syslog_relay(event)
|
|
229
273
|
output_queue << event
|
|
230
274
|
metric.increment(:events)
|
|
231
275
|
end
|
|
232
276
|
rescue => e
|
|
233
277
|
# swallow and log all decoding exceptions, these will never be socket related
|
|
234
|
-
@logger.error("Error decoding data", :data => data.inspect, :exception => e, :backtrace => e.backtrace)
|
|
278
|
+
@logger.error("Error decoding data", :data => data.inspect, :exception => e.class, :message => e.message, :backtrace => e.backtrace)
|
|
235
279
|
@metric_errors.increment(:decoding)
|
|
236
280
|
end
|
|
237
281
|
|
|
238
|
-
|
|
282
|
+
# @see LogStash::Plugin#close
|
|
239
283
|
def stop
|
|
240
284
|
close_udp
|
|
241
285
|
close_tcp
|
|
242
286
|
end
|
|
287
|
+
public :stop
|
|
243
288
|
|
|
244
|
-
private
|
|
245
289
|
def close_udp
|
|
246
290
|
if @udp
|
|
247
|
-
@udp.close_read rescue log_and_squash
|
|
248
|
-
@udp.close_write rescue log_and_squash
|
|
291
|
+
@udp.close_read rescue log_and_squash(:close_udp_read)
|
|
292
|
+
@udp.close_write rescue log_and_squash(:close_udp_write)
|
|
249
293
|
end
|
|
250
294
|
@udp = nil
|
|
251
295
|
end
|
|
252
296
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
# Helper for inline rescues, which logs the squashed exception at "TRACE" level
|
|
256
|
-
# and returns nil.
|
|
297
|
+
# Helper for inline rescues, which logs the exception at "DEBUG" level and returns nil.
|
|
257
298
|
#
|
|
258
299
|
# Instead of:
|
|
259
300
|
# ~~~ ruby
|
|
@@ -261,19 +302,19 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
261
302
|
# ~~~
|
|
262
303
|
# Do:
|
|
263
304
|
# ~~~ ruby
|
|
264
|
-
#. foo rescue log_and_squash
|
|
305
|
+
#. foo rescue log_and_squash(:foo)
|
|
265
306
|
# ~~~
|
|
266
|
-
def log_and_squash
|
|
267
|
-
$! && logger.
|
|
307
|
+
def log_and_squash(label)
|
|
308
|
+
$! && logger.debug("#{label} failed:", :exception => $!.class, :message => $!.message)
|
|
268
309
|
nil
|
|
269
310
|
end
|
|
270
311
|
|
|
271
312
|
def close_tcp
|
|
272
313
|
# If we somehow have this left open, close it.
|
|
273
314
|
@tcp_sockets.each do |socket|
|
|
274
|
-
socket.close rescue log_and_squash
|
|
315
|
+
socket.close rescue log_and_squash(:close_tcp_socket)
|
|
275
316
|
end
|
|
276
|
-
@tcp.close if @tcp rescue log_and_squash
|
|
317
|
+
@tcp.close if @tcp rescue log_and_squash(:close_tcp)
|
|
277
318
|
@tcp = nil
|
|
278
319
|
end
|
|
279
320
|
|
|
@@ -282,46 +323,54 @@ class LogStash::Inputs::Syslog < LogStash::Inputs::Base
|
|
|
282
323
|
# If the message cannot be recognized (see @grok_filter), we'll
|
|
283
324
|
# treat it like the whole event["message"] is correct and try to fill
|
|
284
325
|
# the missing pieces (host, priority, etc)
|
|
285
|
-
public
|
|
286
326
|
def syslog_relay(event)
|
|
287
|
-
@
|
|
327
|
+
@grok_filter_exec.(event)
|
|
288
328
|
|
|
289
329
|
if event.get("tags").nil? || !event.get("tags").include?(@grok_filter.tag_on_failure)
|
|
290
330
|
# Per RFC3164, priority = (facility * 8) + severity
|
|
291
331
|
# = (facility << 3) & (severity)
|
|
292
|
-
priority = event.get(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
event.set("facility", facility)
|
|
298
|
-
|
|
299
|
-
event.set("timestamp", event.get("timestamp8601")) if event.include?("timestamp8601")
|
|
300
|
-
@date_filter.filter(event)
|
|
332
|
+
priority = event.get(@priority_key).to_i rescue 13
|
|
333
|
+
set_priority event, priority
|
|
334
|
+
|
|
335
|
+
@date_filter_exec.(event)
|
|
336
|
+
|
|
301
337
|
else
|
|
302
|
-
@logger.debug? && @logger.debug("
|
|
338
|
+
@logger.debug? && @logger.debug("un-matched syslog message", :message => event.get("message"))
|
|
303
339
|
|
|
304
340
|
# RFC3164 says unknown messages get pri=13
|
|
305
|
-
|
|
306
|
-
event.set("priority", 13)
|
|
307
|
-
event.set("severity", 5) # 13 & 7 == 5
|
|
308
|
-
event.set("facility", 1) # 13 >> 3 == 1
|
|
341
|
+
set_priority event, 13
|
|
309
342
|
metric.increment(:unknown_messages)
|
|
310
343
|
end
|
|
311
344
|
|
|
312
|
-
# Apply severity and facility metadata if
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
345
|
+
# Apply severity and facility metadata if use_labels => true
|
|
346
|
+
set_labels(event) if @use_labels
|
|
347
|
+
end # def syslog_relay
|
|
348
|
+
public :syslog_relay
|
|
349
|
+
|
|
350
|
+
def set_priority(event, priority)
|
|
351
|
+
severity = priority & 7 # 7 is 111 (3 bits)
|
|
352
|
+
facility = priority >> 3
|
|
353
|
+
event.set(@priority_key, priority)
|
|
354
|
+
event.set(@severity_key, severity)
|
|
355
|
+
event.set(@facility_key, facility)
|
|
356
|
+
end
|
|
317
357
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
358
|
+
def set_labels(event)
|
|
359
|
+
facility_number = event.get(@facility_key)
|
|
360
|
+
severity_number = event.get(@severity_key)
|
|
321
361
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
362
|
+
facility_label = @facility_labels[facility_number]
|
|
363
|
+
event.set(@facility_label_key, facility_label) if facility_label
|
|
364
|
+
|
|
365
|
+
severity_label = @severity_labels[severity_number]
|
|
366
|
+
event.set(@severity_label_key, severity_label) if severity_label
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def set_service_fields(event)
|
|
370
|
+
service_type = @service_type
|
|
371
|
+
if service_type && !service_type.empty?
|
|
372
|
+
event.set('[service][type]', service_type) unless event.include?('[service][type]')
|
|
325
373
|
end
|
|
326
|
-
end
|
|
374
|
+
end
|
|
375
|
+
|
|
327
376
|
end # class LogStash::Inputs::Syslog
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
|
|
3
3
|
s.name = 'logstash-input-syslog'
|
|
4
|
-
s.version = '3.
|
|
4
|
+
s.version = '3.5.0'
|
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
|
6
6
|
s.summary = "Reads syslog messages as events"
|
|
7
7
|
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
|
@@ -21,13 +21,13 @@ Gem::Specification.new do |s|
|
|
|
21
21
|
|
|
22
22
|
# Gem dependencies
|
|
23
23
|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
|
24
|
+
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~> 1.1'
|
|
24
25
|
|
|
25
26
|
s.add_runtime_dependency 'concurrent-ruby'
|
|
26
|
-
s.add_runtime_dependency 'thread_safe'
|
|
27
27
|
s.add_runtime_dependency 'stud', '>= 0.0.22', '< 0.1.0'
|
|
28
28
|
|
|
29
29
|
s.add_runtime_dependency 'logstash-codec-plain'
|
|
30
|
-
s.add_runtime_dependency 'logstash-filter-grok'
|
|
30
|
+
s.add_runtime_dependency 'logstash-filter-grok', '>= 4.4.0'
|
|
31
31
|
s.add_runtime_dependency 'logstash-filter-date'
|
|
32
32
|
|
|
33
33
|
s.add_development_dependency 'logstash-devutils'
|
data/spec/inputs/syslog_spec.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
require "logstash/devutils/rspec/spec_helper"
|
|
3
|
+
require "logstash/devutils/rspec/shared_examples"
|
|
4
|
+
|
|
5
|
+
require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
|
|
3
6
|
|
|
4
7
|
# running the grok code outside a logstash package means
|
|
5
8
|
# LOGSTASH_HOME will not be defined, so let's set it here
|
|
@@ -31,6 +34,7 @@ describe LogStash::Inputs::Syslog do
|
|
|
31
34
|
SYSLOG_LINE = "<164>Oct 26 15:19:25 1.2.3.4 %ASA-4-106023: Deny udp src DRAC:10.1.2.3/43434 dst outside:192.168.0.1/53 by access-group \"acl_drac\" [0x0, 0x0]"
|
|
32
35
|
|
|
33
36
|
it "should properly handle priority, severity and facilities" do
|
|
37
|
+
skip_if_stack_known_issue
|
|
34
38
|
port = 5511
|
|
35
39
|
event_count = 10
|
|
36
40
|
conf = <<-CONFIG
|
|
@@ -52,15 +56,16 @@ describe LogStash::Inputs::Syslog do
|
|
|
52
56
|
event_count.times.collect { queue.pop }
|
|
53
57
|
end
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
expect( events.length ).to eql event_count
|
|
56
60
|
events.each do |event|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
expect( event.get("priority") ).to eql 164
|
|
62
|
+
expect( event.get("severity") ).to eql 4
|
|
63
|
+
expect( event.get("facility") ).to eql 20
|
|
60
64
|
end
|
|
61
65
|
end
|
|
62
66
|
|
|
63
67
|
it "should properly PROXY protocol v1" do
|
|
68
|
+
skip_if_stack_known_issue
|
|
64
69
|
port = 5511
|
|
65
70
|
event_count = 10
|
|
66
71
|
conf = <<-CONFIG
|
|
@@ -85,109 +90,199 @@ describe LogStash::Inputs::Syslog do
|
|
|
85
90
|
event_count.times.collect { queue.pop }
|
|
86
91
|
end
|
|
87
92
|
|
|
88
|
-
|
|
93
|
+
expect( events.length ).to eql event_count
|
|
89
94
|
events.each do |event|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
expect( event.get("priority") ).to eql 164
|
|
96
|
+
expect( event.get("severity") ).to eql 4
|
|
97
|
+
expect( event.get("facility") ).to eql 20
|
|
98
|
+
expect( event.get("host") ).to eql "1.2.3.4"
|
|
94
99
|
end
|
|
95
100
|
end
|
|
96
101
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
event_count = 10
|
|
100
|
-
conf = <<-CONFIG
|
|
101
|
-
input {
|
|
102
|
-
syslog {
|
|
103
|
-
type => "blah"
|
|
104
|
-
port => #{port}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
CONFIG
|
|
102
|
+
context 'tag', :ecs_compatibility_support do
|
|
103
|
+
ecs_compatibility_matrix(:disabled, :v1) do
|
|
108
104
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
event_count.times do |i|
|
|
112
|
-
socket.puts("message which causes the a grok parse failure")
|
|
105
|
+
before(:each) do
|
|
106
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
|
113
107
|
end
|
|
114
|
-
socket.close
|
|
115
108
|
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
it "should add unique tag when grok parsing fails with live syslog input" do
|
|
110
|
+
skip_if_stack_known_issue
|
|
111
|
+
port = 5511
|
|
112
|
+
event_count = 10
|
|
113
|
+
conf = <<-CONFIG
|
|
114
|
+
input {
|
|
115
|
+
syslog {
|
|
116
|
+
type => "blah"
|
|
117
|
+
port => #{port}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
CONFIG
|
|
121
|
+
|
|
122
|
+
events = input(conf) do |pipeline, queue|
|
|
123
|
+
socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
|
|
124
|
+
event_count.times do |i|
|
|
125
|
+
socket.puts("message which causes the a grok parse failure")
|
|
126
|
+
end
|
|
127
|
+
socket.close
|
|
128
|
+
|
|
129
|
+
event_count.times.collect { queue.pop }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
expect( events.length ).to eql event_count
|
|
133
|
+
event_count.times do |i|
|
|
134
|
+
expect( events[i].get("tags") ).to eql ["_grokparsefailure_sysloginput"]
|
|
135
|
+
end
|
|
136
|
+
end
|
|
118
137
|
|
|
119
|
-
insist { events.length } == event_count
|
|
120
|
-
event_count.times do |i|
|
|
121
|
-
insist { events[i].get("tags") } == ["_grokparsefailure_sysloginput"]
|
|
122
138
|
end
|
|
123
139
|
end
|
|
124
140
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
event_count = 10
|
|
141
|
+
context 'timestamp', :ecs_compatibility_support do
|
|
142
|
+
ecs_compatibility_matrix(:disabled, :v1) do
|
|
128
143
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
type => "blah"
|
|
133
|
-
port => #{port}
|
|
134
|
-
locale => "en"
|
|
135
|
-
timezone => "UTC"
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
CONFIG
|
|
144
|
+
before(:each) do
|
|
145
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
|
146
|
+
end
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
it "should properly handle locale and timezone" do
|
|
149
|
+
port = 5511
|
|
150
|
+
event_count = 10
|
|
151
|
+
|
|
152
|
+
conf = <<-CONFIG
|
|
153
|
+
input {
|
|
154
|
+
syslog {
|
|
155
|
+
type => "blah"
|
|
156
|
+
port => #{port}
|
|
157
|
+
locale => "en"
|
|
158
|
+
timezone => "UTC"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
CONFIG
|
|
162
|
+
|
|
163
|
+
events = input(conf) do |pipeline, queue|
|
|
164
|
+
socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
|
|
165
|
+
event_count.times do |i|
|
|
166
|
+
socket.puts(SYSLOG_LINE)
|
|
167
|
+
end
|
|
168
|
+
socket.close
|
|
169
|
+
|
|
170
|
+
event_count.times.collect { queue.pop }
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
expect( events.length ).to eql event_count
|
|
174
|
+
events.each do |event|
|
|
175
|
+
expect( event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T15:19:25.000Z"
|
|
176
|
+
end
|
|
144
177
|
end
|
|
145
|
-
socket.close
|
|
146
178
|
|
|
147
|
-
|
|
148
|
-
|
|
179
|
+
it "should properly handle no locale and no timezone" do
|
|
180
|
+
port = 5511
|
|
181
|
+
|
|
182
|
+
conf = <<-CONFIG
|
|
183
|
+
input {
|
|
184
|
+
syslog {
|
|
185
|
+
type => "blah"
|
|
186
|
+
port => #{port}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
CONFIG
|
|
190
|
+
|
|
191
|
+
event = input(conf) do |pipeline, queue|
|
|
192
|
+
socket = Stud.try(5.times) { TCPSocket.new("127.0.0.1", port) }
|
|
193
|
+
socket.puts(SYSLOG_LINE)
|
|
194
|
+
socket.close
|
|
195
|
+
|
|
196
|
+
queue.pop
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# chances platform timezone is not UTC so ignore the hours
|
|
200
|
+
expect( event.get("@timestamp").to_iso8601 ).to match /#{Time.now.year}-10-26T\d\d:19:25.000Z/
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it "should support non UTC timezone" do
|
|
204
|
+
input = LogStash::Inputs::Syslog.new({"timezone" => "-05:00"})
|
|
205
|
+
input.register
|
|
206
|
+
|
|
207
|
+
# event which is not syslog should have a new tag
|
|
208
|
+
|
|
209
|
+
syslog_event = LogStash::Event.new({ "message" => "<164>Oct 26 15:19:25 1.2.3.4 %ASA-4-106023: Deny udp src DRAC:10.1.2.3/43434" })
|
|
210
|
+
input.syslog_relay(syslog_event)
|
|
211
|
+
|
|
212
|
+
expect( syslog_event.get("@timestamp").to_iso8601 ).to eql "#{Time.now.year}-10-26T20:19:25.000Z"
|
|
213
|
+
|
|
214
|
+
input.close
|
|
215
|
+
end
|
|
149
216
|
|
|
150
|
-
insist { events.length } == event_count
|
|
151
|
-
events.each do |event|
|
|
152
|
-
insist { event.get("@timestamp").to_iso8601 } == "#{Time.now.year}-10-26T15:19:25.000Z"
|
|
153
217
|
end
|
|
154
218
|
end
|
|
155
219
|
|
|
156
|
-
|
|
157
|
-
port = 5511
|
|
220
|
+
context 'ECS behavior', :ecs_compatibility_support do
|
|
158
221
|
|
|
159
|
-
|
|
160
|
-
input {
|
|
161
|
-
syslog {
|
|
162
|
-
type => "blah"
|
|
163
|
-
port => #{port}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
CONFIG
|
|
222
|
+
ecs_compatibility_matrix(:v1) do
|
|
167
223
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
socket.close
|
|
224
|
+
before(:each) do
|
|
225
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
|
226
|
+
end
|
|
172
227
|
|
|
173
|
-
|
|
174
|
-
|
|
228
|
+
let(:event) do
|
|
229
|
+
LogStash::Event.new("message" => "<164>Oct 26 15:19:25 1.2.3.4 a sample message")
|
|
230
|
+
end
|
|
175
231
|
|
|
176
|
-
|
|
177
|
-
insist { event.get("@timestamp").to_iso8601 } =~ /#{Time.now.year}-10-26T\d\d:19:25.000Z/
|
|
178
|
-
end
|
|
232
|
+
subject { LogStash::Inputs::Syslog.new }
|
|
179
233
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
input.register
|
|
234
|
+
before { subject.register }
|
|
235
|
+
after { subject.close }
|
|
183
236
|
|
|
184
|
-
|
|
237
|
+
it "should not have a timestamp field" do
|
|
238
|
+
subject.syslog_relay(event)
|
|
185
239
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
insist { syslog_event.get("@timestamp").to_iso8601 } == "#{Time.now.year}-10-26T20:19:25.000Z"
|
|
240
|
+
expect( event.to_hash.keys ).to_not include 'timestamp'
|
|
241
|
+
end
|
|
189
242
|
|
|
190
|
-
|
|
243
|
+
it "overwrites message" do
|
|
244
|
+
subject.syslog_relay(event)
|
|
245
|
+
|
|
246
|
+
expect( event.get('message') ).to eql 'a sample message'
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it "keep original log message" do
|
|
250
|
+
subject.syslog_relay(event)
|
|
251
|
+
|
|
252
|
+
expect( event.get('[event][original]') ).to eql '<164>Oct 26 15:19:25 1.2.3.4 a sample message'
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "sets syslog priority and severity" do
|
|
256
|
+
subject.syslog_relay(event)
|
|
257
|
+
|
|
258
|
+
expect( event.get('log') ).to include 'syslog' => hash_including('priority' => 164)
|
|
259
|
+
expect( event.get('log') ).to include 'syslog' => hash_including('severity' => { 'code' => 4, 'name' => 'Warning' })
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "sets service type" do
|
|
263
|
+
subject.syslog_relay(event)
|
|
264
|
+
|
|
265
|
+
expect( event.get('service') ).to include 'type' => 'system'
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
let(:queue) { Queue.new }
|
|
269
|
+
|
|
270
|
+
let(:socket) do
|
|
271
|
+
server = double('tcp-server')
|
|
272
|
+
allow( server ).to receive(:each).and_yield "<133>Mar 11 08:44:43 precision kernel: [765135.424096] mce: CPU6: Package temperature/speed normal\n"
|
|
273
|
+
allow( server ).to receive(:close)
|
|
274
|
+
server
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "sets host IP" do
|
|
278
|
+
expect( socket ).to receive(:peeraddr).and_return(["AF_INET", 514, "192.168.0.10", "192.168.0.10"])
|
|
279
|
+
subject.send :tcp_receiver, queue, socket
|
|
280
|
+
|
|
281
|
+
expect( queue.size ).to eql 1
|
|
282
|
+
event = queue.pop
|
|
283
|
+
expect( event.get('host') ).to eql 'hostname' => 'precision', 'ip' => '192.168.0.10'
|
|
284
|
+
end
|
|
285
|
+
end
|
|
191
286
|
end
|
|
192
287
|
|
|
193
288
|
it "should add unique tag when grok parsing fails" do
|
|
@@ -197,13 +292,13 @@ describe LogStash::Inputs::Syslog do
|
|
|
197
292
|
# event which is not syslog should have a new tag
|
|
198
293
|
event = LogStash::Event.new({ "message" => "hello world, this is not syslog RFC3164" })
|
|
199
294
|
input.syslog_relay(event)
|
|
200
|
-
|
|
295
|
+
expect( event.get("tags") ).to eql ["_grokparsefailure_sysloginput"]
|
|
201
296
|
|
|
202
297
|
syslog_event = LogStash::Event.new({ "message" => "<164>Oct 26 15:19:25 1.2.3.4 %ASA-4-106023: Deny udp src DRAC:10.1.2.3/43434" })
|
|
203
298
|
input.syslog_relay(syslog_event)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
299
|
+
expect( syslog_event.get("priority") ).to eql 164
|
|
300
|
+
expect( syslog_event.get("severity") ).to eql 4
|
|
301
|
+
expect( syslog_event.get("tags") ).to be nil
|
|
207
302
|
|
|
208
303
|
input.close
|
|
209
304
|
end
|
|
@@ -240,13 +335,13 @@ describe LogStash::Inputs::Syslog do
|
|
|
240
335
|
event_count.times.collect { queue.pop }
|
|
241
336
|
end
|
|
242
337
|
|
|
243
|
-
|
|
338
|
+
expect( events.length ).to eql event_count
|
|
244
339
|
events.each do |event|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
340
|
+
expect( event.get("priority") ).to eql 164
|
|
341
|
+
expect( event.get("severity") ).to eql 4
|
|
342
|
+
expect( event.get("facility") ).to eql 20
|
|
343
|
+
expect( event.get("message") ).to eql "#{message_field}\n"
|
|
344
|
+
expect( event.get("timestamp") ).to eql timestamp
|
|
250
345
|
end
|
|
251
346
|
end
|
|
252
347
|
|
|
@@ -279,13 +374,19 @@ describe LogStash::Inputs::Syslog do
|
|
|
279
374
|
event_count.times.collect { queue.pop }
|
|
280
375
|
end
|
|
281
376
|
|
|
282
|
-
|
|
377
|
+
expect( events.length ).to eql event_count
|
|
283
378
|
events.each do |event|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
379
|
+
expect( event.get("priority") ).to eql 134
|
|
380
|
+
expect( event.get("severity") ).to eql 6
|
|
381
|
+
expect( event.get("facility") ).to eql 16
|
|
382
|
+
expect( event.get("message") ).to eql message_field
|
|
383
|
+
expect( event.get("timestamp") ).to eql timestamp
|
|
289
384
|
end
|
|
290
385
|
end
|
|
386
|
+
|
|
387
|
+
private
|
|
388
|
+
|
|
389
|
+
def skip_if_stack_known_issue
|
|
390
|
+
skip 'elastic/logstash#11196 known LS 7.5 issue' if ENV['ELASTIC_STACK_VERSION'] && JRUBY_VERSION.eql?('9.2.8.0')
|
|
391
|
+
end
|
|
291
392
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: logstash-input-syslog
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Elastic
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-03-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -33,24 +33,24 @@ dependencies:
|
|
|
33
33
|
- !ruby/object:Gem::Dependency
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
35
35
|
requirements:
|
|
36
|
-
- - "
|
|
36
|
+
- - "~>"
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: '
|
|
39
|
-
name:
|
|
38
|
+
version: '1.1'
|
|
39
|
+
name: logstash-mixin-ecs_compatibility_support
|
|
40
40
|
prerelease: false
|
|
41
41
|
type: :runtime
|
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
|
-
- - "
|
|
44
|
+
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
46
|
+
version: '1.1'
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
|
49
49
|
requirements:
|
|
50
50
|
- - ">="
|
|
51
51
|
- !ruby/object:Gem::Version
|
|
52
52
|
version: '0'
|
|
53
|
-
name:
|
|
53
|
+
name: concurrent-ruby
|
|
54
54
|
prerelease: false
|
|
55
55
|
type: :runtime
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -97,7 +97,7 @@ dependencies:
|
|
|
97
97
|
requirements:
|
|
98
98
|
- - ">="
|
|
99
99
|
- !ruby/object:Gem::Version
|
|
100
|
-
version:
|
|
100
|
+
version: 4.4.0
|
|
101
101
|
name: logstash-filter-grok
|
|
102
102
|
prerelease: false
|
|
103
103
|
type: :runtime
|
|
@@ -105,7 +105,7 @@ dependencies:
|
|
|
105
105
|
requirements:
|
|
106
106
|
- - ">="
|
|
107
107
|
- !ruby/object:Gem::Version
|
|
108
|
-
version:
|
|
108
|
+
version: 4.4.0
|
|
109
109
|
- !ruby/object:Gem::Dependency
|
|
110
110
|
requirement: !ruby/object:Gem::Requirement
|
|
111
111
|
requirements:
|
|
@@ -188,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
188
188
|
version: '0'
|
|
189
189
|
requirements: []
|
|
190
190
|
rubyforge_project:
|
|
191
|
-
rubygems_version: 2.6.
|
|
191
|
+
rubygems_version: 2.6.13
|
|
192
192
|
signing_key:
|
|
193
193
|
specification_version: 4
|
|
194
194
|
summary: Reads syslog messages as events
|