Skip to content
Open
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]
### Added
- procurve: model unit test (@thanegill)

### Changed
- procurve: rstrip trailing whitespace from commented command sections; add `String#rstrip_lines` refinement (@thanegill)
- procurve: remove ANSI escape codes with `clean :escape_codes` and simplify the prompt regexp (@thanegill)
- procurve: redact the additional credentials exposed by `include-credentials` / `encrypt-credentials`, with unit tests (@thanegill)

### Fixed
- procurve: hide the SNMP community on `snmp-server host <ip> community "<name>"` lines (@thanegill)
- procurve: hide local user password hashes (`password ... sha1 "<hash>"`) when remove_secret is true (@thanegill)
- source/sql: support defining port in configuration. Closes #3853 (@ytti)

### Changed
Expand Down
5 changes: 5 additions & 0 deletions docs/Model-Notes/HPEAruba.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ Older Devices like [ProCurve](/lib/oxidized/model/procurve.rb) or 3Com/Comware
are listed under the Vendor "HP" in the
[Supported OS Types](/docs/Supported-OS-Types.md) list.

HPE Aruba switches running ArubaOS-Switch (the line that succeeded ProCurve -
e.g. the 2530, 2540, 2920, 2930F/2930M, 3810 and 5400R series) also use the
[procurve](/lib/oxidized/model/procurve.rb) model, even though they are branded
"Aruba".

2 changes: 1 addition & 1 deletion docs/Supported-OS-Types.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
|Hirschmann |Classic |[hirschmann](/lib/oxidized/model/hirschmann.rb)
| |HiOS |[hios](/lib/oxidized/model/hios.rb)
|HP |Comware (HP A-series, H3C, 3Com)|[comware](/lib/oxidized/model/comware.rb) |@robertcheramy |[Comware](Model-Notes/Comware.md)
| |Procurve |[procurve](/lib/oxidized/model/procurve.rb) |@robertcheramy
| |Procurve |[procurve](/lib/oxidized/model/procurve.rb) |@robertcheramy, @thanegill
| |BladeSystem (Onboard Administrator)|[hpebladesystem](/lib/oxidized/model/hpebladesystem.rb)
| |MSA |[hpemsa](/lib/oxidized/model/hpemsa.rb)
| |MSM (Wireless Controller) |[hpmsm](/lib/oxidized/model/hpmsm.rb)
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/adtran.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Adtran < Oxidized::Model
prompt /([\w.@-]+[#>]\s?)$/

cmd :all do |cfg|
cfg.each_line.to_a[2..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both(2, 1).rstrip_lines
end

cmd :secret do |cfg|
Expand Down
21 changes: 8 additions & 13 deletions lib/oxidized/model/aosw.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,39 +52,39 @@ class AOSW < Oxidized::Model
/(Switch|AP) uptime/i,
/Reboot Time and Cause/i
]
rstrip_cfg comment cfg
clean_comment cfg
end

cmd 'show inventory' do |cfg|
# Don't show for unsupported devices (IAP and MAS)
cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/
rstrip_cfg clean cfg
clean(cfg).rstrip_lines
end

cmd 'show slots' do |cfg|
# Don't show for unsupported devices (IAP and MAS)
cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/
rstrip_cfg comment cfg
clean_comment cfg
end

cmd 'show license' do |cfg|
# Don't show for unsupported devices (IAP and MAS)
cfg = "" if cfg =~ /(Invalid input detected at '\^' marker|Parse error)/
rstrip_cfg comment cfg
clean_comment cfg
end

cmd 'show license passphrase' do |cfg|
# Don't show for unsupported devices (IAP and MAS)
cfg = "" if cfg.match /(Invalid input detected at '\^' marker|Parse error)/
rstrip_cfg comment cfg
clean_comment cfg
end

cmd 'show running-config' do |cfg|
cfg = cfg.reject_lines [
/^controller config \d+$/,
/^Building Configuration/
]
rstrip_cfg cfg
cfg.rstrip_lines
end

cfg :telnet do
Expand All @@ -105,13 +105,8 @@ class AOSW < Oxidized::Model
pre_logout 'exit'
end

def rstrip_cfg(cfg)
out = []
cfg.each_line do |line|
out << line.rstrip
end
out = out.join "\n"
out << "\n"
def clean_comment(lines)
comment(lines).rstrip_lines
end

def clean(cfg)
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/c4cmts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class C4CMTS < Oxidized::Model
comment '! '

cmd :all do |cfg|
cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both.rstrip_lines
end

cmd :secret do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/coriantgroove.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class CoriantGroove < Oxidized::Model
prompt /^(\w+@.*>\s*)$/

cmd :all do |cfg|
cfg.each_line.to_a[1..-3].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both(1, 2).rstrip_lines
end

cmd 'show inventory' do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/dlink.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Dlink < Oxidized::Model
end

cmd :all do |cfg|
cfg.each_line.to_a[2..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both(2, 1).rstrip_lines
end

cmd 'show switch' do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/dlinknextgen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class DlinkNextGen < Oxidized::Model

cmd :all do |cfg|
cfg.gsub!("\0", "") # Remove NULL bytes that cause Git to detect the file as binary
cfg.each_line.to_a[2..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both(2, 1).rstrip_lines
end

cmd :secret do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/enterasys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Enterasys < Oxidized::Model
end

cmd :all do |cfg|
cfg.each_line.to_a[2..-3].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both(2, 2).rstrip_lines
end

cmd 'show system hardware' do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/hpebladesystem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class HPEBladeSystem < Oxidized::Model
# end

cmd :all do |cfg|
cfg = cfg.delete("\r").each_line.to_a[0..-1].map { |line| line.rstrip }.join("\n") + "\n"
cfg = cfg.delete("\r").rstrip_lines
cfg.cut_tail
end

Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/junos.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def telnet
cfg = cfg.cut_both if screenscrape
cfg.gsub!(/ scale-subscriber (\s+)(\d+)/, ' scale-subscriber <count>')
cfg.gsub!(/VMX-BANDWIDTH\s+(\d+) (.*)/, 'VMX-BANDWIDTH <count> \2')
cfg.lines.map { |line| line.rstrip }.join("\n") + "\n"
cfg.rstrip_lines
end

cmd :secret do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/mtrlrfs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Mtrlrfs < Oxidized::Model
cmd :all do |cfg|
# xos inserts leading \r characters and other trailing white space.
# this deletes extraneous \r and trailing white space.
cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both.rstrip_lines
end

cmd 'show version' do |cfg|
Expand Down
94 changes: 63 additions & 31 deletions lib/oxidized/model/procurve.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
class Procurve < Oxidized::Model
using Refinements

# previous command is repeated followed by "\eE", which sometimes ends up on last line
# ssh switches prompt may start with \r, followed by the prompt itself, regex ([\w\s.-]+[#>] ), which ends the line
# telnet switches may start with various vt100 control characters, regex (\e\[24;[0-9][hH]), followed by the prompt, followed
# by at least 3 other vt100 characters
prompt /(^\r|\e\[24;[0-9][hH])?([\w\s.-]+[#>] )($|(\e\[24;[0-9][0-9]?[hH]){3})/
# The prompt is the device name followed by '#' or '>' and a
# space, optionally preceded by a carriage return on ssh.
prompt /(^\r)?([\w\s.-]+[#>] )$/

comment '! '

# replace next line control sequence with a new line
# These sequences are line breaks in the terminal stream: \e[1M...\e[1L is a
# delete-line/insert-line redraw and \eE is NEL (next line). They must be
# converted to newlines, not stripped, or the surrounding text concatenates.
# This has to run before clean :escape_codes, which would otherwise remove the
# \e[1M / \e[1L sequences (and does not match \eE at all).
expect /(\e\[1M\e\[\??\d+(;\d+)*[A-Za-z]\e\[1L)|(\eE)/ do |data, re|
data.gsub re, "\n"
end

# replace all used vt100 control sequences
expect /\e\[\??\d+(;\d+)*[A-Za-z]/ do |data, re|
data.gsub re, ''
end
# remove all other vt100 control sequences
clean :escape_codes

expect /Press any key to continue(\e\[\??\d+(;\d+)*[A-Za-z])*$/ do
send ' '
expect /Press any key to continue$/ do
send "\n"
""
end

Expand All @@ -32,54 +32,80 @@ class Procurve < Oxidized::Model
cmd :all do |cfg|
cfg = cfg.cut_both
cfg = cfg.gsub /^\r/, ''
# Additional filtering for elder switches sending vt100 control chars via telnet
cfg.gsub! /\e\[\??\d+(;\d+)*[A-Za-z]/, ''
# Additional filtering for power usage reporting which obviously changes over time
cfg.gsub! /^(.*AC [0-9]{3}V\/?([0-9]{3}V)?) *([0-9]{1,3}) (.*)/, '\\1 <removed> \\4'
# Remove failed commands that are not supported on all models
cfg.gsub! /^Invalid input: [A-Za-z-]+\n/, ''
cfg
end

# Most of these credentials only appear in the running-config when
# include-credentials (and/or encrypt-credentials) is enabled; see the
# ArubaOS-Switch Access Security Guide. encrypt-credentials renames the
# plaintext keyword to an encrypted- variant (key -> encrypted-key, etc.) and
# stores an AES blob in place of the cleartext/hashed value.
cmd :secret do |cfg|
# SNMPv1 community names
cfg.gsub! /^(snmp-server community) \S+(.*)/, '\\1 <secret hidden> \\2'
cfg.gsub! /^(snmp-server host \S+) \S+(.*)/, '\\1 <secret hidden> \\2'
cfg.gsub! /^(radius-server host \S+ key) \S+(.*)/, '\\1 <secret hidden> \\2'
cfg.gsub! /^(radius-server key).*/, '\\1 <configuration removed>'
cfg.gsub! /^(tacacs-server host \S+ key) \S+(.*)/, '\\1 <secret hidden> \\2'
cfg.gsub! /^(tacacs-server key).*/, '\\1 <secret hidden>'
cfg.gsub! /^(snmp-server host \S+)( community)? \S+(.*)/, '\\1\\2 <secret hidden>\\3'
# SNMPv3 user authentication and privacy passwords
cfg.gsub! /( auth (?:md5|sha)) "[^"]*"/, '\\1 "<secret hidden>"'
cfg.gsub! /( priv (?:des|aes)) "[^"]*"/, '\\1 "<secret hidden>"'

# encrypt-credentials master pre-shared-key. Must run before the local
# password rule below, whose plaintext "..." pattern would also match it.
cfg.gsub! /^(encrypt-credentials pre-shared-key (?:plaintext|hex)) \S+(.*)/, '\\1 <secret hidden>\\2'
# local manager/operator/port-access and aaa local-user password values;
# the quoted value may wrap onto the next line. hash-type: plaintext|sha1|sha256
cfg.gsub! /((?:plaintext|sha1|sha256)\s+)"[^"]*"/, '\\1"<secret hidden>"'
# encrypt-credentials form: encrypted-password <role> [user-name "x"] <blob>
cfg.gsub! /^(encrypted-password \S+(?: user-name "[^"]*")?) \S+(.*)/, '\\1 <secret hidden>\\2'

# RADIUS/TACACS shared secrets (key or encrypt-credentials encrypted-key)
cfg.gsub! /^(radius-server host \S+ (?:encrypted-)?key) \S+(.*)/, '\\1 <secret hidden>\\2'
cfg.gsub! /^(radius-server (?:encrypted-)?key).*/, '\\1 <configuration removed>'
cfg.gsub! /^(tacacs-server host \S+ (?:encrypted-)?key) \S+(.*)/, '\\1 <secret hidden>\\2'
cfg.gsub! /^(tacacs-server (?:encrypted-)?key).*/, '\\1 <secret hidden>'

# key-chain (routing protocol authentication) key material; rendered as a
# nested block, so key-string / encrypted-key sit on their own indented line
cfg.gsub! /^(\s*key-string) .*/, '\\1 <secret hidden>'
cfg.gsub! /^(\s*encrypted-key) \S+(.*)/, '\\1 <secret hidden>\\2'
# 802.1X supplicant shared secret
cfg.gsub! /^(aaa port-access .* (?:secret|encrypted-secret)) \S+(.*)/, '\\1 <secret hidden>\\2'
# SNTP authentication key
cfg.gsub! /^(sntp authentication .* (?:key-value|encrypted-key)) \S+(.*)/, '\\1 <secret hidden>\\2'
# MACsec pre-shared CAK (ckn is the key name, cak/encrypted-cak the secret)
cfg.gsub! /^(\s*mode pre-shared-key ckn \S+ (?:encrypted-)?cak) \S+(.*)/, '\\1 <secret hidden>\\2'
cfg
end

cmd 'show version' do |cfg|
comment cfg
clean_comment cfg
end

cmd 'show modules' do |cfg|
comment cfg
clean_comment cfg
end

cmd 'show interfaces transceiver' do |cfg|
comment cfg
clean_comment cfg
end

cmd 'show flash' do |cfg|
comment cfg
clean_comment cfg
end

# not supported on all models
cmd 'show system-information' do |cfg|
cfg = cfg.split("\n")[0..-8].join("\n")
comment cfg
cfg = cfg.cut_tail(7)
clean_comment cfg
end

# not supported on all models
cmd 'show system information' do |cfg|
cfg = cfg.each_line.reject do |line|
line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/
end
cfg = cfg.join
comment cfg
cfg = cfg.reject_lines ['CPU', 'Up Time', 'Total', 'Free', 'Lowest', 'Missed']
clean_comment cfg
end

cmd 'show running-config'
Expand All @@ -98,10 +124,16 @@ class Procurve < Oxidized::Model
end
end
post_login 'no page'
pre_logout "logout\ny\nn"
pre_logout 'logout'
pre_logout 'y'
pre_logout 'n'
end

cfg :ssh do
pty_options(chars_wide: 1000)
end

def clean_comment(lines)
comment(lines).rstrip_lines
end
end
2 changes: 1 addition & 1 deletion lib/oxidized/model/routeros.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class RouterOS < Oxidized::Model
cfg.gsub! /^\r+(.+)/, '\1'
cfg.gsub! /([^\r]*)\r+$/, '\1'
end
cfg.lines.map { |line| line.rstrip }.join("\n") + "\n" # strip trailing whitespace
cfg.rstrip_lines # strip trailing whitespace
end

cmd '/system resource print' do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/xos.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class XOS < Oxidized::Model
cmd :all do |cfg|
# xos inserts leading \r characters and other trailing white space.
# this deletes extraneous \r and trailing white space.
cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both.rstrip_lines
end

cmd :secret do |cfg|
Expand Down
2 changes: 1 addition & 1 deletion lib/oxidized/model/zhoneolt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ZhoneOLT < Oxidized::Model
end

cmd :all do |cfg|
cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
cfg.delete("\r").cut_both.rstrip_lines
end

cmd 'swversion' do |cfg|
Expand Down
5 changes: 5 additions & 0 deletions lib/refinements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ def keep_lines(patterns)
end.join
end

# right strip whitespaces from each line
def rstrip_lines
each_line.map(&:rstrip).join("\n") + "\n"
end

# remove lines matching any pattern (String or Regexp)
def reject_lines(patterns)
each_line.reject do |line|
Expand Down
Loading