logstash-output-syslog 2.1.0 → 2.1.1
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 +4 -0
- data/lib/logstash/outputs/syslog.rb +113 -16
- data/logstash-output-syslog.gemspec +3 -2
- data/spec/outputs/syslog_spec.rb +77 -0
- metadata +22 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aee984517a11e5ef3e6940d6a34a4ee6cac6c9fc
|
4
|
+
data.tar.gz: 81de265a5c4f28c56273e9c837e5383a906d91d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eae8c4f8b72bd7ec9891d430fea8573f1b39f80052770cbd8679f8ade14cac266f3ad8ae4a5a7f73c2a8eded295873be893981408a1c270ec7a6a374c7a4208d
|
7
|
+
data.tar.gz: f9df3603f5f561a86f7078998dd4bf075116ff014ed92f1db3dcbe72d43c2ad760763279b08caef440185157fecafa65341c983057b8542b694a6eb1fc9bda4d
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require "logstash/outputs/base"
|
3
3
|
require "logstash/namespace"
|
4
4
|
require "date"
|
5
|
+
require "logstash/codecs/plain"
|
5
6
|
|
6
7
|
|
7
8
|
# Send events to a syslog server.
|
@@ -28,12 +29,10 @@ class LogStash::Outputs::Syslog < LogStash::Outputs::Base
|
|
28
29
|
"network news",
|
29
30
|
"uucp",
|
30
31
|
"clock",
|
31
|
-
"security/authorization",
|
32
32
|
"ftp",
|
33
33
|
"ntp",
|
34
34
|
"log audit",
|
35
35
|
"log alert",
|
36
|
-
"clock",
|
37
36
|
"local0",
|
38
37
|
"local1",
|
39
38
|
"local2",
|
@@ -64,31 +63,66 @@ class LogStash::Outputs::Syslog < LogStash::Outputs::Base
|
|
64
63
|
# when connection fails, retry interval in sec.
|
65
64
|
config :reconnect_interval, :validate => :number, :default => 1
|
66
65
|
|
67
|
-
# syslog server protocol. you can choose between udp and tcp
|
68
|
-
config :protocol, :validate => ["tcp", "udp"], :default => "udp"
|
66
|
+
# syslog server protocol. you can choose between udp, tcp and ssl/tls over tcp
|
67
|
+
config :protocol, :validate => ["tcp", "udp", "ssl-tcp"], :default => "udp"
|
68
|
+
|
69
|
+
# Verify the identity of the other end of the SSL connection against the CA.
|
70
|
+
config :ssl_verify, :validate => :boolean, :default => false
|
71
|
+
|
72
|
+
# The SSL CA certificate, chainfile or CA path. The system CA path is automatically included.
|
73
|
+
config :ssl_cacert, :validate => :path
|
74
|
+
|
75
|
+
# SSL certificate path
|
76
|
+
config :ssl_cert, :validate => :path
|
77
|
+
|
78
|
+
# SSL key path
|
79
|
+
config :ssl_key, :validate => :path
|
80
|
+
|
81
|
+
# SSL key passphrase
|
82
|
+
config :ssl_key_passphrase, :validate => :password, :default => nil
|
83
|
+
|
84
|
+
# use label parsing for severity and facility levels
|
85
|
+
# use priority field if set to false
|
86
|
+
config :use_labels, :validate => :boolean, :default => true
|
87
|
+
|
88
|
+
# syslog priority
|
89
|
+
# The new value can include `%{foo}` strings
|
90
|
+
# to help you build a new value from other parts of the event.
|
91
|
+
config :priority, :validate => :string, :default => "%{syslog_pri}"
|
69
92
|
|
70
93
|
# facility label for syslog message
|
71
|
-
|
94
|
+
# default fallback to user-level as in rfc3164
|
95
|
+
# The new value can include `%{foo}` strings
|
96
|
+
# to help you build a new value from other parts of the event.
|
97
|
+
config :facility, :validate => :string, :default => "user-level"
|
72
98
|
|
73
99
|
# severity label for syslog message
|
74
|
-
|
100
|
+
# default fallback to notice as in rfc3164
|
101
|
+
# The new value can include `%{foo}` strings
|
102
|
+
# to help you build a new value from other parts of the event.
|
103
|
+
config :severity, :validate => :string, :default => "notice"
|
75
104
|
|
76
|
-
# source host for syslog message
|
105
|
+
# source host for syslog message. The new value can include `%{foo}` strings
|
106
|
+
# to help you build a new value from other parts of the event.
|
77
107
|
config :sourcehost, :validate => :string, :default => "%{host}"
|
78
108
|
|
79
109
|
# timestamp for syslog message
|
80
110
|
config :timestamp, :validate => :string, :default => "%{@timestamp}", :deprecated => "This setting is no longer necessary. The RFC setting will determine what time format is used."
|
81
111
|
|
82
|
-
# application name for syslog message
|
112
|
+
# application name for syslog message. The new value can include `%{foo}` strings
|
113
|
+
# to help you build a new value from other parts of the event.
|
83
114
|
config :appname, :validate => :string, :default => "LOGSTASH"
|
84
115
|
|
85
|
-
# process id for syslog message
|
116
|
+
# process id for syslog message. The new value can include `%{foo}` strings
|
117
|
+
# to help you build a new value from other parts of the event.
|
86
118
|
config :procid, :validate => :string, :default => "-"
|
87
119
|
|
88
|
-
# message text to log
|
120
|
+
# message text to log. The new value can include `%{foo}` strings
|
121
|
+
# to help you build a new value from other parts of the event.
|
89
122
|
config :message, :validate => :string, :default => "%{message}"
|
90
123
|
|
91
|
-
# message id for syslog message
|
124
|
+
# message id for syslog message. The new value can include `%{foo}` strings
|
125
|
+
# to help you build a new value from other parts of the event.
|
92
126
|
config :msgid, :validate => :string, :default => "-"
|
93
127
|
|
94
128
|
# syslog message format: you can choose between rfc3164 or rfc5424
|
@@ -97,32 +131,59 @@ class LogStash::Outputs::Syslog < LogStash::Outputs::Base
|
|
97
131
|
def register
|
98
132
|
@client_socket = nil
|
99
133
|
|
100
|
-
|
101
|
-
|
102
|
-
|
134
|
+
if ssl?
|
135
|
+
@ssl_context = setup_ssl
|
136
|
+
end
|
137
|
+
|
138
|
+
if @codec.instance_of? LogStash::Codecs::Plain
|
139
|
+
if @codec.config["format"].nil?
|
140
|
+
@codec = LogStash::Codecs::Plain.new({"format" => @message})
|
141
|
+
end
|
142
|
+
end
|
143
|
+
@codec.on_event(&method(:publish))
|
103
144
|
|
104
145
|
# use instance variable to avoid string comparison for each event
|
105
146
|
@is_rfc3164 = (@rfc == "rfc3164")
|
106
147
|
end
|
107
148
|
|
108
149
|
def receive(event)
|
150
|
+
@codec.encode(event)
|
151
|
+
end
|
152
|
+
|
153
|
+
def publish(event, payload)
|
109
154
|
appname = event.sprintf(@appname)
|
110
155
|
procid = event.sprintf(@procid)
|
111
156
|
sourcehost = event.sprintf(@sourcehost)
|
112
157
|
|
158
|
+
message = payload.to_s.rstrip.gsub(/[\r][\n]/, "\n").gsub(/[\n]/, '\n')
|
159
|
+
|
160
|
+
# fallback to pri 13 (facility 1, severity 5)
|
161
|
+
if @use_labels
|
162
|
+
facility_code = (FACILITY_LABELS.index(event.sprintf(@facility)) || 1)
|
163
|
+
severity_code = (SEVERITY_LABELS.index(event.sprintf(@severity)) || 5)
|
164
|
+
priority = (facility_code * 8) + severity_code
|
165
|
+
else
|
166
|
+
priority = Integer(event.sprintf(@priority)) rescue 13
|
167
|
+
priority = 13 if (priority < 0 || priority > 191)
|
168
|
+
end
|
169
|
+
|
113
170
|
if @is_rfc3164
|
114
171
|
timestamp = event.sprintf("%{+MMM dd HH:mm:ss}")
|
115
|
-
syslog_msg = "<#{
|
172
|
+
syslog_msg = "<#{priority.to_s}>#{timestamp} #{sourcehost} #{appname}[#{procid}]: #{message}"
|
116
173
|
else
|
117
174
|
msgid = event.sprintf(@msgid)
|
118
175
|
timestamp = event.sprintf("%{+YYYY-MM-dd'T'HH:mm:ss.SSSZZ}")
|
119
|
-
syslog_msg = "<#{
|
176
|
+
syslog_msg = "<#{priority.to_s}>1 #{timestamp} #{sourcehost} #{appname} #{procid} #{msgid} - #{message}"
|
120
177
|
end
|
121
178
|
|
122
179
|
begin
|
123
180
|
@client_socket ||= connect
|
124
181
|
@client_socket.write(syslog_msg + "\n")
|
125
182
|
rescue => e
|
183
|
+
# We don't expect udp connections to fail because they are stateless, but ...
|
184
|
+
# udp connections may fail/raise an exception if used with localhost/127.0.0.1
|
185
|
+
return if udp?
|
186
|
+
|
126
187
|
@logger.warn("syslog " + @protocol + " output exception: closing, reconnecting and resending event", :host => @host, :port => @port, :exception => e, :backtrace => e.backtrace, :event => event)
|
127
188
|
@client_socket.close rescue nil
|
128
189
|
@client_socket = nil
|
@@ -138,6 +199,10 @@ class LogStash::Outputs::Syslog < LogStash::Outputs::Base
|
|
138
199
|
@protocol == "udp"
|
139
200
|
end
|
140
201
|
|
202
|
+
def ssl?
|
203
|
+
@protocol == "ssl-tcp"
|
204
|
+
end
|
205
|
+
|
141
206
|
def connect
|
142
207
|
socket = nil
|
143
208
|
if udp?
|
@@ -145,7 +210,39 @@ class LogStash::Outputs::Syslog < LogStash::Outputs::Base
|
|
145
210
|
socket.connect(@host, @port)
|
146
211
|
else
|
147
212
|
socket = TCPSocket.new(@host, @port)
|
213
|
+
if ssl?
|
214
|
+
socket = OpenSSL::SSL::SSLSocket.new(socket, @ssl_context)
|
215
|
+
begin
|
216
|
+
socket.connect
|
217
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
218
|
+
@logger.error("SSL Error", :exception => ssle,
|
219
|
+
:backtrace => ssle.backtrace)
|
220
|
+
# NOTE(mrichar1): Hack to prevent hammering peer
|
221
|
+
sleep(5)
|
222
|
+
raise
|
223
|
+
end
|
224
|
+
end
|
148
225
|
end
|
149
226
|
socket
|
150
227
|
end
|
228
|
+
|
229
|
+
def setup_ssl
|
230
|
+
require "openssl"
|
231
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
232
|
+
ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@ssl_cert))
|
233
|
+
ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@ssl_key),@ssl_key_passphrase)
|
234
|
+
if @ssl_verify
|
235
|
+
cert_store = OpenSSL::X509::Store.new
|
236
|
+
# Load the system default certificate path to the store
|
237
|
+
cert_store.set_default_paths
|
238
|
+
if File.directory?(@ssl_cacert)
|
239
|
+
cert_store.add_path(@ssl_cacert)
|
240
|
+
else
|
241
|
+
cert_store.add_file(@ssl_cacert)
|
242
|
+
end
|
243
|
+
ssl_context.cert_store = cert_store
|
244
|
+
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
245
|
+
end
|
246
|
+
ssl_context
|
247
|
+
end
|
151
248
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-output-syslog'
|
4
|
-
s.version = '2.1.
|
4
|
+
s.version = '2.1.1'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "Send events to a syslog server."
|
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/plugin install gemname. This gem is not a stand-alone program"
|
@@ -21,8 +21,9 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
# Gem dependencies
|
23
23
|
s.add_runtime_dependency "logstash-core", ">= 2.0.0.beta2", "< 3.0.0"
|
24
|
+
s.add_runtime_dependency 'logstash-codec-plain'
|
24
25
|
|
25
26
|
s.add_development_dependency 'logstash-devutils'
|
26
|
-
s.add_development_dependency 'logstash-codec-
|
27
|
+
s.add_development_dependency 'logstash-codec-json'
|
27
28
|
end
|
28
29
|
|
data/spec/outputs/syslog_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "logstash/devutils/rspec/spec_helper"
|
4
4
|
require "logstash/outputs/syslog"
|
5
|
+
require "logstash/codecs/plain"
|
5
6
|
|
6
7
|
describe LogStash::Outputs::Syslog do
|
7
8
|
|
@@ -47,4 +48,80 @@ describe LogStash::Outputs::Syslog do
|
|
47
48
|
|
48
49
|
it_behaves_like "syslog output"
|
49
50
|
end
|
51
|
+
|
52
|
+
context "sprintf rfc 3164" do
|
53
|
+
let(:event) { LogStash::Event.new({"message" => "bar", "host" => "baz", "facility" => "mail", "severity" => "critical", "appname" => "appname", "procid" => "1000" }) }
|
54
|
+
let(:options) { {"host" => "foo", "port" => "123", "facility" => "%{facility}", "severity" => "%{severity}", "appname" => "%{appname}", "procid" => "%{procid}"} }
|
55
|
+
let(:output) { /^<18>.+baz appname\[1000\]: bar\n/m }
|
56
|
+
|
57
|
+
it_behaves_like "syslog output"
|
58
|
+
end
|
59
|
+
|
60
|
+
context "sprintf rfc 5424" do
|
61
|
+
let(:event) { LogStash::Event.new({"message" => "bar", "host" => "baz", "facility" => "mail", "severity" => "critical", "appname" => "appname", "procid" => "1000", "msgid" => "2000" }) }
|
62
|
+
let(:options) { {"rfc" => "rfc5424", "host" => "foo", "port" => "123", "facility" => "%{facility}", "severity" => "%{severity}", "appname" => "%{appname}", "procid" => "%{procid}", "msgid" => "%{msgid}"} }
|
63
|
+
let(:output) { /^<18>1 .+baz appname 1000 2000 - bar\n/m }
|
64
|
+
|
65
|
+
it_behaves_like "syslog output"
|
66
|
+
end
|
67
|
+
|
68
|
+
context "use_labels == false, default" do
|
69
|
+
let(:event) { LogStash::Event.new({"message" => "bar", "host" => "baz" }) }
|
70
|
+
let(:options) { {"use_labels" => false, "host" => "foo", "port" => "123" } }
|
71
|
+
let(:output) { /^<13>.+baz LOGSTASH\[-\]: bar\n/m }
|
72
|
+
|
73
|
+
it_behaves_like "syslog output"
|
74
|
+
end
|
75
|
+
|
76
|
+
context "use_labels == false, syslog_pri" do
|
77
|
+
let(:event) { LogStash::Event.new({"message" => "bar", "host" => "baz", "syslog_pri" => "18" }) }
|
78
|
+
let(:options) { {"use_labels" => false, "host" => "foo", "port" => "123" } }
|
79
|
+
let(:output) { /^<18>.+baz LOGSTASH\[-\]: bar\n/m }
|
80
|
+
|
81
|
+
it_behaves_like "syslog output"
|
82
|
+
end
|
83
|
+
|
84
|
+
context "use_labels == false, sprintf" do
|
85
|
+
let(:event) { LogStash::Event.new({"message" => "bar", "host" => "baz", "priority" => "18" }) }
|
86
|
+
let(:options) { {"use_labels" => false, "host" => "foo", "port" => "123", "priority" => "%{priority}" } }
|
87
|
+
let(:output) { /^<18>.+baz LOGSTASH\[-\]: bar\n/m }
|
88
|
+
|
89
|
+
it_behaves_like "syslog output"
|
90
|
+
end
|
91
|
+
|
92
|
+
context "use plain codec with format set" do
|
93
|
+
let(:plain) { LogStash::Codecs::Plain.new({"format" => "%{host} %{message}"}) }
|
94
|
+
let(:options) { {"host" => "foo", "port" => "123", "facility" => "kernel", "severity" => "emergency", "codec" => plain} }
|
95
|
+
let(:output) { /^<0>.+baz LOGSTASH\[-\]: baz bar\n/m }
|
96
|
+
|
97
|
+
it_behaves_like "syslog output"
|
98
|
+
end
|
99
|
+
|
100
|
+
context "use codec json" do
|
101
|
+
let(:options) { {"host" => "foo", "port" => "123", "facility" => "kernel", "severity" => "emergency", "codec" => "json" } }
|
102
|
+
let(:output) { /^<0>.+baz LOGSTASH\[-\]: {\"message\":\"bar\",\"host\":\"baz\",\"@version\":\"1\",\"@timestamp\":\"[0-9TZ:.+-]+\"}\n/m }
|
103
|
+
|
104
|
+
it_behaves_like "syslog output"
|
105
|
+
end
|
106
|
+
|
107
|
+
context "escape carriage return, newline and newline to \\n" do
|
108
|
+
let(:options) { {"host" => "foo", "port" => "123", "facility" => "kernel", "severity" => "emergency", "message" => "foo\r\nbar\nbaz" } }
|
109
|
+
let(:output) { /^<0>.+baz LOGSTASH\[-\]: foo\\nbar\\nbaz\n/m }
|
110
|
+
|
111
|
+
it_behaves_like "syslog output"
|
112
|
+
end
|
113
|
+
|
114
|
+
context "tailing newline" do
|
115
|
+
let(:options) { {"host" => "foo", "port" => "123", "facility" => "kernel", "severity" => "emergency", "message" => "%{message}\n" } }
|
116
|
+
let(:output) { /^<0>.+baz LOGSTASH\[-\]: bar\n/m }
|
117
|
+
|
118
|
+
it_behaves_like "syslog output"
|
119
|
+
end
|
120
|
+
|
121
|
+
context "tailing carriage return and newline (windows)" do
|
122
|
+
let(:options) { {"host" => "foo", "port" => "123", "facility" => "kernel", "severity" => "emergency", "message" => "%{message}\n" } }
|
123
|
+
let(:output) { /^<0>.+baz LOGSTASH\[-\]: bar\n/m }
|
124
|
+
|
125
|
+
it_behaves_like "syslog output"
|
126
|
+
end
|
50
127
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-syslog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
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: 2016-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logstash-core
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
version: 3.0.0
|
31
31
|
prerelease: false
|
32
32
|
type: :runtime
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: logstash-codec-plain
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirement: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
prerelease: false
|
46
|
+
type: :runtime
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: logstash-devutils
|
35
49
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -45,7 +59,7 @@ dependencies:
|
|
45
59
|
prerelease: false
|
46
60
|
type: :development
|
47
61
|
- !ruby/object:Gem::Dependency
|
48
|
-
name: logstash-codec-
|
62
|
+
name: logstash-codec-json
|
49
63
|
version_requirements: !ruby/object:Gem::Requirement
|
50
64
|
requirements:
|
51
65
|
- - '>='
|
@@ -64,15 +78,15 @@ executables: []
|
|
64
78
|
extensions: []
|
65
79
|
extra_rdoc_files: []
|
66
80
|
files:
|
67
|
-
- lib/logstash/outputs/syslog.rb
|
68
|
-
- spec/outputs/syslog_spec.rb
|
69
|
-
- logstash-output-syslog.gemspec
|
70
81
|
- CHANGELOG.md
|
71
|
-
- README.md
|
72
82
|
- CONTRIBUTORS
|
73
83
|
- Gemfile
|
74
84
|
- LICENSE
|
75
85
|
- NOTICE.TXT
|
86
|
+
- README.md
|
87
|
+
- lib/logstash/outputs/syslog.rb
|
88
|
+
- logstash-output-syslog.gemspec
|
89
|
+
- spec/outputs/syslog_spec.rb
|
76
90
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
77
91
|
licenses:
|
78
92
|
- Apache License (2.0)
|
@@ -95,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
109
|
version: '0'
|
96
110
|
requirements: []
|
97
111
|
rubyforge_project:
|
98
|
-
rubygems_version: 2.
|
112
|
+
rubygems_version: 2.4.8
|
99
113
|
signing_key:
|
100
114
|
specification_version: 4
|
101
115
|
summary: Send events to a syslog server.
|