oxidized 0.20.0 → 0.28.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +4 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- data/.github/no-response.yml +13 -0
- data/.github/workflows/publishdocker.yml +13 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +73 -0
- data/.rubocop_todo.yml +120 -0
- data/.travis.yml +6 -1
- data/CHANGELOG.md +693 -243
- data/Dockerfile +27 -19
- data/LICENSE +201 -0
- data/README.md +234 -913
- data/Rakefile +48 -7
- data/TODO.md +29 -23
- data/bin/console +1 -1
- data/bin/oxidized +6 -5
- data/docs/Configuration.md +313 -0
- data/docs/Creating-Models.md +140 -0
- data/docs/Hooks.md +274 -0
- data/docs/Model-Notes/AireOS.md +11 -0
- data/docs/Model-Notes/ArbOS.md +11 -0
- data/docs/Model-Notes/Comware.md +13 -0
- data/docs/Model-Notes/Cumulus.md +40 -0
- data/docs/Model-Notes/EOS.md +12 -0
- data/docs/Model-Notes/IOS.md +29 -0
- data/docs/Model-Notes/JunOS.md +33 -0
- data/docs/Model-Notes/LinuxGeneric.md +24 -0
- data/docs/Model-Notes/Netgear.md +87 -0
- data/docs/Model-Notes/Nokia.md +9 -0
- data/docs/Model-Notes/README.md +24 -0
- data/docs/Model-Notes/SmartAX-Huawei.md +35 -0
- data/docs/Model-Notes/VRP-Huawei.md +34 -0
- data/docs/Model-Notes/Viptela.md +12 -0
- data/docs/Model-Notes/XGS4600-Zyxel.md +36 -0
- data/docs/Outputs.md +190 -0
- data/docs/Ruby-API.md +199 -0
- data/docs/Sources.md +171 -0
- data/docs/Supported-OS-Types.md +227 -0
- data/docs/Troubleshooting.md +66 -0
- data/extra/nagios_check_failing_nodes.rb +9 -2
- data/extra/oxidized-report-git-commits +21 -40
- data/extra/oxidized-ubuntu.haproxy +45 -0
- data/extra/oxidized.logrotate +7 -0
- data/extra/oxidized.service +13 -0
- data/extra/rest_client.rb +7 -10
- data/extra/syslog.rb +47 -42
- data/lib/oxidized/cli.rb +41 -31
- data/lib/oxidized/config/vars.rb +9 -14
- data/lib/oxidized/config.rb +20 -13
- data/lib/oxidized/core.rb +8 -10
- data/lib/oxidized/hook/awssns.rb +6 -7
- data/lib/oxidized/hook/ciscosparkdiff.rb +43 -0
- data/lib/oxidized/hook/exec.rb +19 -24
- data/lib/oxidized/hook/githubrepo.rb +17 -17
- data/lib/oxidized/hook/noophook.rb +1 -1
- data/lib/oxidized/hook/slackdiff.rb +32 -19
- data/lib/oxidized/hook/xmppdiff.rb +59 -0
- data/lib/oxidized/hook.rb +63 -64
- data/lib/oxidized/input/cli.rb +22 -12
- data/lib/oxidized/input/exec.rb +28 -0
- data/lib/oxidized/input/ftp.rb +16 -15
- data/lib/oxidized/input/http.rb +72 -0
- data/lib/oxidized/input/input.rb +6 -6
- data/lib/oxidized/input/ssh.rb +64 -56
- data/lib/oxidized/input/telnet.rb +59 -102
- data/lib/oxidized/input/tftp.rb +9 -10
- data/lib/oxidized/jobs.rb +9 -10
- data/lib/oxidized/manager.rb +42 -44
- data/lib/oxidized/model/acos.rb +19 -20
- data/lib/oxidized/model/acsw.rb +62 -0
- data/lib/oxidized/model/adtran.rb +26 -0
- data/lib/oxidized/model/aen.rb +19 -0
- data/lib/oxidized/model/aireos.rb +9 -10
- data/lib/oxidized/model/airfiber.rb +22 -0
- data/lib/oxidized/model/alteonos.rb +58 -0
- data/lib/oxidized/model/alvarion.rb +0 -4
- data/lib/oxidized/model/aos.rb +11 -5
- data/lib/oxidized/model/aos7.rb +6 -7
- data/lib/oxidized/model/aosw.rb +30 -27
- data/lib/oxidized/model/apc_aos.rb +2 -5
- data/lib/oxidized/model/arbos.rb +26 -0
- data/lib/oxidized/model/aricentiss.rb +49 -0
- data/lib/oxidized/model/asa.rb +61 -22
- data/lib/oxidized/model/asyncos.rb +46 -0
- data/lib/oxidized/model/audiocodes.rb +28 -0
- data/lib/oxidized/model/audiocodesmp.rb +28 -0
- data/lib/oxidized/model/awplus.rb +84 -0
- data/lib/oxidized/model/axos.rb +16 -0
- data/lib/oxidized/model/boss.rb +77 -0
- data/lib/oxidized/model/br6910.rb +42 -45
- data/lib/oxidized/model/c4cmts.rb +6 -10
- data/lib/oxidized/model/cambium.rb +23 -0
- data/lib/oxidized/model/casa.rb +1 -1
- data/lib/oxidized/model/catos.rb +1 -3
- data/lib/oxidized/model/cisconga.rb +1 -3
- data/lib/oxidized/model/ciscosma.rb +42 -0
- data/lib/oxidized/model/ciscosmb.rb +30 -10
- data/lib/oxidized/model/ciscovpn3k.rb +11 -0
- data/lib/oxidized/model/cnos.rb +33 -0
- data/lib/oxidized/model/comnetms.rb +43 -0
- data/lib/oxidized/model/comtrol.rb +41 -0
- data/lib/oxidized/model/comware.rb +28 -16
- data/lib/oxidized/model/coriant8600.rb +3 -5
- data/lib/oxidized/model/coriantgroove.rb +26 -0
- data/lib/oxidized/model/corianttmos.rb +1 -3
- data/lib/oxidized/model/cumulus.rb +60 -49
- data/lib/oxidized/model/datacom.rb +1 -4
- data/lib/oxidized/model/dcnos.rb +46 -0
- data/lib/oxidized/model/dellx.rb +76 -0
- data/lib/oxidized/model/dlink.rb +5 -4
- data/lib/oxidized/model/dnos.rb +11 -5
- data/lib/oxidized/model/eciapollo.rb +34 -0
- data/lib/oxidized/model/edgecos.rb +49 -0
- data/lib/oxidized/model/edgeos.rb +12 -5
- data/lib/oxidized/model/edgeswitch.rb +2 -4
- data/lib/oxidized/model/enterasys.rb +28 -0
- data/lib/oxidized/model/eos.rb +8 -8
- data/lib/oxidized/model/fabricos.rb +4 -6
- data/lib/oxidized/model/fastiron.rb +66 -0
- data/lib/oxidized/model/fiberdriver.rb +2 -2
- data/lib/oxidized/model/firebrick.rb +31 -0
- data/lib/oxidized/model/firelinuxos.rb +41 -0
- data/lib/oxidized/model/firewareos.rb +3 -6
- data/lib/oxidized/model/fortios.rb +31 -19
- data/lib/oxidized/model/ftos.rb +8 -5
- data/lib/oxidized/model/fujitsupy.rb +5 -7
- data/lib/oxidized/model/gaiaos.rb +7 -11
- data/lib/oxidized/model/gcombnps.rb +84 -0
- data/lib/oxidized/model/grandstream.rb +9 -0
- data/lib/oxidized/model/hatteras.rb +9 -6
- data/lib/oxidized/model/hirschmann.rb +39 -0
- data/lib/oxidized/model/hpebladesystem.rb +20 -18
- data/lib/oxidized/model/hpemsa.rb +10 -0
- data/lib/oxidized/model/hpmsm.rb +84 -0
- data/lib/oxidized/model/ibos.rb +55 -0
- data/lib/oxidized/model/icotera.rb +27 -0
- data/lib/oxidized/model/ios.rb +63 -70
- data/lib/oxidized/model/iosxe.rb +5 -0
- data/lib/oxidized/model/iosxr.rb +2 -3
- data/lib/oxidized/model/ipos.rb +10 -6
- data/lib/oxidized/model/ironware.rb +20 -19
- data/lib/oxidized/model/isam.rb +5 -6
- data/lib/oxidized/model/junos.rb +9 -11
- data/lib/oxidized/model/linuxgeneric.rb +74 -0
- data/lib/oxidized/model/masteros.rb +3 -6
- data/lib/oxidized/model/mlnxos.rb +9 -10
- data/lib/oxidized/model/model.rb +72 -46
- data/lib/oxidized/model/mtrlrfs.rb +1 -4
- data/lib/oxidized/model/ndms.rb +23 -0
- data/lib/oxidized/model/netgear.rb +35 -15
- data/lib/oxidized/model/netonix.rb +2 -2
- data/lib/oxidized/model/netscaler.rb +6 -3
- data/lib/oxidized/model/nos.rb +5 -7
- data/lib/oxidized/model/nsxconfig.rb +22 -0
- data/lib/oxidized/model/nsxfirewall.rb +22 -0
- data/lib/oxidized/model/nxos.rb +13 -3
- data/lib/oxidized/model/oneos.rb +15 -9
- data/lib/oxidized/model/openbsd.rb +63 -0
- data/lib/oxidized/model/opengear.rb +3 -5
- data/lib/oxidized/model/openwrt.rb +78 -0
- data/lib/oxidized/model/opnsense.rb +19 -0
- data/lib/oxidized/model/os10.rb +46 -0
- data/lib/oxidized/model/outputs.rb +5 -7
- data/lib/oxidized/model/panos.rb +11 -12
- data/lib/oxidized/model/pfsense.rb +11 -6
- data/lib/oxidized/model/planet.rb +14 -17
- data/lib/oxidized/model/powerconnect.rb +24 -19
- data/lib/oxidized/model/procurve.rb +43 -11
- data/lib/oxidized/model/purityos.rb +12 -0
- data/lib/oxidized/model/qtech.rb +41 -0
- data/lib/oxidized/model/quantaos.rb +4 -6
- data/lib/oxidized/model/raisecom.rb +19 -0
- data/lib/oxidized/model/routeros.rb +26 -8
- data/lib/oxidized/model/saos.rb +1 -2
- data/lib/oxidized/model/screenos.rb +8 -11
- data/lib/oxidized/model/sgos.rb +45 -0
- data/lib/oxidized/model/siklu.rb +1 -3
- data/lib/oxidized/model/slxos.rb +59 -0
- data/lib/oxidized/model/smartax.rb +25 -0
- data/lib/oxidized/model/sonicos.rb +51 -0
- data/lib/oxidized/model/speedtouch.rb +34 -0
- data/lib/oxidized/model/sros.rb +96 -0
- data/lib/oxidized/model/stoneos.rb +32 -0
- data/lib/oxidized/model/supermicro.rb +6 -41
- data/lib/oxidized/model/tdre.rb +30 -0
- data/lib/oxidized/model/telco.rb +24 -0
- data/lib/oxidized/model/timos.rb +6 -114
- data/lib/oxidized/model/tmos.rb +6 -3
- data/lib/oxidized/model/tplink.rb +11 -11
- data/lib/oxidized/model/trango.rb +21 -42
- data/lib/oxidized/model/ucs.rb +30 -0
- data/lib/oxidized/model/viptela.rb +29 -0
- data/lib/oxidized/model/voltaire.rb +9 -12
- data/lib/oxidized/model/voss.rb +17 -6
- data/lib/oxidized/model/vrp.rb +11 -6
- data/lib/oxidized/model/vyatta.rb +8 -6
- data/lib/oxidized/model/weos.rb +20 -0
- data/lib/oxidized/model/xos.rb +20 -8
- data/lib/oxidized/model/zhoneolt.rb +2 -2
- data/lib/oxidized/model/zynos.rb +1 -3
- data/lib/oxidized/model/zynoscli.rb +36 -0
- data/lib/oxidized/model/zynosgs.rb +38 -0
- data/lib/oxidized/node/stats.rb +33 -8
- data/lib/oxidized/node.rb +86 -95
- data/lib/oxidized/nodes.rb +48 -44
- data/lib/oxidized/output/file.rb +32 -37
- data/lib/oxidized/output/git.rb +138 -153
- data/lib/oxidized/output/gitcrypt.rb +228 -242
- data/lib/oxidized/output/http.rb +35 -34
- data/lib/oxidized/output/output.rb +2 -3
- data/lib/oxidized/source/csv.rb +50 -44
- data/lib/oxidized/source/http.rb +58 -58
- data/lib/oxidized/source/source.rb +9 -10
- data/lib/oxidized/source/sql.rb +47 -45
- data/lib/oxidized/string.rb +18 -14
- data/lib/oxidized/version.rb +17 -1
- data/lib/oxidized/worker.rb +72 -33
- data/oxidized.gemspec +20 -19
- metadata +180 -36
- data/.ruby-version +0 -1
- data/Gemfile.lock +0 -44
data/Rakefile
CHANGED
@@ -1,8 +1,21 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rake/testtask'
|
3
|
+
require_relative 'lib/oxidized/version'
|
3
4
|
|
4
5
|
gemspec = eval(File.read(Dir['*.gemspec'].first))
|
5
|
-
|
6
|
+
gemfile = [gemspec.name, gemspec.version].join('-') + '.gem'
|
7
|
+
|
8
|
+
# Integrate Rubocop if available
|
9
|
+
begin
|
10
|
+
require 'rubocop/rake_task'
|
11
|
+
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
task(:default).prerequisites << task(:rubocop)
|
14
|
+
rescue LoadError
|
15
|
+
task :rubocop do
|
16
|
+
puts 'Install rubocop to run its rake tasks'
|
17
|
+
end
|
18
|
+
end
|
6
19
|
|
7
20
|
desc 'Validate gemspec'
|
8
21
|
task :gemspec do
|
@@ -19,10 +32,16 @@ task :test do
|
|
19
32
|
end
|
20
33
|
end
|
21
34
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
35
|
+
task build: %i[chmod version_set]
|
36
|
+
task :version_set do
|
37
|
+
Oxidized.version_set
|
38
|
+
Bundler::GemHelper.instance.gemspec.version = Oxidized::VERSION
|
39
|
+
end
|
40
|
+
|
41
|
+
# desc 'Install gem'
|
42
|
+
# task install: :build do
|
43
|
+
# system "sudo -Es sh -c \'umask 022; gem install gems/#{gemfile}\'"
|
44
|
+
# end
|
26
45
|
|
27
46
|
desc 'Remove gems'
|
28
47
|
task :clean do
|
@@ -35,8 +54,30 @@ task :tag do
|
|
35
54
|
end
|
36
55
|
|
37
56
|
desc 'Push to rubygems'
|
38
|
-
task :
|
39
|
-
system "gem push pkg/#{
|
57
|
+
task push: :tag do
|
58
|
+
system "gem push pkg/#{gemfile}"
|
59
|
+
end
|
60
|
+
|
61
|
+
desc 'Normalise file permissions'
|
62
|
+
task :chmod do
|
63
|
+
xbit = %w[
|
64
|
+
bin/oxidized
|
65
|
+
bin/console
|
66
|
+
extra/auto-reload-config.runit
|
67
|
+
extra/nagios_check_failing_nodes.rb
|
68
|
+
extra/oxidized-report-git-commits
|
69
|
+
extra/oxidized.init
|
70
|
+
extra/oxidized.init.d
|
71
|
+
extra/oxidized.runit
|
72
|
+
extra/syslog.rb
|
73
|
+
extra/update-ca-certificates.runit
|
74
|
+
]
|
75
|
+
dirs = []
|
76
|
+
%x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }.each do |file|
|
77
|
+
dirs.push(File.dirname(file))
|
78
|
+
xbit.include?(file) ? File.chmod(0o0755, file) : File.chmod(0o0644, file)
|
79
|
+
end
|
80
|
+
dirs.sort.uniq.each { |dir| File.chmod(0o0755, dir) }
|
40
81
|
end
|
41
82
|
|
42
83
|
task default: :test
|
data/TODO.md
CHANGED
@@ -1,23 +1,29 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
# To Do
|
2
|
+
|
3
|
+
## refactor core
|
4
|
+
|
5
|
+
* move state from memory to disk, sqlite probably
|
6
|
+
* allows us to retain stats etc over restart
|
7
|
+
* simplifies code
|
8
|
+
* keep only running nodes in memory
|
9
|
+
* negligible I/O cost, as majority is I/O wait getting config
|
10
|
+
|
11
|
+
## separate login to own package
|
12
|
+
|
13
|
+
* oxidized-script is not only use-case
|
14
|
+
* it would be good to have minimal package used to login to routers
|
15
|
+
* oxidized just one consumer of that functionality
|
16
|
+
* what to do with models, we need model to know how to login. Should models be separated to another package? oxidized-core, oxidized-models and oxidized-login?
|
17
|
+
* how can we allow interactive login in oxidized-login? With functional VTY etc? REPL loop in input/ssh and input/telnet?
|
18
|
+
|
19
|
+
## thread number
|
20
|
+
|
21
|
+
* think about algo
|
22
|
+
* if job ended later than now-iteration have rand(node.size) == 0 to add thread
|
23
|
+
* if now is less than job_ended+iteration same chance to remove thread?
|
24
|
+
* should we try to avoid max threads from being hit? (like maybe non-success thread is pulling average?)
|
25
|
+
|
26
|
+
## docs, testing
|
27
|
+
|
28
|
+
* yard docs
|
29
|
+
* minitest tests
|
data/bin/console
CHANGED
data/bin/oxidized
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
3
|
# FIX ME, killing oxidized needs -9
|
5
4
|
trap("INT") { exit } # sinatra will otherwise steal this from us
|
6
5
|
|
7
6
|
begin
|
8
|
-
|
7
|
+
require_relative '../lib/oxidized/cli'
|
9
8
|
Oxidized::CLI.new.run
|
10
|
-
rescue => error
|
11
|
-
warn
|
12
|
-
debug =
|
9
|
+
rescue StandardError => error
|
10
|
+
warn error.to_s
|
11
|
+
debug = Oxidized.config.debug rescue true
|
13
12
|
raise if debug
|
13
|
+
|
14
|
+
exit 1
|
14
15
|
end
|
@@ -0,0 +1,313 @@
|
|
1
|
+
# Configuration
|
2
|
+
|
3
|
+
## Debugging
|
4
|
+
|
5
|
+
In case a model plugin doesn't work correctly (ios, procurve, etc.), you can enable live debugging of SSH/Telnet sessions. Just add a `debug` option containing the value true to the `input` section. The log files will be created depending on the parent directory of the logfile option.
|
6
|
+
|
7
|
+
The following example will log an active ssh/telnet session `/home/oxidized/.config/oxidized/log/<IP-Address>-<PROTOCOL>`. The file will be truncated on each consecutive ssh/telnet session, so you need to put a `tailf` or `tail -f` on that file!
|
8
|
+
|
9
|
+
```yaml
|
10
|
+
log: /home/oxidized/.config/oxidized/log
|
11
|
+
|
12
|
+
...
|
13
|
+
|
14
|
+
input:
|
15
|
+
default: ssh, telnet
|
16
|
+
debug: true
|
17
|
+
ssh:
|
18
|
+
secure: false
|
19
|
+
http:
|
20
|
+
ssl_verify: true
|
21
|
+
```
|
22
|
+
|
23
|
+
## Privileged mode
|
24
|
+
|
25
|
+
To start privileged mode before pulling the configuration, Oxidized needs to send the enable command. You can globally enable this, by adding the following snippet to the global section of the configuration file.
|
26
|
+
|
27
|
+
```yaml
|
28
|
+
vars:
|
29
|
+
enable: S3cre7
|
30
|
+
```
|
31
|
+
|
32
|
+
## Removing secrets
|
33
|
+
|
34
|
+
To strip out secrets from configurations before storing them, Oxidized needs the `remove_secret` flag. You can globally enable this by adding the following snippet to the global section of the configuration file.
|
35
|
+
|
36
|
+
```yaml
|
37
|
+
vars:
|
38
|
+
remove_secret: true
|
39
|
+
```
|
40
|
+
|
41
|
+
Device models that contain substitution filters to remove sensitive data will now be run on any fetched configuration.
|
42
|
+
|
43
|
+
As a partial example from ios.rb:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
cmd :secret do |cfg|
|
47
|
+
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
|
48
|
+
(...)
|
49
|
+
cfg
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
The above strips out snmp community strings from your saved configs.
|
54
|
+
|
55
|
+
**NOTE:** Removing secrets reduces the usefulness as a full configuration backup, but it may make sharing configs easier.
|
56
|
+
|
57
|
+
## Disabling SSH exec channels
|
58
|
+
|
59
|
+
Oxidized uses exec channels to make information extraction simpler, but there are some situations where this doesn't work well, e.g. configuring devices. This feature can be turned off by setting the `ssh_no_exec`
|
60
|
+
variable.
|
61
|
+
|
62
|
+
```yaml
|
63
|
+
vars:
|
64
|
+
ssh_no_exec: true
|
65
|
+
```
|
66
|
+
|
67
|
+
## Disabling SSH keepalives
|
68
|
+
|
69
|
+
Oxidized SSH input makes use of SSH keepalives to prevent timeouts from slower devices and to quickly tear down stale sessions in larger deployments. There have been reports of SSH keepalives breaking compatibility with certain OS types. They can be disabled using the `ssh_no_keepalive` variable on a per-node basis (by specifying it in the source) or configured application-wide.
|
70
|
+
|
71
|
+
```yaml
|
72
|
+
vars:
|
73
|
+
ssh_no_keepalive: true
|
74
|
+
```
|
75
|
+
|
76
|
+
## SSH Auth Methods
|
77
|
+
|
78
|
+
By default, Oxidized registers the following auth methods: `none`, `publickey` and `password`. However you can configure this globally, by groups, models or nodes.
|
79
|
+
|
80
|
+
```yaml
|
81
|
+
vars:
|
82
|
+
auth_methods: [ "none", "publickey", "password", "keyboard-interactive" ]
|
83
|
+
```
|
84
|
+
|
85
|
+
## Public Key Authentication with SSH
|
86
|
+
|
87
|
+
Instead of password-based login, Oxidized can make use of key-based SSH authentication.
|
88
|
+
|
89
|
+
You can tell Oxidized to use one or more private keys globally, or specify the key to be used on a per-node basis. The latter can be done by mapping the `ssh_keys` variable through the active source.
|
90
|
+
|
91
|
+
Global:
|
92
|
+
|
93
|
+
```yaml
|
94
|
+
vars:
|
95
|
+
ssh_keys: "~/.ssh/id_rsa"
|
96
|
+
```
|
97
|
+
|
98
|
+
Per-Node:
|
99
|
+
|
100
|
+
```yaml
|
101
|
+
...
|
102
|
+
map:
|
103
|
+
name: 0
|
104
|
+
model: 1
|
105
|
+
vars_map:
|
106
|
+
enable: 2
|
107
|
+
ssh_keys: 3
|
108
|
+
...
|
109
|
+
```
|
110
|
+
|
111
|
+
If you are using a non-standard path, especially when copying the private key via a secured channel, make sure that the permissions are set correctly:
|
112
|
+
|
113
|
+
```bash
|
114
|
+
foo@bar:~$ ls -la ~/.ssh/
|
115
|
+
total 20
|
116
|
+
drwx------ 2 oxidized oxidized 4096 Mar 13 17:03 .
|
117
|
+
drwx------ 5 oxidized oxidized 4096 Mar 13 21:40 ..
|
118
|
+
-r-------- 1 oxidized oxidized 103 Mar 13 17:03 authorized_keys
|
119
|
+
-rw------- 1 oxidized oxidized 399 Mar 13 17:02 id_ed25519
|
120
|
+
-rw-r--r-- 1 oxidized oxidized 94 Mar 13 17:02 id_ed25519.pub
|
121
|
+
```
|
122
|
+
|
123
|
+
Finally, multiple private keys can be specified as an array of file paths, such as `["~/.ssh/id_rsa", "~/.ssh/id_another_rsa"]`.
|
124
|
+
|
125
|
+
## SSH Proxy Command
|
126
|
+
|
127
|
+
Oxidized can `ssh` through a proxy as well. To do so we just need to set `ssh_proxy` variable with the proxy host information and optionally set the `ssh_proxy_port` with the SSH port if it is not listening no port 22.
|
128
|
+
|
129
|
+
This can be provided on a per-node basis by mapping the proper fields from your source.
|
130
|
+
|
131
|
+
An example for a `csv` input source that maps the 4th field as the `ssh_proxy` value and the 5th field as `ssh_proxy_port`.
|
132
|
+
|
133
|
+
```yaml
|
134
|
+
...
|
135
|
+
map:
|
136
|
+
name: 0
|
137
|
+
model: 1
|
138
|
+
vars_map:
|
139
|
+
enable: 2
|
140
|
+
ssh_proxy: 3
|
141
|
+
ssh_proxy_port: 4
|
142
|
+
...
|
143
|
+
```
|
144
|
+
|
145
|
+
## SSH enabling legacy algorithms
|
146
|
+
|
147
|
+
When connecting to older firmware over SSH, it is sometimes necessary to enable legacy/disabled settings like KexAlgorithms, HostKeyAlgorithms, MAC or the Encryption.
|
148
|
+
|
149
|
+
These settings can be provided on a per-node basis by mapping the ssh_kex, ssh_host_key, ssh_hmac and the ssh_encryption fields from you source.
|
150
|
+
|
151
|
+
```yaml
|
152
|
+
...
|
153
|
+
map:
|
154
|
+
name: 0
|
155
|
+
model: 1
|
156
|
+
vars_map:
|
157
|
+
enable: 2
|
158
|
+
ssh_kex: 3
|
159
|
+
ssh_host_key: 4
|
160
|
+
ssh_hmac: 5
|
161
|
+
ssh_encryption: 6
|
162
|
+
...
|
163
|
+
```
|
164
|
+
|
165
|
+
## FTP Passive Mode
|
166
|
+
|
167
|
+
Oxidized uses ftp passive mode by default. Some devices require passive mode to be disabled. To do so, we can set `input.ftp.passive` to false - this will make use of FTP active mode.
|
168
|
+
|
169
|
+
```yaml
|
170
|
+
input:
|
171
|
+
ftp:
|
172
|
+
passive: false
|
173
|
+
```
|
174
|
+
|
175
|
+
## Advanced Configuration
|
176
|
+
|
177
|
+
Below is an advanced example configuration. You will be able to (optionally) override options per device. The router.db format used is `hostname:model:username:password:enable_password`. Hostname and model will be the only required options, all others override the global configuration sections.
|
178
|
+
|
179
|
+
```yaml
|
180
|
+
---
|
181
|
+
username: oxidized
|
182
|
+
password: S3cr3tx
|
183
|
+
model: junos
|
184
|
+
interval: 3600 #interval in seconds
|
185
|
+
log: ~/.config/oxidized/log
|
186
|
+
debug: false
|
187
|
+
threads: 30
|
188
|
+
timeout: 20
|
189
|
+
retries: 3
|
190
|
+
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
|
191
|
+
crash:
|
192
|
+
directory: ~/.config/oxidized/crashes
|
193
|
+
hostnames: false
|
194
|
+
vars:
|
195
|
+
enable: S3cr3tx
|
196
|
+
groups: {}
|
197
|
+
rest: 127.0.0.1:8888
|
198
|
+
pid: ~/.config/oxidized/oxidized.pid
|
199
|
+
input:
|
200
|
+
default: ssh, telnet
|
201
|
+
debug: false
|
202
|
+
ssh:
|
203
|
+
secure: false
|
204
|
+
output:
|
205
|
+
default: git
|
206
|
+
git:
|
207
|
+
user: Oxidized
|
208
|
+
email: oxidized@example.com
|
209
|
+
repo: "~/.config/oxidized/oxidized.git"
|
210
|
+
source:
|
211
|
+
default: csv
|
212
|
+
csv:
|
213
|
+
file: ~/.config/oxidized/router.db
|
214
|
+
delimiter: !ruby/regexp /:/
|
215
|
+
map:
|
216
|
+
name: 0
|
217
|
+
model: 1
|
218
|
+
username: 2
|
219
|
+
password: 3
|
220
|
+
vars_map:
|
221
|
+
enable: 4
|
222
|
+
model_map:
|
223
|
+
cisco: ios
|
224
|
+
juniper: junos
|
225
|
+
```
|
226
|
+
|
227
|
+
## Advanced Group Configuration
|
228
|
+
|
229
|
+
For group specific credentials
|
230
|
+
|
231
|
+
```yaml
|
232
|
+
groups:
|
233
|
+
mikrotik:
|
234
|
+
username: admin
|
235
|
+
password: blank
|
236
|
+
ubiquiti:
|
237
|
+
username: ubnt
|
238
|
+
password: ubnt
|
239
|
+
```
|
240
|
+
|
241
|
+
and add group mapping
|
242
|
+
|
243
|
+
```yaml
|
244
|
+
map:
|
245
|
+
model: 0
|
246
|
+
name: 1
|
247
|
+
group: 2
|
248
|
+
```
|
249
|
+
|
250
|
+
For model specific credentials
|
251
|
+
|
252
|
+
You can add 'username: nil' if the device only expects a Password at prompt.
|
253
|
+
|
254
|
+
```yaml
|
255
|
+
models:
|
256
|
+
junos:
|
257
|
+
username: admin
|
258
|
+
password: password
|
259
|
+
ironware:
|
260
|
+
username: admin
|
261
|
+
password: password
|
262
|
+
vars:
|
263
|
+
enable: enablepassword
|
264
|
+
apc_aos:
|
265
|
+
username: apc
|
266
|
+
password: password
|
267
|
+
cisco:
|
268
|
+
username: nil
|
269
|
+
password: pass
|
270
|
+
```
|
271
|
+
|
272
|
+
## RESTful API and Web Interface
|
273
|
+
|
274
|
+
The RESTful API and Web Interface is enabled by configuring the `rest:` parameter in the config file. This parameter can optionally contain a relative URI.
|
275
|
+
|
276
|
+
```yaml
|
277
|
+
# Listen on http://127.0.0.1:8888/
|
278
|
+
rest: 127.0.0.1:8888
|
279
|
+
```
|
280
|
+
|
281
|
+
```yaml
|
282
|
+
# Listen on http://10.0.0.1:8000/oxidized/
|
283
|
+
rest: 10.0.0.1:8000/oxidized
|
284
|
+
```
|
285
|
+
|
286
|
+
## Triggered backups
|
287
|
+
|
288
|
+
A node can be moved to head-of-queue via the REST API `GET/POST /node/next/[NODE]`. This can be useful to immediately schedule a fetch of the configuration after some other event such as a syslog message indicating a configuration update on the device.
|
289
|
+
|
290
|
+
In the default configuration this node will be processed when the next job worker becomes available, it could take some time if existing backups are in progress. To execute moved jobs immediately a new job can be added automatically:
|
291
|
+
|
292
|
+
```yaml
|
293
|
+
next_adds_job: true
|
294
|
+
```
|
295
|
+
|
296
|
+
This will allow for a more timely fetch of the device configuration.
|
297
|
+
|
298
|
+
## Disabling DNS resolution
|
299
|
+
|
300
|
+
In some instances it might not be desirable to attempt to resolve names of nodes. One such use case is when nodes are accessed through an SSH proxy, where the remote end resolves the names differently than the host on which Oxidized runs would.
|
301
|
+
|
302
|
+
Names can instead be passed verbatim to the input:
|
303
|
+
|
304
|
+
```yaml
|
305
|
+
resolve_dns: false
|
306
|
+
```
|
307
|
+
|
308
|
+
## Environment variables
|
309
|
+
|
310
|
+
You can use some environment variables to change default root directories values.
|
311
|
+
|
312
|
+
* `OXIDIZED_HOME` may be used to set oxidized configuration directory, which defaults to `~/.config/oxidized`
|
313
|
+
* `OXIDIZED_LOGS` may be used to set oxidzied logs and crash directories root, which default to `~/.config/oxidized`
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# Creating and Extending Models
|
2
|
+
|
3
|
+
Oxidized supports a growing list of [operating system types](Supported-OS-Types.md). Out of the box, most model implementations collect configuration data. Some implementations also include a conservative set of additional commands that collect basic device information (device make and model, software version, licensing information, ...) which are appended to the configuration as comments.
|
4
|
+
|
5
|
+
A user may wish to extend an existing model to collect the output of additional commands. Oxidized offers smart loading of models in order to facilitate this with ease, without the need to introduce changes to the upstream source code.
|
6
|
+
|
7
|
+
This methodology allows local site changes to be preserved during Oxidized version updates / gem updates. It also enables convenient local development of new models.
|
8
|
+
|
9
|
+
## Creating a new model
|
10
|
+
|
11
|
+
An Oxidized model, at minimum, requires just three elements:
|
12
|
+
|
13
|
+
* A model file, this file should be placed in the ~/.config/oxidized directory and named after the target OS type.
|
14
|
+
* A class defined within this file with the same name as the file itself that inherits from `Oxidized::Model`, the base model class.
|
15
|
+
* At least one command that will be executed and the output of which will be collected by Oxidized.
|
16
|
+
|
17
|
+
A bare-bone example for a fictional model running the OS type `rootware` could be introduced by creating the file `~/.config/oxidized/rootware.rb`, with the following content:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
class RootWare < Oxidized::Model
|
21
|
+
|
22
|
+
cmd 'show complete-config'
|
23
|
+
```
|
24
|
+
|
25
|
+
This model, as-is will:
|
26
|
+
|
27
|
+
* Log into the device and expect the default prompt.
|
28
|
+
* Upon matching it, execute the command `show complete-config`
|
29
|
+
* Collect the output.
|
30
|
+
|
31
|
+
It is often useful to, at minimum, define the following additional elements for any newly introduced module:
|
32
|
+
|
33
|
+
* A regexp for the prompt, via the `prompt` statement.
|
34
|
+
* A comment prefix, via the `comment` statement.
|
35
|
+
* A regexp for telnet username and password prompts.
|
36
|
+
* A mechanism for handling `enable` or similar functionality.
|
37
|
+
|
38
|
+
The API documentation contains a list of [methods](https://github.com/ytti/oxidized/blob/master/docs/Ruby-API.md#model) that can be used in modules.
|
39
|
+
|
40
|
+
A more fleshed out example can be found in the `IOS` and `JunOS` models.
|
41
|
+
|
42
|
+
## Extending an existing model with a new command
|
43
|
+
|
44
|
+
The example below can be used to extend the `JunOS` model to collect the output of `show interfaces diagnostics optics` and append the output to the configuration file as a comment. This command retrieves DOM information on pluggable optics present in a `JunOS`-powered chassis.
|
45
|
+
|
46
|
+
Create the file `~/.config/oxidized/model/junos.rb` with the following contents:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'oxidized/model/junos.rb'
|
50
|
+
|
51
|
+
|
52
|
+
class JunOS
|
53
|
+
|
54
|
+
|
55
|
+
cmd 'show interfaces diagnostics optics' do |cfg|
|
56
|
+
comment cfg
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
Due to smart loading, the user-supplied `~/.config/oxidized/model/junos.rb` file will take precedence over the model with the same name included in the Oxidized distribution.
|
64
|
+
|
65
|
+
The code then uses `require` to initially load the Oxidized-supplied model, and extends the class defined therein with an additional command.
|
66
|
+
|
67
|
+
Intuitively, it is also possible to:
|
68
|
+
|
69
|
+
* Completely re-define an existing model by creating a file in `~/.config/oxidized/model/` with the same name as an existing model, but not `require`-ing the upstream model file.
|
70
|
+
* Create a named variation of an existing model, by creating a file with a new name (such as `~/.config/oxidized/model/junos-extra.rb`), Then `require` the original model and extend its base class as in the above example. The named variation can then be specified as an OS type for specific devices that can benefit from the extra functionality. This allows for preservation of the base functionality for the default model types.
|
71
|
+
* Create a completely new model, with a new name, for a new operating system type.
|
72
|
+
* Testing/validation of an updated model from the [Oxidized GitHub repo models](https://github.com/ytti/oxidized/tree/master/lib/oxidized/model) by placing an updated model in the proper location without disrupting the gem-supplied model files.
|
73
|
+
|
74
|
+
## Advanced features
|
75
|
+
|
76
|
+
The loosely-coupled architecture of Oxidized allows for easy extensibility in more advanced use cases as well.
|
77
|
+
|
78
|
+
The example below extends the functionality of the `JunOS` model further to collect `display set` formatted configuration from the device, and utilizes the multi-output functionality of the `git` output to place the returned configuration in a separate file within a git repository.
|
79
|
+
|
80
|
+
It is possible to configure the `git` output to create new subdirectories under an existing repository instead of creating new repositories for each new defined output type (the default) by including the following configuration in the `~/.config/oxidized/config` file:
|
81
|
+
|
82
|
+
```yaml
|
83
|
+
output:
|
84
|
+
git:
|
85
|
+
type_as_directory: true
|
86
|
+
```
|
87
|
+
|
88
|
+
Then, `~/.config/oxidized/model/junos.rb` is adapted as following:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
require 'oxidized/model/junos.rb'
|
92
|
+
|
93
|
+
|
94
|
+
class JunOS
|
95
|
+
|
96
|
+
|
97
|
+
cmd 'show interface diagnostic optics' do |cfg|
|
98
|
+
comment cfg
|
99
|
+
end
|
100
|
+
|
101
|
+
cmd 'show configuration | display set' do |cfg|
|
102
|
+
cfg.type = "junos-set"
|
103
|
+
cfg.name = "set"
|
104
|
+
cfg
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
The output of the `show configuration | display set` command is marked with a new arbitrary alternative output type, `junos-set`. The `git` output will use the output type to create a new subdirectory by the same name. In this subdirectory, the `git` output will create files with the name `<devicename>--set` that will contain the output of this command for each device.
|
112
|
+
|
113
|
+
## Monkey-patching blocks in existing models
|
114
|
+
|
115
|
+
In addition to adding new commands and blocks to existing models, Oxidized offers convenience methods for monkey-patching existing commands and blocks within existing models.
|
116
|
+
|
117
|
+
When defining a monkey-patched block, two boolean arguments can be passed as part of the block definition:
|
118
|
+
|
119
|
+
* `clear: true`, which resets the existing block, allowing the user to completely override its contents.
|
120
|
+
* `prepend: true`, which ensures that the contents of the block are prepended, rather than appended (the default) to an existing block.
|
121
|
+
|
122
|
+
This functionality is supported for `cfg`, `cmd`, `pre`, `post`, and `expect` blocks.
|
123
|
+
|
124
|
+
Examples:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
cmd :secret clear: true do
|
128
|
+
... "(new code for secret removal which replaces the existing :secret definition in the model)" ...
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
cmd :ssh do prepend: true do
|
134
|
+
... "(code that should run first, before any code in the existing :ssh definition in the model)" ...
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
## Help
|
139
|
+
|
140
|
+
If you experience difficulties creating a new model, you can often get help by installing an Internet reachable sanitized device and opening a new issue on Github asking for help with creating the model. You should research what is the device vendor name is, the vendor's OS type name is, the exact device model name and firmware version. This information should be included in the issue.
|