logstash-output-lmlogs 1.2.1 → 1.3.0
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 +12 -0
- data/lib/logstash/outputs/lmlogs.rb +39 -34
- data/logstash-output-lmlogs.gemspec +1 -1
- data/spec/outputs/auth_spec.rb +60 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 870bd26e9fabeb697cb8dd8f66eeb7f243b4be3fcf51c0d3babb81260a08b3d9
|
4
|
+
data.tar.gz: 548fff67d397ef9a6c51a2bebb0c4f44d2b3decd57faa801bd9ac2e1048edad2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 504cdc43d302a8d504a38627e3b914e8514331ae889dbcfba7fa3f0da6f010aeb09aa19437f5d32e73e100db4d0f839f9c182eb4135b78cfb1d538a6ea0f4314
|
7
|
+
data.tar.gz: 78a8b8b391c4887bfa5a06b12d044d03c9d3b9f2cfdc9231ae5a9d0a70ac28d824e59ce493cf8a4f3d2fc7675ecd0a7ce8b7d71c60fa8fc57664a7937793ad07
|
data/CHANGELOG.md
CHANGED
@@ -1,2 +1,14 @@
|
|
1
1
|
## 1.0.0
|
2
2
|
- First version of the plugin
|
3
|
+
## 1.0.1
|
4
|
+
- Proxy support
|
5
|
+
## 1.0.2
|
6
|
+
- Update debug logs
|
7
|
+
## 1.1.0
|
8
|
+
- Disable mfa for gem push
|
9
|
+
## 1.2.0
|
10
|
+
- Add metadata by default to every log
|
11
|
+
## 1.2.1
|
12
|
+
- Fix ensuring metadata exists before deleting the original while forwarding to lm-logs
|
13
|
+
## 1.3.0
|
14
|
+
- Add bearer token support for authentication with Logicmonitor
|
@@ -30,7 +30,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
30
30
|
|
31
31
|
# Keep logstash timestamp
|
32
32
|
config :keep_timestamp, :validate => :boolean, :default => true
|
33
|
-
|
33
|
+
|
34
34
|
# Use a configured message key for timestamp values
|
35
35
|
# Valid timestamp formats are ISO8601 strings or epoch in seconds, milliseconds or nanoseconds
|
36
36
|
config :timestamp_is_key, :validate => :boolean, :default => false
|
@@ -91,13 +91,16 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
91
91
|
config :portal_name, :validate => :string, :required => true
|
92
92
|
|
93
93
|
# Username to use for HTTP auth.
|
94
|
-
config :access_id, :validate => :string, :required =>
|
94
|
+
config :access_id, :validate => :string, :required => false, :default => nil
|
95
95
|
|
96
96
|
# Include/Exclude metadata from sending to LM Logs
|
97
97
|
config :include_metadata, :validate => :boolean, :default => true
|
98
98
|
|
99
99
|
# Password to use for HTTP auth
|
100
|
-
config :access_key, :validate => :password, :required =>
|
100
|
+
config :access_key, :validate => :password, :required => false, :default => nil
|
101
|
+
|
102
|
+
# Use bearer token instead of access key/id for authentication.
|
103
|
+
config :bearer_token, :validate => :password, :required => false, :default => nil
|
101
104
|
|
102
105
|
@@MAX_PAYLOAD_SIZE = 8*1024*1024
|
103
106
|
|
@@ -110,9 +113,9 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
110
113
|
@total_failed = 0
|
111
114
|
logger.info("Initialized LogicMonitor output plugin with configuration",
|
112
115
|
:host => @host)
|
113
|
-
logger.info("Max Payload Size: ",
|
116
|
+
logger.info("Max Payload Size: ",
|
114
117
|
:size => @@MAX_PAYLOAD_SIZE)
|
115
|
-
|
118
|
+
configure_auth
|
116
119
|
end # def register
|
117
120
|
|
118
121
|
def client_config
|
@@ -137,19 +140,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
137
140
|
@proxy
|
138
141
|
end
|
139
142
|
|
140
|
-
|
141
|
-
if !@access_key || !@access_key.value
|
142
|
-
raise ::LogStash::ConfigurationError, "access_id '#{@access_id}' specified without access_key!"
|
143
|
-
end
|
144
|
-
|
145
|
-
# Symbolize keys if necessary
|
146
|
-
# c[:auth] = {
|
147
|
-
# :user => @access_id,
|
148
|
-
# :password => @access_key.value,
|
149
|
-
# :eager => true
|
150
|
-
# }
|
151
|
-
end
|
152
|
-
log_debug("manticore client config: ", :client => c)
|
143
|
+
log_debug("manticore client config: ", :client => c)
|
153
144
|
return c
|
154
145
|
end
|
155
146
|
|
@@ -168,21 +159,35 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
168
159
|
@client.close
|
169
160
|
end
|
170
161
|
|
171
|
-
|
162
|
+
def configure_auth
|
163
|
+
@use_bearer_instead_of_lmv1 = false
|
164
|
+
if @access_id == nil || @access_key.value == nil
|
165
|
+
@logger.info "Access Id or access key null. Using bearer token for authentication."
|
166
|
+
@use_bearer_instead_of_lmv1 = true
|
167
|
+
end
|
168
|
+
if @use_bearer_instead_of_lmv1 && @bearer_token.value == nil
|
169
|
+
@logger.error "Bearer token not specified. Either access_id and access_key both or bearer_token must be specified for authentication with Logicmonitor."
|
170
|
+
raise LogStash::ConfigurationError, 'No valid authentication specified. Either access_id and access_key both or bearer_token must be specified for authentication with Logicmonitor.'
|
171
|
+
end
|
172
|
+
end
|
172
173
|
def generate_auth_string(body)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
174
|
+
if @use_bearer_instead_of_lmv1
|
175
|
+
return "Bearer #{@bearer_token.value}"
|
176
|
+
else
|
177
|
+
timestamp = DateTime.now.strftime('%Q')
|
178
|
+
hash_this = "POST#{timestamp}#{body}/log/ingest"
|
179
|
+
sign_this = OpenSSL::HMAC.hexdigest(
|
180
|
+
OpenSSL::Digest.new('sha256'),
|
181
|
+
"#{@access_key.value}",
|
182
|
+
hash_this
|
183
|
+
)
|
184
|
+
signature = Base64.strict_encode64(sign_this)
|
185
|
+
return "LMv1 #{@access_id}:#{signature}:#{timestamp}"
|
186
|
+
end
|
182
187
|
end
|
183
188
|
|
184
189
|
def send_batch(events)
|
185
|
-
log_debug("Started sending logs to LM: ",
|
190
|
+
log_debug("Started sending logs to LM: ",
|
186
191
|
:time => Time::now.utc)
|
187
192
|
url = "https://" + @portal_name + ".logicmonitor.com/rest/log/ingest"
|
188
193
|
body = events.to_json
|
@@ -249,7 +254,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
249
254
|
elsif debug
|
250
255
|
@logger.debug(message, *opts)
|
251
256
|
end
|
252
|
-
end
|
257
|
+
end
|
253
258
|
|
254
259
|
public
|
255
260
|
def multi_receive(events)
|
@@ -268,7 +273,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
268
273
|
lmlogs_event.delete("@timestamp") # remove redundant timestamp field
|
269
274
|
if lmlogs_event.dig("event", "original") != nil
|
270
275
|
lmlogs_event["event"].delete("original") # remove redundant log field
|
271
|
-
end
|
276
|
+
end
|
272
277
|
end
|
273
278
|
|
274
279
|
lmlogs_event["message"] = event.get(@message_key).to_s
|
@@ -278,7 +283,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
278
283
|
if @keep_timestamp
|
279
284
|
lmlogs_event["timestamp"] = event.get("@timestamp")
|
280
285
|
end
|
281
|
-
|
286
|
+
|
282
287
|
if @timestamp_is_key
|
283
288
|
lmlogs_event["timestamp"] = event.get(@timestamp_key.to_s)
|
284
289
|
end
|
@@ -295,10 +300,10 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
|
|
295
300
|
end
|
296
301
|
|
297
302
|
def isValidPayloadSize(documents,lmlogs_event,max_payload_size)
|
298
|
-
if (documents.to_json.bytesize + lmlogs_event.to_json.bytesize) > max_payload_size
|
303
|
+
if (documents.to_json.bytesize + lmlogs_event.to_json.bytesize) > max_payload_size
|
299
304
|
send_batch(documents)
|
300
305
|
documents = []
|
301
|
-
|
306
|
+
|
302
307
|
end
|
303
308
|
documents.push(lmlogs_event)
|
304
309
|
return documents
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-lmlogs'
|
3
|
-
s.version = '1.
|
3
|
+
s.version = '1.3.0'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "Logstash output plugin for LM Logs"
|
6
6
|
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"
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/devutils/rspec/spec_helper"
|
3
|
+
require "logstash/outputs/lmlogs"
|
4
|
+
require "logstash/event"
|
5
|
+
|
6
|
+
describe LogStash::Outputs::LMLogs do
|
7
|
+
|
8
|
+
let(:sample_lm_logs_event){{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"}}
|
9
|
+
|
10
|
+
def create_output_plugin_with_conf(conf)
|
11
|
+
return LogStash::Outputs::LMLogs.new(conf)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "with no auth specified" do
|
15
|
+
puts "auth test"
|
16
|
+
plugin = create_output_plugin_with_conf({
|
17
|
+
"portal_name" => "localhost"
|
18
|
+
})
|
19
|
+
expect { plugin.configure_auth() }.to raise_error(LogStash::ConfigurationError)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "access_key id is specified with no bearer" do
|
23
|
+
puts "auth test"
|
24
|
+
plugin = create_output_plugin_with_conf({
|
25
|
+
"portal_name" => "localhost",
|
26
|
+
"access_id" => "abcd",
|
27
|
+
"access_key" => "abcd"
|
28
|
+
})
|
29
|
+
plugin.configure_auth()
|
30
|
+
auth_string = plugin.generate_auth_string([sample_lm_logs_event])
|
31
|
+
|
32
|
+
expect(auth_string).to start_with("LMv1 abcd:")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "when access id /key not specified but bearer specified" do
|
36
|
+
plugin = create_output_plugin_with_conf({
|
37
|
+
"portal_name" => "localhost",
|
38
|
+
"access_id" => "abcd",
|
39
|
+
"bearer_token" => "abcd"
|
40
|
+
})
|
41
|
+
plugin.configure_auth()
|
42
|
+
auth_string = plugin.generate_auth_string([sample_lm_logs_event])
|
43
|
+
|
44
|
+
expect(auth_string).to eq("Bearer abcd")
|
45
|
+
end
|
46
|
+
|
47
|
+
it "when access id /key bearer all specified, use lmv1" do
|
48
|
+
puts "auth test"
|
49
|
+
plugin = create_output_plugin_with_conf({
|
50
|
+
"portal_name" => "localhost",
|
51
|
+
"access_id" => "abcd",
|
52
|
+
"access_key" => "abcd",
|
53
|
+
"bearer_token" => "abcd"
|
54
|
+
})
|
55
|
+
plugin.configure_auth()
|
56
|
+
auth_string = plugin.generate_auth_string([sample_lm_logs_event])
|
57
|
+
|
58
|
+
expect(auth_string).to start_with("LMv1 abcd:")
|
59
|
+
end
|
60
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-lmlogs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- LogicMonitor
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- README.md
|
92
92
|
- lib/logstash/outputs/lmlogs.rb
|
93
93
|
- logstash-output-lmlogs.gemspec
|
94
|
+
- spec/outputs/auth_spec.rb
|
94
95
|
- spec/outputs/lmlogs_spec.rb
|
95
96
|
homepage: https://www.logicmonitor.com
|
96
97
|
licenses:
|
@@ -119,4 +120,5 @@ signing_key:
|
|
119
120
|
specification_version: 4
|
120
121
|
summary: Logstash output plugin for LM Logs
|
121
122
|
test_files:
|
123
|
+
- spec/outputs/auth_spec.rb
|
122
124
|
- spec/outputs/lmlogs_spec.rb
|