logstash-output-lmlogs 1.2.1 → 2.0.0

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
  SHA256:
3
- metadata.gz: 3236f68981e8e3fb68a9335240874b9f8fb93b59372893425992f0c9c86f2895
4
- data.tar.gz: 850265953883226fd2c82b3ad00acf894667aaca86396af454af6d9d59411acc
3
+ metadata.gz: 46b4784b47b720c638e2f6cb53ace887c3ff3bd821cc27ca675fc3bf6b5b3325
4
+ data.tar.gz: 2dd4c277e4b769d4580ea1474d00f058d2f08f1d718da6e715c51ab16f722679
5
5
  SHA512:
6
- metadata.gz: 86a1e6be32d0c8f976371dd9441aa282c980a7886e4940b5e298ae28406c5f9e1934b751264a40010e7b94a307076248274c350ae87e51ce33d1b5cea1a1b57a
7
- data.tar.gz: 01ca2ae8f258141614eef6312fe18c394b7602bd9e88e86c57d6f810471ee204889da918da4704c999d2942ef368925ba675df9a6bc2fb4169e842beb4fe7455
6
+ metadata.gz: 118161034fbd6b10b946449a75ccabc6fcce733006824711bdbcde2fff864f65ac249bd1de2f78600e975e71f47740881e946c4f2335a82956e6a8b130f44af5
7
+ data.tar.gz: f28a74d295e3f14bca4bfed4389c5dd32cfaaecb8f5b550168f2542494b0876c50b95d42661d101879284f9a7f532a74551b7fa1989abf83289b046f210e33de
data/CHANGELOG.md CHANGED
@@ -1,2 +1,18 @@
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
15
+ ## 1.3.1
16
+ - Fix user agent populated in headers
17
+ ## 2.0.0
18
+ - Dont send event metadata by default. Add config include_metadata_keys for including custom metadata
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/logstash-output-lmlogs.svg)](https://badge.fury.io/rb/logstash-output-lmlogs)
2
2
 
3
- This plugin sends Logstash events to the [Logicmonitor Logs](https://www.logicmonitor.com)
3
+ This plugin sends Logstash events to the [Logicmonitor Logs](https://www.logicmonitor.com)
4
4
 
5
5
  # Getting started
6
6
 
@@ -20,6 +20,7 @@ output {
20
20
  }
21
21
  }
22
22
  ```
23
+ You would need either `access_id` and `access_id` both or `bearer_token` for authentication with Logicmonitor.
23
24
 
24
25
 
25
26
 
@@ -27,27 +28,28 @@ output {
27
28
 
28
29
  | Option | Description| Default |
29
30
  | --- | --- | --- |
30
- | batch_size | Event batch size to send to LM Logs.| 100 |
31
+ | batch_size | Event batch size to send to LM Logs.| 100 |
31
32
  | message_key | Key that will be used by the plugin as the system key | "message" |
32
33
  | lm_property | Key that will be used by LM to match resource based on property | "system.hostname" |
33
34
  | keep_timestamp | If false, LM Logs will use the ingestion timestamp as the event timestamp | true |
34
35
  | timestamp_is_key | If true, LM Logs will use a specified key as the event timestamp | false |
35
36
  | timestamp_key | If timestamp_is_key is set, LM Logs will use this key in the event as the timestamp | "logtimestamp" |
36
- | include_metadata | If false, the metadata fields will not be sent to LM Logs | true |
37
+ | include_metadata | If true, all metadata fields will be sent to LM Logs | false |
38
+ | include_metadata_keys | Array of json keys for which plugin looks for these keys and adds as event meatadata. A dot "." can be used to add nested subjson. If config `include_metadata` is set to true, all metadata will be sent regardless of this config. | [] |
37
39
 
38
40
  See the [source code](lib/logstash/outputs/lmlogs.rb) for the full list of options
39
41
 
40
42
  The syntax for `message_key` and `source_key` values are available in the [Logstash Event API Documentation](https://www.elastic.co/guide/en/logstash/current/event-api.html)
41
43
 
42
- ## Known issues
44
+ ## Known issues
43
45
  - Installation of the plugin fails on Logstash 6.2.1.
44
-
45
-
46
+
47
+
46
48
  ## Contributing
47
-
49
+
48
50
  Bug reports and pull requests are welcome. This project is intended to
49
51
  be a safe, welcoming space for collaboration.
50
-
52
+
51
53
  ## Development
52
-
54
+
53
55
  We use docker to build the plugin. You can build it by running `docker-compose run jruby gem build logstash-output-lmlogs.gemspec `
@@ -8,6 +8,7 @@ require 'date'
8
8
  require 'base64'
9
9
  require 'openssl'
10
10
  require 'manticore'
11
+ require_relative "version"
11
12
 
12
13
  # An example output that does nothing.
13
14
  class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
@@ -30,7 +31,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
30
31
 
31
32
  # Keep logstash timestamp
32
33
  config :keep_timestamp, :validate => :boolean, :default => true
33
-
34
+
34
35
  # Use a configured message key for timestamp values
35
36
  # Valid timestamp formats are ISO8601 strings or epoch in seconds, milliseconds or nanoseconds
36
37
  config :timestamp_is_key, :validate => :boolean, :default => false
@@ -91,13 +92,19 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
91
92
  config :portal_name, :validate => :string, :required => true
92
93
 
93
94
  # Username to use for HTTP auth.
94
- config :access_id, :validate => :string, :required => true
95
+ config :access_id, :validate => :string, :required => false, :default => nil
95
96
 
96
97
  # Include/Exclude metadata from sending to LM Logs
97
- config :include_metadata, :validate => :boolean, :default => true
98
+ config :include_metadata, :validate => :boolean, :default => false
98
99
 
99
100
  # Password to use for HTTP auth
100
- config :access_key, :validate => :password, :required => true
101
+ config :access_key, :validate => :password, :required => false, :default => nil
102
+
103
+ # Use bearer token instead of access key/id for authentication.
104
+ config :bearer_token, :validate => :password, :required => false, :default => nil
105
+
106
+ # json keys for which plugin looks for these keys and adds as event meatadata. A dot "." can be used to add nested subjson.
107
+ config :include_metadata_keys, :validate => :array, :required => false, :default => []
101
108
 
102
109
  @@MAX_PAYLOAD_SIZE = 8*1024*1024
103
110
 
@@ -110,8 +117,16 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
110
117
  @total_failed = 0
111
118
  logger.info("Initialized LogicMonitor output plugin with configuration",
112
119
  :host => @host)
113
- logger.info("Max Payload Size: ",
120
+ logger.info("Max Payload Size: ",
114
121
  :size => @@MAX_PAYLOAD_SIZE)
122
+ configure_auth
123
+
124
+ @final_metadata_keys = Hash.new
125
+ if @include_metadata_keys.any?
126
+ include_metadata_keys.each do | nested_key |
127
+ @final_metadata_keys[nested_key] = nested_key.to_s.split('.')
128
+ end
129
+ end
115
130
 
116
131
  end # def register
117
132
 
@@ -137,19 +152,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
137
152
  @proxy
138
153
  end
139
154
 
140
- if @access_id
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)
155
+ log_debug("manticore client config: ", :client => c)
153
156
  return c
154
157
  end
155
158
 
@@ -168,21 +171,35 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
168
171
  @client.close
169
172
  end
170
173
 
171
-
174
+ def configure_auth
175
+ @use_bearer_instead_of_lmv1 = false
176
+ if @access_id == nil || @access_key.value == nil
177
+ @logger.info "Access Id or access key null. Using bearer token for authentication."
178
+ @use_bearer_instead_of_lmv1 = true
179
+ end
180
+ if @use_bearer_instead_of_lmv1 && @bearer_token.value == nil
181
+ @logger.error "Bearer token not specified. Either access_id and access_key both or bearer_token must be specified for authentication with Logicmonitor."
182
+ raise LogStash::ConfigurationError, 'No valid authentication specified. Either access_id and access_key both or bearer_token must be specified for authentication with Logicmonitor.'
183
+ end
184
+ end
172
185
  def generate_auth_string(body)
173
- timestamp = DateTime.now.strftime('%Q')
174
- hash_this = "POST#{timestamp}#{body}/log/ingest"
175
- sign_this = OpenSSL::HMAC.hexdigest(
176
- OpenSSL::Digest.new('sha256'),
177
- "#{@access_key.value}",
178
- hash_this
179
- )
180
- signature = Base64.strict_encode64(sign_this)
181
- "LMv1 #{@access_id}:#{signature}:#{timestamp}"
186
+ if @use_bearer_instead_of_lmv1
187
+ return "Bearer #{@bearer_token.value}"
188
+ else
189
+ timestamp = DateTime.now.strftime('%Q')
190
+ hash_this = "POST#{timestamp}#{body}/log/ingest"
191
+ sign_this = OpenSSL::HMAC.hexdigest(
192
+ OpenSSL::Digest.new('sha256'),
193
+ "#{@access_key.value}",
194
+ hash_this
195
+ )
196
+ signature = Base64.strict_encode64(sign_this)
197
+ return "LMv1 #{@access_id}:#{signature}:#{timestamp}"
198
+ end
182
199
  end
183
200
 
184
201
  def send_batch(events)
185
- log_debug("Started sending logs to LM: ",
202
+ log_debug("Started sending logs to LM: ",
186
203
  :time => Time::now.utc)
187
204
  url = "https://" + @portal_name + ".logicmonitor.com/rest/log/ingest"
188
205
  body = events.to_json
@@ -191,7 +208,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
191
208
  :body => body,
192
209
  :headers => {
193
210
  "Content-Type" => "application/json",
194
- "User-Agent" => "LM Logs Logstash Plugin",
211
+ "User-Agent" => "lm-logs-logstash/" + LmLogsLogstashPlugin::VERSION,
195
212
  "Authorization" => "#{auth_string}"
196
213
  }
197
214
  })
@@ -249,7 +266,7 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
249
266
  elsif debug
250
267
  @logger.debug(message, *opts)
251
268
  end
252
- end
269
+ end
253
270
 
254
271
  public
255
272
  def multi_receive(events)
@@ -260,34 +277,48 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
260
277
  events.each_slice(@batch_size) do |chunk|
261
278
  documents = []
262
279
  chunk.each do |event|
263
- event_json = JSON.parse(event.to_json)
264
- lmlogs_event = {}
265
-
266
- if @include_metadata
267
- lmlogs_event = event_json
268
- lmlogs_event.delete("@timestamp") # remove redundant timestamp field
269
- if lmlogs_event.dig("event", "original") != nil
270
- lmlogs_event["event"].delete("original") # remove redundant log field
271
- end
272
- end
273
280
 
274
- lmlogs_event["message"] = event.get(@message_key).to_s
275
- lmlogs_event["_lm.resourceId"] = {}
276
- lmlogs_event["_lm.resourceId"]["#{@lm_property}"] = event.get(@property_key.to_s)
281
+ documents = isValidPayloadSize(documents, processEvent(event), @@MAX_PAYLOAD_SIZE)
282
+ end
283
+ send_batch(documents)
284
+ end
285
+ end
277
286
 
278
- if @keep_timestamp
279
- lmlogs_event["timestamp"] = event.get("@timestamp")
280
- end
281
-
282
- if @timestamp_is_key
283
- lmlogs_event["timestamp"] = event.get(@timestamp_key.to_s)
284
- end
285
287
 
286
- documents = isValidPayloadSize(documents,lmlogs_event,@@MAX_PAYLOAD_SIZE)
288
+ def processEvent(event)
289
+ event_json = JSON.parse(event.to_json)
290
+ lmlogs_event = {}
287
291
 
292
+ if @include_metadata
293
+ lmlogs_event = event_json
294
+ lmlogs_event.delete("@timestamp") # remove redundant timestamp field
295
+ if lmlogs_event.dig("event", "original") != nil
296
+ lmlogs_event["event"].delete("original") # remove redundant log field
297
+ end
298
+ elsif @final_metadata_keys
299
+ @final_metadata_keys.each do | key, value |
300
+ nestedVal = event_json
301
+ value.each { |x| nestedVal = nestedVal[x] }
302
+ if nestedVal != nil
303
+ lmlogs_event[key] = nestedVal
304
+ end
288
305
  end
289
- send_batch(documents)
290
306
  end
307
+
308
+ lmlogs_event["message"] = event.get(@message_key).to_s
309
+ lmlogs_event["_lm.resourceId"] = {}
310
+ lmlogs_event["_lm.resourceId"]["#{@lm_property}"] = event.get(@property_key.to_s)
311
+
312
+ if @keep_timestamp
313
+ lmlogs_event["timestamp"] = event.get("@timestamp")
314
+ end
315
+
316
+ if @timestamp_is_key
317
+ lmlogs_event["timestamp"] = event.get(@timestamp_key.to_s)
318
+ end
319
+
320
+ return lmlogs_event
321
+
291
322
  end
292
323
 
293
324
  def log_failure(message, opts)
@@ -295,10 +326,10 @@ class LogStash::Outputs::LMLogs < LogStash::Outputs::Base
295
326
  end
296
327
 
297
328
  def isValidPayloadSize(documents,lmlogs_event,max_payload_size)
298
- if (documents.to_json.bytesize + lmlogs_event.to_json.bytesize) > max_payload_size
329
+ if (documents.to_json.bytesize + lmlogs_event.to_json.bytesize) > max_payload_size
299
330
  send_batch(documents)
300
331
  documents = []
301
-
332
+
302
333
  end
303
334
  documents.push(lmlogs_event)
304
335
  return documents
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LmLogsLogstashPlugin
4
+ VERSION = '2.0.0'
5
+ end
@@ -1,6 +1,14 @@
1
+
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require "logstash/outputs/version.rb"
6
+
7
+
8
+
1
9
  Gem::Specification.new do |s|
2
10
  s.name = 'logstash-output-lmlogs'
3
- s.version = '1.2.1'
11
+ s.version = LmLogsLogstashPlugin::VERSION
4
12
  s.licenses = ['Apache-2.0']
5
13
  s.summary = "Logstash output plugin for LM Logs"
6
14
  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"
@@ -25,4 +33,5 @@ Gem::Specification.new do |s|
25
33
  s.add_runtime_dependency 'manticore', '>= 0.5.2', '< 1.0.0'
26
34
 
27
35
  s.add_development_dependency 'logstash-devutils'
36
+ s.add_development_dependency 'hashdiff', '>= 1.0.0'
28
37
  end
@@ -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
@@ -0,0 +1,86 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/outputs/lmlogs"
4
+ require "logstash/event"
5
+ require "hashdiff"
6
+
7
+
8
+ describe LogStash::Outputs::LMLogs do
9
+
10
+
11
+ let(:logstash_event) {LogStash::Event.new("message" => "hello this is log 1",
12
+ "host" => "host1",
13
+ "nested1" => {"nested2" => {"nested3" => "value"},
14
+ "nested2a" => {"nested3a" => {"nested4" => "valueA"}},
15
+ "nested2b" => {"nested3b" => "value"}
16
+ },
17
+ "nested1_" => "value",
18
+ "nested" => {"nested2" => {"nested3" => "value",
19
+ "nested3b" => "value"},
20
+ "nested_ignored" => "somevalue"
21
+ }
22
+ )}
23
+ let(:sample_lm_logs_event){{"message" => "hello this is log 1", "_lm.resourceId" => {"test.property" => "host1"}, "timestamp" => "2021-03-22T04:28:55.907121106Z"}}
24
+ let(:include_metadata_keys) {["host", "nested1.nested2.nested3", "nested1.nested2a", "nested.nested2" ]}
25
+
26
+ def create_output_plugin_with_conf(conf)
27
+ return LogStash::Outputs::LMLogs.new(conf)
28
+ end
29
+
30
+ def check_same_hash(h1,h2)
31
+
32
+ end
33
+
34
+ it "default behaviour" do
35
+ puts "default behaviour"
36
+ plugin = create_output_plugin_with_conf({
37
+ "portal_name" => "localhost",
38
+ "access_id" => "abcd",
39
+ "access_key" => "abcd",
40
+ "lm_property" => "system.hostname",
41
+ "property_key" => "host"
42
+ })
43
+ constructed_event = plugin.processEvent(logstash_event)
44
+ expected_event = {
45
+ "message" => "hello this is log 1",
46
+ "timestamp" => logstash_event.timestamp,
47
+ "_lm.resourceId" => {"system.hostname" => "host1"},
48
+
49
+ }
50
+ puts " actual : #{constructed_event} \n expected : #{expected_event}"
51
+
52
+ expect(Hashdiff.diff(constructed_event,expected_event)).to eq([])
53
+ end
54
+
55
+ it "with include_metadata set to true" do
56
+ puts "with include_metadata set to true"
57
+ plugin = create_output_plugin_with_conf({
58
+ "portal_name" => "localhost",
59
+ "access_id" => "abcd",
60
+ "access_key" => "abcd",
61
+ "lm_property" => "system.hostname",
62
+ "property_key" => "host",
63
+ "include_metadata" => true
64
+ })
65
+ constructed_event = plugin.processEvent(logstash_event)
66
+ expected_event = {
67
+ "message" => "hello this is log 1",
68
+ "timestamp" => logstash_event.timestamp,
69
+ "@version" => "1",
70
+ "_lm.resourceId" => {"system.hostname" => "host1"},
71
+ "host" => "host1",
72
+ "nested1" => {"nested2" => {"nested3" => "value"},
73
+ "nested2a" => {"nested3a" => {"nested4" => "valueA"}},
74
+ "nested2b" => {"nested3b" => "value"}
75
+ },
76
+ "nested1_" => "value",
77
+ "nested" => {"nested2" => {"nested3" => "value",
78
+ "nested3b" => "value"},
79
+ "nested_ignored" => "somevalue"
80
+ }
81
+ }
82
+ puts " actual : #{constructed_event} \n expected : #{expected_event}"
83
+ puts " hash diff : #{Hashdiff.diff(constructed_event,expected_event)}"
84
+ expect(Hashdiff.diff(constructed_event,expected_event)).to eq([])
85
+ end
86
+ 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.2.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LogicMonitor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-23 00:00:00.000000000 Z
11
+ date: 2023-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -78,6 +78,20 @@ dependencies:
78
78
  - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
+ - !ruby/object:Gem::Dependency
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 1.0.0
87
+ name: hashdiff
88
+ prerelease: false
89
+ type: :development
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 1.0.0
81
95
  description: This gem is a Logstash plugin required to be installed on top of the
82
96
  Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
83
97
  gem is not a stand-alone program
@@ -90,8 +104,11 @@ files:
90
104
  - Gemfile
91
105
  - README.md
92
106
  - lib/logstash/outputs/lmlogs.rb
107
+ - lib/logstash/outputs/version.rb
93
108
  - logstash-output-lmlogs.gemspec
109
+ - spec/outputs/auth_spec.rb
94
110
  - spec/outputs/lmlogs_spec.rb
111
+ - spec/outputs/metadata_spec.rb
95
112
  homepage: https://www.logicmonitor.com
96
113
  licenses:
97
114
  - Apache-2.0
@@ -119,4 +136,6 @@ signing_key:
119
136
  specification_version: 4
120
137
  summary: Logstash output plugin for LM Logs
121
138
  test_files:
139
+ - spec/outputs/auth_spec.rb
122
140
  - spec/outputs/lmlogs_spec.rb
141
+ - spec/outputs/metadata_spec.rb