logstash-output-syslog 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
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.