logstash-input-snmp 1.3.0 → 1.3.1
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 +3 -0
- data/lib/logstash/inputs/snmp/base_client.rb +2 -2
- data/lib/logstash/inputs/snmp.rb +56 -36
- data/logstash-input-snmp.gemspec +1 -1
- data/spec/inputs/snmp_spec.rb +123 -40
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13fdcfbd3e486a466a7fa32e1de3e6bbdccd30779f5eb4fce9ef8645355c8322
|
4
|
+
data.tar.gz: b8e80f54fbe399f262e48aff1fd614d578b16d493cded3e15446593ebffd1f93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc44139cfc59066ffa89fc916903e4507972b9650cc056ee0bb897a8028dcf93abf30c07627926ce717a0da275d084ebf45b7e631355d04752ef55e868eef3f7
|
7
|
+
data.tar.gz: 1ca064497bd573c6d3de4c00bf0d744fb14339926d61203d6a7e74fcbb6887c64f784e32ecb579db11fc2ff849c329b7479df92a44b24803d653b316ab41cbd6
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
## 1.3.1
|
2
|
+
- Refactor: handle no response(s) wout error logging [#105](https://github.com/logstash-plugins/logstash-input-snmp/pull/105)
|
3
|
+
|
1
4
|
## 1.3.0
|
2
5
|
- Feat: ECS compliance + optional target [#99](https://github.com/logstash-plugins/logstash-input-snmp/pull/99)
|
3
6
|
- Internal: update to Gradle 7 [#102](https://github.com/logstash-plugins/logstash-input-snmp/pull/102)
|
@@ -52,13 +52,13 @@ module LogStash
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def walk(oid, strip_root = 0, path_length = 0)
|
55
|
-
result = {}
|
56
|
-
|
57
55
|
pdufactory = get_pdu_factory
|
58
56
|
treeUtils = TreeUtils.new(@snmp, pdufactory)
|
59
57
|
events = treeUtils.getSubtree(@target, OID.new(oid))
|
60
58
|
return nil if events.nil? || events.size == 0
|
61
59
|
|
60
|
+
result = {}
|
61
|
+
|
62
62
|
events.each do |event|
|
63
63
|
next if event.nil?
|
64
64
|
|
data/lib/logstash/inputs/snmp.rb
CHANGED
@@ -192,53 +192,73 @@ class LogStash::Inputs::Snmp < LogStash::Inputs::Base
|
|
192
192
|
|
193
193
|
def run(queue)
|
194
194
|
# for now a naive single threaded poller which sleeps off the remaining interval between
|
195
|
-
# each run. each run polls all the defined hosts for the get and walk options.
|
195
|
+
# each run. each run polls all the defined hosts for the get, table and walk options.
|
196
196
|
stoppable_interval_runner.every(@interval, "polling hosts") do
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
197
|
+
poll_clients(queue)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def poll_clients(queue)
|
202
|
+
@client_definitions.each do |definition|
|
203
|
+
client = definition[:client]
|
204
|
+
host = definition[:host_address]
|
205
|
+
result = {}
|
206
|
+
|
207
|
+
if !definition[:get].empty?
|
208
|
+
oids = definition[:get]
|
209
|
+
begin
|
210
|
+
data = client.get(oids, @oid_root_skip, @oid_path_length)
|
211
|
+
if data
|
212
|
+
result.update(data)
|
213
|
+
else
|
214
|
+
logger.debug? && logger.debug("get operation returned no response", host: host, oids: oids)
|
207
215
|
end
|
216
|
+
rescue => e
|
217
|
+
logger.error("error invoking get operation, ignoring", host: host, oids: oids, exception: e, backtrace: e.backtrace)
|
208
218
|
end
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
219
|
+
end
|
220
|
+
|
221
|
+
if !definition[:walk].empty?
|
222
|
+
definition[:walk].each do |oid|
|
223
|
+
begin
|
224
|
+
data = client.walk(oid, @oid_root_skip, @oid_path_length)
|
225
|
+
if data
|
226
|
+
result.update(data)
|
227
|
+
else
|
228
|
+
logger.debug? && logger.debug("walk operation returned no response", host: host, oid: oid)
|
216
229
|
end
|
230
|
+
rescue => e
|
231
|
+
logger.error("error invoking walk operation, ignoring", host: host, oid: oid, exception: e, backtrace: e.backtrace)
|
217
232
|
end
|
218
233
|
end
|
234
|
+
end
|
219
235
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
236
|
+
if !Array(@tables).empty?
|
237
|
+
@tables.each do |table_entry|
|
238
|
+
begin
|
239
|
+
data = client.table(table_entry, @oid_root_skip, @oid_path_length)
|
240
|
+
if data
|
241
|
+
result.update(data)
|
242
|
+
else
|
243
|
+
logger.debug? && logger.debug("table operation returned no response", host: host, table: table_entry)
|
227
244
|
end
|
245
|
+
rescue => e
|
246
|
+
logger.error("error invoking table operation, ignoring",
|
247
|
+
host: host, table_name: table_entry['name'], exception: e, backtrace: e.backtrace)
|
228
248
|
end
|
229
249
|
end
|
250
|
+
end
|
230
251
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
end
|
252
|
+
unless result.empty?
|
253
|
+
event = targeted_event_factory.new_event(result)
|
254
|
+
event.set(@host_protocol_field, definition[:host_protocol])
|
255
|
+
event.set(@host_address_field, definition[:host_address])
|
256
|
+
event.set(@host_port_field, definition[:host_port])
|
257
|
+
event.set(@host_community_field, definition[:host_community])
|
258
|
+
decorate(event)
|
259
|
+
queue << event
|
260
|
+
else
|
261
|
+
logger.debug? && logger.debug("no snmp data retrieved", host: definition[:host_address])
|
242
262
|
end
|
243
263
|
end
|
244
264
|
end
|
data/logstash-input-snmp.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-input-snmp'
|
3
|
-
s.version = '1.3.
|
3
|
+
s.version = '1.3.1'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "SNMP input plugin"
|
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"
|
data/spec/inputs/snmp_spec.rb
CHANGED
@@ -136,43 +136,46 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
136
136
|
|
137
137
|
before(:each) do
|
138
138
|
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
139
|
-
end
|
140
139
|
|
141
|
-
before do
|
142
140
|
expect(LogStash::SnmpClient).to receive(:new).and_return(mock_client)
|
143
|
-
expect(mock_client).to receive(:get).and_return({"foo" => "bar"})
|
144
141
|
# devutils in v6 calls close on the test pipelines while it does not in v7+
|
145
|
-
|
142
|
+
allow(mock_client).to receive(:close).at_most(:once)
|
146
143
|
end
|
147
144
|
|
148
|
-
|
149
|
-
|
145
|
+
context 'mocked get' do
|
146
|
+
|
147
|
+
before do
|
148
|
+
expect(mock_client).to receive(:get).and_return({"foo" => "bar"})
|
149
|
+
end
|
150
|
+
|
151
|
+
it "shoud add @metadata fields and add default host field" do
|
152
|
+
config = <<-CONFIG
|
150
153
|
input {
|
151
154
|
snmp {
|
152
155
|
get => ["1.3.6.1.2.1.1.1.0"]
|
153
156
|
hosts => [{ host => "udp:127.0.0.1/161" community => "public" }]
|
154
157
|
}
|
155
158
|
}
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
159
|
+
CONFIG
|
160
|
+
event = input(config) { |_, queue| queue.pop }
|
161
|
+
|
162
|
+
if ecs_select.active_mode == :disabled
|
163
|
+
expect(event.get("[@metadata][host_protocol]")).to eq("udp")
|
164
|
+
expect(event.get("[@metadata][host_address]")).to eq("127.0.0.1")
|
165
|
+
expect(event.get("[@metadata][host_port]")).to eq("161")
|
166
|
+
expect(event.get("[@metadata][host_community]")).to eq("public")
|
167
|
+
expect(event.get("host")).to eql("127.0.0.1")
|
168
|
+
else
|
169
|
+
expect(event.get("[@metadata][input][snmp][host][protocol]")).to eq("udp")
|
170
|
+
expect(event.get("[@metadata][input][snmp][host][address]")).to eq("127.0.0.1")
|
171
|
+
expect(event.get("[@metadata][input][snmp][host][port]")).to eq('161')
|
172
|
+
expect(event.get("[@metadata][input][snmp][host][community]")).to eq("public")
|
173
|
+
expect(event.get("host")).to eql('ip' => "127.0.0.1")
|
174
|
+
end
|
171
175
|
end
|
172
|
-
end
|
173
176
|
|
174
|
-
|
175
|
-
|
177
|
+
it "should add custom host field (legacy metadata)" do
|
178
|
+
config = <<-CONFIG
|
176
179
|
input {
|
177
180
|
snmp {
|
178
181
|
get => ["1.3.6.1.2.1.1.1.0"]
|
@@ -180,14 +183,14 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
180
183
|
add_field => { host => "%{[@metadata][host_protocol]}:%{[@metadata][host_address]}/%{[@metadata][host_port]},%{[@metadata][host_community]}" }
|
181
184
|
}
|
182
185
|
}
|
183
|
-
|
184
|
-
|
186
|
+
CONFIG
|
187
|
+
event = input(config) { |_, queue| queue.pop }
|
185
188
|
|
186
|
-
|
187
|
-
|
189
|
+
expect(event.get("host")).to eq("udp:127.0.0.1/161,public")
|
190
|
+
end if ecs_select.active_mode == :disabled
|
188
191
|
|
189
|
-
|
190
|
-
|
192
|
+
it "should add custom host field (ECS mode)" do
|
193
|
+
config = <<-CONFIG
|
191
194
|
input {
|
192
195
|
snmp {
|
193
196
|
get => ["1.3.6.1.2.1.1.1.0"]
|
@@ -195,14 +198,14 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
195
198
|
add_field => { "[host][formatted]" => "%{[@metadata][input][snmp][host][protocol]}://%{[@metadata][input][snmp][host][address]}:%{[@metadata][input][snmp][host][port]}" }
|
196
199
|
}
|
197
200
|
}
|
198
|
-
|
199
|
-
|
201
|
+
CONFIG
|
202
|
+
event = input(config) { |_, queue| queue.pop }
|
200
203
|
|
201
|
-
|
202
|
-
|
204
|
+
expect(event.get("host")).to eq('formatted' => "tcp://192.168.1.11:1161")
|
205
|
+
end if ecs_select.active_mode != :disabled
|
203
206
|
|
204
|
-
|
205
|
-
|
207
|
+
it "should target event data" do
|
208
|
+
config = <<-CONFIG
|
206
209
|
input {
|
207
210
|
snmp {
|
208
211
|
get => ["1.3.6.1.2.1.1.1.0"]
|
@@ -210,12 +213,92 @@ describe LogStash::Inputs::Snmp, :ecs_compatibility_support do
|
|
210
213
|
target => "snmp_data"
|
211
214
|
}
|
212
215
|
}
|
213
|
-
|
214
|
-
|
216
|
+
CONFIG
|
217
|
+
event = input(config) { |_, queue| queue.pop }
|
218
|
+
|
219
|
+
expect( event.include?('foo') ).to be false
|
220
|
+
expect( event.get('[snmp_data]') ).to eql 'foo' => 'bar'
|
221
|
+
end
|
215
222
|
|
216
|
-
expect( event.include?('foo') ).to be false
|
217
|
-
expect( event.get('[snmp_data]') ).to eql 'foo' => 'bar'
|
218
223
|
end
|
224
|
+
|
225
|
+
context 'mocked nil get response' do
|
226
|
+
|
227
|
+
let(:config) do
|
228
|
+
{
|
229
|
+
'get' => ["1.3.6.1.2.1.1.1.0"],
|
230
|
+
"hosts" => [{"host" => "udp:127.0.0.1/161", "community" => "public"}]
|
231
|
+
}
|
232
|
+
end
|
233
|
+
|
234
|
+
let(:logger) { double("Logger").as_null_object }
|
235
|
+
|
236
|
+
before do
|
237
|
+
expect(mock_client).to receive(:get).once.and_return(nil)
|
238
|
+
allow_any_instance_of(described_class).to receive(:logger).and_return(logger)
|
239
|
+
expect(logger).not_to receive(:error)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'generates no events when client returns no response' do
|
243
|
+
input = described_class.new(config).tap { |input| input.register }
|
244
|
+
input.poll_clients queue = Queue.new
|
245
|
+
|
246
|
+
expect( queue.size ).to eql 0
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context 'mocked nil table response' do
|
251
|
+
|
252
|
+
let(:config) do
|
253
|
+
{
|
254
|
+
'tables' => [
|
255
|
+
{ 'name' => "a1Table", 'columns' => ["1.3.6.1.4.1.3375.2.2.5.2.3.1.1"] }
|
256
|
+
],
|
257
|
+
"hosts" => [{"host" => "udp:127.0.0.1/161", "community" => "public"}]
|
258
|
+
}
|
259
|
+
end
|
260
|
+
|
261
|
+
let(:logger) { double("Logger").as_null_object }
|
262
|
+
|
263
|
+
before do
|
264
|
+
expect(mock_client).to receive(:table).once.and_return(nil)
|
265
|
+
allow_any_instance_of(described_class).to receive(:logger).and_return(logger)
|
266
|
+
expect(logger).not_to receive(:error)
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'generates no events when client returns no response' do
|
270
|
+
input = described_class.new(config).tap { |input| input.register }
|
271
|
+
input.poll_clients queue = Queue.new
|
272
|
+
|
273
|
+
expect( queue.size ).to eql 0
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
context 'mocked nil walk response' do
|
278
|
+
|
279
|
+
let(:config) do
|
280
|
+
{
|
281
|
+
'walk' => ["1.3.6.1.2.1.1"],
|
282
|
+
"hosts" => [{"host" => "udp:127.0.0.1/161", "community" => "public"}]
|
283
|
+
}
|
284
|
+
end
|
285
|
+
|
286
|
+
let(:logger) { double("Logger").as_null_object }
|
287
|
+
|
288
|
+
before do
|
289
|
+
expect(mock_client).to receive(:walk).once.and_return(nil)
|
290
|
+
allow_any_instance_of(described_class).to receive(:logger).and_return(logger)
|
291
|
+
expect(logger).not_to receive(:error)
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'generates no events when client returns no response' do
|
295
|
+
input = described_class.new(config).tap { |input| input.register }
|
296
|
+
input.poll_clients queue = Queue.new
|
297
|
+
|
298
|
+
expect( queue.size ).to eql 0
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
219
302
|
end
|
220
303
|
|
221
304
|
context "StoppableIntervalRunner" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-snmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elasticsearch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|