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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fed3005266aeadaa979f5943e57231766a852a1c
4
- data.tar.gz: e9b7625982c94a62f18e80d7819fb23681ed65a8
3
+ metadata.gz: aee984517a11e5ef3e6940d6a34a4ee6cac6c9fc
4
+ data.tar.gz: 81de265a5c4f28c56273e9c837e5383a906d91d5
5
5
  SHA512:
6
- metadata.gz: 876f0086824fb91936086645f1290f2864b450c301a9f5201512f8f3d75ed01d162cfe9ec203669a3578132b57a31b94729c18a33132d74f64ff624da8904880
7
- data.tar.gz: cf49d0c4b980c542333d4691d3fb57d0f531439a8649cffb661b917795388a33bf42dbabfa7b6435c73626bb7eb3b82ee1223f347a517434d16654bfb8d2fdef
6
+ metadata.gz: eae8c4f8b72bd7ec9891d430fea8573f1b39f80052770cbd8679f8ade14cac266f3ad8ae4a5a7f73c2a8eded295873be893981408a1c270ec7a6a374c7a4208d
7
+ data.tar.gz: f9df3603f5f561a86f7078998dd4bf075116ff014ed92f1db3dcbe72d43c2ad760763279b08caef440185157fecafa65341c983057b8542b694a6eb1fc9bda4d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 2.1.1
2
+ - Add SSL/TLS support to syslog output plugin (thanks @breml)
3
+ - Added ability to use codecs for this output (thanks @breml)
4
+
1
5
  ## 2.1.0
2
6
  - reconnect on exception. added basic specs
3
7
 
@@ -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
- config :facility, :validate => FACILITY_LABELS, :required => true
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
- config :severity, :validate => SEVERITY_LABELS, :required => true
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
- facility_code = FACILITY_LABELS.index(@facility)
101
- severity_code = SEVERITY_LABELS.index(@severity)
102
- @priority = (facility_code * 8) + severity_code
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 = "<#{@priority.to_s}>#{timestamp} #{sourcehost} #{appname}[#{procid}]: #{event.sprintf(@message)}"
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 = "<#{@priority.to_s}>1 #{timestamp} #{sourcehost} #{appname} #{procid} #{msgid} - #{event.sprintf(@message)}"
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.0'
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-plain'
27
+ s.add_development_dependency 'logstash-codec-json'
27
28
  end
28
29
 
@@ -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.0
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: 2015-11-18 00:00:00.000000000 Z
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-plain
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.1.9
112
+ rubygems_version: 2.4.8
99
113
  signing_key:
100
114
  specification_version: 4
101
115
  summary: Send events to a syslog server.