oxidized 0.29.1 → 0.37.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 +4 -4
- data/.coderabbit.yaml +21 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +45 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- data/.github/ISSUE_TEMPLATE/support-request.md +39 -0
- data/.github/workflows/codeql.yml +4 -4
- data/.github/workflows/publishdocker.yml +108 -13
- data/.github/workflows/ruby.yml +3 -12
- data/.github/workflows/stale.yml +6 -1
- data/.gitignore +2 -0
- data/.rubocop.yml +69 -13
- data/.rubocop_todo.yml +13 -143
- data/CHANGELOG.md +431 -4
- data/CONTRIBUTING.md +189 -0
- data/Dockerfile +89 -34
- data/README.md +59 -188
- data/Rakefile +58 -12
- data/bin/oxidized +2 -5
- data/docs/Configuration.md +382 -149
- data/docs/Creating-Models.md +262 -10
- data/docs/DeviceSimulation.md +196 -0
- data/docs/Docker.md +246 -0
- data/docs/Hooks.md +146 -51
- data/docs/Inputs.md +237 -0
- data/docs/Issues.md +123 -0
- data/docs/Model-Notes/APC.md +72 -0
- data/docs/Model-Notes/Cumulus.md +5 -0
- data/docs/Model-Notes/EatonNetwork.md +18 -0
- data/docs/Model-Notes/ExaLink.md +43 -0
- data/docs/Model-Notes/FSOS.md +17 -0
- data/docs/Model-Notes/Fortinet.md +75 -0
- data/docs/Model-Notes/GrandstreamHT8xx.md +8 -0
- data/docs/Model-Notes/HPEAruba.md +32 -0
- data/docs/Model-Notes/IvantiConnectSecure.md +59 -0
- data/docs/Model-Notes/OS6.md +10 -0
- data/docs/Model-Notes/README.md +1 -20
- data/docs/Model-Notes/RouterOS.md +28 -0
- data/docs/Model-Notes/SikluMHTG.md +7 -0
- data/docs/Model-Notes/TrueNAS.md +23 -0
- data/docs/Model-Notes/XGS4600-Zyxel.md +5 -0
- data/docs/ModelUnitTests.md +219 -0
- data/docs/Outputs.md +102 -5
- data/docs/Release.md +102 -0
- data/docs/Ruby-API.md +135 -2
- data/docs/Sources.md +34 -0
- data/docs/Supported-OS-Types.md +207 -270
- data/docs/Troubleshooting.md +43 -1
- data/extra/device2yaml.rb +259 -0
- data/extra/gitdiff-msteams.sh +32 -5
- data/extra/hooks/modelrules.rb +55 -0
- data/extra/hooks/modelrulesadvanced.rb +167 -0
- data/extra/hooks/srcipmap.rb +54 -0
- data/extra/nagios_check_failing_nodes.rb +1 -1
- data/extra/oxidized.runit +1 -1
- data/extra/rest_client.rb +5 -4
- data/extra/syslog.rb +11 -6
- data/lib/oxidized/cli/support.rb +152 -0
- data/lib/oxidized/cli.rb +21 -6
- data/lib/oxidized/config/vars.rb +33 -14
- data/lib/oxidized/config.rb +28 -17
- data/lib/oxidized/core.rb +50 -8
- data/lib/oxidized/hook/ciscosparkdiff.rb +11 -9
- data/lib/oxidized/hook/exec.rb +5 -4
- data/lib/oxidized/hook/githubrepo.rb +55 -18
- data/lib/oxidized/hook/noophook.rb +2 -2
- data/lib/oxidized/hook/slackdiff.rb +50 -14
- data/lib/oxidized/hook/xmppdiff.rb +9 -9
- data/lib/oxidized/hook.rb +68 -16
- data/lib/oxidized/input/cli.rb +8 -3
- data/lib/oxidized/input/debugtext.rb +40 -0
- data/lib/oxidized/input/debugyaml.rb +82 -0
- data/lib/oxidized/input/exec.rb +2 -11
- data/lib/oxidized/input/ftp.rb +2 -19
- data/lib/oxidized/input/http.rb +67 -17
- data/lib/oxidized/input/input.rb +35 -14
- data/lib/oxidized/input/scp.rb +27 -0
- data/lib/oxidized/input/ssh.rb +59 -83
- data/lib/oxidized/input/sshbase.rb +102 -0
- data/lib/oxidized/input/telnet.rb +20 -19
- data/lib/oxidized/input/tftp.rb +8 -8
- data/lib/oxidized/job.rb +18 -7
- data/lib/oxidized/jobs.rb +11 -1
- data/lib/oxidized/logger.rb +51 -0
- data/lib/oxidized/manager.rb +18 -17
- data/lib/oxidized/model/acos.rb +2 -1
- data/lib/oxidized/model/addpack.rb +26 -0
- data/lib/oxidized/model/adtran.rb +5 -1
- data/lib/oxidized/model/adva.rb +3 -3
- data/lib/oxidized/model/airfiber.rb +1 -1
- data/lib/oxidized/model/aos7.rb +11 -0
- data/lib/oxidized/model/aoscx.rb +37 -29
- data/lib/oxidized/model/aosw.rb +39 -29
- data/lib/oxidized/model/apc_aos.rb +7 -2
- data/lib/oxidized/model/apcaos.rb +39 -0
- data/lib/oxidized/model/aricentiss.rb +9 -2
- data/lib/oxidized/model/arubainstant.rb +93 -0
- data/lib/oxidized/model/asa.rb +11 -10
- data/lib/oxidized/model/asternos.rb +22 -0
- data/lib/oxidized/model/asyncos.rb +3 -3
- data/lib/oxidized/model/audiocodes.rb +2 -2
- data/lib/oxidized/model/awplus.rb +15 -12
- data/lib/oxidized/model/axos.rb +1 -1
- data/lib/oxidized/model/bdcom.rb +1 -0
- data/lib/oxidized/model/c4cmts.rb +1 -2
- data/lib/oxidized/model/ciscosma.rb +1 -1
- data/lib/oxidized/model/ciscosmb.rb +6 -1
- data/lib/oxidized/model/cnos.rb +13 -10
- data/lib/oxidized/model/comtrol.rb +1 -1
- data/lib/oxidized/model/comware.rb +5 -3
- data/lib/oxidized/model/cumulus.rb +14 -2
- data/lib/oxidized/model/defacto.rb +26 -0
- data/lib/oxidized/model/dellx.rb +1 -1
- data/lib/oxidized/model/dlink.rb +5 -2
- data/lib/oxidized/model/dlinknextgen.rb +55 -0
- data/lib/oxidized/model/dnos.rb +3 -0
- data/lib/oxidized/model/dslcommands.rb +93 -0
- data/lib/oxidized/model/dslsetup.rb +102 -0
- data/lib/oxidized/model/eatonnetwork.rb +70 -0
- data/lib/oxidized/model/edgecos.rb +3 -1
- data/lib/oxidized/model/edgeos.rb +7 -6
- data/lib/oxidized/model/edgeswitch.rb +3 -1
- data/lib/oxidized/model/efos.rb +41 -0
- data/lib/oxidized/model/eltex.rb +4 -2
- data/lib/oxidized/model/enterasys800.rb +2 -2
- data/lib/oxidized/model/enterprise_sonic.rb +46 -0
- data/lib/oxidized/model/eos.rb +3 -1
- data/lib/oxidized/model/exalink.rb +36 -0
- data/lib/oxidized/model/f5os.rb +17 -0
- data/lib/oxidized/model/fabricos.rb +2 -2
- data/lib/oxidized/model/fastiron.rb +5 -3
- data/lib/oxidized/model/firebrick.rb +2 -2
- data/lib/oxidized/model/firelinuxos.rb +13 -6
- data/lib/oxidized/model/firewareos.rb +10 -1
- data/lib/oxidized/model/fortigate.rb +160 -0
- data/lib/oxidized/model/fortios.rb +38 -48
- data/lib/oxidized/model/fsos.rb +46 -0
- data/lib/oxidized/model/gaiaos.rb +4 -4
- data/lib/oxidized/model/garderos.rb +38 -0
- data/lib/oxidized/model/grandstreamht8xx.rb +19 -0
- data/lib/oxidized/model/h3c.rb +1 -1
- data/lib/oxidized/model/ibos.rb +1 -0
- data/lib/oxidized/model/ingate.rb +47 -0
- data/lib/oxidized/model/ios.rb +57 -30
- data/lib/oxidized/model/iosxr.rb +2 -2
- data/lib/oxidized/model/ironware.rb +7 -5
- data/lib/oxidized/model/ivanti.rb +54 -0
- data/lib/oxidized/model/junos.rb +12 -5
- data/lib/oxidized/model/kornfeldos.rb +33 -0
- data/lib/oxidized/model/lenovonos.rb +2 -0
- data/lib/oxidized/model/linksyssrw.rb +3 -3
- data/lib/oxidized/model/linuxgeneric.rb +4 -2
- data/lib/oxidized/model/macros.rb +60 -0
- data/lib/oxidized/model/mimosab11.rb +34 -0
- data/lib/oxidized/model/ml66.rb +33 -0
- data/lib/oxidized/model/mlnxos.rb +18 -14
- data/lib/oxidized/model/model.rb +98 -103
- data/lib/oxidized/model/mtrlrfs.rb +1 -0
- data/lib/oxidized/model/ndms.rb +6 -0
- data/lib/oxidized/model/netgear.rb +14 -3
- data/lib/oxidized/model/netonix.rb +1 -1
- data/lib/oxidized/model/netscaler.rb +1 -1
- data/lib/oxidized/model/nodegrid.rb +1 -1
- data/lib/oxidized/model/nsxdfw.rb +31 -0
- data/lib/oxidized/model/nsxfirewall.rb +2 -1
- data/lib/oxidized/model/nxos.rb +20 -15
- data/lib/oxidized/model/ocnos.rb +42 -0
- data/lib/oxidized/model/onefinity.rb +18 -0
- data/lib/oxidized/model/openbsd.rb +1 -1
- data/lib/oxidized/model/opengear.rb +36 -1
- data/lib/oxidized/model/openwrt.rb +6 -6
- data/lib/oxidized/model/opnsense.rb +9 -1
- data/lib/oxidized/model/os6.rb +48 -0
- data/lib/oxidized/model/outputs.rb +5 -0
- data/lib/oxidized/model/panos.rb +2 -0
- data/lib/oxidized/model/perle.rb +41 -0
- data/lib/oxidized/model/pfsense.rb +9 -0
- data/lib/oxidized/model/powerconnect.rb +32 -11
- data/lib/oxidized/model/procurve.rb +6 -2
- data/lib/oxidized/model/qtech.rb +3 -1
- data/lib/oxidized/model/quantaos.rb +8 -6
- data/lib/oxidized/model/rgos.rb +33 -0
- data/lib/oxidized/model/riverbed.rb +104 -0
- data/lib/oxidized/model/routeros.rb +18 -11
- data/lib/oxidized/model/saos.rb +18 -1
- data/lib/oxidized/model/saos10.rb +38 -0
- data/lib/oxidized/model/siklu.rb +1 -1
- data/lib/oxidized/model/siklumhtg.rb +22 -0
- data/lib/oxidized/model/sixwind.rb +28 -0
- data/lib/oxidized/model/slxos.rb +3 -3
- data/lib/oxidized/model/smartbyte.rb +48 -0
- data/lib/oxidized/model/sonicos.rb +27 -20
- data/lib/oxidized/model/speedtouch.rb +1 -1
- data/lib/oxidized/model/sros.rb +3 -3
- data/lib/oxidized/model/srosmd.rb +1 -1
- data/lib/oxidized/model/supermicro.rb +1 -1
- data/lib/oxidized/model/telco.rb +1 -1
- data/lib/oxidized/model/tmos.rb +1 -0
- data/lib/oxidized/model/tnsr.rb +57 -0
- data/lib/oxidized/model/tplink.rb +5 -5
- data/lib/oxidized/model/trango.rb +4 -2
- data/lib/oxidized/model/truenas.rb +64 -3
- data/lib/oxidized/model/ucs.rb +1 -1
- data/lib/oxidized/model/unifiap.rb +144 -0
- data/lib/oxidized/model/uplinkolt.rb +46 -0
- data/lib/oxidized/model/voltaire.rb +1 -1
- data/lib/oxidized/model/voss.rb +3 -0
- data/lib/oxidized/model/vrp.rb +5 -1
- data/lib/oxidized/model/vyatta.rb +9 -3
- data/lib/oxidized/model/vyos.rb +37 -0
- data/lib/oxidized/model/xos.rb +10 -1
- data/lib/oxidized/model/zhoneolt.rb +4 -2
- data/lib/oxidized/model/zynos.rb +67 -3
- data/lib/oxidized/model/zynosadsl.rb +14 -0
- data/lib/oxidized/model/zynoscli.rb +1 -1
- data/lib/oxidized/model/zynosgs.rb +2 -0
- data/lib/oxidized/model/zynosmgs.rb +32 -0
- data/lib/oxidized/node.rb +99 -64
- data/lib/oxidized/nodes.rb +40 -19
- data/lib/oxidized/output/file.rb +80 -43
- data/lib/oxidized/output/git.rb +295 -151
- data/lib/oxidized/output/gitcrypt.rb +193 -185
- data/lib/oxidized/output/http.rb +63 -51
- data/lib/oxidized/output/output.rb +20 -4
- data/lib/oxidized/signals.rb +44 -0
- data/lib/oxidized/source/csv.rb +49 -49
- data/lib/oxidized/source/http.rb +76 -63
- data/lib/oxidized/source/jsonfile.rb +68 -0
- data/lib/oxidized/source/source.rb +73 -18
- data/lib/oxidized/source/sql.rb +71 -59
- data/lib/oxidized/version.rb +6 -4
- data/lib/oxidized/worker.rb +57 -29
- data/lib/oxidized.rb +4 -24
- data/lib/refinements.rb +21 -1
- data/oxidized.gemspec +45 -21
- metadata +248 -41
- data/lib/oxidized/model/timos.rb +0 -10
data/lib/oxidized/model/model.rb
CHANGED
|
@@ -1,22 +1,40 @@
|
|
|
1
1
|
require 'strscan'
|
|
2
2
|
require_relative 'outputs'
|
|
3
|
+
require_relative 'dslsetup'
|
|
4
|
+
require_relative 'dslcommands'
|
|
5
|
+
require_relative 'macros'
|
|
3
6
|
|
|
4
7
|
module Oxidized
|
|
5
8
|
class Model
|
|
9
|
+
include SemanticLogger::Loggable
|
|
10
|
+
|
|
6
11
|
using Refinements
|
|
7
12
|
|
|
13
|
+
# Domain Specific Language for models
|
|
14
|
+
extend Oxidized::Model::DSLSetup
|
|
15
|
+
extend Oxidized::Model::DSLCommands
|
|
16
|
+
extend Oxidized::Model::Macros
|
|
17
|
+
|
|
8
18
|
include Oxidized::Config::Vars
|
|
9
19
|
|
|
20
|
+
# rubocop:disable Style/FormatStringToken
|
|
21
|
+
METADATA_DEFAULT = "%{comment}Fetched by Oxidized with model %{model} " \
|
|
22
|
+
"from host %{name} [%{ip}]\n".freeze
|
|
23
|
+
# rubocop:enable Style/FormatStringToken
|
|
24
|
+
|
|
10
25
|
class << self
|
|
11
26
|
def inherited(klass)
|
|
12
27
|
super
|
|
13
28
|
if klass.superclass == Oxidized::Model
|
|
14
|
-
klass.instance_variable_set
|
|
15
|
-
klass.instance_variable_set
|
|
16
|
-
klass.instance_variable_set
|
|
29
|
+
klass.instance_variable_set('@cmd', Hash.new { |h, k| h[k] = [] })
|
|
30
|
+
klass.instance_variable_set('@cfg', Hash.new { |h, k| h[k] = [] })
|
|
31
|
+
klass.instance_variable_set('@procs', Hash.new { |h, k| h[k] = [] })
|
|
17
32
|
klass.instance_variable_set '@expect', []
|
|
18
33
|
klass.instance_variable_set '@comment', nil
|
|
19
34
|
klass.instance_variable_set '@prompt', nil
|
|
35
|
+
klass.instance_variable_set '@metadata', {}
|
|
36
|
+
klass.instance_variable_set '@inputs', nil
|
|
37
|
+
|
|
20
38
|
else # we're subclassing some existing model, take its variables
|
|
21
39
|
instance_variables.each do |var|
|
|
22
40
|
iv = instance_variable_get(var)
|
|
@@ -25,101 +43,20 @@ module Oxidized
|
|
|
25
43
|
end
|
|
26
44
|
end
|
|
27
45
|
end
|
|
28
|
-
|
|
29
|
-
def comment(str = "# ")
|
|
30
|
-
@comment = if block_given?
|
|
31
|
-
yield
|
|
32
|
-
elsif not @comment
|
|
33
|
-
str
|
|
34
|
-
else
|
|
35
|
-
@comment
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def prompt(regex = nil)
|
|
40
|
-
@prompt = regex || @prompt
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def cfg(*methods, **args, &block)
|
|
44
|
-
[methods].flatten.each do |method|
|
|
45
|
-
process_args_block(@cfg[method.to_s], args, block)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def cfgs
|
|
50
|
-
@cfg
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def cmd(cmd_arg = nil, **args, &block)
|
|
54
|
-
if cmd_arg.instance_of?(Symbol)
|
|
55
|
-
process_args_block(@cmd[cmd_arg], args, block)
|
|
56
|
-
else
|
|
57
|
-
process_args_block(@cmd[:cmd], args, [cmd_arg, block])
|
|
58
|
-
end
|
|
59
|
-
Oxidized.logger.debug "lib/oxidized/model/model.rb Added #{cmd_arg} to the commands list"
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def cmds
|
|
63
|
-
@cmd
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def expect(regex, **args, &block)
|
|
67
|
-
process_args_block(@expect, args, [regex, block])
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def expects
|
|
71
|
-
@expect
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# calls the block at the end of the model, prepending the output of the
|
|
75
|
-
# block to the output string
|
|
76
|
-
#
|
|
77
|
-
# @author Saku Ytti <saku@ytti.fi>
|
|
78
|
-
# @since 0.0.39
|
|
79
|
-
# @yield expects block which should return [String]
|
|
80
|
-
# @return [void]
|
|
81
|
-
def pre(**args, &block)
|
|
82
|
-
process_args_block(@procs[:pre], args, block)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# calls the block at the end of the model, adding the output of the block
|
|
86
|
-
# to the output string
|
|
87
|
-
#
|
|
88
|
-
# @author Saku Ytti <saku@ytti.fi>
|
|
89
|
-
# @since 0.0.39
|
|
90
|
-
# @yield expects block which should return [String]
|
|
91
|
-
# @return [void]
|
|
92
|
-
def post(**args, &block)
|
|
93
|
-
process_args_block(@procs[:post], args, block)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# @author Saku Ytti <saku@ytti.fi>
|
|
97
|
-
# @since 0.0.39
|
|
98
|
-
# @return [Hash] hash proc procs :pre+:post to be prepended/postfixed to output
|
|
99
|
-
attr_reader :procs
|
|
100
|
-
|
|
101
|
-
private
|
|
102
|
-
|
|
103
|
-
def process_args_block(target, args, block)
|
|
104
|
-
if args[:clear]
|
|
105
|
-
if block.instance_of?(Array)
|
|
106
|
-
target.reject! { |k, _| k == block[0] }
|
|
107
|
-
target.push(block)
|
|
108
|
-
else
|
|
109
|
-
target.replace([block])
|
|
110
|
-
end
|
|
111
|
-
else
|
|
112
|
-
method = args[:prepend] ? :unshift : :push
|
|
113
|
-
target.send(method, block)
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
46
|
end
|
|
117
47
|
|
|
118
48
|
attr_accessor :input, :node
|
|
119
49
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
50
|
+
# input specifies to run this command only with this input type
|
|
51
|
+
# if input is not specified, always run the command
|
|
52
|
+
def cmd(string, input: nil, &block)
|
|
53
|
+
logger.debug "Executing #{string}"
|
|
54
|
+
out = if input.nil? || input.include?(@input.to_sym)
|
|
55
|
+
out = @input.cmd(string)
|
|
56
|
+
else
|
|
57
|
+
# Do not run this command
|
|
58
|
+
return ''
|
|
59
|
+
end
|
|
123
60
|
return false unless out
|
|
124
61
|
|
|
125
62
|
out = out.b unless Oxidized.config.input.utf8_encoded?
|
|
@@ -135,6 +72,44 @@ module Oxidized
|
|
|
135
72
|
process_cmd_output out, string
|
|
136
73
|
end
|
|
137
74
|
|
|
75
|
+
def metadata(position)
|
|
76
|
+
return unless %i[top bottom].include? position
|
|
77
|
+
|
|
78
|
+
model_metadata = self.class.instance_variable_get(:@metadata)
|
|
79
|
+
var_position = { top: "metadata_top", bottom: "metadata_bottom" }
|
|
80
|
+
if model_metadata[:top] || model_metadata[:bottom]
|
|
81
|
+
# the model defines metadata at :top ot :bottom, use the model
|
|
82
|
+
value = model_metadata[position]
|
|
83
|
+
value.is_a?(Proc) ? instance_eval(&value) : interpolate_string(value)
|
|
84
|
+
elsif vars("metadata_top") || vars("metadata_bottom")
|
|
85
|
+
# vars defines metadata_top or metadata bottom, use the vars
|
|
86
|
+
interpolate_string(vars(var_position[position]))
|
|
87
|
+
elsif position == :top
|
|
88
|
+
# default: use METADATA_DEFAULT for top
|
|
89
|
+
interpolate_string(METADATA_DEFAULT)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def interpolate_string(template)
|
|
94
|
+
return nil unless template
|
|
95
|
+
|
|
96
|
+
time = Time.now
|
|
97
|
+
template_variables = {
|
|
98
|
+
model: self.class.name,
|
|
99
|
+
name: node.name,
|
|
100
|
+
ip: node.ip,
|
|
101
|
+
group: node.group,
|
|
102
|
+
comment: self.class.comment,
|
|
103
|
+
year: time.year,
|
|
104
|
+
month: "%02d" % time.month,
|
|
105
|
+
day: "%02d" % time.day,
|
|
106
|
+
hour: "%02d" % time.hour,
|
|
107
|
+
minute: "%02d" % time.min,
|
|
108
|
+
second: "%02d" % time.sec
|
|
109
|
+
}
|
|
110
|
+
template % template_variables
|
|
111
|
+
end
|
|
112
|
+
|
|
138
113
|
def output
|
|
139
114
|
@input.output
|
|
140
115
|
end
|
|
@@ -143,8 +118,8 @@ module Oxidized
|
|
|
143
118
|
@input.send data
|
|
144
119
|
end
|
|
145
120
|
|
|
146
|
-
def expect(
|
|
147
|
-
self.class.expect
|
|
121
|
+
def expect(...)
|
|
122
|
+
self.class.expect(...)
|
|
148
123
|
end
|
|
149
124
|
|
|
150
125
|
def cfg
|
|
@@ -164,27 +139,40 @@ module Oxidized
|
|
|
164
139
|
data
|
|
165
140
|
end
|
|
166
141
|
|
|
142
|
+
# Get the commands from the model
|
|
167
143
|
def get
|
|
168
|
-
|
|
144
|
+
logger.debug 'Collecting commands\' outputs'
|
|
169
145
|
outputs = Outputs.new
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
146
|
+
self.class.cmds[:cmd].each do |data|
|
|
147
|
+
command = data[:cmd]
|
|
148
|
+
args = data[:args]
|
|
149
|
+
block = data[:block]
|
|
150
|
+
|
|
151
|
+
next if args.include?(:if) && !instance_exec(&args[:if])
|
|
152
|
+
|
|
153
|
+
out = cmd command, input: args[:input], &block
|
|
173
154
|
return false unless out
|
|
174
155
|
|
|
175
156
|
outputs << out
|
|
176
157
|
end
|
|
158
|
+
procs = self.class.procs
|
|
177
159
|
procs[:pre].each do |pre_proc|
|
|
178
160
|
outputs.unshift process_cmd_output(instance_eval(&pre_proc), '')
|
|
179
161
|
end
|
|
180
162
|
procs[:post].each do |post_proc|
|
|
181
163
|
outputs << process_cmd_output(instance_eval(&post_proc), '')
|
|
182
164
|
end
|
|
165
|
+
if vars("metadata") == true
|
|
166
|
+
metadata_top = metadata(:top)
|
|
167
|
+
metadata_bottom = metadata(:bottom)
|
|
168
|
+
outputs.unshift metadata_top if metadata_top
|
|
169
|
+
outputs << metadata_bottom if metadata_bottom
|
|
170
|
+
end
|
|
183
171
|
outputs
|
|
184
172
|
end
|
|
185
173
|
|
|
186
174
|
def comment(str)
|
|
187
|
-
data = ''
|
|
175
|
+
data = String.new('')
|
|
188
176
|
str.each_line do |line|
|
|
189
177
|
data << self.class.comment << line
|
|
190
178
|
end
|
|
@@ -202,7 +190,7 @@ module Oxidized
|
|
|
202
190
|
# Also, XML Comments must not contain --. So we put a space between
|
|
203
191
|
# any double hyphens, by replacing any - that is followed by another -
|
|
204
192
|
# with '- '
|
|
205
|
-
data = ''
|
|
193
|
+
data = String.new('')
|
|
206
194
|
str.each_line do |_line|
|
|
207
195
|
data << '<!-- ' << str.gsub(/-(?=-)/, '- ').chomp << " -->\n"
|
|
208
196
|
end
|
|
@@ -213,11 +201,18 @@ module Oxidized
|
|
|
213
201
|
@input.class.to_s.match(/Telnet/) || vars(:ssh_no_exec)
|
|
214
202
|
end
|
|
215
203
|
|
|
204
|
+
def significant_changes(config)
|
|
205
|
+
self.class.cmds[:significant_changes].each do |block|
|
|
206
|
+
config = instance_exec config, &block
|
|
207
|
+
end
|
|
208
|
+
config
|
|
209
|
+
end
|
|
210
|
+
|
|
216
211
|
private
|
|
217
212
|
|
|
218
213
|
def process_cmd_output(output, name)
|
|
219
214
|
output = String.new('') unless output.instance_of?(String)
|
|
220
|
-
output.
|
|
215
|
+
output.process_cmd(name)
|
|
221
216
|
output
|
|
222
217
|
end
|
|
223
218
|
end
|
data/lib/oxidized/model/ndms.rb
CHANGED
|
@@ -2,7 +2,14 @@ class Netgear < Oxidized::Model
|
|
|
2
2
|
using Refinements
|
|
3
3
|
|
|
4
4
|
comment '!'
|
|
5
|
-
prompt
|
|
5
|
+
prompt /^\(?[\w \-+.]+\)? ?[#>] ?$/
|
|
6
|
+
clean :escape_codes
|
|
7
|
+
|
|
8
|
+
# Handle pager for "show version" on old Netgear models: #2394
|
|
9
|
+
expect /^--More--(?: or \(q\)uit)?$/ do |data, re|
|
|
10
|
+
send ' '
|
|
11
|
+
data.sub re, ''
|
|
12
|
+
end
|
|
6
13
|
|
|
7
14
|
cmd :secret do |cfg|
|
|
8
15
|
cfg.gsub!(/password (\S+)/, 'password <hidden>')
|
|
@@ -13,7 +20,7 @@ class Netgear < Oxidized::Model
|
|
|
13
20
|
end
|
|
14
21
|
|
|
15
22
|
cfg :telnet do
|
|
16
|
-
username /^(User:|Applying Interface configuration, please wait ...)/
|
|
23
|
+
username /^(Username:|User:|Applying Interface configuration, please wait ...)/
|
|
17
24
|
password /^Password:/i
|
|
18
25
|
end
|
|
19
26
|
|
|
@@ -51,7 +58,11 @@ class Netgear < Oxidized::Model
|
|
|
51
58
|
comment cfg
|
|
52
59
|
end
|
|
53
60
|
cmd 'show running-config' do |cfg|
|
|
54
|
-
cfg.gsub! /(System Up Time
|
|
61
|
+
cfg.gsub! /(System Up Time:?\s+).*/, '\\1 <removed>'
|
|
55
62
|
cfg.gsub! /(Current SNTP Synchronized Time:).*/, '\\1 <removed>'
|
|
63
|
+
cfg.gsub! /(Current System Time:).*/, '\\1 <removed>'
|
|
64
|
+
# Remove standalone backspace lines
|
|
65
|
+
cfg.gsub!(/(?:\r?\n)?\x08(?:\r?\n)?/, "\n")
|
|
66
|
+
cfg
|
|
56
67
|
end
|
|
57
68
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
class NSXDfw < Oxidized::Model
|
|
3
|
+
using Refinements
|
|
4
|
+
|
|
5
|
+
cmd "/policy/api/v1/infra/domains/" do |cfg|
|
|
6
|
+
domains = JSON.parse(cfg.encode('UTF-8', { invalid: :replace, undef: :replace, replace: '?' }))["results"]
|
|
7
|
+
domain_config = {}
|
|
8
|
+
domains.each do |domain|
|
|
9
|
+
domain_config[domain['id']] = {}
|
|
10
|
+
policies_data = cmd "/policy/api/v1/infra/domains/#{domain['id']}/security-policies/"
|
|
11
|
+
policies = JSON.parse(policies_data.encode('UTF-8',
|
|
12
|
+
{ invalid: :replace, undef: :replace, replace: '?' }))["results"]
|
|
13
|
+
policies_config = {}
|
|
14
|
+
policies.each do |policy|
|
|
15
|
+
rules_data = cmd "/policy/api/v1/infra/domains/#{domain['id']}/security-policies/#{policy['id']}/rules"
|
|
16
|
+
rules = JSON.parse(rules_data.encode('UTF-8', { invalid: :replace, undef: :replace, replace: '?' }))["results"]
|
|
17
|
+
policies_config[policy['id']] = rules
|
|
18
|
+
end
|
|
19
|
+
domain_config[domain['id']] = policies_config
|
|
20
|
+
end
|
|
21
|
+
JSON.pretty_generate(domain_config)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
cfg :http do
|
|
25
|
+
@username = @node.auth[:username]
|
|
26
|
+
@password = @node.auth[:password]
|
|
27
|
+
@headers['Content-Type'] = 'application/json'
|
|
28
|
+
@headers['Accept'] = 'application/json'
|
|
29
|
+
@secure = true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -8,7 +8,8 @@ class NSXFirewall < Oxidized::Model
|
|
|
8
8
|
edges.each do |edge|
|
|
9
9
|
firewall_config = cmd "/api/4.0/edges/#{edge['id']}/firewall/config"
|
|
10
10
|
json_config = {}
|
|
11
|
-
json_config["#{edge['id']} #{edge['name']}"] =
|
|
11
|
+
json_config["#{edge['id']} #{edge['name']}"] =
|
|
12
|
+
JSON.parse(firewall_config.encode('UTF-8', { invalid: :replace, undef: :replace, replace: '?' }))
|
|
12
13
|
data.push(json_config)
|
|
13
14
|
end
|
|
14
15
|
JSON.pretty_generate(data)
|
data/lib/oxidized/model/nxos.rb
CHANGED
|
@@ -1,39 +1,44 @@
|
|
|
1
1
|
class NXOS < Oxidized::Model
|
|
2
2
|
using Refinements
|
|
3
3
|
|
|
4
|
-
prompt /^(\r?[\w.@_()-]
|
|
4
|
+
prompt /^(\r?[\w.@_()-]+\#\s?)$/
|
|
5
5
|
comment '! '
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
cfg.
|
|
9
|
-
cfg.gsub! prompt, ''
|
|
7
|
+
cmd :all do |cfg|
|
|
8
|
+
cfg.cut_both
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
cmd :secret do |cfg|
|
|
13
|
-
cfg.gsub! /^(snmp-server community).*/, '\\1 <
|
|
14
|
-
cfg.gsub!
|
|
12
|
+
cfg.gsub! /^(snmp-server community).*/, '\\1 <secret hidden>'
|
|
13
|
+
cfg.gsub!(
|
|
14
|
+
/^(snmp-server user \S+ \S+ auth \S+) \S+ (priv \S+) \S+ /,
|
|
15
|
+
'\\1 <secret hidden> \\2 <secret hidden> '
|
|
16
|
+
)
|
|
17
|
+
cfg.gsub! /^(snmp-server host.*? )\S+( udp-port \d+)?$/, '\\1<secret hidden>\\2'
|
|
18
|
+
cfg.gsub! /^(snmp-server mib community-map) \S+ ?(.*)/, '\\1 <secret hidden> \\2'
|
|
15
19
|
cfg.gsub! /(password \d+) (\S+)/, '\\1 <secret hidden>'
|
|
16
|
-
cfg.gsub! /^(radius-server key)
|
|
17
|
-
cfg.gsub! /^(tacacs-server
|
|
20
|
+
cfg.gsub! /^(radius-server .*key(?: \d+)?) \S+/, '\\1 <secret hidden>'
|
|
21
|
+
cfg.gsub! /^(tacacs-server .*key(?: \d+)?) \S+/, '\\1 <secret hidden>'
|
|
18
22
|
cfg
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
cmd 'show version' do |cfg|
|
|
22
|
-
cfg =
|
|
23
|
-
|
|
24
|
-
comment cfg.join
|
|
26
|
+
cfg = cfg.each_line.take_while { |line| not line.match(/uptime|bootflash:\s+\d+\skB|sysmgrcli_show_flash_size/i) }
|
|
27
|
+
comment cfg.join + "\n"
|
|
25
28
|
end
|
|
26
29
|
|
|
27
|
-
cmd 'show inventory' do |cfg|
|
|
28
|
-
cfg
|
|
30
|
+
cmd 'show inventory all' do |cfg|
|
|
31
|
+
if cfg.match? /^% Invalid .* at '\^' marker\./
|
|
32
|
+
# 'show inventory all' isn't supported on older versions (See Issues #3657, #3779)
|
|
33
|
+
cfg = cmd 'show inventory'
|
|
34
|
+
end
|
|
29
35
|
comment cfg
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
cmd 'show running-config' do |cfg|
|
|
33
|
-
cfg = filter cfg
|
|
34
39
|
cfg.gsub! /^(show run.*)$/, '! \1'
|
|
35
40
|
cfg.gsub! /^!Time:[^\n]*\n/, ''
|
|
36
|
-
cfg.gsub! /^[\w.@_()-]
|
|
41
|
+
cfg.gsub! /^[\w.@_()-]+\#.*$/, ''
|
|
37
42
|
cfg
|
|
38
43
|
end
|
|
39
44
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class OcNOS < Oxidized::Model
|
|
2
|
+
using Refinements
|
|
3
|
+
|
|
4
|
+
prompt /([\w.@-]+[#>]\s?)$/
|
|
5
|
+
comment '# '
|
|
6
|
+
|
|
7
|
+
cfg :ssh do
|
|
8
|
+
post_login 'terminal length 0'
|
|
9
|
+
pre_logout do
|
|
10
|
+
send "disable\r"
|
|
11
|
+
send "logout\r"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
cmd :all do |cfg|
|
|
16
|
+
cfg.lines.to_a[1..-2].join
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
cmd 'show version' do |cfg|
|
|
20
|
+
comment cfg
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
cmd 'show system fru' do |cfg|
|
|
24
|
+
comment cfg
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
cmd 'show system-information board-info' do |cfg|
|
|
28
|
+
comment cfg
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
cmd 'show forwarding profile limit' do |cfg|
|
|
32
|
+
comment cfg
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
cmd 'show license' do |cfg|
|
|
36
|
+
comment cfg
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
cmd 'show running-config' do |cfg|
|
|
40
|
+
cfg
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class OneFinity < Oxidized::Model
|
|
2
|
+
using Refinements
|
|
3
|
+
|
|
4
|
+
# Fujitsu 1finity
|
|
5
|
+
|
|
6
|
+
prompt /(\r?[\w.@_()-]+>\s?)$/
|
|
7
|
+
|
|
8
|
+
cmd :all do |cfg|
|
|
9
|
+
cfg.each_line.to_a[1..-3].join
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
cmd 'show configuration | display set | nomore'
|
|
13
|
+
|
|
14
|
+
cfg :ssh do
|
|
15
|
+
pre_logout 'exit'
|
|
16
|
+
exec true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -5,7 +5,7 @@ class Openbsd < Oxidized::Model
|
|
|
5
5
|
# you can edit the one that your user uses, with root would be /root/.profile using the next PS1 def
|
|
6
6
|
# export PS1="\033[32m\u@\h\033[00m:\033[36m\w\033[00m$ "
|
|
7
7
|
|
|
8
|
-
prompt
|
|
8
|
+
prompt /^.+@.+:.+\$/
|
|
9
9
|
comment '# '
|
|
10
10
|
|
|
11
11
|
# Add a comment between files/configs
|
|
@@ -8,12 +8,47 @@ class OpenGear < Oxidized::Model
|
|
|
8
8
|
cmd :secret do |cfg|
|
|
9
9
|
cfg.gsub!(/password (\S+)/, 'password <secret removed>')
|
|
10
10
|
cfg.gsub!(/community (\S+)/, 'community <secret removed>')
|
|
11
|
+
cfg.gsub!(/community=(\S+)/, 'community=<secret removed>')
|
|
12
|
+
cfg.gsub!(/private_key=(\S+)/, 'private_key=<secret removed>')
|
|
13
|
+
cfg.gsub!(/ key=(\S+)/, ' key=<secret removed>')
|
|
14
|
+
cfg.gsub!(/hashed_password=(\S+)/, 'hashed_password=<secret removed>')
|
|
11
15
|
cfg
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
cmd('cat /etc/version') { |cfg| comment cfg }
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
# newer opengear firmware versions
|
|
21
|
+
cmd 'ogdeviceinfo -r' do |cfg|
|
|
22
|
+
comment cfg unless cfg.include? "ogdeviceinfo: command not found"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
cmd 'config export' do |cfg|
|
|
26
|
+
unless cfg.include? "usage: config"
|
|
27
|
+
out = ''
|
|
28
|
+
cfg.each_line do |line|
|
|
29
|
+
out << line
|
|
30
|
+
end
|
|
31
|
+
out
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# older opengear firmware versions
|
|
36
|
+
cmd 'showserial' do |cfg|
|
|
37
|
+
unless cfg.include? "showserial: command not found"
|
|
38
|
+
cfg.gsub! /^/, 'Serial Number: '
|
|
39
|
+
comment cfg
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
cmd 'config -g config' do |cfg|
|
|
44
|
+
unless cfg.include? "config: error: argument"
|
|
45
|
+
out = ''
|
|
46
|
+
cfg.each_line do |line|
|
|
47
|
+
out << line
|
|
48
|
+
end
|
|
49
|
+
out
|
|
50
|
+
end
|
|
51
|
+
end
|
|
17
52
|
|
|
18
53
|
cfg :ssh do
|
|
19
54
|
exec true # don't run shell, run each command in exec channel
|
|
@@ -38,26 +38,26 @@ class OpenWrt < Oxidized::Model
|
|
|
38
38
|
filename = sysupgradefile.split('/')[-1]
|
|
39
39
|
cfg << comment("#### File: #{sysupgradefile} #####")
|
|
40
40
|
uciexport = cmd("uci export #{filename}")
|
|
41
|
-
|
|
41
|
+
logger.debug "Exporting uci config - #{filename}"
|
|
42
42
|
if vars(:remove_secret) && !(non_sensitive_files.include? filename)
|
|
43
|
-
|
|
43
|
+
logger.debug "Scrubbing uci config - #{filename}"
|
|
44
44
|
uciexport.gsub!(/^(\s+option\s+(password|key)\s+')[^']+'/, '\\1<secret hidden>\'')
|
|
45
45
|
end
|
|
46
46
|
cfg << uciexport
|
|
47
47
|
end
|
|
48
48
|
elsif binary_files.include? sysupgradefile
|
|
49
|
-
|
|
49
|
+
logger.debug "Exporting binary file - #{sysupgradefile}"
|
|
50
50
|
cfg << comment("#### Binary file: #{sysupgradefile} #####")
|
|
51
51
|
cfg << comment("Decode using 'echo -en <data> | gzip -dc > #{sysupgradefile}'")
|
|
52
52
|
cfg << cmd("gzip -c #{sysupgradefile} | hexdump -ve '1/1 \"_x%.2x\"' | tr _ \\")
|
|
53
53
|
elsif vars(:remove_secret) && sysupgradefile == '/etc/shadow'
|
|
54
|
-
|
|
54
|
+
logger.debug 'Exporting and scrubbing /etc/shadow'
|
|
55
55
|
cfg << comment("#### File: #{sysupgradefile} #####")
|
|
56
56
|
shadow = cmd("cat #{sysupgradefile}")
|
|
57
57
|
shadow.gsub!(/^([^:]+:)[^:]*(:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:)/, '\\1\\2')
|
|
58
58
|
cfg << shadow
|
|
59
59
|
else
|
|
60
|
-
|
|
60
|
+
logger.debug "Exporting file - #{sysupgradefile}"
|
|
61
61
|
cfg << comment("#### File: #{sysupgradefile} #####")
|
|
62
62
|
cfg << cmd("cat #{sysupgradefile}")
|
|
63
63
|
end
|
|
@@ -65,7 +65,7 @@ class OpenWrt < Oxidized::Model
|
|
|
65
65
|
@mtdpartitions.scan(/(\w+):\s+\w+\s+\w+\s+"(.*)"/).each do |partition, name|
|
|
66
66
|
next unless vars(:openwrt_backup_partitions) && partitions_to_backup.include?(name)
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
logger.debug "Exporting partition - #{name}(#{partition})"
|
|
69
69
|
cfg << comment("#### Partition: #{name} /dev/#{partition} #####")
|
|
70
70
|
cfg << comment("Decode using 'echo -en <data> | gzip -dc > #{name}'")
|
|
71
71
|
cfg << cmd("dd if=/dev/#{partition} 2>/dev/null | gzip -c | hexdump -ve '1/1 \"%.2x\"'")
|
|
@@ -18,10 +18,18 @@ class OpnSense < Oxidized::Model
|
|
|
18
18
|
# that lack the opnsense-version command. Newer versions of OPNsense no longer
|
|
19
19
|
# store the version information in this file, so both versions have to be
|
|
20
20
|
# supported here for now.
|
|
21
|
-
cmd 'opnsense-version
|
|
21
|
+
cmd 'opnsense-version || echo "OPNsense "`cat /usr/local/opnsense/version/opnsense`' do |version|
|
|
22
22
|
xmlcomment version
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
metadata :bottom do
|
|
26
|
+
xmlcomment interpolate_string(
|
|
27
|
+
vars("metadata_bottom") ||
|
|
28
|
+
vars("metadata_top") ||
|
|
29
|
+
Oxidized::Model::METADATA_DEFAULT
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
25
33
|
cfg :ssh do
|
|
26
34
|
exec true
|
|
27
35
|
pre_logout 'exit'
|