Add report-only Lynis host audit
This commit is contained in:
parent
c8be38a213
commit
adb2b921ed
|
|
@ -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
10
jeannie
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue