Add hardering
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user