oxidized 0.36.0 → 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/.rubocop.yml +3 -0
- data/CHANGELOG.md +26 -0
- data/Rakefile +1 -1
- data/docs/Configuration.md +10 -1
- data/docs/Creating-Models.md +1 -1
- data/docs/Hooks.md +92 -67
- data/docs/Inputs.md +15 -12
- data/docs/Model-Notes/GrandstreamHT8xx.md +8 -0
- data/docs/Model-Notes/RouterOS.md +13 -0
- data/docs/Model-Notes/TrueNAS.md +11 -7
- data/docs/Release.md +6 -1
- data/docs/Supported-OS-Types.md +1 -0
- data/extra/hooks/modelrulesadvanced.rb +0 -1
- data/lib/oxidized/cli/support.rb +152 -0
- data/lib/oxidized/cli.rb +9 -0
- data/lib/oxidized/hook.rb +2 -0
- data/lib/oxidized/input/debugtext.rb +40 -0
- data/lib/oxidized/input/debugyaml.rb +82 -0
- data/lib/oxidized/input/exec.rb +1 -6
- data/lib/oxidized/input/ftp.rb +0 -4
- data/lib/oxidized/input/http.rb +1 -8
- data/lib/oxidized/input/ssh.rb +28 -21
- data/lib/oxidized/input/sshbase.rb +7 -12
- data/lib/oxidized/input/telnet.rb +12 -9
- data/lib/oxidized/input/tftp.rb +0 -4
- data/lib/oxidized/model/aoscx.rb +13 -9
- data/lib/oxidized/model/cumulus.rb +3 -3
- data/lib/oxidized/model/dlinknextgen.rb +1 -0
- data/lib/oxidized/model/fortigate.rb +1 -1
- data/lib/oxidized/model/grandstreamht8xx.rb +19 -0
- data/lib/oxidized/model/ios.rb +2 -0
- data/lib/oxidized/model/junos.rb +2 -2
- data/lib/oxidized/model/linuxgeneric.rb +4 -2
- data/lib/oxidized/model/nxos.rb +4 -1
- data/lib/oxidized/model/routeros.rb +4 -0
- data/lib/oxidized/model/tplink.rb +4 -6
- data/lib/oxidized/model/truenas.rb +56 -5
- data/lib/oxidized/model/vyos.rb +1 -0
- data/lib/oxidized/version.rb +2 -2
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 59eeea5dc9024b545f633379b4ab663cf5ea26fe478a4dafffe0e0b80909d2b7
|
|
4
|
+
data.tar.gz: 26363d11d322e4f797db86050dce16532b8cf2e0e5419de0b92b0dae0b8076df
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b47b07aaa4528bfa49559ae27785f64da5de07e00305878b840cad7f00068e83c84951350494b37765e0a2499a59881d15979360a8c911702f81531613dd674
|
|
7
|
+
data.tar.gz: e103734e361736470524ea88f650fa0007a498273c2b54597a0d6fe3d0e768013f2a13f9edea755b72955ce57684614b7a824a745b81c41f0f2fe539b3d13b4d
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,32 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [0.37.0 - 2026-05-20]
|
|
8
|
+
### Added
|
|
9
|
+
- routeros: support store mode `on_significant` (@infabo)
|
|
10
|
+
- model for Grandstream HT8xx (@mklopocki)
|
|
11
|
+
- Add --support option to gather system diagnostics (@robertcheramy)
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- input/ssh: validate that cmd is a String. See #3700 (@robertcheramy)
|
|
15
|
+
- junos: changed "show system license" regex to reduce notification noise for PTX routers. See #3794 (@ctomkow)
|
|
16
|
+
- ios: keep motherboard information in show version. Closes #3798 (@robertcheramy)
|
|
17
|
+
- aoscx: use oxidized filtering instead of "show system | exclude...". (@robertcheramy)
|
|
18
|
+
- input/*: rewrite debug logging; remove unused logging; input/ssh: write a YAML simulation file (@robertcheramy)
|
|
19
|
+
- truenas: capture app, replication, cloudsync configurations without constant changes. See #3795 (@neilschelly)
|
|
20
|
+
- Set Rake::TestTask to `verbose = false` since the behavior changed with rake 13.4.2 (@robertcheramy)
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- VyOS: detect community string in SNMP traps. Fixes: #3793 (@nicolasberens)
|
|
24
|
+
- fortigate: show Part No. of SFPs. Fixes: #3800 (@robertcheramy)
|
|
25
|
+
- aoscx: Hide total power consumption (stacking). Fixes #3801 (@robertcheramy)
|
|
26
|
+
- linuxgeneric: fix prompt, telnet username and clean ANSI Escape Codes (@robertcheramy)
|
|
27
|
+
- cumulus: fix prompt (make : and space optional). Fixes #3812 (@robertcheramy)
|
|
28
|
+
- dlinknexgen: NULL byte handling. Fixes #3816 (@ziotibia81)
|
|
29
|
+
- nxos: hide snmpv3 priv key when remove_secret is true. Fixes: #3805 (@robertcheramy)
|
|
30
|
+
- tpink: use `\r\n` when sending commands and set `terminal length 0`. Fixes #3804 (@robertcheramy)
|
|
31
|
+
|
|
32
|
+
|
|
7
33
|
## [0.36.0 - 2026-03-31]
|
|
8
34
|
### Release Notes
|
|
9
35
|
The fortios model has been split into fortigate and fortios. You need the new fortigate model for FortiGate firewalls. Be sure to check the [Fortinet model notes](docs/Model-Notes/Fortinet.md) before upgrading.
|
data/Rakefile
CHANGED
data/docs/Configuration.md
CHANGED
|
@@ -83,7 +83,6 @@ username: oxidized
|
|
|
83
83
|
password: S3cr3tx
|
|
84
84
|
model: junos
|
|
85
85
|
interval: 3600 #interval in seconds, when 0 is configured no fetch config is done at initial start and after
|
|
86
|
-
log: ~/.config/oxidized/log
|
|
87
86
|
debug: false
|
|
88
87
|
threads: 30 # maximum number of threads
|
|
89
88
|
# use_max_threads:
|
|
@@ -143,6 +142,16 @@ model_map:
|
|
|
143
142
|
cisco: ios
|
|
144
143
|
juniper: junos
|
|
145
144
|
!ruby/regexp /procurve/: procurve
|
|
145
|
+
logger:
|
|
146
|
+
# The default level is :info
|
|
147
|
+
# level: :info
|
|
148
|
+
appenders:
|
|
149
|
+
- type: syslog
|
|
150
|
+
level: :error
|
|
151
|
+
- type: stdout
|
|
152
|
+
level: :warn
|
|
153
|
+
- type: file
|
|
154
|
+
file: ~/.config/oxidized/info.log
|
|
146
155
|
```
|
|
147
156
|
|
|
148
157
|
## Advanced Group Configuration
|
data/docs/Creating-Models.md
CHANGED
data/docs/Hooks.md
CHANGED
|
@@ -109,50 +109,102 @@ hooks:
|
|
|
109
109
|
|
|
110
110
|
## Hook type: githubrepo
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
The `githubrepo` hook executes a `git push` to a configured `remote_repo` when
|
|
113
|
+
the specified event is triggered.
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
### Configuration keys
|
|
115
116
|
|
|
116
|
-
|
|
117
|
+
| Key | Description |
|
|
118
|
+
|---------------|-------------|
|
|
119
|
+
| `remote_repo` | The remote repository to push to. Use a URL string (no groups) or a group dictionary (see [Using groups](#using-groups)). |
|
|
120
|
+
| `username` | Username for authentication. Defaults to the user part of the `remote_repo` URI, falling back to `git`. |
|
|
121
|
+
| `password` | Password for username/password authentication. |
|
|
122
|
+
| `privatekey` | Path to the private key file. Must be in legacy PEM format (see note below). |
|
|
123
|
+
| `publickey` | Path to the public key file (optional — inferred from `privatekey` + `.pub` if omitted). |
|
|
117
124
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
Notes:
|
|
126
|
+
- `remote_repo` must not match the name of any local `git` output repo configured under `output`. Use unique names for each.
|
|
127
|
+
- If using SSH key authentication with a passphrase-protected private key, provide the passphrase with the `OXIDIZED_SSH_PASSPHRASE` environment variable.
|
|
128
|
+
- The `privatekey` must be in the legacy PEM format (`BEGIN RSA PRIVATE KEY`), not the newer OpenSSH format (`BEGIN OPENSSH PRIVATE KEY`). See [#1877](https://github.com/ytti/oxidized/issues/1877) and [#2324](https://github.com/ytti/oxidized/issues/2324).
|
|
129
|
+
- To convert an existing key to PEM format, run:
|
|
130
|
+
```shell
|
|
131
|
+
ssh-keygen -p -m PEM -f $MY_KEY_HERE
|
|
132
|
+
```
|
|
122
133
|
|
|
123
|
-
|
|
134
|
+
### Authentication methods
|
|
124
135
|
|
|
125
|
-
|
|
136
|
+
Choose one of the following methods:
|
|
126
137
|
|
|
127
|
-
|
|
138
|
+
| Method | Required keys |
|
|
139
|
+
|-------------------------------|---------------|
|
|
140
|
+
| Username + password | `username` (optional), `password` |
|
|
141
|
+
| SSH key pair | `privatekey`, `publickey` (optional - assumed to be at `privatekey` + `.pub`) |
|
|
142
|
+
| SSH agent | no credentials needed |
|
|
128
143
|
|
|
129
|
-
|
|
130
|
-
* `username`: username for repository auth.
|
|
131
|
-
* `password`: password for repository auth.
|
|
132
|
-
* `publickey`: public key file path for repository auth. (optional)
|
|
133
|
-
* `privatekey`: private key file path for repository auth.
|
|
134
|
-
* NOTE: this key needs to be in the legacy PEM format, not the newer OpenSSL format [#1877](https://github.com/ytti/oxidized/issues/1877), [#2324](https://github.com/ytti/oxidized/issues/2324)
|
|
135
|
-
* To convert a key beginning with `BEGIN OPENSSH PRIVATE KEY` to the legacy PEM format, run this command:
|
|
136
|
-
`ssh-keygen -p -m PEM -f $MY_KEY_HERE`
|
|
144
|
+
### Configuration examples
|
|
137
145
|
|
|
138
|
-
|
|
146
|
+
**Username and password:**
|
|
139
147
|
|
|
140
|
-
|
|
148
|
+
```yaml
|
|
149
|
+
hooks:
|
|
150
|
+
push_to_remote:
|
|
151
|
+
type: githubrepo
|
|
152
|
+
events: [post_store]
|
|
153
|
+
remote_repo: git@git.intranet:oxidized/test.git
|
|
154
|
+
username: user
|
|
155
|
+
password: pass
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**SSH key pair:**
|
|
141
159
|
|
|
142
160
|
```yaml
|
|
143
161
|
hooks:
|
|
144
162
|
push_to_remote:
|
|
163
|
+
type: githubrepo
|
|
164
|
+
events: [post_store]
|
|
165
|
+
remote_repo: git@git.intranet:oxidized/test.git
|
|
166
|
+
publickey: /root/.ssh/id_rsa.pub
|
|
167
|
+
privatekey: /root/.ssh/id_rsa
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
**SSH agent:**
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
hooks:
|
|
175
|
+
push_to_remote:
|
|
176
|
+
type: githubrepo
|
|
177
|
+
events: [post_store]
|
|
178
|
+
remote_repo: git@git.intranet:oxidized/test.git
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Using groups
|
|
182
|
+
|
|
183
|
+
When using groups and `single_repo` is set to `true` (default) in the
|
|
184
|
+
configuration section output/git, `remote_repo` must be a dictionary mapping
|
|
185
|
+
group names to remote repositories. Groups not listed in the dictionary are
|
|
186
|
+
silently skipped.
|
|
187
|
+
|
|
188
|
+
Each entry can be either a plain URL string:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
hooks:
|
|
192
|
+
push_to_remote:
|
|
193
|
+
type: githubrepo
|
|
194
|
+
events: [post_store]
|
|
145
195
|
remote_repo:
|
|
146
196
|
routers: git@git.intranet:oxidized/routers.git
|
|
147
197
|
switches: git@git.intranet:oxidized/switches.git
|
|
148
198
|
firewalls: git@git.intranet:oxidized/firewalls.git
|
|
149
199
|
```
|
|
150
200
|
|
|
151
|
-
...
|
|
201
|
+
...or a dictionary with `url` and `privatekey` to use a per-group SSH key:
|
|
152
202
|
|
|
153
203
|
```yaml
|
|
154
204
|
hooks:
|
|
155
205
|
push_to_remote:
|
|
206
|
+
type: githubrepo
|
|
207
|
+
events: [post_store]
|
|
156
208
|
remote_repo:
|
|
157
209
|
routers:
|
|
158
210
|
url: git@git.intranet:oxidized/routers.git
|
|
@@ -165,58 +217,31 @@ hooks:
|
|
|
165
217
|
privatekey: /root/.ssh/id_rsa_firewalls
|
|
166
218
|
```
|
|
167
219
|
|
|
168
|
-
Both forms can be mixed
|
|
220
|
+
Both forms can be mixed within the same configuration.
|
|
169
221
|
|
|
170
|
-
###
|
|
222
|
+
### Custom branch name
|
|
171
223
|
|
|
172
|
-
|
|
224
|
+
The `githubrepo` hook uses the branch name from the
|
|
225
|
+
[git output](Outputs.md#output-git) as the remote branch name. When the
|
|
226
|
+
repository is first created, Oxidized uses the default branch name from
|
|
227
|
+
`git config --global init.defaultBranch`. The default is `master`.
|
|
173
228
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
push_to_remote:
|
|
177
|
-
type: githubrepo
|
|
178
|
-
events: [post_store]
|
|
179
|
-
remote_repo: git@git.intranet:oxidized/test.git
|
|
180
|
-
username: user
|
|
181
|
-
password: pass
|
|
182
|
-
```
|
|
229
|
+
You can manually rename the branch after Oxidized has already created the
|
|
230
|
+
repository. Be aware that you may break things, so make backups.
|
|
183
231
|
|
|
184
|
-
|
|
232
|
+
To rename the branch after Oxidized has already created the repository:
|
|
185
233
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
```
|
|
234
|
+
1. Stop oxidized.
|
|
235
|
+
2. Back up your oxidized git repository.
|
|
236
|
+
3. Change to your oxidized git repository directory.
|
|
237
|
+
4. Inspect the current branches: `git branch -avv`
|
|
238
|
+
5. Rename the local branch: `git branch -m <NewName>`
|
|
239
|
+
6. Remove the stale remote-tracking reference: `git branch -r -d origin/<OldName>`
|
|
240
|
+
7. Verify the result: `git branch -avv`
|
|
241
|
+
8. Restart oxidized.
|
|
195
242
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
[git output](Outputs.md#output-git) as a remote branch name. When creating the
|
|
199
|
-
git repository for the first time, Oxidized uses the default branch name
|
|
200
|
-
configured in git with `git config --global init.defaultBranch <Name>`. The
|
|
201
|
-
default is `master`.
|
|
202
|
-
|
|
203
|
-
If you need to rename the branch name after Oxidized has created it, you may do
|
|
204
|
-
it manually. Be aware that you may break things. Make backups and do not
|
|
205
|
-
complain if something goes wrong!
|
|
206
|
-
|
|
207
|
-
1. Stop oxidized (no one should access the git repository while doing the
|
|
208
|
-
following steps)
|
|
209
|
-
2. Make a backup of your oxidized data, especially the git repository
|
|
210
|
-
3. Change directory to your oxidized git repository (as configured in oxidized
|
|
211
|
-
configuration file)
|
|
212
|
-
4. Inspect the current branches with `git branch -avv`
|
|
213
|
-
5. Rename the default branch with `git branch -m <NewName>`
|
|
214
|
-
6. Remove the reference to the old remote branch with
|
|
215
|
-
`git branch -r -d origin/<OldName>`
|
|
216
|
-
6. Inspect the change with `git branch -avv`
|
|
217
|
-
7. Restart oxidized - you're done!
|
|
218
|
-
|
|
219
|
-
Note that you will also have to clean your remote git repository.
|
|
243
|
+
Oxidized will push to a new remote branch. When everything is fine, you can
|
|
244
|
+
remove the old branch from the remote repository.
|
|
220
245
|
|
|
221
246
|
## Hook type: awssns
|
|
222
247
|
|
data/docs/Inputs.md
CHANGED
|
@@ -208,25 +208,28 @@ input:
|
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
## Debugging
|
|
211
|
-
|
|
212
211
|
In case a model plugin doesn't work correctly (ios, procurve, etc.), you can
|
|
213
|
-
enable live debugging of SSH
|
|
214
|
-
|
|
215
|
-
depending on the parent directory of the logfile option.
|
|
212
|
+
enable live debugging of SSH and Telnet sessions with the `debug` option of
|
|
213
|
+
the `input` section.
|
|
216
214
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
Starting with version 0.37.0, `debug` can take different values:
|
|
216
|
+
- `text`: log input and output to a text file (ssh, telnet)
|
|
217
|
+
- `yaml`: produce a yaml simulation file (ssh, scp)
|
|
218
|
+
- `library`: activate debug logging of the underlying library
|
|
219
|
+
- a combination of the options above (`text, yaml`)
|
|
220
|
+
- `true`; activate all debugging options (Only option for versions prior 0.37.0)
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
log: /home/oxidized/.config/oxidized/log
|
|
222
|
+
The log files will be created in `~/.config/oxidized/logs/` (or `$OXIDIZED_LOGS/logs/`).
|
|
224
223
|
|
|
225
|
-
|
|
224
|
+
The following example will log an active ssh/telnet session to
|
|
225
|
+
`~/.config/oxidized/logs/<IP-Address>-<PROTOCOL>-<timestamp>.txt` and for ssh
|
|
226
|
+
`~/.config/oxidized/logs/<IP-Address>-<PROTOCOL>-<timestamp>.yaml`. A new file
|
|
227
|
+
is created for each session.
|
|
226
228
|
|
|
229
|
+
```yaml
|
|
227
230
|
input:
|
|
228
231
|
default: ssh, telnet
|
|
229
|
-
debug:
|
|
232
|
+
debug: yaml, text
|
|
230
233
|
ssh:
|
|
231
234
|
secure: false
|
|
232
235
|
http:
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Grandstream HT8xx
|
|
2
|
+
|
|
3
|
+
You need to have enabled access to device by SSH.
|
|
4
|
+
Connection using user/password for retrieve the configuration containing XML file with all params stored in device memory.
|
|
5
|
+
|
|
6
|
+
Tested on hardware: v1 and software version: 1.0.61.2.
|
|
7
|
+
|
|
8
|
+
Back to [Model-Notes](README.md)
|
|
@@ -12,4 +12,17 @@ and attach the public key.
|
|
|
12
12
|
|
|
13
13
|
Oxidized can now retrieve your configuration!
|
|
14
14
|
|
|
15
|
+
## Save significant changes only
|
|
16
|
+
|
|
17
|
+
You can [store the configuration only on significant changes](/docs/Configuration.md#store-configuration-only-on-significant-changes)
|
|
18
|
+
by setting the [variable](/docs/Configuration.md#options-credentials-vars-etc-precedence)
|
|
19
|
+
`output_store_mode` to `on_significant`. On RouterOS, this prevents Oxidized from saving a
|
|
20
|
+
new configuration version when only the system history has changed without any actual
|
|
21
|
+
configuration change.
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
vars:
|
|
25
|
+
output_store_mode: on_significant
|
|
26
|
+
```
|
|
27
|
+
|
|
15
28
|
Back to [Model-Notes](README.md)
|
data/docs/Model-Notes/TrueNAS.md
CHANGED
|
@@ -6,14 +6,18 @@ TrueNAS SCALE (Linux-based) devices.
|
|
|
6
6
|
## Authentication
|
|
7
7
|
|
|
8
8
|
Ensure that the user configured for oxidized to login to your device has the
|
|
9
|
-
permissions to read the configuration database. On older
|
|
10
|
-
just work.
|
|
9
|
+
permissions to read the configuration database. On older CORE instances, this
|
|
10
|
+
would just work without sudo. On newer devices, the `/data/freenas-v1.db` file
|
|
11
|
+
can only be read by the root user.
|
|
11
12
|
|
|
12
|
-
On
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
On SCALE devices with Apps support, it's also necessary to add some privileges
|
|
14
|
+
to read the container configurations for any apps you have installed, which can
|
|
15
|
+
be found under `/mnt/.ix-apps`.
|
|
16
|
+
|
|
17
|
+
You can make sure that the user that oxidized uses to login (`oxidized` in this
|
|
18
|
+
example) can dump the configuration using `sudo` by adding something like this
|
|
19
|
+
to your `/etc/sudoers` file:
|
|
16
20
|
|
|
17
21
|
```
|
|
18
|
-
oxidized ALL=(ALL) NOPASSWD: /usr/bin/sqlite3 file
|
|
22
|
+
oxidized ALL=(ALL) NOPASSWD: /usr/bin/find /mnt/.ix-apps/app_configs *, /usr/bin/sqlite3 -readonly file\:/data/freenas-v1.db *
|
|
19
23
|
```
|
data/docs/Release.md
CHANGED
|
@@ -71,9 +71,14 @@ git push origin 0.xx.yy
|
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
Make a release from the tag in github.
|
|
74
|
-
-
|
|
74
|
+
- Name the release `0.xx.yy`
|
|
75
|
+
- Generate release notes
|
|
76
|
+
- Remove `## What's changed`
|
|
77
|
+
- Take the release notes from CHANGELOG.md
|
|
75
78
|
- List new contributors (generated automatically)
|
|
76
79
|
- Keep the Full Changelog (generated automatically)
|
|
80
|
+
- Preview
|
|
81
|
+
- Publish
|
|
77
82
|
|
|
78
83
|
Close the corresponding milestone in github.
|
|
79
84
|
|
data/docs/Supported-OS-Types.md
CHANGED
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
|[Garderos](https://garderos.com/) |GRS (Garderos Router Software) |[garderos](/lib/oxidized/model/garderos.rb) | @robertcheramy |Routers for harsh environments
|
|
109
109
|
|GCOM Technologies |Broadband Network Platform Software|[gcombnps](/lib/oxidized/model/gcombnps.rb)
|
|
110
110
|
|Grandstream Networks|GSX |[grandstream](/lib/oxidized/model/grandstream.rb)
|
|
111
|
+
| |HT8xx |[grandstream](/lib/oxidized/model/grandstreamht8xx.rb) | @mklopocki | [Grandstream](Model-Notes/GrandstreamHT8xx.md)
|
|
111
112
|
|Hatteras |Hatteras |[hatteras](/lib/oxidized/model/hatteras.rb)
|
|
112
113
|
|Hillstone Networks |StoneOS |[stoneos](/lib/oxidized/model/stoneos.rb)
|
|
113
114
|
|Hirschmann |Classic |[hirschmann](/lib/oxidized/model/hirschmann.rb)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
|
|
3
|
+
module Oxidized
|
|
4
|
+
class CLI
|
|
5
|
+
module Support
|
|
6
|
+
SENSITIVE_NAME_RE = /(password|passphrase|secret|token|enable|
|
|
7
|
+
(private|api|access)_?key|
|
|
8
|
+
community|credential|auth
|
|
9
|
+
)/ix
|
|
10
|
+
ROOT_GEMS = %w[oxidized oxidized-web].freeze
|
|
11
|
+
EXPLICIT_ENV_KEYS = %w[
|
|
12
|
+
OXIDIZED_HOME
|
|
13
|
+
OXIDIZED_LOGS
|
|
14
|
+
CONFIG_RELOAD_INTERVAL
|
|
15
|
+
UPDATE_CA_CERTIFICATES
|
|
16
|
+
].freeze
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def show_support_details
|
|
21
|
+
print_intro
|
|
22
|
+
print_environment
|
|
23
|
+
print_config_files
|
|
24
|
+
print_rugged_support
|
|
25
|
+
print_installed_gems
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def print_intro
|
|
29
|
+
os_release = read_os_release
|
|
30
|
+
runit_path = '/etc/service/oxidized/run'
|
|
31
|
+
|
|
32
|
+
puts '> :warning:'
|
|
33
|
+
puts '> The --support option is intended for diagnostic purposes and may include sensitive information.'
|
|
34
|
+
puts '> Remove any sensitive data before sharing this output.'
|
|
35
|
+
puts
|
|
36
|
+
puts '## Oxidized Support Data'
|
|
37
|
+
puts "- Timestamp: #{Time.now.utc.iso8601}"
|
|
38
|
+
puts "- Oxidized version: #{Oxidized::VERSION_FULL}"
|
|
39
|
+
puts "- OS release: #{os_release}" if os_release
|
|
40
|
+
puts "- Container hint (#{runit_path} exists): #{File.exist?(runit_path)}"
|
|
41
|
+
puts "- Ruby engine: #{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}"
|
|
42
|
+
puts "- Ruby version: #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
|
|
43
|
+
puts "- Working directory: #{Dir.pwd}"
|
|
44
|
+
puts "- Gem paths: #{Gem.path.join(', ')}"
|
|
45
|
+
puts
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def print_environment
|
|
49
|
+
puts '### Environment Variables'
|
|
50
|
+
keys = (ENV.keys.grep(/^OXIDIZED_/) + EXPLICIT_ENV_KEYS).uniq.sort
|
|
51
|
+
|
|
52
|
+
keys.each do |key|
|
|
53
|
+
next unless ENV.has_key?(key)
|
|
54
|
+
|
|
55
|
+
value = ENV.fetch(key)
|
|
56
|
+
puts key.match?(SENSITIVE_NAME_RE) ? "#{key}=[REDACTED]" : "#{key}=#{value}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
puts
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def print_config_files
|
|
63
|
+
puts '### Configuration Files'
|
|
64
|
+
config_paths.each do |path|
|
|
65
|
+
config_path = File.expand_path(path)
|
|
66
|
+
exists = File.exist?(config_path)
|
|
67
|
+
puts "- #{config_path} exists: #{exists ? 'yes' : 'no'}"
|
|
68
|
+
next unless exists
|
|
69
|
+
|
|
70
|
+
print_sanitized_config(config_path)
|
|
71
|
+
end
|
|
72
|
+
puts
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def print_rugged_support
|
|
76
|
+
puts '### Rugged'
|
|
77
|
+
begin
|
|
78
|
+
require 'rugged'
|
|
79
|
+
puts "- Rugged version: #{Rugged::VERSION}"
|
|
80
|
+
|
|
81
|
+
ssh_supported = Rugged.respond_to?(:features) && Rugged.features.include?(:ssh)
|
|
82
|
+
puts "- Rugged SSH support: #{ssh_supported}"
|
|
83
|
+
rescue LoadError
|
|
84
|
+
puts '- Rugged: not available'
|
|
85
|
+
puts '- Rugged SSH support: false'
|
|
86
|
+
end
|
|
87
|
+
puts
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def print_installed_gems
|
|
91
|
+
puts '### Relevant Installed Gems'
|
|
92
|
+
relevant_gem_names.each do |name|
|
|
93
|
+
versions = Gem::Specification.find_all_by_name(name).sort_by(&:version).map { |s| s.version.to_s }
|
|
94
|
+
puts "- #{name} (#{versions.join(', ')})" unless versions.empty?
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def relevant_gem_names
|
|
99
|
+
names = ROOT_GEMS.select { |name| Gem::Specification.any? { |s| s.name == name } }
|
|
100
|
+
|
|
101
|
+
root_specs = names.flat_map { |name| Gem::Specification.find_all_by_name(name) }
|
|
102
|
+
runtime_deps = root_specs.flat_map { |spec| spec.dependencies }
|
|
103
|
+
names.concat(runtime_deps.map(&:name))
|
|
104
|
+
names.sort.uniq
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def config_paths
|
|
108
|
+
user_default = File.join(Dir.home, '.config', 'oxidized', 'config')
|
|
109
|
+
home_from_env = File.join(File.expand_path(Oxidized::Config::ROOT), 'config')
|
|
110
|
+
|
|
111
|
+
[
|
|
112
|
+
'/etc/oxidized/config',
|
|
113
|
+
user_default,
|
|
114
|
+
home_from_env
|
|
115
|
+
].uniq
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def print_sanitized_config(path)
|
|
119
|
+
content = File.read(path)
|
|
120
|
+
puts '```yaml'
|
|
121
|
+
content.each_line(chomp: true) do |line|
|
|
122
|
+
key, separator, = line.partition(':')
|
|
123
|
+
|
|
124
|
+
if separator.empty? || key.empty?
|
|
125
|
+
puts line
|
|
126
|
+
next
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
if key.match?(SENSITIVE_NAME_RE)
|
|
130
|
+
puts "#{key}: [REDACTED]"
|
|
131
|
+
else
|
|
132
|
+
puts line
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
puts '```'
|
|
136
|
+
rescue StandardError => e
|
|
137
|
+
puts " <failed to read: #{e.class}: #{e.message}>"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def read_os_release
|
|
141
|
+
return nil unless File.exist?('/etc/os-release')
|
|
142
|
+
|
|
143
|
+
line = File.foreach('/etc/os-release').find { |entry| entry.start_with?('PRETTY_NAME=') }
|
|
144
|
+
return nil unless line
|
|
145
|
+
|
|
146
|
+
line.split('=', 2).last.to_s.strip.gsub(/^"|"$/, '')
|
|
147
|
+
rescue StandardError
|
|
148
|
+
nil
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
data/lib/oxidized/cli.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
require 'semantic_logger'
|
|
2
|
+
require_relative 'cli/support'
|
|
2
3
|
|
|
3
4
|
module Oxidized
|
|
4
5
|
class CLI
|
|
5
6
|
include SemanticLogger::Loggable
|
|
7
|
+
include Support
|
|
6
8
|
|
|
7
9
|
require 'slop'
|
|
8
10
|
require 'oxidized'
|
|
@@ -48,6 +50,7 @@ module Oxidized
|
|
|
48
50
|
opts = Slop.parse do |opt|
|
|
49
51
|
opt.on '-d', '--debug', 'turn on debugging'
|
|
50
52
|
opt.on '--daemonize', 'Daemonize/fork the process'
|
|
53
|
+
opt.on '--support', 'show support diagnostics and exit'
|
|
51
54
|
opt.string '--home-dir', 'Oxidized home dir', default: nil
|
|
52
55
|
opt.string '--config-file', 'Oxidized config file', default: nil
|
|
53
56
|
opt.on '-h', '--help', 'show usage' do
|
|
@@ -64,6 +67,12 @@ module Oxidized
|
|
|
64
67
|
Kernel.exit
|
|
65
68
|
end
|
|
66
69
|
end
|
|
70
|
+
|
|
71
|
+
if opts[:support]
|
|
72
|
+
show_support_details
|
|
73
|
+
Kernel.exit
|
|
74
|
+
end
|
|
75
|
+
|
|
67
76
|
[opts.arguments, opts]
|
|
68
77
|
end
|
|
69
78
|
|
data/lib/oxidized/hook.rb
CHANGED