104 lines
3.3 KiB
Bash
Executable File
104 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
HOMELAB_STATE_DIR="${HOMELAB_STATE_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/homelab}"
|
|
SECURITY_REPORT_DIR="${SECURITY_REPORT_DIR:-${HOMELAB_STATE_DIR}/security-reports}"
|
|
SECURITY_LOG_SINCE="${SECURITY_LOG_SINCE:-24h}"
|
|
GITEA_CONTAINER="${GITEA_CONTAINER:-${LAB_GITEA_CONTAINER_NAME:-homelab-gitea}}"
|
|
KUBECONFIG="${KUBECONFIG:-${HOME}/.kube/config}"
|
|
|
|
timestamp() {
|
|
date -u +%Y%m%dT%H%M%SZ
|
|
}
|
|
|
|
ensure_report_dir() {
|
|
mkdir -p "${SECURITY_REPORT_DIR}"
|
|
}
|
|
|
|
print_matches() {
|
|
local title="$1"
|
|
local log_file="$2"
|
|
local pattern="$3"
|
|
local limit="${4:-20}"
|
|
|
|
printf '\n== %s ==\n' "${title}"
|
|
if [[ ! -s "${log_file}" ]]; then
|
|
printf 'no log input\n'
|
|
return 0
|
|
fi
|
|
|
|
if grep -Eai "${pattern}" "${log_file}" >/dev/null; then
|
|
grep -Eai "${pattern}" "${log_file}" | tail -n "${limit}"
|
|
else
|
|
printf 'none\n'
|
|
fi
|
|
}
|
|
|
|
collect_gitea_logs() {
|
|
local output_file="$1"
|
|
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
if ! docker ps --format '{{.Names}}' | grep -Fxq "${GITEA_CONTAINER}"; then
|
|
return 0
|
|
fi
|
|
|
|
docker logs --since "${SECURITY_LOG_SINCE}" "${GITEA_CONTAINER}" >"${output_file}" 2>&1 || true
|
|
}
|
|
|
|
collect_traefik_logs() {
|
|
local output_file="$1"
|
|
|
|
if ! command -v kubectl >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
if [[ ! -f "${KUBECONFIG}" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
kubectl --kubeconfig "${KUBECONFIG}" -n traefik logs \
|
|
-l app.kubernetes.io/name=traefik \
|
|
--since="${SECURITY_LOG_SINCE}" \
|
|
--tail="${SECURITY_LOG_TAIL:-5000}" >"${output_file}" 2>&1 || true
|
|
}
|
|
|
|
main() {
|
|
local stamp
|
|
local gitea_log
|
|
local traefik_log
|
|
local report_file
|
|
local suspicious_paths
|
|
local suspicious_agents
|
|
|
|
stamp="$(timestamp)"
|
|
ensure_report_dir
|
|
gitea_log="${SECURITY_REPORT_DIR}/security-gitea-logs-${stamp}.txt"
|
|
traefik_log="${SECURITY_REPORT_DIR}/security-traefik-logs-${stamp}.txt"
|
|
report_file="${SECURITY_REPORT_DIR}/security-logs-${stamp}.txt"
|
|
suspicious_paths='/(wp-admin|wp-login|xmlrpc\.php|\.env|\.git|vendor/phpunit|cgi-bin|boaform|solr|actuator|server-status)|\.\./|%2e%2e|/etc/passwd|/proc/self/environ'
|
|
suspicious_agents='nikto|sqlmap|nuclei|masscan|zgrab|gobuster|dirbuster|dirsearch|wpscan|acunetix|nessus|openvas|curl/[0-9]|python-requests|Go-http-client'
|
|
|
|
collect_gitea_logs "${gitea_log}"
|
|
collect_traefik_logs "${traefik_log}"
|
|
|
|
{
|
|
echo "Homelab security log summary"
|
|
echo "Generated: ${stamp}"
|
|
echo "Window: ${SECURITY_LOG_SINCE}"
|
|
echo
|
|
print_matches "Gitea auth or permission failures" "${gitea_log}" 'authentication failed|invalid credentials|denied|forbidden|unauthorized|failed login|401|403'
|
|
print_matches "Gitea suspicious repo/path activity" "${gitea_log}" "${suspicious_paths}"
|
|
print_matches "Traefik suspicious paths" "${traefik_log}" "${suspicious_paths}"
|
|
print_matches "Traefik suspicious user agents" "${traefik_log}" "${suspicious_agents}"
|
|
print_matches "Traefik client/server errors" "${traefik_log}" ' 4[0-9][0-9] | 5[0-9][0-9] |level=error|level=warn'
|
|
echo
|
|
echo "Raw Gitea log sample: ${gitea_log}"
|
|
echo "Raw Traefik log sample: ${traefik_log}"
|
|
} | tee "${report_file}"
|
|
|
|
echo "Security log report: ${report_file}"
|
|
}
|
|
|
|
main "$@"
|