Add report-only Lynis host audit

This commit is contained in:
juvdiaz 2026-06-29 14:35:12 -06:00
parent c8be38a213
commit adb2b921ed
4 changed files with 100 additions and 2 deletions

View File

@ -142,6 +142,10 @@ baseline passive scans for targets in `security/targets.txt`.
`security-k8s`
: Run kube-bench CIS checks against the Debian kubeadm host.
`security-host`
: Run a Lynis host audit on Debian and print only warnings and suggestions.
This command is report-only.
`security-trivy`
: Run only Trivy filesystem and IaC/config scans.
@ -219,6 +223,10 @@ smoke test. Defaults to `cloudflare.com`.
`SECURITY_NUCLEI_TARGET`
: Optional single URL override for `security-nuclei`.
`lynis`
: `security-host` requires Lynis to be installed on the Debian host. Install it
explicitly with `sudo apt install lynis`.
`LAB_AUTO_APPROVE=false`
: Disable automatic OpenTofu approval for apply paths that support confirmation.
@ -328,6 +336,12 @@ Run a ZAP baseline scan against one URL:
SECURITY_ZAP_TARGET=https://lab2025.duckdns.org/ ./jeannie security-zap
```
Run a report-only Lynis host audit:
```sh
./jeannie security-host
```
Run the blocking pre-apply doctor directly:
```sh

10
jeannie
View File

@ -5780,6 +5780,11 @@ security_k8s() {
"${REPO_ROOT}/scripts/security-scan" kube-bench
}
security_host() {
require_debian_server "security-host"
"${REPO_ROOT}/scripts/security-scan" host
}
security_trivy() {
require_debian_server "security-trivy"
"${REPO_ROOT}/scripts/security-scan" trivy
@ -5903,6 +5908,9 @@ case "${1:-}" in
security-k8s)
security_k8s
;;
security-host)
security_host
;;
security-trivy)
security_trivy
;;
@ -5920,7 +5928,7 @@ case "${1:-}" in
echo "Log: ${JEANNIE_LOG_FILE}"
;;
*)
echo "Usage: $0 {up|plan [all|provisioning|cluster|platform|apps|edge]|rebuild-cluster|stop-cluster|start-cluster|status|apps|website-translation-model|website-ollama-listen|ollama-setup|deploy-gitea|rpi-services|bootstrap-gitea-repo|backup-gitea|drill-gitea-restore|install-gitea-runner|move-prometheus-stack-workers|doctor-versions|doctor-edge|doctor-gitea|doctor-rpi|doctor-cluster|preflight|doctor-preapply|inventory-check|state-backup|fix-debian-docker-root|secrets-init|secrets-check|tailnet-policy-check|ai-index|ai-check|security-scan|security-prepare|security-zap|security-k8s|security-trivy|security-nuclei|openwrt|nuke}"
echo "Usage: $0 {up|plan [all|provisioning|cluster|platform|apps|edge]|rebuild-cluster|stop-cluster|start-cluster|status|apps|website-translation-model|website-ollama-listen|ollama-setup|deploy-gitea|rpi-services|bootstrap-gitea-repo|backup-gitea|drill-gitea-restore|install-gitea-runner|move-prometheus-stack-workers|doctor-versions|doctor-edge|doctor-gitea|doctor-rpi|doctor-cluster|preflight|doctor-preapply|inventory-check|state-backup|fix-debian-docker-root|secrets-init|secrets-check|tailnet-policy-check|ai-index|ai-check|security-scan|security-prepare|security-zap|security-k8s|security-host|security-trivy|security-nuclei|openwrt|nuke}"
exit 1
;;
esac

View File

@ -12,7 +12,7 @@ NUCLEI_IMAGE="${NUCLEI_IMAGE:-projectdiscovery/nuclei:latest}"
usage() {
cat <<'EOF'
Usage: scripts/security-scan {all|prepare|trivy|zap|kube-bench|nuclei}
Usage: scripts/security-scan {all|prepare|trivy|zap|kube-bench|nuclei|host}
Environment:
SECURITY_REPORT_DIR Report output directory.
@ -182,6 +182,71 @@ run_kube_bench() {
"${KUBE_BENCH_IMAGE}" run --targets master,node | tee "${SECURITY_REPORT_DIR}/kube-bench-${stamp}.txt"
}
print_lynis_recommendations() {
local report_file="$1"
local warnings
local suggestions
local hardening_index
hardening_index="$(awk -F= '$1 == "hardening_index" { print $2; exit }' "${report_file}" 2>/dev/null || true)"
warnings="$(sed -n 's/^warning\[\]=//p' "${report_file}" 2>/dev/null | awk -F'|' '{ print $1 (NF > 1 ? " [" $NF "]" : "") }')"
suggestions="$(sed -n 's/^suggestion\[\]=//p' "${report_file}" 2>/dev/null | awk -F'|' '{ print $1 (NF > 1 ? " [" $NF "]" : "") }')"
printf '\n== Lynis Host Recommendations ==\n'
if [[ -n "${hardening_index}" ]]; then
printf 'Hardening index: %s\n' "${hardening_index}"
fi
printf '\n-- Warnings\n'
if [[ -n "${warnings}" ]]; then
printf '%s\n' "${warnings}" | sed 's/^/- /'
else
printf 'none\n'
fi
printf '\n-- Suggestions\n'
if [[ -n "${suggestions}" ]]; then
printf '%s\n' "${suggestions}" | sed 's/^/- /'
else
printf 'none\n'
fi
}
run_lynis_host() {
local stamp
local report_file
local log_file
stamp="$(timestamp)"
ensure_report_dir
report_file="${SECURITY_REPORT_DIR}/lynis-host-${stamp}.dat"
log_file="${SECURITY_REPORT_DIR}/lynis-host-${stamp}.log"
if ! command -v lynis >/dev/null 2>&1; then
cat >&2 <<'EOF'
lynis is not installed on this host.
Install it on Debian with:
sudo apt install lynis
Jeannie does not install Lynis automatically because host hardening audits should
remain explicit and report-only.
EOF
exit 1
fi
echo "Running Lynis host audit in report-only mode..."
sudo lynis audit system \
--no-colors \
--quiet \
--report-file "${report_file}" \
--log-file "${log_file}" >/dev/null
print_lynis_recommendations "${report_file}"
printf '\nFull Lynis report: %s\n' "${report_file}"
printf 'Full Lynis log: %s\n' "${log_file}"
}
case "${1:-all}" in
all)
run_trivy
@ -202,6 +267,9 @@ case "${1:-all}" in
kube-bench)
run_kube_bench
;;
host)
run_lynis_host
;;
-h | --help | help)
usage
;;

View File

@ -10,6 +10,7 @@ Use Jeannie from the Debian homelab host:
./jeannie security-scan
./jeannie security-zap
./jeannie security-k8s
./jeannie security-host
```
The default `security-scan` runs:
@ -23,6 +24,8 @@ The focused commands are:
images.
- `security-zap`: OWASP ZAP baseline scan only.
- `security-k8s`: kube-bench CIS checks against the kubeadm host.
- `security-host`: Lynis host audit summary for Debian. This command is
report-only and prints warnings/suggestions.
- `security-trivy`: Trivy repo and IaC/config scans only.
- `security-nuclei`: low-rate nuclei HTTP exposure scans only.
@ -38,3 +41,8 @@ understand the traffic it will generate.
`security/targets.txt` is the public target allowlist. Keep it limited to
services you own.
`security-host` intentionally does not self-fix Lynis findings. Some hardening
recommendations can break SSH access, Docker networking, kubeadm, or public edge
routing. Use Lynis output to choose one narrow remediation at a time, then add an
explicit Jeannie command for that specific change.