diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index e479dd1..695f646 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -10,19 +10,24 @@ unbefugte Manipulationen. Der Scanner läuft lokal im Verantwortungsbereich des Sie brauchen kein IT-Wissen. Das Programm zeigt eine **Ampel** und erklärt alles in einfachen Worten. -**Schritt 1 — Erststand speichern** (einmalig, wenn die Website in Ordnung ist): +**Schritt 1 — Ersten Scan durchführen** (Scanner legt das Zielverzeichnis automatisch an): ``` -python -m scanner approve --all --note "Erststand geprüft" +python -m scanner https://ihre-website.de init ``` -**Schritt 2 — täglich prüfen** (am besten automatisch per Cron, siehe Abschnitt 10): +**Schritt 2 — Erststand speichern** (einmalig, wenn die Website in Ordnung ist): ``` -python -m scanner scan +python -m scanner https://ihre-website.de approve --all --note "Erststand geprüft" ``` -**Schritt 3 — bei 🟡 oder 🔴 nachschauen:** +**Schritt 3 — täglich prüfen** (am besten automatisch per Cron, siehe Abschnitt 10): ``` -python -m scanner report +python -m scanner https://ihre-website.de scan +``` + +**Bei 🟡 oder 🔴 nachschauen:** +``` +python -m scanner https://ihre-website.de report ``` Was die Ampel bedeutet: @@ -105,29 +110,37 @@ source venv/bin/activate pip install -r requirements.txt ``` -Alle Befehle müssen aus dem Projektverzeichnis ausgeführt werden (dort liegt `config.yaml`). +Alle Befehle müssen aus dem Projektverzeichnis ausgeführt werden. --- ## 3. Erstinbetriebnahme +Die URL-Syntax legt das Zielverzeichnis beim ersten Aufruf **automatisch** an — +kein manuelles Anlegen von Verzeichnissen oder Konfigurieren von Pfaden nötig. + ### Schritt 1: Ersten Crawl durchführen ```bash -python -m scanner init +python -m scanner https://ihre-website.de init ``` +Der Scanner legt beim ersten Aufruf automatisch `ihre-website.de/` mit einer +angepassten `config.yaml` an und beginnt sofort mit dem Crawl. + Die Ausgabe zeigt: - alle gefundenen internen URLs - alle externen Domains (mit Hinweis, ob in der Whitelist) - potenzielle Auffälligkeiten (Hidden Content, Meta-Refresh, verdächtige Scripts) - Crawl-Fehler (Seiten, die nicht erreichbar waren) +Außerdem erscheint ein Hinweis, welche Zeilen in `.gitignore` noch einzutragen sind. + ### Schritt 2: Ausgabe manuell prüfen Wichtig vor dem nächsten Schritt: -- Alle externen Domains prüfen. Legitime Domains in `config/allowed_external.yaml` eintragen - (siehe [Abschnitt 13](#13-externe-domains-verwalten)). +- Alle externen Domains prüfen. Legitime Domains in `ihre-website.de/config/allowed_external.yaml` + eintragen (siehe [Abschnitt 13](#13-externe-domains-verwalten)). - Auffälligkeiten im Browser nachschauen. ### Schritt 3: Baseline freigeben @@ -135,7 +148,7 @@ Wichtig vor dem nächsten Schritt: Nur wenn alles sauber ist: ```bash -python -m scanner approve --all --note "Initiale Baseline, geprüft am $(date +%Y-%m-%d)" +python -m scanner https://ihre-website.de approve --all --note "Initiale Baseline, geprüft am $(date +%Y-%m-%d)" ``` Ab jetzt ist der tägliche Betrieb möglich. diff --git a/README.md b/README.md index a6603d6..7a0ae6c 100644 --- a/README.md +++ b/README.md @@ -21,16 +21,21 @@ pip install -r requirements.txt ``` ```bash -# Schritt 1: Wenn Ihre Website gerade in Ordnung ist, speichern Sie diesen Zustand: -python -m scanner approve --all --note "Erststand, Website geprüft" +# Schritt 1: Erste Prüfung — Scanner legt das Zielverzeichnis automatisch an: +python -m scanner https://ihre-website.de init -# Schritt 2: Ab jetzt täglich prüfen (am besten automatisch, siehe unten): -python -m scanner scan +# Schritt 2: Wenn die Website in Ordnung ist, Zustand als Referenz speichern: +python -m scanner https://ihre-website.de approve --all --note "Erststand geprüft" -# Schritt 3: Bei Gelb/Rot den Bericht ansehen: -python -m scanner report +# Schritt 3: Ab jetzt täglich prüfen (am besten automatisch, siehe unten): +python -m scanner https://ihre-website.de scan + +# Bei Gelb/Rot den Bericht ansehen: +python -m scanner https://ihre-website.de report ``` +Das Verzeichnis `ihre-website.de/` wird beim ersten Aufruf automatisch angelegt. + **Gut zu wissen:** Die selteneren Prüfungen (Tarnung, externe Links, Dateien) laufen **automatisch einmal pro Woche** beim täglichen `scan` mit. Sie brauchen dafür **nichts** extra einzurichten — ein täglicher Aufruf genügt für alles. diff --git a/scanner.sh b/scanner.sh new file mode 100755 index 0000000..ba40fec --- /dev/null +++ b/scanner.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Wrapper-Script für den integrity-scanner. +# Wechselt ins Projektverzeichnis und ruft python -m scanner auf. +# Verwendung: ./scanner.sh https://domain.de scan +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" +exec python -m scanner "$@" diff --git a/scanner/__main__.py b/scanner/__main__.py index 327f09a..dacc767 100644 --- a/scanner/__main__.py +++ b/scanner/__main__.py @@ -2,7 +2,8 @@ integrity-scanner — CLI entry point. Usage: - python -m scanner [options] + python -m scanner [options] + python -m scanner --config /config.yaml [options] Subcommands: init First-time crawl + baseline setup workflow @@ -16,6 +17,8 @@ Subcommands: import argparse import json import logging +import re +import shutil import sys from datetime import datetime, timezone from pathlib import Path @@ -1327,9 +1330,66 @@ def _build_parser() -> argparse.ArgumentParser: # Main # --------------------------------------------------------------------------- +def _auto_setup(url: str, domain: str) -> None: + """Create a new target directory from the meine-seite.de template.""" + project_root = Path(__file__).parent.parent + template_dir = project_root / "meine-seite.de" + target_dir = project_root / domain + + if not template_dir.exists(): + print( + f"[scanner] Fehler: Template-Verzeichnis '{template_dir}' nicht gefunden.\n" + f"[scanner] Bitte sicherstellen, dass 'meine-seite.de/' im Projektverzeichnis existiert.", + file=sys.stderr, + ) + sys.exit(1) + + target_dir.mkdir(parents=True, exist_ok=True) + + config_dst = target_dir / "config.yaml" + if not config_dst.exists(): + content = (template_dir / "config.yaml").read_text(encoding="utf-8") + # Absolute Pfade anpassen + content = content.replace( + str(project_root / "meine-seite.de"), + str(project_root / domain), + ) + # URL und Domain ersetzen + content = content.replace("https://meine-seite.de", url.rstrip("/")) + content = content.replace("meine-seite.de", domain) + config_dst.write_text(content, encoding="utf-8") + + config_src_dir = template_dir / "config" + config_dst_dir = target_dir / "config" + if config_src_dir.exists() and not config_dst_dir.exists(): + shutil.copytree(config_src_dir, config_dst_dir) + + print(f"[scanner] Neues Target angelegt: {target_dir}") + print(f"[scanner] Bitte .gitignore ergänzen:") + print(f"[scanner] {domain}/data/") + print(f"[scanner] {domain}/reports/") + print(f"[scanner] {domain}/logs/") + print() + + def main() -> None: + argv = list(sys.argv[1:]) + + # URL-first syntax: scanner https://domain.de scan [options] + if argv and re.match(r"https?://", argv[0]): + url = argv.pop(0) + domain = urlparse(url).netloc + if not domain: + print(f"[scanner] Fehler: Ungültige URL: {url}", file=sys.stderr) + sys.exit(1) + + if not Path(domain).exists(): + _auto_setup(url, domain) + + argv = ["--config", str(Path(domain) / "config.yaml")] + argv + parser = _build_parser() - args = parser.parse_args() + args = parser.parse_args(argv) cfg = load_config(args.config) base_dir = Path(args.config).parent.resolve()