release 1.8.0: simplified mon pages + surface nmap + mail hosts
Public layout: only taler-monitoring-surface(+_err) for ecosystem software/versions; nine landing stacks keep /monitoring(+_err). Fold mail (firefly.gnunet.org, anastasis.taler-systems.com) and mattermost into the surface job; deprecate separate mon pages/timers. nmap OS fingerprinting; package-behind defaults to ERROR.
This commit is contained in:
parent
2b846dab7a
commit
e7a3cd558f
15 changed files with 263 additions and 154 deletions
112
check_surface.sh
112
check_surface.sh
|
|
@ -32,6 +32,10 @@ PORT_TIMEOUT="${SURFACE_PORT_TIMEOUT:-2}"
|
|||
HTTP_TIMEOUT="${SURFACE_HTTP_TIMEOUT:-12}"
|
||||
# CVE via OSV (public, no key). Disable: SURFACE_CVE=0
|
||||
: "${SURFACE_CVE:=1}"
|
||||
# nmap OS / service fingerprint (v1.8.0+). Disable: SURFACE_NMAP=0
|
||||
: "${SURFACE_NMAP:=1}"
|
||||
# OS detection (-O) often needs root; falls back to -sV when denied
|
||||
: "${SURFACE_NMAP_OS:=1}"
|
||||
# Extra ports when -d domain mode
|
||||
DOMAIN_EXTRA_PORTS="${SURFACE_DOMAIN_PORTS:-22,80,443,8443}"
|
||||
|
||||
|
|
@ -496,6 +500,109 @@ cert_expiry_check() {
|
|||
return 0
|
||||
}
|
||||
|
||||
# nmap OS / service fingerprint (v1.8.0+).
|
||||
# ERROR when fingerprint indicates an OS that is EOL / should be upgraded.
|
||||
# Soft/info when nmap missing or unprivileged OS scan fails.
|
||||
nmap_fingerprint_host() {
|
||||
local h="$1"
|
||||
local xml out osline accuracy eol=0
|
||||
[ "${SURFACE_NMAP:-1}" = "1" ] || return 0
|
||||
if ! command -v nmap >/dev/null 2>&1; then
|
||||
warn "nmap" "$h · nmap not installed (apt install nmap) — skip OS fingerprint"
|
||||
return 0
|
||||
fi
|
||||
xml=$(mktemp)
|
||||
out=$(mktemp)
|
||||
# Prefer OS detection when allowed; always try service version light
|
||||
if [ "${SURFACE_NMAP_OS:-1}" = "1" ] && {
|
||||
nmap -Pn -n -T4 -O --osscan-guess --max-os-tries 1 --host-timeout 45s \
|
||||
-p 22,80,443,25,465,587,993 "$h" -oX "$xml" >"$out" 2>&1
|
||||
}; then
|
||||
:
|
||||
else
|
||||
nmap -Pn -n -T4 -sV --version-light --host-timeout 35s \
|
||||
-p 22,80,443,25,465,587,993 "$h" -oX "$xml" >"$out" 2>&1 || true
|
||||
fi
|
||||
# Parse best OS match from XML
|
||||
osline=$(
|
||||
python3 - "$xml" <<'PY' 2>/dev/null || true
|
||||
import sys, xml.etree.ElementTree as ET
|
||||
path = sys.argv[1]
|
||||
try:
|
||||
root = ET.parse(path).getroot()
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
best = None
|
||||
best_acc = -1
|
||||
for osm in root.findall(".//osmatch"):
|
||||
name = osm.get("name") or ""
|
||||
try:
|
||||
acc = int(osm.get("accuracy") or "0")
|
||||
except ValueError:
|
||||
acc = 0
|
||||
if name and acc >= best_acc:
|
||||
best_acc = acc
|
||||
best = name
|
||||
if best:
|
||||
print(f"{best_acc}|{best}")
|
||||
# also surface product/version from service table
|
||||
svcs = []
|
||||
for port in root.findall(".//port"):
|
||||
state = (port.find("state").get("state") if port.find("state") is not None else "")
|
||||
if state != "open":
|
||||
continue
|
||||
svc = port.find("service")
|
||||
if svc is None:
|
||||
continue
|
||||
prod = svc.get("product") or svc.get("name") or ""
|
||||
ver = svc.get("version") or ""
|
||||
if prod:
|
||||
svcs.append(f"{prod} {ver}".strip())
|
||||
if svcs:
|
||||
print("SVC|" + "; ".join(svcs[:8]))
|
||||
PY
|
||||
)
|
||||
rm -f "$xml" "$out"
|
||||
if [ -z "$osline" ]; then
|
||||
info "nmap" "$h · no OS/service fingerprint (need root for -O, or host filtered)"
|
||||
return 0
|
||||
fi
|
||||
local osname="" svcinfo=""
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
SVC\|*) svcinfo=${line#SVC|} ;;
|
||||
*\|*)
|
||||
accuracy=${line%%|*}
|
||||
osname=${line#*|}
|
||||
ok "nmap-os" "$h · OS guess ${accuracy}% · $osname"
|
||||
;;
|
||||
esac
|
||||
done <<<"$osline"
|
||||
[ -n "$svcinfo" ] && info "nmap-svc" "$h · $svcinfo"
|
||||
|
||||
# EOL / upgrade-required OS fingerprints → ERROR
|
||||
case "$(printf '%s' "$osname" | tr 'A-Z' 'a-z')" in
|
||||
*debian*6*|*debian*7*|*debian*8*|*debian*9*|*debian*10*|*debian*\"buster\"*|*debian*buster*)
|
||||
eol=1 ;;
|
||||
*ubuntu*12.04*|*ubuntu*14.04*|*ubuntu*16.04*|*ubuntu*18.04*|*ubuntu*20.04*)
|
||||
eol=1 ;;
|
||||
*centos*[5-7]*|*red\ hat\ enterprise*5*|*red\ hat\ enterprise*6*|*red\ hat\ enterprise*7*)
|
||||
eol=1 ;;
|
||||
*windows\ server\ 2008*|*windows\ server\ 2012*|*windows\ xp*|*windows\ 7*)
|
||||
eol=1 ;;
|
||||
*freebsd\ 1[0-2]*|*freebsd\ [0-9].*)
|
||||
eol=1 ;;
|
||||
esac
|
||||
if [ "$eol" = "1" ]; then
|
||||
err "nmap-upgrade" "$h OS fingerprint indicates EOL / upgrade required" "$osname"
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$osname" ]; then
|
||||
info "nmap-upgrade" "$h OS fingerprint not on EOL list · $osname"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
scan_host() {
|
||||
local h="$1"
|
||||
local ports proto label expect
|
||||
|
|
@ -621,6 +728,9 @@ scan_host() {
|
|||
fi
|
||||
fi
|
||||
|
||||
# nmap OS / service fingerprint (v1.8.0+) — ERROR on EOL OS
|
||||
nmap_fingerprint_host "$h" || true
|
||||
|
||||
# Expected service must answer protocol (not just ping/port)
|
||||
# Note: ${array[*]:-x} is NOT valid default syntax (bash treats : as slice).
|
||||
local ports_txt="${open_ports[*]}"
|
||||
|
|
@ -667,7 +777,7 @@ else
|
|||
fi
|
||||
|
||||
info "inventory" "${#ORDERED_HOSTS[@]} hosts to probe (remote only · no SSH · no local podman on targets)"
|
||||
info "flags" "SURFACE_CVE=${SURFACE_CVE:-1} PORT_TIMEOUT=${PORT_TIMEOUT:-2} HTTP_TIMEOUT=${HTTP_TIMEOUT:-12}"
|
||||
info "flags" "SURFACE_CVE=${SURFACE_CVE:-1} SURFACE_NMAP=${SURFACE_NMAP:-1} SURFACE_NMAP_OS=${SURFACE_NMAP_OS:-1} PORT_TIMEOUT=${PORT_TIMEOUT:-2} HTTP_TIMEOUT=${HTTP_TIMEOUT:-12}"
|
||||
|
||||
for h in "${ORDERED_HOSTS[@]}"; do
|
||||
[ -n "$h" ] || continue
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue