oxidized 0.26.3 → 0.27.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +20 -4
  3. data/CHANGELOG.md +48 -4
  4. data/Dockerfile +6 -4
  5. data/README.md +2 -2
  6. data/Rakefile +4 -4
  7. data/bin/oxidized +2 -0
  8. data/docs/Configuration.md +40 -0
  9. data/docs/Creating-Models.md +39 -1
  10. data/docs/Model-Notes/JunOS.md +7 -7
  11. data/docs/Model-Notes/LinuxGeneric.md +23 -0
  12. data/docs/Model-Notes/Netgear.md +12 -1
  13. data/docs/Model-Notes/README.md +2 -0
  14. data/docs/Model-Notes/ios.md +29 -0
  15. data/docs/Supported-OS-Types.md +19 -3
  16. data/docs/Troubleshooting.md +66 -0
  17. data/extra/nagios_check_failing_nodes.rb +9 -2
  18. data/extra/oxidized.service +2 -0
  19. data/extra/syslog.rb +28 -23
  20. data/lib/oxidized/cli.rb +10 -6
  21. data/lib/oxidized/config/vars.rb +8 -9
  22. data/lib/oxidized/hook/githubrepo.rb +1 -1
  23. data/lib/oxidized/input/exec.rb +28 -0
  24. data/lib/oxidized/input/telnet.rb +1 -1
  25. data/lib/oxidized/model/adtran.rb +4 -0
  26. data/lib/oxidized/model/airfiber.rb +22 -0
  27. data/lib/oxidized/model/aos.rb +8 -0
  28. data/lib/oxidized/model/aosw.rb +1 -1
  29. data/lib/oxidized/model/c4cmts.rb +1 -1
  30. data/lib/oxidized/model/cambium.rb +1 -0
  31. data/lib/oxidized/model/ciscosmb.rb +0 -5
  32. data/lib/oxidized/model/comware.rb +17 -8
  33. data/lib/oxidized/model/dlink.rb +1 -1
  34. data/lib/oxidized/model/fastiron.rb +66 -0
  35. data/lib/oxidized/model/firelinuxos.rb +41 -0
  36. data/lib/oxidized/model/fortios.rb +5 -0
  37. data/lib/oxidized/model/hpmsm.rb +84 -0
  38. data/lib/oxidized/model/icotera.rb +27 -0
  39. data/lib/oxidized/model/ios.rb +4 -0
  40. data/lib/oxidized/model/ironware.rb +1 -0
  41. data/lib/oxidized/model/junos.rb +2 -2
  42. data/lib/oxidized/model/linuxgeneric.rb +74 -0
  43. data/lib/oxidized/model/model.rb +23 -13
  44. data/lib/oxidized/model/netgear.rb +16 -1
  45. data/lib/oxidized/model/oneos.rb +8 -0
  46. data/lib/oxidized/model/procurve.rb +8 -6
  47. data/lib/oxidized/model/purityos.rb +12 -0
  48. data/lib/oxidized/model/routeros.rb +13 -3
  49. data/lib/oxidized/model/screenos.rb +2 -3
  50. data/lib/oxidized/model/sonicos.rb +46 -0
  51. data/lib/oxidized/model/speedtouch.rb +34 -0
  52. data/lib/oxidized/model/sros.rb +11 -32
  53. data/lib/oxidized/model/voss.rb +5 -2
  54. data/lib/oxidized/model/zynosgs.rb +38 -0
  55. data/lib/oxidized/node.rb +14 -14
  56. data/lib/oxidized/version.rb +2 -2
  57. data/oxidized.gemspec +6 -4
  58. metadata +52 -17
  59. data/lib/oxidized/model/netgearxs716.rb +0 -23
@@ -0,0 +1,66 @@
1
+ class FastIron < Oxidized::Model
2
+ prompt /^([\w.@()-]+[#>]\s?)$/
3
+ comment '! '
4
+
5
+ cmd :all do |cfg|
6
+ # cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
7
+ # cfg.gsub! /\cH+/, '' # example how to handle pager
8
+ # get rid of errors for commands that don't work on some devices
9
+ cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
10
+ cfg.cut_both
11
+ end
12
+
13
+ cmd 'show version' do |cfg|
14
+ comments = []
15
+ comments << cfg.lines.first
16
+ lines = cfg.lines
17
+ lines.each_with_index do |line, _i|
18
+ comments << "Version: #{Regexp.last_match(1)}" if line =~ /^\s+SW: Version (.*)$/
19
+
20
+ comments << "Boot-Monitor Version: #{Regexp.last_match(1)}" if line =~ /^\s+Compressed Boot-Monitor Image size = \d+, Version:(.*)$/
21
+
22
+ comments << "Serial: #{Regexp.last_match(1)}" if line =~ /^\s+Serial #:(.*)$/
23
+ end
24
+ comments << "\n"
25
+ comment comments.join "\n"
26
+ end
27
+
28
+ cmd 'show module' do |cfg|
29
+ cfg.gsub! /^$\n/, ''
30
+ cfg.gsub! /^/, 'Modules: ' unless cfg.empty?
31
+ comment "#{cfg}\n"
32
+ end
33
+
34
+ cmd 'show media | exclude EMPTY' do |cfg|
35
+ comment cfg
36
+ end
37
+
38
+ cmd 'show hardware-info' do |cfg|
39
+ comment cfg
40
+ end
41
+
42
+ cmd 'show stack' do |cfg|
43
+ comment cfg
44
+ end
45
+
46
+ cmd 'show running-config'
47
+
48
+ cfg :telnet do
49
+ username /^.* login: /
50
+ password /^Password:/
51
+ end
52
+
53
+ cfg :telnet, :ssh do
54
+ # preferred way to handle additional passwords
55
+ post_login do
56
+ if vars(:enable) == true
57
+ cmd "enable"
58
+ elsif vars(:enable)
59
+ cmd "enable", /^[pP]assword:/
60
+ cmd vars(:enable)
61
+ end
62
+ end
63
+ post_login 'skip-page-display'
64
+ pre_logout 'exit'
65
+ end
66
+ end
@@ -0,0 +1,41 @@
1
+ class FireLinuxOS < Oxidized::Model
2
+ # Fire Linux OS is what the new FTD (FirePOWER) series devices from Cisco run. At the backend, it's mostly identical to ASA's.
3
+
4
+ prompt /^[#>]\(?.+\)?\s?/
5
+ comment '! '
6
+
7
+ cmd :all do |cfg|
8
+ cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
9
+ cfg.each_line.to_a[1..-2].join
10
+ end
11
+
12
+ cmd :secret do |cfg|
13
+ cfg.gsub! /enable password (\S+) (.*)/, 'enable password <secret hidden> \2'
14
+ cfg.gsub! /username (\S+) password (\S+) (.*)/, 'username \1 password <secret hidden> \3'
15
+ cfg.gsub! /(ikev[12] ((remote|local)-authentication )?pre-shared-key) (\S+)/, '\1 <secret hidden>'
16
+ cfg.gsub! /^(aaa-server TACACS\+? \(\S+\) host.*\n\skey) \S+$/mi, '\1 <secret hidden>'
17
+ cfg.gsub! /ldap-login-password (\S+)/, 'ldap-login-password <secret hidden>'
18
+ cfg.gsub! /^snmp-server host (.*) community (\S+)/, 'snmp-server host \1 community <secret hidden>'
19
+ cfg
20
+ end
21
+
22
+ cmd 'show version system' do |cfg|
23
+ cfg = cfg.each_line.reject { |line| line.match /(\s+up\s+\d+\s+)|(.*days.*)/ }
24
+ cfg = cfg.join
25
+ comment cfg
26
+ end
27
+
28
+ cmd 'show inventory' do |cfg|
29
+ comment cfg
30
+ end
31
+
32
+ cmd 'show running-config all' do |cfg|
33
+ cfg = cfg.each_line.to_a[3..-1].join
34
+ cfg.gsub! /^: [^\n]*\n/, ''
35
+ cfg
36
+ end
37
+
38
+ cfg :ssh do
39
+ pre_logout 'exit'
40
+ end
41
+ end
@@ -34,6 +34,11 @@ class FortiOS < Oxidized::Model
34
34
  comment cfg
35
35
  end
36
36
 
37
+ cmd 'get system ha status' do |cfg|
38
+ cfg = cfg.each_line.select { |line| line.match /^(HA Health Status|Mode|Model|Master|Slave\s+):/ }.join
39
+ comment cfg
40
+ end
41
+
37
42
  post do
38
43
  cfg = []
39
44
  cfg << cmd('config global') if @vdom_enabled
@@ -0,0 +1,84 @@
1
+ class HPMSM < Oxidized::Model
2
+ prompt /^CLI[>#] +$/
3
+
4
+ comment '! '
5
+
6
+ # replace next line control sequence with a new line
7
+ expect /(\e\[1M\e\[\??\d+(;\d+)*[A-Za-z]\e\[1L)|(\eE)/ do |data, re|
8
+ data.gsub re, "\n"
9
+ end
10
+
11
+ # replace all used vt100 control sequences
12
+ expect /\e\[\??\d+(;\d+)*[A-Za-z]/ do |data, re|
13
+ data.gsub re, ''
14
+ end
15
+
16
+ cmd :all do |cfg|
17
+ cfg = cfg.cut_both
18
+ cfg = cfg.gsub /^\r/, ''
19
+ cfg
20
+ end
21
+
22
+ cmd :secret do |cfg|
23
+ cfg.gsub! /^(snmp-server community) \S+(.*)/, '\\1 <secret hidden> \\2'
24
+ cfg.gsub! /^(snmp-server host \S+) \S+(.*)/, '\\1 <secret hidden> \\2'
25
+ cfg.gsub! /^(radius-server host \S+ key) \S+(.*)/, '\\1 <secret hidden> \\2'
26
+ cfg.gsub! /^(radius-server key).*/, '\\1 <configuration removed>'
27
+ cfg.gsub! /^(tacacs-server host \S+ key) \S+(.*)/, '\\1 <secret hidden> \\2'
28
+ cfg.gsub! /^(tacacs-server key).*/, '\\1 <secret hidden>'
29
+ cfg
30
+ end
31
+
32
+ cmd 'show system info' do |cfg|
33
+ sysinfo = ''
34
+ ram = cfg.match(/Total RAM:\s+(\S+)/)[1].to_i / 1024 / 1024
35
+ sysinfo << "Memory: #{ram}M\n"
36
+
37
+ serial = cfg.match(/Serial Number:\s+(\S+)/)[1]
38
+ sysinfo << "Serial Number: #{serial}\n"
39
+
40
+ firmware = cfg.match(/Firmware Version:\s+(\S+)/)[1]
41
+ sysinfo << "Firmware: #{firmware}\n"
42
+
43
+ comment sysinfo
44
+ end
45
+
46
+ cmd 'show ip' do |cfg|
47
+ comment cfg
48
+ end
49
+
50
+ cmd 'show ip route' do |cfg|
51
+ comment cfg
52
+ end
53
+
54
+ cmd 'show certificate' do |cfg|
55
+ comment cfg
56
+ end
57
+
58
+ cmd 'show certificate binding' do |cfg|
59
+ comment cfg
60
+ end
61
+
62
+ cmd 'show satellites' do |cfg|
63
+ comment cfg
64
+ end
65
+
66
+ cmd 'show web content' do |cfg|
67
+ comment cfg
68
+ end
69
+
70
+ cmd 'show all config' do |cfg|
71
+ cfg = cfg.each_line.reject { |line| line.match /^running configuration:/ }.join
72
+ # The who line contains SSH source port number, and the When line contains the timestamp of the run
73
+ cfg = cfg.each_line.reject { |line| line.match /(^#\s+Who:)|(^#\s+When:)/ }.join
74
+ # igmp proxy line keeps changing with weird characters every run, filter it out
75
+ cfg = cfg.each_line.reject { |line| line.match /^[ \t]*igmp proxy (upstream|downstream)/ }.join
76
+ cfg
77
+ end
78
+
79
+ cfg :ssh do
80
+ post_login "enable"
81
+ pre_logout "quit"
82
+ pty_options(chars_wide: 1000)
83
+ end
84
+ end
@@ -0,0 +1,27 @@
1
+ class Icotera < Oxidized::Model
2
+ comment '## '
3
+
4
+ cmd :all do |cfg|
5
+ cfg.cut_both
6
+ end
7
+
8
+ cmd 'show management' do |cfg|
9
+ cfg.gsub! /^\s+System uptime.*\n/, ""
10
+ cfg.gsub! /^\s+Bytes in.*\n/, ""
11
+ cfg.gsub! /^\s+Pkts in.*\n/, ""
12
+ cfg.gsub! /^\s+Ucast in.*\n/, ""
13
+ cfg.gsub! /^\s+Bcast in.*\n/, ""
14
+ cfg.gsub! /^\s+Mcast in.*\n/, ""
15
+ cfg.gsub! /^\s+Ucast in pps.*\n/, ""
16
+ cfg.gsub! /^\s+Mcast in pps.*\n/, ""
17
+ cfg.gsub! /^\s+Total in bps.*\n/, ""
18
+
19
+ comment cfg
20
+ end
21
+
22
+ cmd 'copy progress screen'
23
+
24
+ cfg :ssh do
25
+ pre_logout 'exit'
26
+ end
27
+ end
@@ -41,6 +41,7 @@ class IOS < Oxidized::Model
41
41
  cfg.gsub! /^(\s+standby \d+ authentication md5 key-string) .+?( timeout \d+)?$/, '\\1 <secret hidden> \\2'
42
42
  cfg.gsub! /^(\s+key-string) .+/, '\\1 <secret hidden>'
43
43
  cfg.gsub! /^((tacacs|radius) server [^\n]+\n(\s+[^\n]+\n)*\s+key) [^\n]+$/m, '\1 <secret hidden>'
44
+ cfg.gsub! /^(\s+ppp (chap|pap) password \d) .+/, '\\1 <secret hidden>'
44
45
  cfg
45
46
  end
46
47
 
@@ -95,6 +96,7 @@ class IOS < Oxidized::Model
95
96
 
96
97
  cmd 'show vtp status' do |cfg|
97
98
  cfg.gsub! /^$\n/, ''
99
+ cfg.gsub! /Configuration last modified by.*\n/, ''
98
100
  cfg.gsub! /^/, 'VTP: ' unless cfg.empty?
99
101
  comment "#{cfg}\n"
100
102
  end
@@ -107,6 +109,8 @@ class IOS < Oxidized::Model
107
109
  cfg = cfg.each_line.to_a[3..-1]
108
110
  cfg = cfg.reject { |line| line.match /^ntp clock-period / }.join
109
111
  cfg.gsub! /^Current configuration : [^\n]*\n/, ''
112
+ cfg.gsub! /^! (Last|No) configuration change (at|since).*\n/, ''
113
+ cfg.gsub! /^! NVRAM config last updated.*\n/, ''
110
114
  cfg.gsub! /^ tunnel mpls traffic-eng bandwidth[^\n]*\n*(
111
115
  (?: [^\n]*\n*)*
112
116
  tunnel mpls traffic-eng auto-bw)/mx, '\1'
@@ -51,6 +51,7 @@ class IronWare < Oxidized::Model
51
51
 
52
52
  cmd 'show flash' do |cfg|
53
53
  cfg.gsub! /(\d+) bytes/, '' # Fix for ADX flash size
54
+ cfg.gsub! /(^((.*)Code Flash Free Space(.*))$)/, '' # Brocade
54
55
  comment cfg
55
56
  end
56
57
 
@@ -17,8 +17,6 @@ class JunOS < Oxidized::Model
17
17
  cfg
18
18
  end
19
19
 
20
- cmd 'show configuration | display omit'
21
-
22
20
  cmd 'show version' do |cfg|
23
21
  @model = Regexp.last_match(1) if cfg =~ /^Model: (\S+)/
24
22
  comment cfg
@@ -39,6 +37,8 @@ class JunOS < Oxidized::Model
39
37
  cmd('show system license') { |cfg| comment cfg }
40
38
  cmd('show system license keys') { |cfg| comment cfg }
41
39
 
40
+ cmd 'show configuration | display omit'
41
+
42
42
  cfg :telnet do
43
43
  username(/^login:/)
44
44
  password(/^Password:/)
@@ -0,0 +1,74 @@
1
+ class LinuxGeneric < Oxidized::Model
2
+ prompt /^(\w.*|\W.*)(:|#) /
3
+ comment '# '
4
+
5
+ # add a comment in the final conf
6
+ def add_comment(comment)
7
+ "\n###### #{comment} ######\n"
8
+ end
9
+
10
+ cmd :all do |cfg|
11
+ cfg.gsub! /^(default (\S+).* (expires) ).*/, '\\1 <redacted>'
12
+ cfg.cut_both
13
+ end
14
+
15
+ # show the persistent configuration
16
+ pre do
17
+ cfg = add_comment 'THE HOSTNAME'
18
+ cfg += cmd 'cat /etc/hostname'
19
+
20
+ cfg += add_comment 'THE HOSTS'
21
+ cfg += cmd 'cat /etc/hosts'
22
+
23
+ cfg += add_comment 'THE INTERFACES'
24
+ cfg += cmd 'ip link'
25
+
26
+ cfg += add_comment 'RESOLV.CONF'
27
+ cfg += cmd 'cat /etc/resolv.conf'
28
+
29
+ cfg += add_comment 'IP Routes'
30
+ cfg += cmd 'ip route'
31
+
32
+ cfg += add_comment 'IPv6 Routes'
33
+ cfg += cmd 'ip -6 route'
34
+
35
+ cfg += add_comment 'MOTD'
36
+ cfg += cmd 'cat /etc/motd'
37
+
38
+ cfg += add_comment 'PASSWD'
39
+ cfg += cmd 'cat /etc/passwd'
40
+
41
+ cfg += add_comment 'GROUP'
42
+ cfg += cmd 'cat /etc/group'
43
+
44
+ cfg += add_comment 'nsswitch.conf'
45
+ cfg += cmd 'cat /etc/nsswitch.conf'
46
+
47
+ cfg += add_comment 'VERSION'
48
+ cfg += cmd 'cat /etc/issue'
49
+
50
+ cfg
51
+ end
52
+
53
+ cfg :telnet do
54
+ username /^Username:/
55
+ password /^Password:/
56
+ end
57
+
58
+ cfg :telnet, :ssh do
59
+ post_login do
60
+ if vars(:enable) == true
61
+ cmd "sudo su -", /^\[sudo\] password/
62
+ cmd @node.auth[:password]
63
+ elsif vars(:enable)
64
+ cmd "su -", /^Password:/
65
+ cmd vars(:enable)
66
+ end
67
+ end
68
+
69
+ pre_logout do
70
+ cmd "exit" if vars(:enable)
71
+ end
72
+ pre_logout 'exit'
73
+ end
74
+ end
@@ -7,22 +7,32 @@ module Oxidized
7
7
 
8
8
  class << self
9
9
  def inherited(klass)
10
- klass.instance_variable_set '@cmd', (Hash.new { |h, k| h[k] = [] })
11
- klass.instance_variable_set '@cfg', (Hash.new { |h, k| h[k] = [] })
12
- klass.instance_variable_set '@procs', (Hash.new { |h, k| h[k] = [] })
13
- klass.instance_variable_set '@expect', []
14
- klass.instance_variable_set '@comment', nil
15
- klass.instance_variable_set '@prompt', nil
10
+ if klass.superclass == Oxidized::Model
11
+ klass.instance_variable_set '@cmd', (Hash.new { |h, k| h[k] = [] })
12
+ klass.instance_variable_set '@cfg', (Hash.new { |h, k| h[k] = [] })
13
+ klass.instance_variable_set '@procs', (Hash.new { |h, k| h[k] = [] })
14
+ klass.instance_variable_set '@expect', []
15
+ klass.instance_variable_set '@comment', nil
16
+ klass.instance_variable_set '@prompt', nil
17
+ else # we're subclassing some existing model, take its variables
18
+ instance_variables.each do |var|
19
+ klass.instance_variable_set var, instance_variable_get(var)
20
+ end
21
+ end
16
22
  end
17
23
 
18
- def comment(str = '# ')
19
- return @comment if @comment
20
-
21
- @comment = block_given? ? yield : str
24
+ def comment(str = "# ")
25
+ @comment = if block_given?
26
+ yield
27
+ elsif not @comment
28
+ str
29
+ else
30
+ @comment
31
+ end
22
32
  end
23
33
 
24
34
  def prompt(regex = nil)
25
- @prompt || (@prompt = regex)
35
+ @prompt = regex || @prompt
26
36
  end
27
37
 
28
38
  def cfg(*methods, **args, &block)
@@ -178,8 +188,8 @@ module Oxidized
178
188
  private
179
189
 
180
190
  def process_cmd_output(output, name)
181
- output = Oxidized::String.new output if ::String == output.class
182
- output = Oxidized::String.new '' unless Oxidized::String == output.class
191
+ output = Oxidized::String.new(output) if output.is_a?(::String)
192
+ output = Oxidized::String.new('') unless output.instance_of?(Oxidized::String)
183
193
  output.set_cmd(name)
184
194
  output
185
195
  end
@@ -5,6 +5,7 @@ class Netgear < Oxidized::Model
5
5
  cmd :secret do |cfg|
6
6
  cfg.gsub!(/password (\S+)/, 'password <hidden>')
7
7
  cfg.gsub!(/encrypted (\S+)/, 'encrypted <hidden>')
8
+ cfg.gsub!(/snmp-server community (\S+)/, 'snmp-server community <hidden>') # snmp
8
9
  cfg
9
10
  end
10
11
 
@@ -31,7 +32,21 @@ class Netgear < Oxidized::Model
31
32
  # So it is safer simply to disconnect and not issue a pre_logout command
32
33
  end
33
34
 
35
+ cmd :all do |cfg, cmdstring|
36
+ new_cfg = comment "COMMAND: #{cmdstring}\n"
37
+ new_cfg << cfg.each_line.to_a[1..-2].join
38
+ end
39
+
40
+ cmd 'show version' do |cfg|
41
+ cfg.gsub! /(Current Time\.+ ).*/, '\\1 <removed>'
42
+ comment cfg
43
+ end
44
+
45
+ cmd 'show bootvar' do |cfg|
46
+ comment cfg
47
+ end
34
48
  cmd 'show running-config' do |cfg|
35
- cfg.gsub! /^(!.*Time).*$/, '\1'
49
+ cfg.gsub! /(System Up Time\s+).*/, '\\1 <removed>'
50
+ cfg.gsub! /(Current SNTP Synchronized Time:).*/, '\\1 <removed>'
36
51
  end
37
52
  end