telemetry-snmp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/rspec.yml +44 -0
- data/.github/workflows/rubocop.yml +28 -0
- data/.github/workflows/sourcehawk-scan.yml +20 -0
- data/.gitignore +14 -0
- data/.rspec +4 -0
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +4 -0
- data/CODE_OF_CONDUCT.md +75 -0
- data/CONTRIBUTING.md +54 -0
- data/Gemfile +10 -0
- data/INDIVIDUAL_CONTRIBUTOR_LICENSE.md +30 -0
- data/LICENSE +201 -0
- data/NOTICE.txt +9 -0
- data/README.md +54 -0
- data/attribution.txt +1 -0
- data/config.ru +15 -0
- data/exe/snmp_collector +55 -0
- data/lib/telemetry/snmp.rb +23 -0
- data/lib/telemetry/snmp/api.rb +55 -0
- data/lib/telemetry/snmp/auth.rb +54 -0
- data/lib/telemetry/snmp/auth/defaults.rb +41 -0
- data/lib/telemetry/snmp/client.rb +104 -0
- data/lib/telemetry/snmp/controllers/device_creds.rb +105 -0
- data/lib/telemetry/snmp/controllers/devices.rb +94 -0
- data/lib/telemetry/snmp/controllers/oid_groups.rb +71 -0
- data/lib/telemetry/snmp/controllers/oids.rb +80 -0
- data/lib/telemetry/snmp/controllers/users.rb +81 -0
- data/lib/telemetry/snmp/controllers/walks.rb +89 -0
- data/lib/telemetry/snmp/data.rb +69 -0
- data/lib/telemetry/snmp/data/default_opts.rb +73 -0
- data/lib/telemetry/snmp/data/migrations/001_device_creds.rb +19 -0
- data/lib/telemetry/snmp/data/migrations/002_create_devices_table.rb +31 -0
- data/lib/telemetry/snmp/data/migrations/003_create_oids_tables.rb +16 -0
- data/lib/telemetry/snmp/data/migrations/004_create_oid_groups.rb +15 -0
- data/lib/telemetry/snmp/data/migrations/005_create_oids_oid_groups.rb +17 -0
- data/lib/telemetry/snmp/data/migrations/006_device_to_oid_group.rb +15 -0
- data/lib/telemetry/snmp/data/migrations/007_create_users.rb +20 -0
- data/lib/telemetry/snmp/data/migrations/008_create_walks_table.rb +14 -0
- data/lib/telemetry/snmp/data/migrations/009_create_tag_name_column.rb +7 -0
- data/lib/telemetry/snmp/data/migrations/010_create_user_audit_table.rb +18 -0
- data/lib/telemetry/snmp/data/models/device.rb +11 -0
- data/lib/telemetry/snmp/data/models/device_cred.rb +11 -0
- data/lib/telemetry/snmp/data/models/oid.rb +10 -0
- data/lib/telemetry/snmp/data/models/oid_group.rb +10 -0
- data/lib/telemetry/snmp/data/models/oid_oid_groups.rb +10 -0
- data/lib/telemetry/snmp/data/models/oid_walk.rb +10 -0
- data/lib/telemetry/snmp/data/models/user.rb +10 -0
- data/lib/telemetry/snmp/data/models/user_audit_log.rb +19 -0
- data/lib/telemetry/snmp/mibs/AGENTX-MIB.txt +527 -0
- data/lib/telemetry/snmp/mibs/AIRPORT-BASESTATION-3-MIB.txt +461 -0
- data/lib/telemetry/snmp/mibs/BRIDGE-MIB.txt +1472 -0
- data/lib/telemetry/snmp/mibs/DISMAN-EVENT-MIB.txt +1882 -0
- data/lib/telemetry/snmp/mibs/DISMAN-SCHEDULE-MIB.txt +699 -0
- data/lib/telemetry/snmp/mibs/DISMAN-SCRIPT-MIB.txt +1764 -0
- data/lib/telemetry/snmp/mibs/EtherLike-MIB.txt +1862 -0
- data/lib/telemetry/snmp/mibs/HCNUM-TC.txt +118 -0
- data/lib/telemetry/snmp/mibs/HOST-RESOURCES-MIB.txt +1540 -0
- data/lib/telemetry/snmp/mibs/HOST-RESOURCES-TYPES.txt +389 -0
- data/lib/telemetry/snmp/mibs/IANA-ADDRESS-FAMILY-NUMBERS-MIB.txt +123 -0
- data/lib/telemetry/snmp/mibs/IANA-LANGUAGE-MIB.txt +123 -0
- data/lib/telemetry/snmp/mibs/IANA-RTPROTO-MIB.txt +91 -0
- data/lib/telemetry/snmp/mibs/IANAifType-MIB.txt +619 -0
- data/lib/telemetry/snmp/mibs/IF-INVERTED-STACK-MIB.txt +149 -0
- data/lib/telemetry/snmp/mibs/IF-MIB.txt +1814 -0
- data/lib/telemetry/snmp/mibs/INET-ADDRESS-MIB.txt +402 -0
- data/lib/telemetry/snmp/mibs/IP-FORWARD-MIB.txt +1277 -0
- data/lib/telemetry/snmp/mibs/IP-MIB.txt +4993 -0
- data/lib/telemetry/snmp/mibs/IPV6-FLOW-LABEL-MIB.txt +58 -0
- data/lib/telemetry/snmp/mibs/IPV6-ICMP-MIB.txt +529 -0
- data/lib/telemetry/snmp/mibs/IPV6-MIB.txt +1443 -0
- data/lib/telemetry/snmp/mibs/IPV6-TC.txt +67 -0
- data/lib/telemetry/snmp/mibs/IPV6-TCP-MIB.txt +211 -0
- data/lib/telemetry/snmp/mibs/IPV6-UDP-MIB.txt +141 -0
- data/lib/telemetry/snmp/mibs/NET-SNMP-AGENT-MIB.txt +554 -0
- data/lib/telemetry/snmp/mibs/NET-SNMP-EXAMPLES-MIB.txt +285 -0
- data/lib/telemetry/snmp/mibs/NET-SNMP-EXTEND-MIB.txt +325 -0
- data/lib/telemetry/snmp/mibs/NET-SNMP-MIB.txt +67 -0
- data/lib/telemetry/snmp/mibs/NET-SNMP-PASS-MIB.txt +124 -0
- data/lib/telemetry/snmp/mibs/NET-SNMP-TC.txt +128 -0
- data/lib/telemetry/snmp/mibs/NET-SNMP-VACM-MIB.txt +154 -0
- data/lib/telemetry/snmp/mibs/NOTIFICATION-LOG-MIB.txt +753 -0
- data/lib/telemetry/snmp/mibs/PAN-COMMON-MIB.md5 +1 -0
- data/lib/telemetry/snmp/mibs/PAN-COMMON-MIB.my +2293 -0
- data/lib/telemetry/snmp/mibs/PAN-ENTITY-EXT-MIB.md5 +1 -0
- data/lib/telemetry/snmp/mibs/PAN-ENTITY-EXT-MIB.my +293 -0
- data/lib/telemetry/snmp/mibs/PAN-GLOBAL-REG-MIB.md5 +1 -0
- data/lib/telemetry/snmp/mibs/PAN-GLOBAL-REG-MIB.my +84 -0
- data/lib/telemetry/snmp/mibs/PAN-GLOBAL-TC-MIB.md5 +1 -0
- data/lib/telemetry/snmp/mibs/PAN-GLOBAL-TC-MIB.my +68 -0
- data/lib/telemetry/snmp/mibs/PAN-LC-MIB.md5 +1 -0
- data/lib/telemetry/snmp/mibs/PAN-LC-MIB.my +204 -0
- data/lib/telemetry/snmp/mibs/PAN-PRODUCT-MIB.md5 +1 -0
- data/lib/telemetry/snmp/mibs/PAN-PRODUCT-MIB.my +305 -0
- data/lib/telemetry/snmp/mibs/PAN-TRAPS.md5 +1 -0
- data/lib/telemetry/snmp/mibs/PAN-TRAPS.my +7809 -0
- data/lib/telemetry/snmp/mibs/RFC-1215.txt +38 -0
- data/lib/telemetry/snmp/mibs/RFC1155-SMI.txt +119 -0
- data/lib/telemetry/snmp/mibs/RFC1213-MIB.txt +2613 -0
- data/lib/telemetry/snmp/mibs/RMON-MIB.txt +3980 -0
- data/lib/telemetry/snmp/mibs/SCTP-MIB.txt +1342 -0
- data/lib/telemetry/snmp/mibs/SMUX-MIB.txt +160 -0
- data/lib/telemetry/snmp/mibs/SNMP-COMMUNITY-MIB.txt +429 -0
- data/lib/telemetry/snmp/mibs/SNMP-FRAMEWORK-MIB.txt +526 -0
- data/lib/telemetry/snmp/mibs/SNMP-MPD-MIB.txt +145 -0
- data/lib/telemetry/snmp/mibs/SNMP-NOTIFICATION-MIB.txt +589 -0
- data/lib/telemetry/snmp/mibs/SNMP-PROXY-MIB.txt +294 -0
- data/lib/telemetry/snmp/mibs/SNMP-TARGET-MIB.txt +660 -0
- data/lib/telemetry/snmp/mibs/SNMP-USER-BASED-SM-MIB.txt +912 -0
- data/lib/telemetry/snmp/mibs/SNMP-USM-AES-MIB.txt +62 -0
- data/lib/telemetry/snmp/mibs/SNMP-USM-DH-OBJECTS-MIB.txt +532 -0
- data/lib/telemetry/snmp/mibs/SNMP-VIEW-BASED-ACM-MIB.txt +830 -0
- data/lib/telemetry/snmp/mibs/SNMPv2-CONF.txt +322 -0
- data/lib/telemetry/snmp/mibs/SNMPv2-MIB.txt +854 -0
- data/lib/telemetry/snmp/mibs/SNMPv2-SMI.txt +344 -0
- data/lib/telemetry/snmp/mibs/SNMPv2-TC.txt +772 -0
- data/lib/telemetry/snmp/mibs/SNMPv2-TM.txt +176 -0
- data/lib/telemetry/snmp/mibs/TCP-MIB.txt +785 -0
- data/lib/telemetry/snmp/mibs/TRANSPORT-ADDRESS-MIB.txt +421 -0
- data/lib/telemetry/snmp/mibs/TUNNEL-MIB.txt +738 -0
- data/lib/telemetry/snmp/mibs/UCD-DEMO-MIB.txt +74 -0
- data/lib/telemetry/snmp/mibs/UCD-DISKIO-MIB.txt +171 -0
- data/lib/telemetry/snmp/mibs/UCD-DLMOD-MIB.txt +124 -0
- data/lib/telemetry/snmp/mibs/UCD-IPFWACC-MIB.txt +327 -0
- data/lib/telemetry/snmp/mibs/UCD-SNMP-MIB.txt +1712 -0
- data/lib/telemetry/snmp/mibs/UDP-MIB.txt +549 -0
- data/lib/telemetry/snmp/publisher.rb +130 -0
- data/lib/telemetry/snmp/version.rb +7 -0
- data/sourcehawk.yml +4 -0
- data/telemetry-snmp.gemspec +48 -0
- metadata +456 -0
data/NOTICE.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Telemetry::Snmp
|
2
|
+
|
3
|
+
### Telemetry::Snmp Collector Service
|
4
|
+
This is a servce that runs and collects SNMP metrics at whatever frequency is defined inside the basement. As you need
|
5
|
+
additional collectors, you can scale this out to give you more parallel workers
|
6
|
+
|
7
|
+
You can start this service by running
|
8
|
+
```ruby
|
9
|
+
bundle update
|
10
|
+
bundle exec exe/snmp_collector
|
11
|
+
```
|
12
|
+
|
13
|
+
|
14
|
+
### Telemetry::Snmp::API
|
15
|
+
The API allows for you to remotely CRUD devices, oids, users, device credentials, etc
|
16
|
+
The Routes are available via a [postman json](https://github.com/Optum/telemetry-snmp/blob/main/telemetry-snmp.json)
|
17
|
+
|
18
|
+
## OID Mappings
|
19
|
+
The oid_walks table is the most utilized and probably what you are looking for.
|
20
|
+
Table Layout
|
21
|
+
```json
|
22
|
+
{
|
23
|
+
"oid": "the oid you want to grab metrics from(walk)",
|
24
|
+
"oid_index": "the oid to use as an index for naming",
|
25
|
+
"measurement_name": "what name to name the measurement",
|
26
|
+
"active": 1
|
27
|
+
}
|
28
|
+
```
|
29
|
+
|
30
|
+
|
31
|
+
## Settings
|
32
|
+
Telemetry::Snmp::Publisher
|
33
|
+
```ruby
|
34
|
+
ENV['telemetry.snmp.amqp.username'] = 'guest'
|
35
|
+
ENV['telemetry.snmp.amqp.password'] = 'guest'
|
36
|
+
ENV['telemetry.snmp.amqp.nodes'] = 'localhost'
|
37
|
+
ENV['telemetry.snmp.amqp.vhost'] = 'telemetry'
|
38
|
+
ENV['telemetry.snmp.amqp.port'] = '5672'
|
39
|
+
ENV['telemetry.snmp.amqp.use_ssl'] = 'false'
|
40
|
+
ENV['telemetry.snmp.amqp.exchange_name'] = 'telemetry.snmp'
|
41
|
+
```
|
42
|
+
|
43
|
+
Telemetry::Snmp::Data
|
44
|
+
```ruby
|
45
|
+
ENV['telemetry.snmp.data.adapter'] = 'mysql2'
|
46
|
+
ENV['telemetry.snmp.data.username'] = 'root'
|
47
|
+
ENV['telemetry.snmp.data.password'] = ''
|
48
|
+
ENV['telemetry.snmp.data.database'] = 'telemetry_snmp'
|
49
|
+
ENV['telemetry.snmp.data.host'] = '127.0.0.1'
|
50
|
+
ENV['telemetry.snmp.data.port'] = '3306'
|
51
|
+
ENV['telemetry.snmp.data.max_connections'] = '16'
|
52
|
+
ENV['telemetry.snmp.data.pool_timeout'] = '2'
|
53
|
+
ENV['telemetry.snmp.data.preconnect'] = 'concurrently'
|
54
|
+
```
|
data/attribution.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Add attributions here.
|
data/config.ru
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
require 'puma'
|
6
|
+
require 'rack'
|
7
|
+
require 'sinatra'
|
8
|
+
require 'oj'
|
9
|
+
require 'multi_json'
|
10
|
+
|
11
|
+
require 'telemetry/snmp'
|
12
|
+
require 'telemetry/snmp/api'
|
13
|
+
|
14
|
+
Telemetry::Snmp::Data.start!
|
15
|
+
run Telemetry::Snmp::API
|
data/exe/snmp_collector
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'telemetry/snmp'
|
4
|
+
Telemetry::Snmp.bootstrap
|
5
|
+
|
6
|
+
trap('SIGTERM') { @quit = true }
|
7
|
+
trap('SIGHUP') { @quit = true }
|
8
|
+
trap('SIGINT') { @quit = true }
|
9
|
+
|
10
|
+
@quit = false
|
11
|
+
until @quit
|
12
|
+
@lines = []
|
13
|
+
Telemetry::Snmp::Data::Model::Device.each do |row|
|
14
|
+
next if row.values[:last_polled].to_i + row.values[:frequency] > Time.now.to_i
|
15
|
+
|
16
|
+
fields = {}
|
17
|
+
tags = {
|
18
|
+
hostname: row.values[:hostname],
|
19
|
+
ip_address: row.values[:ip_address],
|
20
|
+
env: row.values[:environment],
|
21
|
+
dc: row.values[:datacenter],
|
22
|
+
zone: row.values[:zone],
|
23
|
+
influxdb_node_group: 'snmp'
|
24
|
+
}
|
25
|
+
|
26
|
+
Telemetry::Snmp::Data::Model::OID.each do |oid_row|
|
27
|
+
oid_value = Telemetry::Snmp::Client.oid_value(row[:hostname], oid_row.values[:oid])
|
28
|
+
next if oid_value.nil?
|
29
|
+
next unless oid_value.is_a?(Integer) || oid_value.is_a?(Float)
|
30
|
+
|
31
|
+
fields[oid_row.values[:name]] = "#{Telemetry::Snmp::Client.oid_value(row[:hostname], oid_row.values[:oid])}i"
|
32
|
+
rescue StandardError => e
|
33
|
+
Telemetry::Logger.error "#{e.class}: #{e.message}"
|
34
|
+
end
|
35
|
+
|
36
|
+
@lines.push Telemetry::Metrics::Parser.to_line_protocol(
|
37
|
+
measurement: 'palo_alto_a',
|
38
|
+
fields: fields,
|
39
|
+
tags: tags,
|
40
|
+
timestamp: (DateTime.now.strftime('%Q').to_i * 1000 * 1000)
|
41
|
+
)
|
42
|
+
|
43
|
+
walker = Telemetry::Snmp::Client.grab_oid_metrics(row.values[:hostname])
|
44
|
+
Telemetry::Logger.info "Pushing #{walker.count} lines for #{row.values[:hostname]}" unless walker.empty?
|
45
|
+
Telemetry::Snmp::Publisher.push_lines(walker) unless walker.empty?
|
46
|
+
|
47
|
+
row.update(last_polled: Sequel::CURRENT_TIMESTAMP)
|
48
|
+
row.save
|
49
|
+
rescue StandardError => e
|
50
|
+
Telemetry::Logger.error "#{e.class}: #{e.message}"
|
51
|
+
end
|
52
|
+
|
53
|
+
Telemetry::Snmp::Publisher.push_lines(@lines) unless @lines.empty?
|
54
|
+
sleep(1)
|
55
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'telemetry/snmp/version'
|
4
|
+
require 'telemetry/logger'
|
5
|
+
require 'telemetry/metrics/parser'
|
6
|
+
require 'telemetry/snmp/data'
|
7
|
+
require 'telemetry/snmp/client'
|
8
|
+
require 'telemetry/snmp/publisher'
|
9
|
+
|
10
|
+
module Telemetry
|
11
|
+
module Snmp
|
12
|
+
class << self
|
13
|
+
def bootstrap
|
14
|
+
Telemetry::Logger.setup(level: 'info')
|
15
|
+
Telemetry::Logger.info "Starting Telemetry::Snmp v#{Telemetry::Snmp::VERSION}"
|
16
|
+
Telemetry::Snmp::Data.start!
|
17
|
+
Telemetry::Snmp::Client.load_mibs
|
18
|
+
Telemetry::Snmp::Publisher.start!
|
19
|
+
Telemetry::Logger.info 'Telemetry::Snmp bootstrapped!'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/contrib'
|
3
|
+
require 'sinatra/multi_route'
|
4
|
+
require 'sinatra/respond_with'
|
5
|
+
require 'sinatra/custom_logger'
|
6
|
+
require 'sinatra/namespace'
|
7
|
+
require 'oj'
|
8
|
+
|
9
|
+
require 'telemetry/snmp/controllers/device_creds'
|
10
|
+
require 'telemetry/snmp/controllers/devices'
|
11
|
+
require 'telemetry/snmp/controllers/oid_groups'
|
12
|
+
require 'telemetry/snmp/controllers/oids'
|
13
|
+
require 'telemetry/snmp/controllers/users'
|
14
|
+
require 'telemetry/snmp/controllers/walks'
|
15
|
+
|
16
|
+
module Telemetry
|
17
|
+
module Snmp
|
18
|
+
class API < Sinatra::Base
|
19
|
+
register Sinatra::JSON
|
20
|
+
register Sinatra::Namespace
|
21
|
+
register Sinatra::RespondWith
|
22
|
+
|
23
|
+
error do
|
24
|
+
content_type :json
|
25
|
+
status 500
|
26
|
+
|
27
|
+
{ result: 'error', message: env['sinatra.error'].message }.to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
before do
|
31
|
+
headers 'Access-Control-Allow-Origin' => '*',
|
32
|
+
'Access-Control-Allow-Methods' => %w[OPTIONS GET POST]
|
33
|
+
end
|
34
|
+
|
35
|
+
after do
|
36
|
+
content_type :json
|
37
|
+
response.body = Oj.dump(response.body, mode: :compat) unless response.body.is_a? String
|
38
|
+
end
|
39
|
+
|
40
|
+
get '/version' do
|
41
|
+
{
|
42
|
+
version: Telemetry::Snmp::VERSION,
|
43
|
+
migration_version: Telemetry::Snmp::Data.migration_version
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
namespace('/users') { register Telemetry::Snmp::Controller::Users }
|
48
|
+
namespace('/devices/creds') { register Telemetry::Snmp::Controller::DeviceCreds }
|
49
|
+
namespace('/devices') { register Telemetry::Snmp::Controller::Devices }
|
50
|
+
namespace('/oid_groups') { register Telemetry::Snmp::Controller::OIDGroups }
|
51
|
+
namespace('/oid') { register Telemetry::Snmp::Controller::OIDs }
|
52
|
+
namespace('/walks') { register Telemetry::Snmp::Controller::Walks }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'net/ldap'
|
2
|
+
require 'telemetry/snmp/auth/defaults'
|
3
|
+
|
4
|
+
module Telemetry
|
5
|
+
module Snmp
|
6
|
+
class Auth
|
7
|
+
include Telemetry::Snmp::AuthDefaults
|
8
|
+
|
9
|
+
def initialize(username:, **opts)
|
10
|
+
@username = username
|
11
|
+
@details = {}
|
12
|
+
@opts = opts
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_result(result)
|
16
|
+
unless result.is_a? Net::LDAP::Entry
|
17
|
+
@success = false
|
18
|
+
return
|
19
|
+
end
|
20
|
+
@details[:username] = result.sAMAccountName.first
|
21
|
+
@details[:email] = result.mail.first
|
22
|
+
@details[:first] = result.givenName.first
|
23
|
+
@details[:last] = result.sn.first
|
24
|
+
@success = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def search_user(ldap, username)
|
28
|
+
user_filter = Net::LDAP::Filter.eq('sAMAccountName', username)
|
29
|
+
|
30
|
+
ldap.search(base: treebase, filter: user_filter, attrs: attrs, return_result: false) do |entry|
|
31
|
+
@details[:group_access] = entry.memberof.include?("CN=#{admin_group}, #{treebase}")
|
32
|
+
return entry
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def auth_with_service(password)
|
37
|
+
options = defaults
|
38
|
+
options[:auth] = defaults_auth
|
39
|
+
result = provider.new(options).bind_as(base: defaults[:base], attributes: attrs, filter: filter, password: password) # rubocop:disable Layout/LineLength
|
40
|
+
process_result(result.first)
|
41
|
+
end
|
42
|
+
|
43
|
+
def auth_without_service(password)
|
44
|
+
options = { host: defaults[:host], port: defaults[:port] }
|
45
|
+
options[:auth] = { password: password, username: @username, method: :simple }
|
46
|
+
ldap = provider.new(options)
|
47
|
+
@success = ldap.bind
|
48
|
+
return unless @success
|
49
|
+
|
50
|
+
process_result(search_user(ldap, @username))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Telemetry
|
2
|
+
module Snmp
|
3
|
+
module AuthDefaults
|
4
|
+
def opts
|
5
|
+
@opts ||= {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def attrs
|
9
|
+
%w[mail cn sn objectclass givenName sAMAccountName MemberOf]
|
10
|
+
end
|
11
|
+
|
12
|
+
def treebase
|
13
|
+
opts[:treebase] || ENV['treebase'] || 'CN=Users,DC=com'
|
14
|
+
end
|
15
|
+
|
16
|
+
def ldap_host
|
17
|
+
opts[:ldap_host] || ENV['ldap_host'] || 'localhost'
|
18
|
+
end
|
19
|
+
|
20
|
+
def ldap_port
|
21
|
+
opts[:ldap_port] || ENV['ldap_host'] || '389'
|
22
|
+
end
|
23
|
+
|
24
|
+
def provider
|
25
|
+
Net::LDAP
|
26
|
+
end
|
27
|
+
|
28
|
+
def filter(username = @username)
|
29
|
+
"(sAMAccountName=#{username})"
|
30
|
+
end
|
31
|
+
|
32
|
+
def admin_group
|
33
|
+
opts[:admin_group] || ENV['ldap_admin_group']
|
34
|
+
end
|
35
|
+
|
36
|
+
def users_group
|
37
|
+
opts[:users_group] || ENV['ldap_users_group']
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'netsnmp'
|
3
|
+
|
4
|
+
module Telemetry
|
5
|
+
module Snmp
|
6
|
+
module Client
|
7
|
+
@connections = {}
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def load_mibs
|
11
|
+
ENV['MIBDIRS'] = "#{__dir__}/mibs"
|
12
|
+
NETSNMP::MIB.load_defaults
|
13
|
+
# NETSNMP::MIB.load("#{__dir__}/mibs/PAN-COMMON-MIB.my")
|
14
|
+
# NETSNMP::MIB.load("#{__dir__}/mibs/PAN-ENTITY-EXT-MIB.my")
|
15
|
+
# NETSNMP::MIB.load("#{__dir__}/mibs/PAN-GLOBAL-REG-MIB.my")
|
16
|
+
# NETSNMP::MIB.load("#{__dir__}/mibs/PAN-GLOBAL-TC-MIB.my")
|
17
|
+
# NETSNMP::MIB.load("#{__dir__}/mibs/PAN-LC-MIB.my")
|
18
|
+
# NETSNMP::MIB.load("#{__dir__}/mibs/PAN-PRODUCT-MIB.my")
|
19
|
+
end
|
20
|
+
|
21
|
+
def connection(host)
|
22
|
+
return @connections[host.to_sym] if @connections.key? host.to_sym
|
23
|
+
|
24
|
+
dataset = Telemetry::Snmp::Data::Model::Device[hostname: host]
|
25
|
+
|
26
|
+
@connections[host.to_sym] = NETSNMP::Client.new(
|
27
|
+
host: dataset.values[:ip_address],
|
28
|
+
port: dataset.values[:port],
|
29
|
+
username: dataset.device_cred.values[:username],
|
30
|
+
auth_password: dataset.device_cred.values[:auth_password],
|
31
|
+
auth_protocol: dataset.device_cred.values[:auth_protocol].to_sym,
|
32
|
+
priv_password: dataset.device_cred.values[:priv_password],
|
33
|
+
priv_protocol: dataset.device_cred.values[:priv_protocol].to_sym,
|
34
|
+
security_level: dataset.device_cred.values[:security_level].to_sym
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def oid_value(host, oid)
|
39
|
+
connection(host).get(oid: oid)
|
40
|
+
rescue StandardError
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def oid_walk(host, oid)
|
45
|
+
results = []
|
46
|
+
connection(host).walk(oid: oid).each do |oid_code, value|
|
47
|
+
hash = { oid_code: oid_code, value: value }
|
48
|
+
begin
|
49
|
+
ident = NETSNMP::MIB.identifier(oid_code)
|
50
|
+
|
51
|
+
hash[:identifier] = ident.first
|
52
|
+
rescue StandardError
|
53
|
+
# literally do nothing
|
54
|
+
end
|
55
|
+
results.push hash
|
56
|
+
end
|
57
|
+
|
58
|
+
results
|
59
|
+
end
|
60
|
+
|
61
|
+
def grab_oid_metrics(hostname)
|
62
|
+
device = Telemetry::Snmp::Data::Model::Device[hostname: hostname]
|
63
|
+
@lines = []
|
64
|
+
Telemetry::Snmp::Data::Model::OIDWalks.where(:active).each do |row|
|
65
|
+
index = {}
|
66
|
+
Telemetry::Snmp::Client.oid_walk(device.values[:hostname], row.values[:oid_index]).each do |hash|
|
67
|
+
index[hash[:oid_code].delete_prefix("#{row.values[:oid_index]}.")] = hash[:value].gsub(%r{\\/}, '.')
|
68
|
+
end
|
69
|
+
|
70
|
+
timestamp = DateTime.now.strftime('%Q').to_i * 1000 * 1000
|
71
|
+
Telemetry::Snmp::Client.oid_walk(device.values[:hostname], row.values[:oid_walk]).each do |walk|
|
72
|
+
key = walk[:oid_code].split('.').last
|
73
|
+
next if walk[:value].is_a? String
|
74
|
+
next if walk[:value].nil?
|
75
|
+
|
76
|
+
fields = {}
|
77
|
+
fields[walk[:identifier]] = "#{walk[:value]}i"
|
78
|
+
tags = {
|
79
|
+
hostname: device.values[:hostname],
|
80
|
+
interface: index[key],
|
81
|
+
ip_address: device.values[:ip_address],
|
82
|
+
zone: device.values[:zone],
|
83
|
+
env: device.values[:environment],
|
84
|
+
dc: device.values[:datacenter],
|
85
|
+
influxdb_node_group: 'snmp'
|
86
|
+
}
|
87
|
+
|
88
|
+
line = Telemetry::Metrics::Parser.to_line_protocol(
|
89
|
+
measurement: row.values[:measurement],
|
90
|
+
fields: fields,
|
91
|
+
tags: tags,
|
92
|
+
timestamp: timestamp
|
93
|
+
)
|
94
|
+
|
95
|
+
@lines.push line
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
@lines
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'sinatra/extension'
|
2
|
+
|
3
|
+
module Telemetry
|
4
|
+
module Snmp
|
5
|
+
module Controller
|
6
|
+
module DeviceCreds
|
7
|
+
extend Sinatra::Extension
|
8
|
+
# id, port, username, auth_password, auth_protocol, priv_password, priv_protocol, security_level
|
9
|
+
|
10
|
+
get '' do
|
11
|
+
results = {}
|
12
|
+
|
13
|
+
Telemetry::Snmp::Data::Model::DeviceCred.all.each do |creds|
|
14
|
+
results[creds.values[:id]] = {
|
15
|
+
id: creds.values[:id],
|
16
|
+
port: creds.values[:port],
|
17
|
+
username: creds.values[:username],
|
18
|
+
auth_protocol: creds.values[:auth_protcol],
|
19
|
+
priv_protocol: creds.values[:priv_protocol],
|
20
|
+
security_level: creds.values[:security_level],
|
21
|
+
created: creds.values[:created],
|
22
|
+
updated: creds.values[:updated]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
results
|
27
|
+
end
|
28
|
+
|
29
|
+
get '/:id' do
|
30
|
+
cred = Telemetry::Snmp::Data::Model::DeviceCred[params[:id]]
|
31
|
+
if cred.nil?
|
32
|
+
status 404
|
33
|
+
return {}
|
34
|
+
end
|
35
|
+
|
36
|
+
results = cred.values.dup
|
37
|
+
results.delete(:auth_password)
|
38
|
+
results.delete(:priv_password)
|
39
|
+
|
40
|
+
results
|
41
|
+
end
|
42
|
+
|
43
|
+
post '' do
|
44
|
+
body = MultiJson.load(request.body.read, symbolize_keys: true)
|
45
|
+
|
46
|
+
if params[:username].nil? || params[:auth_password].nil?
|
47
|
+
status 400
|
48
|
+
{
|
49
|
+
error: true,
|
50
|
+
username_missing: params[:username].nil?,
|
51
|
+
auth_password_missing: params[:auth_password].nil?
|
52
|
+
}
|
53
|
+
end
|
54
|
+
insert = {
|
55
|
+
port: body[:port] || 161,
|
56
|
+
username: body[:username],
|
57
|
+
auth_password: body[:auth_password],
|
58
|
+
auth_protocol: body[:auth_protocol] || 'sha',
|
59
|
+
priv_password: body[:priv_password],
|
60
|
+
priv_protocol: body[:priv_protocol] || 'aes',
|
61
|
+
security_level: body[:security_level] || 'auth_priv',
|
62
|
+
created: Sequel::CURRENT_TIMESTAMP
|
63
|
+
}
|
64
|
+
|
65
|
+
{ id: Telemetry::Snmp::Data::Model::DeviceCred.insert(**insert), username: insert[:username] }
|
66
|
+
end
|
67
|
+
|
68
|
+
put '/:id' do
|
69
|
+
status 405
|
70
|
+
{ error: true, message: 'puts not supported', id: params[:id] }
|
71
|
+
end
|
72
|
+
|
73
|
+
patch '/:id' do
|
74
|
+
cred = Telemetry::Snmp::Data::Model::DeviceCred[params[:id]]
|
75
|
+
if cred.nil?
|
76
|
+
status 404
|
77
|
+
return { error: true, id: params[:id], message: "cannot find #{params[:id]}" }
|
78
|
+
end
|
79
|
+
|
80
|
+
body = MultiJson.load(request.body.read, symbolize_keys: true)
|
81
|
+
update = {}
|
82
|
+
fields = %i[port username auth_password auth_protocol priv_password priv_protocol security_level]
|
83
|
+
fields.each { |field| update[field] = body[field] if body.key? field }
|
84
|
+
|
85
|
+
if update.empty?
|
86
|
+
status 400
|
87
|
+
return { error: true, message: 'no valid fields to update' }
|
88
|
+
end
|
89
|
+
|
90
|
+
update[:updated] = Sequel::CURRENT_TIMESTAMP
|
91
|
+
cred.update(**update)
|
92
|
+
{ error: false, updated_field: update.keys, id: params[:id] }
|
93
|
+
end
|
94
|
+
|
95
|
+
delete '/:id' do
|
96
|
+
cred = Telemetry::Snmp::Data::Model::DeviceCred[params[:id]]
|
97
|
+
status 404 if cred.nil?
|
98
|
+
return { error: true, message: "#{params[:id]} not found" } if cred.nil?
|
99
|
+
|
100
|
+
{ error: !result.delete, id: params[:id] }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|