logstash-input-tcp 2.0.5 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/logstash/inputs/tcp.rb +41 -15
- data/logstash-input-tcp.gemspec +4 -1
- data/spec/inputs/tcp_spec.rb +151 -3
- data/spec/spec_helper.rb +69 -0
- metadata +32 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc8a144097d1b6d3ee89c67da0a9598c20816dc0
|
4
|
+
data.tar.gz: db3e1d7399ee28bcdbad61d343c589249287ad3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8b9f22e646a94b0624d961075589d48899595e9aaedb4111fcc1cf6118a9173366f3caf6f7b0315c8048d0a6d850ee6da0319eea9f413413d5a6d2511d09c12
|
7
|
+
data.tar.gz: a5d0c419104ca62126ad38c4e3a0a83a81083df5febe5184a4c7edff44893a9b4141589830a99bbfaff365652cbcb43f8cdeb11e88d3fe6b341e36b32911a175
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 3.0.0
|
2
|
+
- Deprecate ssl_cacert as it's confusing, does it job but when willing to add a chain of certificated the name and behaviour is a bit confusing.
|
3
|
+
- Add ssl_extra_chain_certs that allows you to specify a list of certificates path that will be added to the CAStore.
|
4
|
+
- Make ssl_verify=true as a default value, if using ssl and performing validation is not reasonable as security might be compromised.
|
5
|
+
- Add tests to verify behaviour under different SSL connection circumstances.
|
6
|
+
- Fixes #3 and #9.
|
7
|
+
|
8
|
+
## 2.1.0
|
9
|
+
- Added the receiving port in the event payload, fixes #4
|
10
|
+
|
1
11
|
## 2.0.5
|
2
12
|
- Fixed malformed SSL crashing Logstash, see https://github.com/logstash-plugins/logstash-input-tcp/pull/25
|
3
13
|
|
data/lib/logstash/inputs/tcp.rb
CHANGED
@@ -35,10 +35,10 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
35
35
|
|
36
36
|
# Verify the identity of the other end of the SSL connection against the CA.
|
37
37
|
# For input, sets the field `sslsubject` to that of the client certificate.
|
38
|
-
config :ssl_verify, :validate => :boolean, :default =>
|
38
|
+
config :ssl_verify, :validate => :boolean, :default => true
|
39
39
|
|
40
40
|
# The SSL CA certificate, chainfile or CA path. The system CA path is automatically included.
|
41
|
-
config :ssl_cacert, :validate => :path
|
41
|
+
config :ssl_cacert, :validate => :path, :deprecated => "This setting is deprecated in favor of extra_chain_cert as it sets a more clear expectation to add more X509 certificates to the store"
|
42
42
|
|
43
43
|
# SSL certificate path
|
44
44
|
config :ssl_cert, :validate => :path
|
@@ -49,6 +49,10 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
49
49
|
# SSL key passphrase
|
50
50
|
config :ssl_key_passphrase, :validate => :password, :default => nil
|
51
51
|
|
52
|
+
# An Array of extra X509 certificates to be added to the certificate chain.
|
53
|
+
# Useful when the CA chain is not necessary in the system store.
|
54
|
+
config :ssl_extra_chain_certs, :validate => :array, :default => []
|
55
|
+
|
52
56
|
def initialize(*args)
|
53
57
|
super(*args)
|
54
58
|
|
@@ -126,7 +130,7 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
126
130
|
def run_client(output_queue)
|
127
131
|
while !stop?
|
128
132
|
self.client_socket = new_client_socket
|
129
|
-
handle_socket(client_socket, client_socket.peeraddr[3], output_queue, @codec.clone)
|
133
|
+
handle_socket(client_socket, client_socket.peeraddr[3], client_socket.peeraddr[1], output_queue, @codec.clone)
|
130
134
|
end
|
131
135
|
ensure
|
132
136
|
# catch all rescue nil on close to discard any close errors or invalid socket
|
@@ -137,17 +141,18 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
137
141
|
Thread.new(output_queue, socket) do |q, s|
|
138
142
|
begin
|
139
143
|
@logger.debug? && @logger.debug("Accepted connection", :client => s.peer, :server => "#{@host}:#{@port}")
|
140
|
-
handle_socket(s, s.peeraddr[3], q, @codec.clone)
|
144
|
+
handle_socket(s, s.peeraddr[3], s.peeraddr[1], q, @codec.clone)
|
141
145
|
ensure
|
142
146
|
delete_connection_socket(s)
|
143
147
|
end
|
144
148
|
end
|
145
149
|
end
|
146
150
|
|
147
|
-
def handle_socket(socket, client_address, output_queue, codec)
|
151
|
+
def handle_socket(socket, client_address, client_port, output_queue, codec)
|
148
152
|
while !stop?
|
149
153
|
codec.decode(read(socket)) do |event|
|
150
154
|
event["host"] ||= client_address
|
155
|
+
event["port"] ||= client_port
|
151
156
|
event["sslsubject"] ||= socket.peer_cert.subject if @ssl_enable && @ssl_verify
|
152
157
|
decorate(event)
|
153
158
|
output_queue << event
|
@@ -170,12 +175,28 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
170
175
|
|
171
176
|
codec.respond_to?(:flush) && codec.flush do |event|
|
172
177
|
event["host"] ||= client_address
|
178
|
+
event["port"] ||= client_port
|
173
179
|
event["sslsubject"] ||= socket.peer_cert.subject if @ssl_enable && @ssl_verify
|
174
180
|
decorate(event)
|
175
181
|
output_queue << event
|
176
182
|
end
|
177
183
|
end
|
178
184
|
|
185
|
+
private
|
186
|
+
def client_thread(output_queue, socket)
|
187
|
+
Thread.new(output_queue, socket) do |q, s|
|
188
|
+
begin
|
189
|
+
@logger.debug? && @logger.debug("Accepted connection", :client => s.peer, :server => "#{@host}:#{@port}")
|
190
|
+
handle_socket(s, s.peeraddr[3], s.peeraddr[1], q, @codec.clone)
|
191
|
+
rescue Interrupted
|
192
|
+
s.close rescue nil
|
193
|
+
ensure
|
194
|
+
@client_threads_lock.synchronize{@client_threads.delete(Thread.current)}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
179
200
|
def server?
|
180
201
|
@mode == "server"
|
181
202
|
end
|
@@ -192,15 +213,7 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
192
213
|
@ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@ssl_cert))
|
193
214
|
@ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@ssl_key),@ssl_key_passphrase)
|
194
215
|
if @ssl_verify
|
195
|
-
@cert_store
|
196
|
-
# Load the system default certificate path to the store
|
197
|
-
@cert_store.set_default_paths
|
198
|
-
if File.directory?(@ssl_cacert)
|
199
|
-
@cert_store.add_path(@ssl_cacert)
|
200
|
-
else
|
201
|
-
@cert_store.add_file(@ssl_cacert)
|
202
|
-
end
|
203
|
-
@ssl_context.cert_store = @cert_store
|
216
|
+
@ssl_context.cert_store = load_cert_store
|
204
217
|
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
205
218
|
end
|
206
219
|
rescue => e
|
@@ -211,9 +224,22 @@ class LogStash::Inputs::Tcp < LogStash::Inputs::Base
|
|
211
224
|
@ssl_context
|
212
225
|
end
|
213
226
|
|
227
|
+
def load_cert_store
|
228
|
+
cert_store = OpenSSL::X509::Store.new
|
229
|
+
cert_store.set_default_paths
|
230
|
+
if File.directory?(@ssl_cacert)
|
231
|
+
cert_store.add_path(@ssl_cacert)
|
232
|
+
else
|
233
|
+
cert_store.add_file(@ssl_cacert)
|
234
|
+
end if @ssl_cacert
|
235
|
+
@ssl_extra_chain_certs.each do |cert|
|
236
|
+
cert_store.add_file(cert)
|
237
|
+
end
|
238
|
+
cert_store
|
239
|
+
end
|
240
|
+
|
214
241
|
def new_server_socket
|
215
242
|
@logger.info("Starting tcp input listener", :address => "#{@host}:#{@port}")
|
216
|
-
|
217
243
|
begin
|
218
244
|
socket = TCPServer.new(@host, @port)
|
219
245
|
rescue Errno::EADDRINUSE
|
data/logstash-input-tcp.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-input-tcp'
|
4
|
-
s.version = '
|
4
|
+
s.version = '3.0.0'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "Read events over a TCP socket."
|
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"
|
@@ -26,6 +26,9 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.add_runtime_dependency 'logstash-codec-line'
|
27
27
|
s.add_runtime_dependency 'logstash-codec-json'
|
28
28
|
s.add_runtime_dependency 'logstash-codec-json_lines'
|
29
|
+
|
29
30
|
s.add_development_dependency 'logstash-devutils'
|
31
|
+
s.add_development_dependency 'flores', '~> 0.0.6'
|
32
|
+
s.add_development_dependency 'stud', '~> 0.0.22'
|
30
33
|
end
|
31
34
|
|
data/spec/inputs/tcp_spec.rb
CHANGED
@@ -4,7 +4,10 @@ require "socket"
|
|
4
4
|
require "timeout"
|
5
5
|
require "logstash/json"
|
6
6
|
require "logstash/inputs/tcp"
|
7
|
-
require
|
7
|
+
require "stud/try"
|
8
|
+
require "flores/pki"
|
9
|
+
require "openssl"
|
10
|
+
|
8
11
|
require_relative "../spec_helper"
|
9
12
|
|
10
13
|
describe LogStash::Inputs::Tcp do
|
@@ -251,7 +254,6 @@ describe LogStash::Inputs::Tcp do
|
|
251
254
|
socket.flush
|
252
255
|
end
|
253
256
|
end
|
254
|
-
|
255
257
|
socket.close rescue nil
|
256
258
|
|
257
259
|
result
|
@@ -269,8 +271,154 @@ describe LogStash::Inputs::Tcp do
|
|
269
271
|
end
|
270
272
|
end
|
271
273
|
|
272
|
-
|
274
|
+
it "should add the host and port to the generated event" do
|
275
|
+
events.each do |event|
|
276
|
+
expect(event["host"]).to eq("127.0.0.1")
|
277
|
+
expect(event["port"]).to be_an(Fixnum)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
describe "ssl" do
|
282
|
+
|
283
|
+
let(:certificate) { helper.certificate }
|
284
|
+
|
285
|
+
subject(:input) { LogStash::Plugin.lookup("input", "tcp").new(config) }
|
286
|
+
|
287
|
+
let(:config) do
|
288
|
+
{ "host" => "0.0.0.0", "port" => port, "ssl_verify" => false,
|
289
|
+
"ssl_enable" => true, "ssl_cert" => certificate[0].path, "ssl_key" => certificate[1].path }
|
290
|
+
end
|
291
|
+
|
292
|
+
let(:events) do
|
293
|
+
|
294
|
+
socket = Stud::try(5.times) do
|
295
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
296
|
+
socket = TCPSocket.new("127.0.0.1", port)
|
297
|
+
OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
|
298
|
+
end
|
299
|
+
|
300
|
+
result = helper.pipelineless_input(subject, nevents) do
|
301
|
+
socket.connect
|
302
|
+
nevents.times do |i|
|
303
|
+
socket.puts("msg #{i}")
|
304
|
+
socket.flush
|
305
|
+
end
|
306
|
+
end
|
307
|
+
socket.close rescue nil
|
308
|
+
|
309
|
+
result
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should receive events" do
|
313
|
+
expect(events.size).to be(nevents)
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "when ssl_verify is on" do
|
317
|
+
|
318
|
+
let(:chain_of_certificates) { helper.chain_of_certificates }
|
319
|
+
|
320
|
+
let(:ssl_context) do
|
321
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
322
|
+
ssl_context.cert = OpenSSL::X509::Certificate.new(client_certificate)
|
323
|
+
ssl_context.key = OpenSSL::PKey::RSA.new(client_key)
|
324
|
+
ssl_context
|
325
|
+
end
|
326
|
+
|
327
|
+
context "and the verification fails" do
|
328
|
+
|
329
|
+
let(:config) do
|
330
|
+
{ "host" => "0.0.0.0", "port" => port,
|
331
|
+
"ssl_enable" => true, "ssl_verify" => true,
|
332
|
+
"ssl_cert" => chain_of_certificates[:a_cert].path, "ssl_key" => chain_of_certificates[:a_key].path }
|
333
|
+
end
|
334
|
+
|
335
|
+
let(:client_certificate) { File.read(chain_of_certificates[:b_cert].path) }
|
336
|
+
let(:client_key) { File.read(chain_of_certificates[:b_key].path) }
|
337
|
+
|
338
|
+
let(:socket) do
|
339
|
+
client = TCPSocket.new("127.0.0.1", port)
|
340
|
+
OpenSSL::SSL::SSLSocket.new(client, ssl_context)
|
341
|
+
end
|
273
342
|
|
343
|
+
it "should raise an exception when connecting" do
|
344
|
+
helper.pipelineless_input(subject, 0) do
|
345
|
+
expect { socket.connect }.to raise_error
|
346
|
+
socket.close rescue nil
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
context "and using the root CA" do
|
351
|
+
|
352
|
+
let(:config) do
|
353
|
+
{ "host" => "0.0.0.0", "port" => port,
|
354
|
+
"ssl_enable" => true, "ssl_verify" => true,
|
355
|
+
"ssl_cert" => chain_of_certificates[:a_cert].path, "ssl_key" => chain_of_certificates[:a_key].path,
|
356
|
+
"ssl_cacert" => chain_of_certificates[:root_ca].path }
|
357
|
+
end
|
358
|
+
|
359
|
+
let(:client_certificate) { File.read(chain_of_certificates[:aa_cert].path) }
|
360
|
+
let(:client_key) { File.read(chain_of_certificates[:aa_key].path) }
|
361
|
+
|
362
|
+
let(:events) do
|
363
|
+
socket = Stud::try(5.times) do
|
364
|
+
socket = TCPSocket.new("127.0.0.1", port)
|
365
|
+
OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
|
366
|
+
end
|
367
|
+
result = helper.pipelineless_input(subject, nevents) do
|
368
|
+
socket.connect
|
369
|
+
nevents.times do |i|
|
370
|
+
socket.puts("msg #{i}")
|
371
|
+
socket.flush
|
372
|
+
end
|
373
|
+
end
|
374
|
+
socket.close rescue nil
|
375
|
+
|
376
|
+
result
|
377
|
+
end
|
378
|
+
|
379
|
+
it "should receive events" do
|
380
|
+
expect(events.size).to be(nevents)
|
381
|
+
end
|
382
|
+
|
383
|
+
end
|
384
|
+
|
385
|
+
context "using an extra chain of certificates" do
|
386
|
+
|
387
|
+
let(:config) do
|
388
|
+
{ "host" => "0.0.0.0", "port" => port,
|
389
|
+
"ssl_enable" => true, "ssl_verify" => true,
|
390
|
+
"ssl_cert" => chain_of_certificates[:b_cert].path, "ssl_key" => chain_of_certificates[:b_key].path,
|
391
|
+
"ssl_extra_chain_certs" => [ chain_of_certificates[:root_ca].path, chain_of_certificates[:a_cert].path, chain_of_certificates[:b_cert].path ] }
|
392
|
+
end
|
393
|
+
|
394
|
+
let(:client_certificate) { File.read(chain_of_certificates[:c_cert].path) }
|
395
|
+
let(:client_key) { File.read(chain_of_certificates[:c_key].path) }
|
396
|
+
|
397
|
+
let(:events) do
|
398
|
+
socket = Stud::try(5.times) do
|
399
|
+
socket = TCPSocket.new("127.0.0.1", port)
|
400
|
+
OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
|
401
|
+
end
|
402
|
+
result = helper.pipelineless_input(subject, nevents) do
|
403
|
+
socket.connect
|
404
|
+
nevents.times do |i|
|
405
|
+
socket.puts("msg #{i}")
|
406
|
+
socket.flush
|
407
|
+
end
|
408
|
+
end
|
409
|
+
socket.close rescue nil
|
410
|
+
|
411
|
+
result
|
412
|
+
end
|
413
|
+
|
414
|
+
it "should receive events" do
|
415
|
+
expect(events.size).to be(nevents)
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
end
|
421
|
+
end
|
274
422
|
it_behaves_like "an interruptible input plugin" do
|
275
423
|
let(:config) { { "port" => port } }
|
276
424
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "logstash/devutils/rspec/spec_helper"
|
3
|
+
require "tempfile"
|
4
|
+
require "stud/temporary"
|
3
5
|
|
4
6
|
# this has been taken from the udp input, it should be DRYed
|
5
7
|
|
@@ -19,4 +21,71 @@ class TcpHelpers
|
|
19
21
|
input_thread.join
|
20
22
|
result
|
21
23
|
end
|
24
|
+
|
25
|
+
def certificate
|
26
|
+
certificate, key = Flores::PKI.generate("CN=localhost", { :key_size => 2048 })
|
27
|
+
[new_temp_file('cert', certificate), new_temp_file('key', key)]
|
28
|
+
end
|
29
|
+
|
30
|
+
def chain_of_certificates
|
31
|
+
root_ca, root_key = build_root_ca
|
32
|
+
a_cert, a_key = build_certificate(root_ca, root_key, "A_Cert")
|
33
|
+
aa_cert, aa_key = build_certificate(root_ca, root_key, "AA_Cert")
|
34
|
+
b_cert, b_key = build_certificate(a_cert, a_key, "B_Cert")
|
35
|
+
c_cert, c_key = build_certificate(b_cert, b_key, "C_Cert")
|
36
|
+
{ :root_ca => new_temp_file('', root_ca), :root_key => new_temp_file('', root_key),
|
37
|
+
:a_cert => new_temp_file('', a_cert), :a_key => new_temp_file('', a_key),
|
38
|
+
:aa_cert => new_temp_file('', aa_cert), :aa_key => new_temp_file('', aa_key),
|
39
|
+
:b_cert => new_temp_file('', b_cert), :b_key => new_temp_file('', b_key),
|
40
|
+
:c_cert => new_temp_file('', c_cert), :c_key => new_temp_file('', c_key)}
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def new_temp_file(name, data)
|
46
|
+
file = Stud::Temporary.file
|
47
|
+
file.write(data)
|
48
|
+
file.rewind
|
49
|
+
file
|
50
|
+
end
|
51
|
+
|
52
|
+
def build_certificate(root_ca, root_key=nil, name="")
|
53
|
+
key = ( root_key.nil? ? OpenSSL::PKey::RSA.new(2048) : root_key )
|
54
|
+
options = { :serial => 2, :subject => "/DC=org/DC=ruby-lang/CN=Ruby#{name}", :key => key, :issuer => root_ca.subject}
|
55
|
+
cert = new_certificate(options)
|
56
|
+
add_ca_extensions(cert, nil, root_ca)
|
57
|
+
[ cert.sign(key, OpenSSL::Digest::SHA256.new), key ]
|
58
|
+
end
|
59
|
+
|
60
|
+
def build_root_ca
|
61
|
+
key = OpenSSL::PKey::RSA.new(2048)
|
62
|
+
options = { :serial => 1, :subject => "/DC=org/DC=ruby-lang/CN=Ruby CA", :key => key}
|
63
|
+
ca = new_certificate(options)
|
64
|
+
add_ca_extensions(ca)
|
65
|
+
[ ca.sign(key, OpenSSL::Digest::SHA256.new), key ]
|
66
|
+
end
|
67
|
+
|
68
|
+
def new_certificate(options)
|
69
|
+
cert = OpenSSL::X509::Certificate.new
|
70
|
+
cert.version = 2
|
71
|
+
cert.serial = options.fetch(:serial, 1)
|
72
|
+
cert.subject = OpenSSL::X509::Name.parse(options.fetch(:subject, "/DC=org/DC=ruby-lang/CN=Ruby CA"))
|
73
|
+
cert.issuer = options.fetch(:issuer, cert.subject)
|
74
|
+
cert.public_key = options[:key].public_key
|
75
|
+
cert.not_before = Time.now
|
76
|
+
cert.not_after = cert.not_before + 2 * 365 * 86400
|
77
|
+
cert
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_ca_extensions(certificate, subject=nil, issuer=nil)
|
81
|
+
factory = OpenSSL::X509::ExtensionFactory.new
|
82
|
+
factory.subject_certificate = (subject.nil? ? certificate : subject)
|
83
|
+
factory.issuer_certificate = (issuer.nil? ? certificate : issuer)
|
84
|
+
|
85
|
+
certificate.add_extension(factory.create_extension("basicConstraints","CA:TRUE",true))
|
86
|
+
certificate.add_extension(factory.create_extension("keyUsage","keyCertSign, cRLSign, digitalSignature", true))
|
87
|
+
certificate.add_extension(factory.create_extension("subjectKeyIdentifier","hash",false))
|
88
|
+
certificate.add_extension(factory.create_extension("authorityKeyIdentifier","keyid:always",false))
|
89
|
+
end
|
90
|
+
|
22
91
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-tcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
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-
|
11
|
+
date: 2015-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logstash-core
|
@@ -100,6 +100,34 @@ dependencies:
|
|
100
100
|
version: '0'
|
101
101
|
prerelease: false
|
102
102
|
type: :development
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: flores
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.0.6
|
110
|
+
requirement: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ~>
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 0.0.6
|
115
|
+
prerelease: false
|
116
|
+
type: :development
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: stud
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ~>
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 0.0.22
|
124
|
+
requirement: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ~>
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: 0.0.22
|
129
|
+
prerelease: false
|
130
|
+
type: :development
|
103
131
|
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
|
104
132
|
email: info@elastic.co
|
105
133
|
executables: []
|
@@ -138,10 +166,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
166
|
version: '0'
|
139
167
|
requirements: []
|
140
168
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.4.
|
169
|
+
rubygems_version: 2.4.6
|
142
170
|
signing_key:
|
143
171
|
specification_version: 4
|
144
172
|
summary: Read events over a TCP socket.
|
145
173
|
test_files:
|
146
174
|
- spec/inputs/tcp_spec.rb
|
147
175
|
- spec/spec_helper.rb
|
176
|
+
has_rdoc:
|