fix(get_config): use paramiko directly with group1-sha1 for Mocana SSH 6.3
- Replace netmiko with direct paramiko connection for SSH config fallback - Explicitly set preferred_kex to include diffie-hellman-group1-sha1 (required by old Mocana SSH 6.3 on HP 2530 / YA firmware) - Hard timeout caps: banner_timeout=auth_timeout=8s, no keys/agent
This commit is contained in:
+47
-19
@@ -590,29 +590,57 @@ class ProcurveDriver(ConfigLifecycleMixin, SwitchDriver):
|
|||||||
"""Open a one-shot SSH session to retrieve running-config.
|
"""Open a one-shot SSH session to retrieve running-config.
|
||||||
|
|
||||||
Used as fallback when the REST API does not expose the config endpoint
|
Used as fallback when the REST API does not expose the config endpoint
|
||||||
(e.g. HP 2530 / YA firmware). Tries legacy KEX first (required for
|
(e.g. HP 2530 / YA firmware with Mocana SSH).
|
||||||
older ProCurve firmware), then standard. Each attempt is capped at
|
|
||||||
8 seconds so this fallback never pushes the overall poll over budget.
|
Uses paramiko directly (not netmiko) to:
|
||||||
Returns empty string on any failure.
|
- Explicitly enable diffie-hellman-group1-sha1 (required by Mocana SSH 6.3)
|
||||||
|
- Keep total blocking time ≤ 10 seconds
|
||||||
"""
|
"""
|
||||||
_FALLBACK_TIMEOUT = 8 # seconds per attempt — keeps total ≤ 16 s
|
import paramiko
|
||||||
for legacy in (True, False):
|
|
||||||
|
_FALLBACK_TIMEOUT = 8
|
||||||
|
|
||||||
|
# KEX list that includes the old group1-sha1 required by Mocana SSH 6.3
|
||||||
|
_LEGACY_KEX = [
|
||||||
|
"diffie-hellman-group1-sha1",
|
||||||
|
"diffie-hellman-group14-sha1",
|
||||||
|
"diffie-hellman-group14-sha256",
|
||||||
|
"diffie-hellman-group-exchange-sha256",
|
||||||
|
]
|
||||||
|
_LEGACY_DISABLED = {
|
||||||
|
"pubkeys": ["rsa-sha2-256", "rsa-sha2-512"],
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
kwargs = self._netmiko_kwargs(legacy=legacy)
|
client = paramiko.SSHClient()
|
||||||
kwargs["timeout"] = _FALLBACK_TIMEOUT
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
conn = ConnectHandler(**kwargs)
|
|
||||||
|
# Patch the preferred kex list on the class before connecting so
|
||||||
|
# paramiko will negotiate group1-sha1 with the old Mocana SSH server.
|
||||||
|
orig_kex = paramiko.Transport._preferred_kex
|
||||||
try:
|
try:
|
||||||
return conn.send_command("show running-config")
|
paramiko.Transport._preferred_kex = tuple(_LEGACY_KEX)
|
||||||
finally:
|
client.connect(
|
||||||
conn.disconnect()
|
hostname=self.hostname,
|
||||||
except Exception as exc:
|
port=self.port or 22,
|
||||||
logger.debug(
|
username=self.username,
|
||||||
"SSH config fallback (%s) failed for %s: %s",
|
password=self.password,
|
||||||
"legacy" if legacy else "standard",
|
timeout=_FALLBACK_TIMEOUT,
|
||||||
self.hostname,
|
banner_timeout=_FALLBACK_TIMEOUT,
|
||||||
exc,
|
auth_timeout=_FALLBACK_TIMEOUT,
|
||||||
|
look_for_keys=False,
|
||||||
|
allow_agent=False,
|
||||||
|
disabled_algorithms=_LEGACY_DISABLED,
|
||||||
)
|
)
|
||||||
logger.warning("SSH config fallback failed for %s (all transports)", self.hostname)
|
finally:
|
||||||
|
paramiko.Transport._preferred_kex = orig_kex
|
||||||
|
|
||||||
|
_, stdout, _ = client.exec_command("show running-config", timeout=_FALLBACK_TIMEOUT)
|
||||||
|
config = stdout.read().decode("utf-8", errors="replace")
|
||||||
|
client.close()
|
||||||
|
return config
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("SSH config fallback failed for %s: %s", self.hostname, exc)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user