Add hardering

This commit is contained in:
Johnny
2026-04-06 08:37:54 +02:00
parent 4980d8cf3c
commit c0412d1150
27 changed files with 1527 additions and 82 deletions

View File

@@ -1,7 +1,10 @@
from __future__ import annotations
import json
import os
import re
import stat
import tempfile
from datetime import datetime
from pathlib import Path
@@ -195,8 +198,21 @@ def rootkit_check(context: ExecutionContext, task: TaskDefinition) -> TaskResult
report_path = context.paths.report_dir / f"{datetime.now().strftime('%Y%m%d-%H%M%S')}-rootkit-report.json"
context.runner.write_text_file(report_path, json.dumps(report_payload, indent=2) + "\n", mode=0o640, requires_root=False)
details.append(f"Rapport rootkits: {report_path}")
success = rkhunter_result.returncode == 0 and chkrootkit_result.returncode == 0
return context.make_result(task, success=success, changed=changed, started_at=started_at, details=details, error=None if success else "Vérification rootkit incomplète ou avec alertes")
# rkhunter: rc=0 clean, rc=1 warnings trouvés, rc=2+ erreur critique (outil n'a pas pu tourner)
rkhunter_ran = rkhunter_result.returncode <= 1
rkhunter_warnings = [line for line in rkhunter_result.stdout.splitlines() if line.startswith("Warning:")]
if rkhunter_warnings:
details.append(f"rkhunter: {len(rkhunter_warnings)} warning(s) à vérifier dans le rapport")
# chkrootkit: rc=0 signifie que l'outil a tourné (pas qu'il n'y a pas d'infection — les INFECTED sont dans stdout)
chkrootkit_ran = chkrootkit_result.returncode == 0
infected_lines = [line for line in chkrootkit_result.stdout.splitlines() if "INFECTED" in line]
if infected_lines:
details.append(f"chkrootkit: {len(infected_lines)} détection(s) à vérifier dans le rapport")
success = rkhunter_ran and chkrootkit_ran
error = None if success else "Les outils de vérification n'ont pas pu s'exécuter correctement"
return context.make_result(task, success=success, changed=changed, started_at=started_at, details=details, error=error)
def log_rotation(context: ExecutionContext, task: TaskDefinition) -> TaskResult:
@@ -434,7 +450,6 @@ def utilities_setup(context: ExecutionContext, task: TaskDefinition) -> TaskResu
context.runner.run(["cp", "-f", str(aide_db_new), "/var/lib/aide/aide.db"], requires_root=True, check=False)
details.append("Base AIDE mise à jour")
if context.runner.command_exists("systemctl"):
context.runner.run(["systemctl", "enable", "--now", "aidecheck.timer"], requires_root=True, check=False)
context.runner.run(["systemctl", "enable", "--now", "dailyaidecheck.timer"], requires_root=True, check=False)
details.append("Timers AIDE activés")
@@ -560,6 +575,83 @@ def docker_setup(context: ExecutionContext, task: TaskDefinition) -> TaskResult:
return _result(context, task, started_at, changed=changed, details=details)
def system_hardening(context: ExecutionContext, task: TaskDefinition) -> TaskResult:
started_at = datetime.now()
details: list[str] = []
script_content = asset_text("system_hardening.sh")
tmp_dir = context.paths.state_dir
tmp_dir.mkdir(parents=True, exist_ok=True)
script_path: Path | None = None
try:
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False, dir=tmp_dir, encoding="utf-8"
) as fh:
fh.write(script_content)
script_path = Path(fh.name)
current_mode = stat.S_IMODE(script_path.stat().st_mode)
script_path.chmod(current_mode | 0o111)
env = os.environ.copy()
env.update({
"AUTO_YES": "yes",
"AUTO_SSH_PORT": "22",
"AUTO_CHANGE_ROOT_PWD": "no",
"AUTO_DISABLE_ROOT_LOGIN": "no",
"AUTO_SKIP_LYNIS": "no",
"AUTO_ENABLE_FAIL2BAN": "yes",
"AUTO_ENABLE_UFW": "yes",
"AUTO_ENABLE_AIDE": "yes",
"AUTO_ENABLE_CLAMAV": "yes",
"AUTO_SKIP_PORTS_DETECTION": "no",
"DEBIAN_FRONTEND": "noninteractive",
})
result = context.runner.run(
["bash", str(script_path), "--unattended"],
requires_root=True,
check=False,
capture_output=True,
env=env,
)
ok_steps = [line for line in result.stdout.splitlines() if "[OK]" in line]
warn_steps = [line for line in result.stdout.splitlines() if "[WARN]" in line]
err_steps = [line for line in result.stdout.splitlines() if "[ERR]" in line]
details.append(f"{len(ok_steps)} étape(s) réussie(s)")
if warn_steps:
details.append(f"{len(warn_steps)} avertissement(s)")
if err_steps:
details.append(f"{len(err_steps)} erreur(s)")
for line in err_steps[:5]:
details.append(f" {line.strip()}")
score_line = next(
(line for line in result.stdout.splitlines() if "Score:" in line and "Lynis" in line),
None,
)
if score_line:
details.append(score_line.strip())
log_path = Path("/var/log/system_hardening.log")
if log_path.exists():
details.append(f"Log complet: {log_path}")
backup_path = next(Path("/root").glob("backup_hardening_*"), None) if Path("/root").exists() else None
if backup_path:
details.append(f"Sauvegardes: {backup_path}")
success = result.returncode == 0 and not err_steps
error = None if success else f"Le script s'est terminé avec le code {result.returncode}"
return context.make_result(task, success=success, changed=True, started_at=started_at, details=details, error=error)
finally:
if script_path and script_path.exists():
script_path.unlink(missing_ok=True)
def bind(task: TaskDefinition, func) -> TaskDefinition:
return TaskDefinition(
key=task.key,