fix: what bandit and the remaining lint rules found
- Long shell command lines are split into adjacent string literals. - get_os_users: a first loop over /etc/group filled a map nobody read; it is gone, the output is unchanged. - The five except Exception: pass now log at debug level (B110), so a swallowed failure leaves a trace. - nosec for the staging path on the device (B108) and the sudo hint message (B105); both are false positives. - tests: raise ... from exc, unused loop variable.
This commit is contained in:
1 parent
38391891ec
commit
933f81bd44
3 files changed
+23
-30
No files matched your search
+21
-28
@@ -171,15 +171,16 @@ _NO_STDIN = "exec </dev/null; "
|
|||||||
|
|
||||||
#: Where ``_install_file_as_root`` stages content: a fresh file from ``mktemp``
|
#: Where ``_install_file_as_root`` stages content: a fresh file from ``mktemp``
|
||||||
#: under ``umask 077``, never a fixed name another user could create first.
|
#: under ``umask 077``, never a fixed name another user could create first.
|
||||||
_STAGE_TEMPLATE = "/tmp/netork-stage.XXXXXX"
|
#: The path is on the device, not a local temp file.
|
||||||
|
_STAGE_TEMPLATE = "/tmp/netork-stage.XXXXXX" # nosec B108
|
||||||
_STAGE_PREFIX = _STAGE_TEMPLATE[: -len("XXXXXX")]
|
_STAGE_PREFIX = _STAGE_TEMPLATE[: -len("XXXXXX")]
|
||||||
_STAGE = (
|
_STAGE = (
|
||||||
f"umask 077 && t=$(mktemp {_STAGE_TEMPLATE}) && "
|
f"umask 077 && t=$(mktemp {_STAGE_TEMPLATE}) && "
|
||||||
'{ cat > "$t" && printf %s "$t" || { s=$?; rm -f -- "$t"; exit $s; }; }'
|
'{ cat > "$t" && printf %s "$t" || { s=$?; rm -f -- "$t"; exit $s; }; }'
|
||||||
)
|
)
|
||||||
|
|
||||||
#: What to do when sudo wants a password netOrk does not have.
|
#: What to do when sudo wants a password netOrk does not have (a message, not a password).
|
||||||
_SUDO_PASSWORD_HINT = (
|
_SUDO_PASSWORD_HINT = ( # nosec B105
|
||||||
"sudo requires a password on this host and no sudo password was given: pass one, "
|
"sudo requires a password on this host and no sudo password was given: pass one, "
|
||||||
"or allow this user passwordless sudo (NOPASSWD)."
|
"or allow this user passwordless sudo (NOPASSWD)."
|
||||||
)
|
)
|
||||||
@@ -274,7 +275,10 @@ def _arm_vendor_from_model(model: str) -> str:
|
|||||||
#: Where net-snmp reads its configuration, and how each package manager installs it.
|
#: Where net-snmp reads its configuration, and how each package manager installs it.
|
||||||
_SNMPD_CONF = "/etc/snmp/snmpd.conf"
|
_SNMPD_CONF = "/etc/snmp/snmpd.conf"
|
||||||
_SNMP_INSTALL = {
|
_SNMP_INSTALL = {
|
||||||
"apt": "apt-get update -y >/dev/null 2>&1; DEBIAN_FRONTEND=noninteractive apt-get install -y snmpd snmp 2>&1",
|
"apt": (
|
||||||
|
"apt-get update -y >/dev/null 2>&1; "
|
||||||
|
"DEBIAN_FRONTEND=noninteractive apt-get install -y snmpd snmp 2>&1"
|
||||||
|
),
|
||||||
"dnf": "dnf install -y net-snmp net-snmp-utils 2>&1",
|
"dnf": "dnf install -y net-snmp net-snmp-utils 2>&1",
|
||||||
"yum": "yum install -y net-snmp net-snmp-utils 2>&1",
|
"yum": "yum install -y net-snmp net-snmp-utils 2>&1",
|
||||||
"apk": "apk add --no-cache net-snmp net-snmp-tools 2>&1",
|
"apk": "apk add --no-cache net-snmp net-snmp-tools 2>&1",
|
||||||
@@ -425,7 +429,7 @@ class LinuxDriver(
|
|||||||
"stty cols 10000 2>/dev/null || true", expect_string=r"[#$>]\s*$"
|
"stty cols 10000 2>/dev/null || true", expect_string=r"[#$>]\s*$"
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
logger.debug("%s: ignored", self.hostname, exc_info=True)
|
||||||
|
|
||||||
self._pkg_manager = self._forced_pkg_manager or self._detect_pkg_manager()
|
self._pkg_manager = self._forced_pkg_manager or self._detect_pkg_manager()
|
||||||
logger.debug("Connected to %s, pkg_manager=%s", self.hostname, self._pkg_manager)
|
logger.debug("Connected to %s, pkg_manager=%s", self.hostname, self._pkg_manager)
|
||||||
@@ -436,7 +440,7 @@ class LinuxDriver(
|
|||||||
try:
|
try:
|
||||||
self._device.disconnect()
|
self._device.disconnect()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
logger.debug("%s: ignored", self.hostname, exc_info=True)
|
||||||
self._device = None
|
self._device = None
|
||||||
self._pkg_manager = None
|
self._pkg_manager = None
|
||||||
|
|
||||||
@@ -668,8 +672,10 @@ class LinuxDriver(
|
|||||||
"u=$(cat /sys/class/dmi/id/product_uuid 2>/dev/null); "
|
"u=$(cat /sys/class/dmi/id/product_uuid 2>/dev/null); "
|
||||||
"d=$(systemd-detect-virt 2>/dev/null); d=${d:-none}; "
|
"d=$(systemd-detect-virt 2>/dev/null); d=${d:-none}; "
|
||||||
"dt=$(tr -d '\\0' </sys/firmware/devicetree/base/model 2>/dev/null); "
|
"dt=$(tr -d '\\0' </sys/firmware/devicetree/base/model 2>/dev/null); "
|
||||||
"cs=$(grep '^Serial' /proc/cpuinfo 2>/dev/null | head -1 | cut -d: -f2 | xargs 2>/dev/null); "
|
"cs=$(grep '^Serial' /proc/cpuinfo 2>/dev/null | head -1 | cut -d: -f2 "
|
||||||
"cm=$(grep '^Model' /proc/cpuinfo 2>/dev/null | head -1 | cut -d: -f2 | xargs 2>/dev/null); "
|
"| xargs 2>/dev/null); "
|
||||||
|
"cm=$(grep '^Model' /proc/cpuinfo 2>/dev/null | head -1 | cut -d: -f2 "
|
||||||
|
"| xargs 2>/dev/null); "
|
||||||
# DMIBEGIN sentinel: _send() strips leading blank lines (ARM has no DMI
|
# DMIBEGIN sentinel: _send() strips leading blank lines (ARM has no DMI
|
||||||
# files, so fields 0-4 are empty). The sentinel anchors the output so
|
# files, so fields 0-4 are empty). The sentinel anchors the output so
|
||||||
# splitlines()[start+N] always maps to the correct field index.
|
# splitlines()[start+N] always maps to the correct field index.
|
||||||
@@ -1075,7 +1081,7 @@ class LinuxDriver(
|
|||||||
_make_entry(mapped_proto, nexthop, iface, metric, prefix)
|
_make_entry(mapped_proto, nexthop, iface, metric, prefix)
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
logger.debug("%s: ignored", self.hostname, exc_info=True)
|
||||||
|
|
||||||
return routes
|
return routes
|
||||||
|
|
||||||
@@ -1324,7 +1330,8 @@ class LinuxDriver(
|
|||||||
|
|
||||||
def _get_packages_rpm(self) -> list[PackageDict]:
|
def _get_packages_rpm(self) -> list[PackageDict]:
|
||||||
out = self._send(
|
out = self._send(
|
||||||
"rpm -qa --queryformat '%{NAME}\\t%{VERSION}-%{RELEASE}\\t%{SIZE}\\t%{SUMMARY}\\n' 2>/dev/null"
|
"rpm -qa --queryformat "
|
||||||
|
"'%{NAME}\\t%{VERSION}-%{RELEASE}\\t%{SIZE}\\t%{SUMMARY}\\n' 2>/dev/null"
|
||||||
)
|
)
|
||||||
packages: list[PackageDict] = []
|
packages: list[PackageDict] = []
|
||||||
for line in out.splitlines():
|
for line in out.splitlines():
|
||||||
@@ -1863,19 +1870,7 @@ class LinuxDriver(
|
|||||||
passwd_out = self._send("getent passwd 2>/dev/null || cat /etc/passwd")
|
passwd_out = self._send("getent passwd 2>/dev/null || cat /etc/passwd")
|
||||||
groups_out = self._send("getent group 2>/dev/null || cat /etc/group")
|
groups_out = self._send("getent group 2>/dev/null || cat /etc/group")
|
||||||
|
|
||||||
# Build uid→[group] map from /etc/group
|
# username → supplementary groups, joined with passwd below
|
||||||
uid_to_groups: dict[int, list[str]] = {}
|
|
||||||
for line in groups_out.splitlines():
|
|
||||||
parts = line.split(":")
|
|
||||||
if len(parts) < 4:
|
|
||||||
continue
|
|
||||||
gname = parts[0]
|
|
||||||
members = [m.strip() for m in parts[3].split(",") if m.strip()]
|
|
||||||
for member in members:
|
|
||||||
# We'll convert username→uid below; collect by username first
|
|
||||||
uid_to_groups.setdefault(-1, []) # placeholder
|
|
||||||
|
|
||||||
# Simpler: collect username→groups, then join with passwd
|
|
||||||
username_to_groups: dict[str, list[str]] = {}
|
username_to_groups: dict[str, list[str]] = {}
|
||||||
for line in groups_out.splitlines():
|
for line in groups_out.splitlines():
|
||||||
parts = line.split(":")
|
parts = line.split(":")
|
||||||
@@ -1994,9 +1989,7 @@ class LinuxDriver(
|
|||||||
return jobs
|
return jobs
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_cron_line(
|
def _parse_cron_line(line: str, source_user: str, has_user_field: bool) -> CronJobDict | None:
|
||||||
line: str, source_user: str, has_user_field: bool
|
|
||||||
) -> CronJobDict | None:
|
|
||||||
"""Parse a single crontab line; returns ``None`` for comments/blanks."""
|
"""Parse a single crontab line; returns ``None`` for comments/blanks."""
|
||||||
stripped = line.strip()
|
stripped = line.strip()
|
||||||
# Remove trailing comment
|
# Remove trailing comment
|
||||||
@@ -2064,7 +2057,7 @@ class LinuxDriver(
|
|||||||
community = parts[3]
|
community = parts[3]
|
||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
logger.debug("%s: ignored", self.hostname, exc_info=True)
|
||||||
|
|
||||||
# Detect port override
|
# Detect port override
|
||||||
try:
|
try:
|
||||||
@@ -2076,7 +2069,7 @@ class LinuxDriver(
|
|||||||
if m:
|
if m:
|
||||||
port = int(m.group(1))
|
port = int(m.group(1))
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
logger.debug("%s: ignored", self.hostname, exc_info=True)
|
||||||
|
|
||||||
return SNMPConfigDict(running=True, community=community, port=port, version="2c")
|
return SNMPConfigDict(running=True, community=community, port=port, version="2c")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ def test_every_annotation_resolves():
|
|||||||
import inspect
|
import inspect
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
for name, member in inspect.getmembers(LinuxDriver, inspect.isfunction):
|
for _name, member in inspect.getmembers(LinuxDriver, inspect.isfunction):
|
||||||
if member.__module__ == "napalm_linux.linux":
|
if member.__module__ == "napalm_linux.linux":
|
||||||
typing.get_type_hints(member)
|
typing.get_type_hints(member)
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ def test_a_changed_key_is_refused():
|
|||||||
try:
|
try:
|
||||||
raise paramiko.BadHostKeyException("10.0.0.8", SERVER_KEY, OTHER_KEY)
|
raise paramiko.BadHostKeyException("10.0.0.8", SERVER_KEY, OTHER_KEY)
|
||||||
except paramiko.SSHException as exc: # what netmiko does with it
|
except paramiko.SSHException as exc: # what netmiko does with it
|
||||||
raise NetmikoTimeoutException(f"A paramiko SSHException occurred: {exc}")
|
raise NetmikoTimeoutException(f"A paramiko SSHException occurred: {exc}") from exc
|
||||||
|
|
||||||
driver = _driver(seen, SshHostKey.of(OTHER_KEY))
|
driver = _driver(seen, SshHostKey.of(OTHER_KEY))
|
||||||
with patch("napalm_linux.linux.ConnectHandler", side_effect=refuse):
|
with patch("napalm_linux.linux.ConnectHandler", side_effect=refuse):
|
||||||
|
|||||||
Reference in new issue
Block a user