Welle 2 · Sicherheits-Markierung: Debian-Sicherheitsupdates, Alpine über secdb, Lücken-Scans aus Arcane
Der Ausführer zählt je Gast, wie viele offene Updates aus einer Sicherheits-Suite kommen („-security“ in apt list), beim Proxmox-Host ebenso; für Alpine (NPMplus) schickt er die Paketliste, und der Homelab-Teil gleicht sie mit Alpines Sicherheitsdatenbank ab (im Hintergrund geladen, zwölf Stunden gemerkt, Alpine-Versionsvergleich). Die Update-Tabelle, die Kacheln und die Übersicht zeigen „· 3 Sicherheit“, die Rückfrage nennt es. Je Docker-Container steht, was Arcanes Lücken-Scan (Trivy, sonntags 02:00) im Image fand, kritische und hohe. Der Ausführer braucht ausfuehrer-einrichten.sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
995a0f34ee
commit
1c66daad0b
@@ -320,21 +320,54 @@ def _app_version(vmid: int, kennung: str) -> str | None:
|
||||
return m.group(1) if m else zeile[:40]
|
||||
|
||||
|
||||
# Sicherheitsupdates (seit 25.09.2026, Ausbauplan Welle 2, Punkt 11): Debian und Ubuntu liefern sie aus eigenen Suiten
|
||||
# („trixie-security“, „jammy-security“) — das steht in `apt list --upgradable` hinter dem Paketnamen. Alpine hat das
|
||||
# nicht; dort geht die Liste mit den Versionen mit, und der Homelab-Teil gleicht sie mit Alpines Sicherheitsdatenbank ab.
|
||||
APT_ZAEHLEN = ("LC_ALL=C apt list --upgradable 2>/dev/null"
|
||||
" | awk '/upgradable/{n++; if ($1 ~ /-security/) s++} END{print n+0; print s+0}'; "
|
||||
"stat -c %Y /var/lib/apt/lists 2>/dev/null || echo 0")
|
||||
APK_LISTE = ("cat /etc/alpine-release 2>/dev/null || echo ?; stat -c %Y /var/cache/apk 2>/dev/null || echo 0; "
|
||||
"apk version -l '<' 2>/dev/null | tail -n +2")
|
||||
_APK_ZEILE = re.compile(r"^(\S+?)-(\d\S*)\s+<\s+(\S+)$")
|
||||
|
||||
|
||||
def apk_auswerten(text: str) -> dict:
|
||||
"""Ausgabe von APK_LISTE → {"anzahl", "listen_stand", "alpine", "pakete": [{"name", "alt", "neu"}]}."""
|
||||
zeilen = text.splitlines()
|
||||
pakete = [{"name": m.group(1), "alt": m.group(2), "neu": m.group(3)}
|
||||
for z in zeilen[2:] if (m := _APK_ZEILE.match(z.strip()))]
|
||||
try:
|
||||
stand = int(zeilen[1].strip()) or None
|
||||
except (IndexError, ValueError):
|
||||
stand = None
|
||||
return {"anzahl": len(pakete), "listen_stand": stand, "alpine": zeilen[0].strip() if zeilen else None,
|
||||
"pakete": pakete[:300]}
|
||||
|
||||
|
||||
def _os_updates(vmid: int, ostype: str) -> dict:
|
||||
"""Aktualisierbare Pakete nach den vorhandenen Paketlisten (liest nur) und wie alt die Listen sind."""
|
||||
"""Aktualisierbare Pakete nach den vorhandenen Paketlisten (liest nur), wie alt die Listen sind und — seit
|
||||
25.09.2026 — wie viele davon Sicherheitsupdates sind (Alpine: die Liste für den Abgleich im Homelab-Teil)."""
|
||||
if ostype == "alpine":
|
||||
code, text = _im_gast(vmid, "apk version -l '<' 2>/dev/null | tail -n +2 | wc -l; "
|
||||
"stat -c %Y /var/cache/apk 2>/dev/null || echo 0", 30)
|
||||
else:
|
||||
code, text = _im_gast(vmid, "LC_ALL=C apt list --upgradable 2>/dev/null | grep -c upgradable; "
|
||||
"stat -c %Y /var/lib/apt/lists 2>/dev/null || echo 0", 30)
|
||||
code, text = _im_gast(vmid, APK_LISTE, 30)
|
||||
return apk_auswerten(text) if code in (0, 1) else {"anzahl": None, "listen_stand": None, "fehler": text[:160]}
|
||||
code, text = _im_gast(vmid, APT_ZAEHLEN, 30)
|
||||
zeilen = text.split() if code in (0, 1) else []
|
||||
try:
|
||||
return {"anzahl": int(zeilen[0]), "listen_stand": int(zeilen[1]) or None}
|
||||
return {"anzahl": int(zeilen[0]), "sicherheit": int(zeilen[1]), "listen_stand": int(zeilen[2]) or None}
|
||||
except (IndexError, ValueError):
|
||||
return {"anzahl": None, "listen_stand": None, "fehler": text[:160]}
|
||||
|
||||
|
||||
def sicherheit_auf_dem_host(apt_liste: str) -> list[str]:
|
||||
"""Die Pakete aus `apt list --upgradable`, die aus einer Sicherheits-Suite kommen."""
|
||||
namen = []
|
||||
for zeile in apt_liste.splitlines():
|
||||
kopf = zeile.split(" ", 1)[0]
|
||||
if "upgradable" in zeile and "/" in kopf and "-security" in kopf.split("/", 1)[1]:
|
||||
namen.append(kopf.split("/", 1)[0])
|
||||
return namen
|
||||
|
||||
|
||||
def _ip_lxc(vmid: int) -> str | None:
|
||||
try:
|
||||
for schnitt in _pvesh(f"/nodes/{NODE}/lxc/{vmid}/interfaces"):
|
||||
@@ -834,6 +867,9 @@ def _host() -> dict:
|
||||
host["version"] = _pvesh("/version").get("version")
|
||||
host["updates"] = [{"paket": p.get("Package"), "alt": p.get("OldVersion"), "neu": p.get("Version"),
|
||||
"herkunft": p.get("Origin")} for p in _pvesh(f"/nodes/{NODE}/apt/update")]
|
||||
code, liste = _laufen(["env", "LC_ALL=C", "apt", "list", "--upgradable"], 60)
|
||||
if code == 0:
|
||||
host["updates_sicherheit"] = sicherheit_auf_dem_host(liste)
|
||||
except Exception as exc:
|
||||
host["fehler"] = str(exc)[:200]
|
||||
code, kernel = _laufen(["uname", "-r"], 5)
|
||||
|
||||
Reference in New Issue
Block a user