feat: URL-first CLI + auto-setup for new targets
- python -m scanner https://domain.de scan (URL as first positional arg) - On first use, the domain directory is auto-created from the meine-seite.de template with all paths and target URL substituted - scanner.sh wrapper script for convenient ./scanner.sh usage - --config syntax fully preserved (cron jobs unchanged) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
08566c7807
commit
fcbccce422
4 changed files with 104 additions and 19 deletions
|
|
@ -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.
|
||||
|
|
|
|||
17
README.md
17
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.
|
||||
|
|
|
|||
7
scanner.sh
Executable file
7
scanner.sh
Executable file
|
|
@ -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 "$@"
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
integrity-scanner — CLI entry point.
|
||||
|
||||
Usage:
|
||||
python -m scanner <subcommand> [options]
|
||||
python -m scanner <URL> <subcommand> [options]
|
||||
python -m scanner --config <site>/config.yaml <subcommand> [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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue