apscanner 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1b54660d1fd088dc9ce7842f06a72cae042836b9
4
+ data.tar.gz: f9e183125d770824637dc9b74e27ef10a679e4d1
5
+ SHA512:
6
+ metadata.gz: 37b30665d129ed274792bfa9bb5c2f88efb01b26f01107b1b1d4fc058b8a9cb3098981954ea792e820fc340580b64876b813b71f15f3030fa7979d3f4ea903ff
7
+ data.tar.gz: 641a7a0c9c01b652347045d4cc78bc0a18b9e03e4abb074b72c8b6b1453dce141343ecd8f7bd02740aac54d113f3a46cf6aae45126be0c6b39f899daeae4ea29
data/bin/console ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'apscanner'
4
+ require 'irb'
5
+
6
+ IRB.start
@@ -0,0 +1,16 @@
1
+ module Apscanner
2
+ class AccessPoint
3
+ attr_reader :name, :mac_address
4
+
5
+ def initialize(options = {})
6
+ @name = options[:name]
7
+ @mac_address = options[:mac_address]
8
+ end
9
+
10
+ def to_h
11
+ instance_variables.map do |var|
12
+ [var.to_s.delete('@').to_sym, instance_variable_get(var)]
13
+ end.to_h
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module Apscanner
2
+ class Sensor
3
+ attr_reader :port, :ip_address, :community, :uuid, :access_points
4
+ attr_accessor :type
5
+
6
+ def initialize(options = {})
7
+ @port = options[:port]
8
+ @ip_address = options[:ip_address]
9
+ @community = options[:community]
10
+ @uuid = options[:uuid]
11
+ @type = options[:type]
12
+ @access_points = []
13
+ end
14
+
15
+ def scan
16
+ t0 = Time.now
17
+ @access_points = SnmpManager.new(self).run
18
+ Apscanner.logger.info("Scanned #{@access_points.count} APs from " \
19
+ "#{@ip_address} in #{(Time.now - t0).round(2)}s.")
20
+ self
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,90 @@
1
+ module Apscanner
2
+ class SnmpManager
3
+ SNMP_OID = {
4
+ wlc: {
5
+ name: '1.3.6.1.4.1.9.9.513.1.1.1.1.5',
6
+ mac: '1.3.6.1.4.1.9.9.513.1.1.1.1.2'
7
+ },
8
+ meraki: {
9
+ name: '1.3.6.1.4.1.29671.1.1.4.1.1',
10
+ mac: '1.3.6.1.4.1.29671.1.1.4.1.2'
11
+ }
12
+ }.freeze
13
+
14
+ def initialize(sensor)
15
+ @sensor = sensor
16
+ end
17
+
18
+ def run
19
+ response = request_by_type
20
+ return [] if response.empty?
21
+ parse(response, SNMP_OID[@sensor.type])
22
+ end
23
+
24
+ private
25
+
26
+ def manager
27
+ SNMP4EM::Manager.new(
28
+ host: @sensor.ip_address,
29
+ community: @sensor.community || 'public',
30
+ version: :SNMPv2c,
31
+ port: @sensor.port || 161,
32
+ retries: 2
33
+ )
34
+ end
35
+
36
+ def discover
37
+ response = {}
38
+ SNMP_OID.each do |type, oids|
39
+ response = request(oids.values)
40
+ unless response.empty?
41
+ @sensor.type = type
42
+ break
43
+ end
44
+ end
45
+ response
46
+ end
47
+
48
+ def request_by_type
49
+ if SNMP_OID.keys.include?(@sensor.type)
50
+ request(SNMP_OID[@sensor.type].values)
51
+ else
52
+ discover
53
+ end
54
+ end
55
+
56
+ def request(oids)
57
+ response = {}
58
+ EM.run do
59
+ req = manager.bulkwalk(oids)
60
+ req.errback do |error|
61
+ Apscanner.logger.error(error)
62
+ EM.stop
63
+ end
64
+
65
+ req.callback do |resp|
66
+ Apscanner.logger.debug("#{@sensor.ip_address}: #{resp}")
67
+ response = resp
68
+ EM.stop
69
+ end
70
+ end
71
+ response
72
+ end
73
+
74
+ def parse(response, oids)
75
+ access_points = []
76
+ response[oids[:mac]].each do |oid, value|
77
+ ap_oid = oid.gsub("#{oids[:mac]}.", '')
78
+ access_points << AccessPoint.new(
79
+ name: response[oids[:name]][oids[:name] + '.' + ap_oid],
80
+ mac_address: parse_mac(value)
81
+ )
82
+ end
83
+ access_points
84
+ end
85
+
86
+ def parse_mac(mac)
87
+ mac.unpack('H2H2H2H2H2H2').join(':').upcase
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,7 @@
1
+ module Apscanner
2
+ class SnmpParser
3
+ def initialize(sensor)
4
+ @sensor = sensor
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Apscanner
2
+ module Loggable
3
+ def logger
4
+ @logger ||= default_logger
5
+ end
6
+
7
+ def logger=(logger)
8
+ @logger = logger
9
+ end
10
+
11
+ def default_logger
12
+ logger = Logger.new(STDOUT)
13
+ logger.level = Logger::INFO
14
+ logger
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Apscanner
2
+ class Scanner
3
+ def initialize(sensors_json)
4
+ @sensors = sensors_json.map { |s| Sensor.new(s) }
5
+ end
6
+
7
+ def run
8
+ @sensors.each do |sensor|
9
+ sensor.scan
10
+ yield(sensor) if block_given?
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Apscanner
2
+ VERSION = '1.0.0'.freeze
3
+ end
data/lib/apscanner.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'apscanner/loggable'
2
+ require 'apscanner/scanner'
3
+ require 'apscanner/entities/snmp_manager'
4
+ require 'apscanner/entities/sensor'
5
+ require 'apscanner/entities/access_point'
6
+
7
+ require 'snmp4em'
8
+ require 'json'
9
+ require 'logger'
10
+
11
+ module Apscanner
12
+ extend Loggable
13
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apscanner
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Julio J Garcia Perez
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: snmp4em
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Access Point SNMP Scanner
56
+ email:
57
+ - jjgarcia@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - bin/console
63
+ - lib/apscanner.rb
64
+ - lib/apscanner/entities/access_point.rb
65
+ - lib/apscanner/entities/sensor.rb
66
+ - lib/apscanner/entities/snmp_manager.rb
67
+ - lib/apscanner/entities/snmp_parser.rb
68
+ - lib/apscanner/loggable.rb
69
+ - lib/apscanner/scanner.rb
70
+ - lib/apscanner/version.rb
71
+ homepage: https://github.com/juliojgarciaperez/apscanner
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.2.2
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Access Points SNMP Scanner
95
+ test_files: []