79 lines
3.0 KiB
Python
79 lines
3.0 KiB
Python
"""YakPanel - read-only security checklist (local server probes)."""
|
|
import os
|
|
import re
|
|
|
|
from fastapi import APIRouter, Depends
|
|
|
|
from app.api.auth import get_current_user
|
|
from app.models.user import User
|
|
from app.core.utils import read_file, exec_shell_sync
|
|
|
|
router = APIRouter(prefix="/security", tags=["security"])
|
|
|
|
|
|
@router.get("/checklist")
|
|
async def security_checklist(current_user: User = Depends(get_current_user)):
|
|
"""Non-destructive hints: SSH config, firewall helper, fail2ban. Not a full audit."""
|
|
items: list[dict] = []
|
|
sshd = "/etc/ssh/sshd_config"
|
|
body = read_file(sshd) if os.path.isfile(sshd) else None
|
|
if isinstance(body, str) and body:
|
|
if re.search(r"^\s*PasswordAuthentication\s+no\s*$", body, re.MULTILINE | re.IGNORECASE):
|
|
items.append({
|
|
"id": "ssh_password_auth",
|
|
"ok": True,
|
|
"title": "SSH password auth",
|
|
"detail": "PasswordAuthentication appears set to no (prefer key-based login).",
|
|
})
|
|
elif re.search(r"^\s*PasswordAuthentication\s+yes", body, re.MULTILINE | re.IGNORECASE):
|
|
items.append({
|
|
"id": "ssh_password_auth",
|
|
"ok": False,
|
|
"title": "SSH password auth",
|
|
"detail": "PasswordAuthentication is yes — consider disabling and using SSH keys.",
|
|
})
|
|
else:
|
|
items.append({
|
|
"id": "ssh_password_auth",
|
|
"ok": None,
|
|
"title": "SSH password auth",
|
|
"detail": "Could not find an explicit PasswordAuthentication line (defaults depend on distro).",
|
|
})
|
|
else:
|
|
items.append({
|
|
"id": "ssh_password_auth",
|
|
"ok": None,
|
|
"title": "SSH password auth",
|
|
"detail": "/etc/ssh/sshd_config not readable from the panel process.",
|
|
})
|
|
|
|
ufw_out, _ = exec_shell_sync("ufw status 2>/dev/null", timeout=5)
|
|
ufw = ufw_out or ""
|
|
if "Status: active" in ufw:
|
|
items.append({"id": "ufw", "ok": True, "title": "UFW firewall", "detail": "UFW reports active."})
|
|
elif "Status: inactive" in ufw:
|
|
items.append({
|
|
"id": "ufw",
|
|
"ok": None,
|
|
"title": "UFW firewall",
|
|
"detail": "UFW installed but inactive — enable if this host is public.",
|
|
})
|
|
else:
|
|
items.append({
|
|
"id": "ufw",
|
|
"ok": None,
|
|
"title": "UFW firewall",
|
|
"detail": "UFW not detected (OK if you use firewalld/iptables only).",
|
|
})
|
|
|
|
f2_out, _ = exec_shell_sync("systemctl is-active fail2ban 2>/dev/null", timeout=5)
|
|
f2_active = (f2_out or "").strip() == "active"
|
|
items.append({
|
|
"id": "fail2ban",
|
|
"ok": f2_active,
|
|
"title": "fail2ban",
|
|
"detail": "fail2ban is active." if f2_active else "fail2ban not active (optional hardening).",
|
|
})
|
|
|
|
return {"items": items, "disclaimer": "YakPanel reads local settings only; this is not a compliance scan."}
|