logstash-input-beats 4.0.2-java → 4.0.3-java
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 +19 -4
- data/VERSION +1 -1
- data/docs/index.asciidoc +1 -1
- data/lib/logstash-input-beats_jars.rb +1 -1
- data/lib/logstash/inputs/beats.rb +1 -2
- data/lib/logstash/inputs/beats/message_listener.rb +6 -0
- data/lib/tasks/test.rake +3 -2
- data/spec/inputs/beats/message_listener_spec.rb +29 -1
- data/spec/integration/filebeat_spec.rb +11 -5
- data/spec/support/client_process_helpers.rb +15 -2
- data/spec/support/flores_extensions.rb +52 -29
- data/spec/support/integration_shared_context.rb +1 -1
- data/vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/4.0.3/logstash-input-beats-4.0.3.jar +0 -0
- metadata +3 -3
- data/vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/4.0.2/logstash-input-beats-4.0.2.jar +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d406faf577912c1b8e53353eb01a297b91ca4de5
|
4
|
+
data.tar.gz: ac879f92b4b6e6699ed9c56fd40db3248b6810ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cb70e0661a794b5be172bf87c7b5d186b0107d3e37cee6590592610ce00c06b2d05c494febbf9afb48b6a77a599199919f9c5f89063ad9dc766bc1419c4cd96
|
7
|
+
data.tar.gz: ba72af919b0d49bb3fb392e22a8d2475a0a11c92c2d321881c9f07cce7ffa5e4f25bc9ce74567d7d51c7e96dae196bd71d2430beb1219bb0ba309f029db05fcc
|
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,29 @@
|
|
1
|
+
## 4.0.3
|
2
|
+
- Include remote ip_address in metadata. #180
|
3
|
+
- Require Java 8 #221
|
4
|
+
- Fix ability to set SSL protocols #228
|
5
|
+
|
1
6
|
## 4.0.2
|
2
|
-
|
7
|
+
- Relax version of concurrent-ruby to `~> 1.0` #216
|
3
8
|
|
4
9
|
## 4.0.1
|
5
|
-
- Breaking change: Logstash will no longer start when multiline codec is used with the Beats input plugin
|
10
|
+
- Breaking change: Logstash will no longer start when multiline codec is used with the Beats input plugin #201
|
6
11
|
|
7
12
|
## 4.0.0
|
8
|
-
-
|
13
|
+
- Version yanked from RubyGems for packaging issues
|
14
|
+
|
15
|
+
## 3.1.19
|
16
|
+
- Fix ability to set SSL protocols #228
|
17
|
+
|
18
|
+
## 3.1.18
|
19
|
+
- Relax version of concurrent-ruby to ~> 1.0 #216
|
20
|
+
|
21
|
+
## 3.1.17
|
22
|
+
- Docs: Add note indicating that the multiline codec should not be used with the Beats input plugin
|
23
|
+
- Deprecate warning for multiline codec with the Beats input plugin
|
9
24
|
|
10
25
|
## 3.1.16
|
11
|
-
-
|
26
|
+
- Version yanked from RubyGems for packaging issues
|
12
27
|
|
13
28
|
## 3.1.15
|
14
29
|
- DEBUG: Add information about the remote when an exception is catched #192
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.0.
|
1
|
+
4.0.3
|
data/docs/index.asciidoc
CHANGED
@@ -9,4 +9,4 @@ require_jar('com.fasterxml.jackson.core', 'jackson-annotations', '2.7.5')
|
|
9
9
|
require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.7.5')
|
10
10
|
require_jar('com.fasterxml.jackson.module', 'jackson-module-afterburner', '2.7.5')
|
11
11
|
require_jar('log4j', 'log4j', '1.2.17')
|
12
|
-
require_jar('org.logstash.beats', 'logstash-input-beats', '4.0.
|
12
|
+
require_jar('org.logstash.beats', 'logstash-input-beats', '4.0.3')
|
@@ -39,8 +39,7 @@ require_relative "beats/patch"
|
|
39
39
|
# IMPORTANT: If you are shipping events that span multiple lines, you need to
|
40
40
|
# use the configuration options available in Filebeat to handle multiline events
|
41
41
|
# before sending the event data to Logstash. You cannot use the
|
42
|
-
# <<plugins-codecs-multiline>> codec to handle multiline events.
|
43
|
-
# result in the mixing of streams and corrupted event data.
|
42
|
+
# <<plugins-codecs-multiline>> codec to handle multiline events.
|
44
43
|
#
|
45
44
|
class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
46
45
|
require "logstash/inputs/beats/codec_callback_listener"
|
@@ -29,6 +29,12 @@ module LogStash module Inputs class Beats
|
|
29
29
|
def onNewMessage(ctx, message)
|
30
30
|
hash = message.getData()
|
31
31
|
|
32
|
+
begin
|
33
|
+
hash.get("@metadata").put("ip_address", ctx.channel().remoteAddress().getAddress().getHostAddress())
|
34
|
+
rescue #should never happen, but don't allow an error here to stop beats input
|
35
|
+
input.logger.warn("Could not retrieve remote IP address for beats input.")
|
36
|
+
end
|
37
|
+
|
32
38
|
target_field = extract_target_field(hash)
|
33
39
|
|
34
40
|
if target_field.nil?
|
data/lib/tasks/test.rake
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
OS_PLATFORM = RbConfig::CONFIG["host_os"]
|
3
3
|
VENDOR_PATH = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "vendor"))
|
4
4
|
|
5
|
+
#TODO: Figure out better means to keep this version in sync
|
5
6
|
if OS_PLATFORM == "linux"
|
6
|
-
FILEBEAT_URL = "https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-
|
7
|
+
FILEBEAT_URL = "https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.0.0-alpha2-linux-x86_64.tar.gz"
|
7
8
|
elsif OS_PLATFORM == "darwin"
|
8
|
-
FILEBEAT_URL = "https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-
|
9
|
+
FILEBEAT_URL = "https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.0.0-alpha2-darwin-x86_64.tar.gz"
|
9
10
|
end
|
10
11
|
|
11
12
|
LSF_URL = "https://download.elastic.co/logstash-forwarder/binaries/logstash-forwarder_#{OS_PLATFORM}_amd64"
|
@@ -6,7 +6,10 @@ require "logstash/inputs/beats/message_listener"
|
|
6
6
|
require "logstash/instrument/namespaced_null_metric"
|
7
7
|
require "thread"
|
8
8
|
|
9
|
+
java_import java.util.HashMap
|
10
|
+
|
9
11
|
class MockMessage
|
12
|
+
|
10
13
|
def initialize(identity_stream, data = {})
|
11
14
|
@identity_stream = identity_stream
|
12
15
|
@data = data
|
@@ -21,6 +24,22 @@ class MockMessage
|
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
27
|
+
# General purpose single method mock class. Will keep generating mocks until requested method name (no args) is found.
|
28
|
+
class OngoingMethodMock
|
29
|
+
def initialize(method_name, return_value)
|
30
|
+
@method_name = method_name
|
31
|
+
@return_value = return_value
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(method)
|
35
|
+
if(method.to_s.eql? @method_name)
|
36
|
+
return @return_value
|
37
|
+
else
|
38
|
+
return OngoingMethodMock.new(@method_name, @return_value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
24
43
|
class DummyCodec < LogStash::Codecs::Base
|
25
44
|
DUMMY_EVENT = LogStash::Event.new
|
26
45
|
|
@@ -98,7 +117,14 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
98
117
|
end
|
99
118
|
|
100
119
|
context "when the message is from any libbeat" do
|
101
|
-
|
120
|
+
#Requires data modeled as Java, not Ruby since the actual code pulls from Java backed (Netty) object
|
121
|
+
data = java.util.HashMap.new
|
122
|
+
data.put("@metadata", java.util.HashMap.new)
|
123
|
+
data.put("metric", 1)
|
124
|
+
data.put("name", "super-stats")
|
125
|
+
|
126
|
+
let(:message) { MockMessage.new("abc", data)}
|
127
|
+
let(:ctx) {OngoingMethodMock.new("getHostAddress", "10.0.0.1")}
|
102
128
|
|
103
129
|
it "extract the event" do
|
104
130
|
subject.onNewMessage(ctx, message)
|
@@ -106,8 +132,10 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
106
132
|
expect(event.get("message")).to be_nil
|
107
133
|
expect(event.get("metric")).to eq(1)
|
108
134
|
expect(event.get("name")).to eq("super-stats")
|
135
|
+
expect(event.get("[@metadata][ip_address]")).to eq("10.0.0.1")
|
109
136
|
end
|
110
137
|
end
|
138
|
+
|
111
139
|
end
|
112
140
|
|
113
141
|
context "onException" do
|
@@ -52,6 +52,7 @@ describe "Filebeat", :integration => true do
|
|
52
52
|
before :each do
|
53
53
|
FileUtils.rm_rf(File.join(File.dirname(__FILE__), "..", "..", "vendor", "filebeat", "data"))
|
54
54
|
start_client
|
55
|
+
raise 'Filebeat did not start in alloted time' unless is_alive
|
55
56
|
sleep(20) # give some time to FB to send something
|
56
57
|
end
|
57
58
|
|
@@ -76,7 +77,7 @@ describe "Filebeat", :integration => true do
|
|
76
77
|
end
|
77
78
|
|
78
79
|
############################################################
|
79
|
-
# Actuals tests
|
80
|
+
# Actuals tests
|
80
81
|
context "Plain TCP" do
|
81
82
|
include_examples "send events"
|
82
83
|
end
|
@@ -190,6 +191,9 @@ describe "Filebeat", :integration => true do
|
|
190
191
|
context "CA root" do
|
191
192
|
include_context "Root CA"
|
192
193
|
|
194
|
+
let_tmp_file(:certificate_key_file) { convert_to_pkcs8(certificate_data.last) }
|
195
|
+
let_tmp_file(:certificate_file) { certificate_data.first }
|
196
|
+
|
193
197
|
context "directly signed client certificate" do
|
194
198
|
let(:certificate_authorities) { [root_ca_certificate_file] }
|
195
199
|
let(:certificate_data) { Flores::PKI.create_client_certicate("CN=localhost", root_ca_certificate, root_ca_key) }
|
@@ -202,7 +206,7 @@ describe "Filebeat", :integration => true do
|
|
202
206
|
|
203
207
|
let(:certificate_data) { Flores::PKI.create_client_certicate("CN=localhost", intermediate_ca_certificate, intermediate_ca_key) }
|
204
208
|
let(:certificate_authorities) { [certificate_authorities_chain] }
|
205
|
-
|
209
|
+
|
206
210
|
include_examples "send events"
|
207
211
|
end
|
208
212
|
end
|
@@ -224,7 +228,7 @@ describe "Filebeat", :integration => true do
|
|
224
228
|
end
|
225
229
|
|
226
230
|
let(:input_config) do
|
227
|
-
super.merge({
|
231
|
+
super.merge({
|
228
232
|
"ssl" => true,
|
229
233
|
"ssl_certificate_authorities" => certificate_authorities,
|
230
234
|
"ssl_certificate" => server_certificate_file,
|
@@ -249,6 +253,8 @@ describe "Filebeat", :integration => true do
|
|
249
253
|
|
250
254
|
let_tmp_file(:server_certificate_file) { server_certificate_data.first }
|
251
255
|
let_tmp_file(:server_certificate_key_file) { convert_to_pkcs8(server_certificate_data.last) }
|
256
|
+
let_tmp_file(:certificate_file) { certificate_data.first }
|
257
|
+
let_tmp_file(:certificate_key_file) { convert_to_pkcs8(certificate_data.last) }
|
252
258
|
|
253
259
|
context "directly signed client certificate" do
|
254
260
|
let(:certificate_authorities) { [root_ca_certificate_file] }
|
@@ -262,7 +268,7 @@ describe "Filebeat", :integration => true do
|
|
262
268
|
include_context "Intermediate CA"
|
263
269
|
|
264
270
|
let(:certificate_data) { Flores::PKI.create_client_certicate("CN=localhost", intermediate_ca_certificate, intermediate_ca_key) }
|
265
|
-
let(:server_certificate_data) { Flores::PKI.create_client_certicate("CN=localhost", intermediate_ca_certificate, intermediate_ca_key) }
|
271
|
+
let(:server_certificate_data) { Flores::PKI.create_client_certicate("CN=localhost", intermediate_ca_certificate, intermediate_ca_key) }
|
266
272
|
let(:certificate_authorities) { [intermediate_ca_certificate_file] }
|
267
273
|
|
268
274
|
include_examples "send events"
|
@@ -298,7 +304,7 @@ describe "Filebeat", :integration => true do
|
|
298
304
|
|
299
305
|
let(:server_certificate_data) { Flores::PKI.create_client_certicate("CN=localhost", root_ca_certificate, root_ca_key) }
|
300
306
|
|
301
|
-
context "client from primary CA" do
|
307
|
+
context "client from primary CA" do
|
302
308
|
include_examples "send events"
|
303
309
|
end
|
304
310
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "childprocess"
|
3
3
|
module ClientProcessHelpers
|
4
|
-
def start_client(timeout =
|
4
|
+
def start_client(timeout = 5)
|
5
5
|
@client_out = Stud::Temporary.file
|
6
6
|
@client_out.sync
|
7
7
|
|
@@ -11,13 +11,26 @@ module ClientProcessHelpers
|
|
11
11
|
ChildProcess.posix_spawn = true
|
12
12
|
@process.start
|
13
13
|
|
14
|
-
|
14
|
+
sleep_interval = 0.1
|
15
|
+
max_iterations = (timeout / sleep_interval).to_i
|
16
|
+
max_iterations.times do
|
17
|
+
sleep(sleep_interval)
|
18
|
+
if @process.alive?
|
19
|
+
break
|
20
|
+
end
|
21
|
+
end
|
22
|
+
#Note - can not raise error here if process failed to start, since some tests expects for the process to not start due to invalid configuration
|
23
|
+
|
15
24
|
@client_out.rewind
|
16
25
|
|
17
26
|
# can be used to helper debugging when a test fails
|
18
27
|
@execution_output = @client_out.read
|
19
28
|
end
|
20
29
|
|
30
|
+
def is_alive
|
31
|
+
return @process.alive?
|
32
|
+
end
|
33
|
+
|
21
34
|
def stop_client
|
22
35
|
begin
|
23
36
|
@process.poll_for_exit(5)
|
@@ -1,49 +1,68 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "flores/pki"
|
3
3
|
require "flores/random"
|
4
|
+
require "socket"
|
4
5
|
|
5
6
|
module Flores
|
6
7
|
module Random
|
7
8
|
DEFAULT_PORT_RANGE = 1024..65535
|
8
|
-
DEFAULT_PORT_CHECK_TIMEOUT = 1
|
9
|
-
DEFAULT_MAXIMUM_PORT_FIND_TRY = 15
|
10
|
-
|
11
9
|
class << self
|
12
10
|
def port(range = DEFAULT_PORT_RANGE)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
11
|
+
integer(range)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module PKI
|
17
|
+
|
18
|
+
# Monkey patched the fix for https://github.com/jordansissel/ruby-flores/issues/9
|
19
|
+
# TODO: remove this once Flores is released with fix.
|
20
|
+
CertificateSigningRequest.class_eval do
|
21
|
+
def create
|
22
|
+
validate!
|
23
|
+
extensions = OpenSSL::X509::ExtensionFactory.new
|
24
|
+
extensions.subject_certificate = certificate
|
25
|
+
extensions.issuer_certificate = self_signed? ? certificate : signing_certificate
|
26
|
+
|
27
|
+
certificate.issuer = extensions.issuer_certificate.subject
|
28
|
+
certificate.add_extension(extensions.create_extension("subjectKeyIdentifier", "hash", false))
|
29
|
+
|
30
|
+
if want_signature_ability?
|
31
|
+
# Create a CA.
|
32
|
+
certificate.add_extension(extensions.create_extension("basicConstraints", "CA:TRUE", true))
|
33
|
+
# Rough googling seems to indicate at least keyCertSign is required for CA and intermediate certs.
|
34
|
+
certificate.add_extension(extensions.create_extension("keyUsage", "keyCertSign, cRLSign, digitalSignature", true))
|
35
|
+
else
|
36
|
+
# Create a client+server certificate
|
37
|
+
#
|
38
|
+
# It feels weird to create a certificate that's valid as both server and client, but a brief inspection of major
|
39
|
+
# web properties (apple.com, google.com, yahoo.com, github.com, fastly.com, mozilla.com, amazon.com) reveals that
|
40
|
+
# major web properties have certificates with both clientAuth and serverAuth extended key usages. Further,
|
41
|
+
# these major server certificates all have digitalSignature and keyEncipherment for key usage.
|
42
|
+
#
|
43
|
+
# Here's the command I used to check this:
|
44
|
+
# echo mozilla.com apple.com github.com google.com yahoo.com fastly.com elastic.co amazon.com \
|
45
|
+
# | xargs -n1 sh -c 'openssl s_client -connect $1:443 \
|
46
|
+
# | sed -ne "/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p" \
|
47
|
+
# | openssl x509 -text -noout | sed -ne "/X509v3 extensions/,/Signature Algorithm/p" | sed -e "s/^/$1 /"' - \
|
48
|
+
# | grep -A2 'Key Usage'
|
49
|
+
certificate.add_extension(extensions.create_extension("keyUsage", "digitalSignature, keyEncipherment", true))
|
50
|
+
certificate.add_extension(extensions.create_extension("extendedKeyUsage", "clientAuth, serverAuth", false))
|
22
51
|
end
|
23
|
-
|
24
|
-
raise "Flores.random_port: Cannot find an available port, tried #{DEFAULT_MAXIMUM_PORT_FIND_TRY} times, range was: #{range}" if try == DEFAULT_MAXIMUM_PORT_FIND_TRY
|
25
52
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
def port_available?(port)
|
30
|
-
begin
|
31
|
-
server = TCPServer.new(port)
|
32
|
-
available = true
|
33
|
-
rescue # Assume that any errors can do this
|
34
|
-
available = false
|
35
|
-
ensure
|
36
|
-
server.close if server
|
53
|
+
if @subject_alternates
|
54
|
+
certificate.add_extension(extensions.create_extension("subjectAltName", @subject_alternates.join(",")))
|
37
55
|
end
|
38
56
|
|
39
|
-
|
57
|
+
certificate.serial = OpenSSL::BN.new(serial)
|
58
|
+
certificate.sign(signing_key, digest_method)
|
59
|
+
certificate
|
40
60
|
end
|
41
61
|
end
|
42
|
-
end
|
43
62
|
|
44
|
-
|
63
|
+
|
45
64
|
DEFAULT_CERTIFICATE_OPTIONS = {
|
46
|
-
:duration =>
|
65
|
+
:duration => 86400, #one day
|
47
66
|
:key_size => GENERATE_DEFAULT_KEY_SIZE,
|
48
67
|
:exponent => GENERATE_DEFAULT_EXPONENT,
|
49
68
|
:want_signature_ability => false
|
@@ -78,5 +97,9 @@ module Flores
|
|
78
97
|
|
79
98
|
[csr.create, client_key]
|
80
99
|
end
|
100
|
+
|
101
|
+
|
102
|
+
|
81
103
|
end
|
82
104
|
end
|
105
|
+
|
@@ -3,7 +3,7 @@ require "flores/random"
|
|
3
3
|
|
4
4
|
shared_examples "send events" do
|
5
5
|
it "successfully send the events" do
|
6
|
-
try(
|
6
|
+
try(25) { expect(queue.size).to eq(number_of_events), "Expected: #{number_of_events} got: #{queue.size}, execution output:\n #{@execution_output}" }
|
7
7
|
expect(queue.collect { |e| e.get("message") }).to eq(events)
|
8
8
|
end
|
9
9
|
end
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-beats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.3
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -264,7 +264,7 @@ files:
|
|
264
264
|
- vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/1.1.33.Fork23/netty-tcnative-boringssl-static-1.1.33.Fork23.jar
|
265
265
|
- vendor/jar-dependencies/log4j/log4j/1.2.17/log4j-1.2.17.jar
|
266
266
|
- vendor/jar-dependencies/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar
|
267
|
-
- vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/4.0.
|
267
|
+
- vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/4.0.3/logstash-input-beats-4.0.3.jar
|
268
268
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
269
269
|
licenses:
|
270
270
|
- Apache License (2.0)
|