logstash-input-snmp 1.3.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|