logstash-input-beats 3.1.24-java → 5.1.9-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +111 -14
- data/Gemfile +3 -2
- data/LICENSE +1 -1
- data/VERSION +1 -1
- data/docs/index.asciidoc +74 -41
- data/lib/logstash/inputs/beats/event_transform_common.rb +1 -0
- data/lib/logstash/inputs/beats/message_listener.rb +63 -5
- data/lib/logstash/inputs/beats.rb +31 -21
- data/lib/logstash-input-beats_jars.rb +9 -9
- data/logstash-input-beats.gemspec +2 -2
- data/spec/inputs/beats/message_listener_spec.rb +103 -12
- data/spec/inputs/beats_spec.rb +15 -26
- data/spec/integration/logstash_forwarder_spec.rb +0 -1
- data/spec/support/client_process_helpers.rb +6 -4
- data/spec/support/helpers.rb +8 -1
- data/spec/support/shared_examples.rb +111 -16
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-annotations/2.9.9/jackson-annotations-2.9.9.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-databind/2.9.9.3/jackson-databind-2.9.9.3.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/module/jackson-module-afterburner/2.9.9/jackson-module-afterburner-2.9.9.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-all/4.1.30.Final/netty-all-4.1.30.Final.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/2.0.12.Final/netty-tcnative-boringssl-static-2.0.12.Final.jar +0 -0
- data/vendor/jar-dependencies/org/apache/logging/log4j/log4j-api/2.11.1/log4j-api-2.11.1.jar +0 -0
- data/vendor/jar-dependencies/org/javassist/javassist/3.24.0-GA/javassist-3.24.0-GA.jar +0 -0
- data/vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/5.1.9/logstash-input-beats-5.1.9.jar +0 -0
- metadata +22 -14
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-annotations/2.7.5/jackson-annotations-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.7.5/jackson-core-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-databind/2.7.5/jackson-databind-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/com/fasterxml/jackson/module/jackson-module-afterburner/2.7.5/jackson-module-afterburner-2.7.5.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-all/4.1.3.Final/netty-all-4.1.3.Final.jar +0 -0
- data/vendor/jar-dependencies/io/netty/netty-tcnative-boringssl-static/1.1.33.Fork23/netty-tcnative-boringssl-static-1.1.33.Fork23.jar +0 -0
- data/vendor/jar-dependencies/org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar +0 -0
- data/vendor/jar-dependencies/org/logstash/beats/logstash-input-beats/3.1.24/logstash-input-beats-3.1.24.jar +0 -0
@@ -2,7 +2,6 @@
|
|
2
2
|
require "logstash/inputs/base"
|
3
3
|
require "logstash/namespace"
|
4
4
|
require "logstash/timestamp"
|
5
|
-
require "logstash/codecs/identity_map_codec"
|
6
5
|
require "logstash/codecs/multiline"
|
7
6
|
require "logstash/util"
|
8
7
|
require "logstash-input-beats_jars"
|
@@ -40,8 +39,7 @@ require_relative "beats/patch"
|
|
40
39
|
# IMPORTANT: If you are shipping events that span multiple lines, you need to
|
41
40
|
# use the configuration options available in Filebeat to handle multiline events
|
42
41
|
# before sending the event data to Logstash. You cannot use the
|
43
|
-
# <<plugins-codecs-multiline>> codec to handle multiline events.
|
44
|
-
# result in the mixing of streams and corrupted event data.
|
42
|
+
# <<plugins-codecs-multiline>> codec to handle multiline events.
|
45
43
|
#
|
46
44
|
class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
47
45
|
require "logstash/inputs/beats/codec_callback_listener"
|
@@ -84,6 +82,10 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
84
82
|
#
|
85
83
|
config :ssl_certificate_authorities, :validate => :array, :default => []
|
86
84
|
|
85
|
+
# Flag to determine whether to add host information (provided by the beat in the 'hostname' field) to the event
|
86
|
+
config :add_hostname, :validate => :boolean, :default => true, :deprecated => 'Host field will not be automatically populated by future version of the Beats input'
|
87
|
+
|
88
|
+
|
87
89
|
# By default the server doesn't do any client verification.
|
88
90
|
#
|
89
91
|
# `peer` will make the server ask the client to provide a certificate.
|
@@ -95,6 +97,10 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
95
97
|
# This option needs to be used with `ssl_certificate_authorities` and a defined list of CAs.
|
96
98
|
config :ssl_verify_mode, :validate => ["none", "peer", "force_peer"], :default => "none"
|
97
99
|
|
100
|
+
# Enables storing client certificate information in event's metadata. You need
|
101
|
+
# to configure the `ssl_verify_mode` to `peer` or `force_peer` to enable this.
|
102
|
+
config :ssl_peer_metadata, :validate => :boolean, :default => false
|
103
|
+
|
98
104
|
config :include_codec_tag, :validate => :boolean, :default => true
|
99
105
|
|
100
106
|
# Time in milliseconds for an incomplete ssl handshake to timeout
|
@@ -102,10 +108,10 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
102
108
|
|
103
109
|
# The number of seconds before we raise a timeout.
|
104
110
|
# This option is useful to control how much time to wait if something is blocking the pipeline.
|
105
|
-
config :congestion_threshold, :validate => :number, :
|
111
|
+
config :congestion_threshold, :validate => :number, :obsolete => "This option is obsolete since congestion control is done automatically"
|
106
112
|
|
107
113
|
# This is the default field to which the specified codec will be applied.
|
108
|
-
config :target_field_for_codec, :validate => :string, :
|
114
|
+
config :target_field_for_codec, :validate => :string, :obsolete => "This option is obsolete"
|
109
115
|
|
110
116
|
# The minimum TLS version allowed for the encrypted connections. The value must be one of the following:
|
111
117
|
# 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2
|
@@ -121,6 +127,9 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
121
127
|
# Close Idle clients after X seconds of inactivity.
|
122
128
|
config :client_inactivity_timeout, :validate => :number, :default => 60
|
123
129
|
|
130
|
+
# Beats handler executor thread
|
131
|
+
config :executor_threads, :validate => :number, :default => LogStash::Config::CpuCoreStrategy.maximum
|
132
|
+
|
124
133
|
def register
|
125
134
|
# For Logstash 2.4 we need to make sure that the logger is correctly set for the
|
126
135
|
# java classes before actually loading them.
|
@@ -147,26 +156,22 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
147
156
|
raise LogStash::ConfigurationError, "Using `verify_mode` set to PEER or FORCE_PEER, requires the configuration of `certificate_authorities`"
|
148
157
|
end
|
149
158
|
|
159
|
+
if client_authentication_metadata? && !require_certificate_authorities?
|
160
|
+
raise LogStash::ConfigurationError, "Enabling `peer_metadata` requires using `verify_mode` set to PEER or FORCE_PEER"
|
161
|
+
end
|
162
|
+
|
163
|
+
# Logstash 6.x breaking change (introduced with 4.0.0 of this gem)
|
150
164
|
if @codec.kind_of? LogStash::Codecs::Multiline
|
151
|
-
|
165
|
+
raise LogStash::ConfigurationError, "Multiline codec with beats input is not supported. Please refer to the beats documentation for how to best manage multiline data. See https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html"
|
152
166
|
end
|
153
167
|
|
154
168
|
@logger.info("Beats inputs: Starting input listener", :address => "#{@host}:#{@port}")
|
155
169
|
|
156
|
-
# wrap the configured codec to support identity stream
|
157
|
-
# from the producers if running with the multiline codec.
|
158
|
-
#
|
159
|
-
# If they dont need an identity map, codec are stateless and can be reused
|
160
|
-
# accross multiples connections.
|
161
|
-
if need_identity_map?
|
162
|
-
@codec = LogStash::Codecs::IdentityMapCodec.new(@codec)
|
163
|
-
end
|
164
|
-
|
165
170
|
@server = create_server
|
166
171
|
end # def register
|
167
172
|
|
168
173
|
def create_server
|
169
|
-
server = org.logstash.beats.Server.new(@host, @port, @client_inactivity_timeout)
|
174
|
+
server = org.logstash.beats.Server.new(@host, @port, @client_inactivity_timeout, @executor_threads)
|
170
175
|
if @ssl
|
171
176
|
|
172
177
|
begin
|
@@ -182,13 +187,14 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
182
187
|
if client_authentification?
|
183
188
|
if @ssl_verify_mode.upcase == "FORCE_PEER"
|
184
189
|
ssl_builder.setVerifyMode(org.logstash.netty.SslSimpleBuilder::SslClientVerifyMode::FORCE_PEER)
|
190
|
+
elsif @ssl_verify_mode.upcase == "PEER"
|
191
|
+
ssl_builder.setVerifyMode(org.logstash.netty.SslSimpleBuilder::SslClientVerifyMode::VERIFY_PEER)
|
185
192
|
end
|
186
193
|
ssl_builder.setCertificateAuthorities(@ssl_certificate_authorities)
|
187
194
|
end
|
188
195
|
|
189
196
|
server.enableSSL(ssl_builder)
|
190
197
|
end
|
191
|
-
|
192
198
|
server
|
193
199
|
end
|
194
200
|
|
@@ -210,14 +216,18 @@ class LogStash::Inputs::Beats < LogStash::Inputs::Base
|
|
210
216
|
@server.stop unless @server.nil?
|
211
217
|
end
|
212
218
|
|
213
|
-
def need_identity_map?
|
214
|
-
@codec.kind_of?(LogStash::Codecs::Multiline)
|
215
|
-
end
|
216
|
-
|
217
219
|
def client_authentification?
|
218
220
|
@ssl_certificate_authorities && @ssl_certificate_authorities.size > 0
|
219
221
|
end
|
220
222
|
|
223
|
+
def client_authentication_metadata?
|
224
|
+
@ssl_peer_metadata && ssl_configured? && client_authentification?
|
225
|
+
end
|
226
|
+
|
227
|
+
def client_authentication_required?
|
228
|
+
@ssl_verify_mode == "force_peer"
|
229
|
+
end
|
230
|
+
|
221
231
|
def require_certificate_authorities?
|
222
232
|
@ssl_verify_mode == "force_peer" || @ssl_verify_mode == "peer"
|
223
233
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# AUTOGENERATED BY THE GRADLE SCRIPT. DO NOT EDIT.
|
2
2
|
|
3
3
|
require 'jar_dependencies'
|
4
|
-
require_jar('io.netty', 'netty-all', '4.1.
|
5
|
-
require_jar('io.netty', 'netty-tcnative-boringssl-static', '
|
6
|
-
require_jar('org.javassist', 'javassist', '3.
|
7
|
-
require_jar('com.fasterxml.jackson.core', 'jackson-core', '2.
|
8
|
-
require_jar('com.fasterxml.jackson.core', 'jackson-annotations', '2.
|
9
|
-
require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.
|
10
|
-
require_jar('com.fasterxml.jackson.module', 'jackson-module-afterburner', '2.
|
11
|
-
require_jar('org.apache.logging.log4j', 'log4j-api', '2.
|
12
|
-
require_jar('org.logstash.beats', 'logstash-input-beats', '
|
4
|
+
require_jar('io.netty', 'netty-all', '4.1.30.Final')
|
5
|
+
require_jar('io.netty', 'netty-tcnative-boringssl-static', '2.0.12.Final')
|
6
|
+
require_jar('org.javassist', 'javassist', '3.24.0-GA')
|
7
|
+
require_jar('com.fasterxml.jackson.core', 'jackson-core', '2.9.9')
|
8
|
+
require_jar('com.fasterxml.jackson.core', 'jackson-annotations', '2.9.9')
|
9
|
+
require_jar('com.fasterxml.jackson.core', 'jackson-databind', '2.9.9.3')
|
10
|
+
require_jar('com.fasterxml.jackson.module', 'jackson-module-afterburner', '2.9.9')
|
11
|
+
require_jar('org.apache.logging.log4j', 'log4j-api', '2.11.1')
|
12
|
+
require_jar('org.logstash.beats', 'logstash-input-beats', '5.1.9')
|
@@ -4,7 +4,7 @@ Gem::Specification.new do |s|
|
|
4
4
|
s.name = "logstash-input-beats"
|
5
5
|
s.version = BEATS_VERSION
|
6
6
|
s.licenses = ["Apache License (2.0)"]
|
7
|
-
s.summary = "
|
7
|
+
s.summary = "Receives events from the Elastic Beats framework"
|
8
8
|
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
9
9
|
s.authors = ["Elastic"]
|
10
10
|
s.email = "info@elastic.co"
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
27
27
|
s.add_runtime_dependency "thread_safe", "~> 0.3.5"
|
28
28
|
s.add_runtime_dependency "logstash-codec-multiline", ">= 2.0.5"
|
29
|
-
s.add_runtime_dependency 'jar-dependencies', '~> 0.3.4'
|
29
|
+
s.add_runtime_dependency 'jar-dependencies', '~> 0.3', '>= 0.3.4'
|
30
30
|
|
31
31
|
s.add_development_dependency "flores", "~>0.0.6"
|
32
32
|
s.add_development_dependency "rspec"
|
@@ -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
|
|
@@ -37,7 +56,11 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
37
56
|
let(:queue) { Queue.new }
|
38
57
|
let(:codec) { DummyCodec.new }
|
39
58
|
let(:input) { LogStash::Inputs::Beats.new({ "port" => 5555, "codec" => codec }) }
|
40
|
-
|
59
|
+
|
60
|
+
let(:ip_address) { "10.0.0.1" }
|
61
|
+
let(:remote_address) { OngoingMethodMock.new("getHostAddress", ip_address) }
|
62
|
+
let(:ctx) {OngoingMethodMock.new("remoteAddress", remote_address)}
|
63
|
+
|
41
64
|
let(:message) { MockMessage.new("abc", { "message" => "hello world"}) }
|
42
65
|
|
43
66
|
subject { described_class.new(queue, input) }
|
@@ -47,28 +70,54 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
47
70
|
end
|
48
71
|
|
49
72
|
context "onNewConnection" do
|
50
|
-
|
51
|
-
|
73
|
+
let(:second_ip_address) { "10.0.0.2" }
|
74
|
+
let(:second_ctx) {OngoingMethodMock.new("getHostAddress", second_ip_address)}
|
75
|
+
|
76
|
+
shared_examples 'a valid new connection' do
|
77
|
+
it "register the connection to the connection list" do
|
78
|
+
expect { subject.onNewConnection(second_ctx) }.to change { subject.connections_list.count }.by(1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it_behaves_like 'a valid new connection'
|
83
|
+
|
84
|
+
context 'with a nil remote address' do
|
85
|
+
let(:second_ip_address) { nil}
|
86
|
+
|
87
|
+
it_behaves_like 'a valid new connection'
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when the channel throws retrieving remote address' do
|
91
|
+
before do
|
92
|
+
allow(second_ctx).to receive(:channel).and_raise('nope')
|
93
|
+
end
|
94
|
+
|
95
|
+
it_behaves_like 'a valid new connection'
|
52
96
|
end
|
53
97
|
|
54
98
|
describe "metrics" do
|
55
99
|
it "new connection should increment connection count" do
|
56
100
|
expect(subject).to receive(:increment_connection_count).once
|
57
|
-
subject.onNewConnection(
|
101
|
+
subject.onNewConnection(second_ctx)
|
58
102
|
end
|
59
103
|
|
60
104
|
describe "peak connections" do
|
105
|
+
let (:ctxes) { [1, 2, 3, 4].inject([]) do |result, element|
|
106
|
+
result << OngoingMethodMock.new("getHostAddress", "10.0.0.#{element}")
|
107
|
+
result
|
108
|
+
end
|
109
|
+
}
|
61
110
|
it "closing and open connections should keep highest count" do
|
62
111
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(1)
|
63
|
-
subject.onNewConnection(
|
112
|
+
subject.onNewConnection(ctxes[0])
|
64
113
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(2)
|
65
|
-
subject.onNewConnection(
|
114
|
+
subject.onNewConnection(ctxes[1])
|
66
115
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(3)
|
67
|
-
subject.onConnectionClose(
|
116
|
+
subject.onConnectionClose(ctxes[1])
|
68
117
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(3)
|
69
|
-
subject.onNewConnection(
|
118
|
+
subject.onNewConnection(ctxes[2])
|
70
119
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(3)
|
71
|
-
subject.onNewConnection(
|
120
|
+
subject.onNewConnection(ctxes[3])
|
72
121
|
expect(subject.instance_eval("@peak_connection_count").value).to eq(4)
|
73
122
|
end
|
74
123
|
end
|
@@ -78,7 +127,7 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
78
127
|
|
79
128
|
context "onNewMessage" do
|
80
129
|
context "when the message is from filebeat" do
|
81
|
-
let(:message) { MockMessage.new("abc", { "message" => "hello world" } )}
|
130
|
+
let(:message) { MockMessage.new("abc", { "message" => "hello world", "@metadata" => {} } )}
|
82
131
|
|
83
132
|
it "extract the event" do
|
84
133
|
subject.onNewMessage(ctx, message)
|
@@ -88,7 +137,7 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
88
137
|
end
|
89
138
|
|
90
139
|
context "when the message is from LSF" do
|
91
|
-
let(:message) { MockMessage.new("abc", { "line" => "hello world" } )}
|
140
|
+
let(:message) { MockMessage.new("abc", { "line" => "hello world", '@metadata' => {} } )}
|
92
141
|
|
93
142
|
it "extract the event" do
|
94
143
|
subject.onNewMessage(ctx, message)
|
@@ -98,7 +147,16 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
98
147
|
end
|
99
148
|
|
100
149
|
context "when the message is from any libbeat" do
|
101
|
-
|
150
|
+
#Requires data modeled as Java, not Ruby since the actual code pulls from Java backed (Netty) object
|
151
|
+
let(:data) do
|
152
|
+
d = HashMap.new
|
153
|
+
d.put('@metadata', HashMap.new)
|
154
|
+
d.put('metric', 1)
|
155
|
+
d.put('name', "super-stats")
|
156
|
+
d
|
157
|
+
end
|
158
|
+
|
159
|
+
let(:message) { MockMessage.new("abc", data)}
|
102
160
|
|
103
161
|
it "extract the event" do
|
104
162
|
subject.onNewMessage(ctx, message)
|
@@ -106,7 +164,40 @@ describe LogStash::Inputs::Beats::MessageListener do
|
|
106
164
|
expect(event.get("message")).to be_nil
|
107
165
|
expect(event.get("metric")).to eq(1)
|
108
166
|
expect(event.get("name")).to eq("super-stats")
|
167
|
+
expect(event.get("[@metadata][ip_address]")).to eq(ip_address)
|
109
168
|
end
|
169
|
+
|
170
|
+
context 'when the remote address is nil' do
|
171
|
+
let(:ctx) { OngoingMethodMock.new("remoteAddress", nil)}
|
172
|
+
|
173
|
+
it 'extracts the event' do
|
174
|
+
subject.onNewMessage(ctx, message)
|
175
|
+
event = queue.pop
|
176
|
+
expect(event.get("message")).to be_nil
|
177
|
+
expect(event.get("metric")).to eq(1)
|
178
|
+
expect(event.get("name")).to eq("super-stats")
|
179
|
+
expect(event.get("[@metadata][ip_address]")).to eq(nil)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'when getting the remote address raises' do
|
184
|
+
let(:raising_ctx) { double("context")}
|
185
|
+
|
186
|
+
before do
|
187
|
+
allow(raising_ctx).to receive(:channel).and_raise("nope")
|
188
|
+
subject.onNewConnection(raising_ctx)
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'extracts the event' do
|
192
|
+
subject.onNewMessage(raising_ctx, message)
|
193
|
+
event = queue.pop
|
194
|
+
expect(event.get("message")).to be_nil
|
195
|
+
expect(event.get("metric")).to eq(1)
|
196
|
+
expect(event.get("name")).to eq("super-stats")
|
197
|
+
expect(event.get("[@metadata][ip_address]")).to eq(nil)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
110
201
|
end
|
111
202
|
end
|
112
203
|
|
data/spec/inputs/beats_spec.rb
CHANGED
@@ -16,43 +16,20 @@ describe LogStash::Inputs::Beats do
|
|
16
16
|
|
17
17
|
context "#register" do
|
18
18
|
context "host related configuration" do
|
19
|
-
let(:config) { super.merge!({ "host" => host, "port" => port, "client_inactivity_timeout" => client_inactivity_timeout }) }
|
19
|
+
let(:config) { super.merge!({ "host" => host, "port" => port, "client_inactivity_timeout" => client_inactivity_timeout, "executor_threads" => threads }) }
|
20
20
|
let(:host) { "192.168.1.20" }
|
21
21
|
let(:port) { 9000 }
|
22
22
|
let(:client_inactivity_timeout) { 400 }
|
23
|
+
let(:threads) { 10 }
|
23
24
|
|
24
25
|
subject(:plugin) { LogStash::Inputs::Beats.new(config) }
|
25
26
|
|
26
27
|
it "sends the required options to the server" do
|
27
|
-
expect(org.logstash.beats.Server).to receive(:new).with(host, port, client_inactivity_timeout)
|
28
|
+
expect(org.logstash.beats.Server).to receive(:new).with(host, port, client_inactivity_timeout, threads)
|
28
29
|
subject.register
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
|
-
context "identity map" do
|
33
|
-
subject(:plugin) { LogStash::Inputs::Beats.new(config) }
|
34
|
-
before { plugin.register }
|
35
|
-
|
36
|
-
context "when using the multiline codec" do
|
37
|
-
let(:codec) { LogStash::Codecs::Multiline.new("pattern" => '^2015',
|
38
|
-
"what" => "previous",
|
39
|
-
"negate" => true) }
|
40
|
-
let(:config) { super.merge({ "codec" => codec }) }
|
41
|
-
|
42
|
-
it "wraps the codec with the identity_map" do
|
43
|
-
expect(plugin.codec).to be_kind_of(LogStash::Codecs::IdentityMapCodec)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
context "when using non buffered codecs" do
|
48
|
-
let(:config) { super.merge({ "codec" => "json" }) }
|
49
|
-
|
50
|
-
it "doesnt wrap the codec with the identity map" do
|
51
|
-
expect(plugin.codec).to be_kind_of(LogStash::Codecs::JSON)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
33
|
it "raise no exception" do
|
57
34
|
plugin = LogStash::Inputs::Beats.new(config)
|
58
35
|
expect { plugin.register }.not_to raise_error
|
@@ -146,6 +123,18 @@ describe LogStash::Inputs::Beats do
|
|
146
123
|
end
|
147
124
|
end
|
148
125
|
end
|
126
|
+
|
127
|
+
context "with multiline codec" do
|
128
|
+
let(:codec) { LogStash::Codecs::Multiline.new("pattern" => '^2015',
|
129
|
+
"what" => "previous",
|
130
|
+
"negate" => true) }
|
131
|
+
let(:config) { super.merge({ "codec" => codec }) }
|
132
|
+
|
133
|
+
it "raise a ConfigurationError when multiline codec is set" do
|
134
|
+
plugin = LogStash::Inputs::Beats.new(config)
|
135
|
+
expect {plugin.register}.to raise_error(LogStash::ConfigurationError, "Multiline codec with beats input is not supported. Please refer to the beats documentation for how to best manage multiline data. See https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html")
|
136
|
+
end
|
137
|
+
end
|
149
138
|
end
|
150
139
|
|
151
140
|
context "when interrupting the plugin" do
|
@@ -32,10 +32,12 @@ module ClientProcessHelpers
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def stop_client
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
unless @process.nil?
|
36
|
+
begin
|
37
|
+
@process.poll_for_exit(5)
|
38
|
+
rescue ChildProcess::TimeoutError
|
39
|
+
Process.kill("KILL", @process.pid)
|
40
|
+
end
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
data/spec/support/helpers.rb
CHANGED
@@ -11,6 +11,13 @@ OPEN_SSL_TOPK8 = "openssl pkcs8 -nocrypt -topk8 -inform PEM -outform PEM"
|
|
11
11
|
#
|
12
12
|
def convert_to_pkcs8(key)
|
13
13
|
out, e, s = Open3.capture3(OPEN_SSL_TOPK8, :stdin_data => key.to_s)
|
14
|
-
|
14
|
+
# attempt to address random failures by trying again
|
15
|
+
unless s.success?
|
16
|
+
sleep 1
|
17
|
+
out, e, s = Open3.capture3(OPEN_SSL_TOPK8, :stdin_data => key.to_s)
|
18
|
+
raise e if e != ""
|
19
|
+
out
|
20
|
+
end
|
21
|
+
|
15
22
|
out
|
16
23
|
end
|
@@ -25,31 +25,126 @@ shared_examples "Common Event Transformation" do
|
|
25
25
|
expect(subject.get("tags")).to include(tag)
|
26
26
|
end
|
27
27
|
|
28
|
-
context
|
29
|
-
let(:
|
30
|
-
let(:event_map) { super.merge({ "host" => already_exist }) }
|
28
|
+
context 'when add_hostname is true' do
|
29
|
+
let(:config) { super.merge({'add_hostname' => true})}
|
31
30
|
|
32
|
-
|
33
|
-
|
31
|
+
context 'when a host is provided in beat.host.name' do
|
32
|
+
let(:already_exist) { "already_exist" }
|
33
|
+
let(:producer_host) { "newhost01" }
|
34
|
+
let(:event_map) { super.merge({ "beat" => { "host" => {"name" => producer_host }}}) }
|
35
|
+
|
36
|
+
context "when no `host` key already exists on the event" do
|
37
|
+
it "does not set the host value" do
|
38
|
+
expect(subject.get("host")).to be_nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when `host` key exists on the event" do
|
43
|
+
let(:already_exist) { "already_exist" }
|
44
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
45
|
+
|
46
|
+
it "doesn't override it" do
|
47
|
+
expect(subject.get("host")).to eq(already_exist)
|
48
|
+
end
|
49
|
+
end
|
34
50
|
end
|
35
|
-
end
|
36
51
|
|
37
|
-
|
38
|
-
|
39
|
-
|
52
|
+
context "when a host is set in `beat.hostname`" do
|
53
|
+
let(:producer_host) { "newhost01" }
|
54
|
+
let(:event_map) { super.merge({ "beat" => { "hostname" => producer_host }}) }
|
40
55
|
|
41
|
-
|
42
|
-
|
43
|
-
|
56
|
+
context "when no `host` key already exists on the event" do
|
57
|
+
it "copies the value in `beat.hostname` to `host`" do
|
58
|
+
expect(subject.get("host")).to eq(producer_host)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when `host` key exists on the event" do
|
63
|
+
let(:already_exist) { "already_exist" }
|
64
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
65
|
+
|
66
|
+
it "doesn't override it" do
|
67
|
+
expect(subject.get("host")).to eq(already_exist)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when no host is provided in beat" do
|
73
|
+
context "when no `host` key already exists on the event" do
|
74
|
+
it "does not set the host" do
|
75
|
+
expect(subject.get("host")).to be_nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when `host` key already exists on the event" do
|
80
|
+
let(:already_exist) { "already_exist" }
|
81
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
82
|
+
|
83
|
+
it "doesn't override it" do
|
84
|
+
expect(subject.get("host")).to eq(already_exist)
|
85
|
+
end
|
44
86
|
end
|
45
87
|
end
|
88
|
+
end
|
46
89
|
|
47
|
-
|
90
|
+
context 'when add hostname is false' do
|
91
|
+
let(:config) { super.merge({'add_hostname' => false})}
|
92
|
+
|
93
|
+
context 'when a host is provided in beat.host.name' do
|
48
94
|
let(:already_exist) { "already_exist" }
|
49
|
-
let(:
|
95
|
+
let(:producer_host) { "newhost01" }
|
96
|
+
let(:event_map) { super.merge({ "beat" => { "host" => {"name" => producer_host }}}) }
|
97
|
+
|
98
|
+
context "when no `host` key already exists on the event" do
|
99
|
+
it "does not set the host" do
|
100
|
+
expect(subject.get("host")).to be_nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when `host` key already exists on the event" do
|
105
|
+
let(:already_exist) { "already_exist" }
|
106
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
107
|
+
|
108
|
+
it "doesn't override it" do
|
109
|
+
expect(subject.get("host")).to eq(already_exist)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "when a host is provided in `beat.hostname`" do
|
115
|
+
let(:producer_host) { "newhost01" }
|
116
|
+
let(:event_map) { super.merge({ "beat" => { "hostname" => producer_host }}) }
|
117
|
+
|
118
|
+
context "when no `host` key already exists on the event" do
|
119
|
+
it "does not set the host" do
|
120
|
+
expect(subject.get("host")).to be_nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when `host` key already exists on the event" do
|
125
|
+
let(:already_exist) { "already_exist" }
|
126
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
127
|
+
|
128
|
+
it "doesn't override it" do
|
129
|
+
expect(subject.get("host")).to eq(already_exist)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when no host is provided in beat" do
|
135
|
+
context "when no `host` key already exists on the event" do
|
136
|
+
it "does not set the host" do
|
137
|
+
expect(subject.get("host")).to be_nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "when `host` key already exists on the event" do
|
142
|
+
let(:already_exist) { "already_exist" }
|
143
|
+
let(:event_map) { super.merge({ "host" => already_exist }) }
|
50
144
|
|
51
|
-
|
52
|
-
|
145
|
+
it "doesn't override it" do
|
146
|
+
expect(subject.get("host")).to eq(already_exist)
|
147
|
+
end
|
53
148
|
end
|
54
149
|
end
|
55
150
|
end
|
Binary file
|
data/vendor/jar-dependencies/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9.jar
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|