Files
tessera-ctl/.planning/quick/261009-p0m-sicherheitsprotokoll-und-ci-sicherheitsp/checks/zap-testserver.py
T
schalli d62e6c2dbe
Tessera CI/CD / Lint & Type Check (push) Successful in 53s
Tessera CI/CD / Tests (push) Failing after 2m14s
Tessera CI/CD / Desktop-Pakete bauen (push) Has been skipped
Tessera CI/CD / Build & Publish Images (push) Has been skipped
Tessera CI/CD / Sicherheitspruefung (nur Bericht) (push) Has been skipped
docs(quick-261009-p0m): Sicherheitsprotokoll und CI-Pruefungen
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 21:07:46 +02:00

60 lines
2.2 KiB
Python

"""Kleiner Testserver fuer den lokalen Passivitaetsbeweis der ZAP-Grundpruefung.
Aufruf: python3 -I zap-testserver.py PORT LOGDATEI [require-auth]
/ verweist auf /login und /info, /login enthaelt ein POST-Formular mit Benutzer,
Passwort und Absende-Knopf. Jede Anfrage wird als "METHODE PFAD auth=ja|nein"
protokolliert. Mit require-auth beantwortet der Server jede Anfrage ohne
Authorization-Kopf mit 401. Nur Testwerte, keine echten Zugangsdaten.
"""
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
PORT = int(sys.argv[1])
LOG = sys.argv[2]
REQUIRE_AUTH = len(sys.argv) > 3 and sys.argv[3] == "require-auth"
PAGES = {
"/": '<html><body><a href="/login">Anmelden</a> <a href="/info">Info</a></body></html>',
"/login": (
'<html><body><form method="POST" action="/login">'
'<input type="text" name="user"><input type="password" name="password">'
'<input type="submit" value="Anmelden"></form></body></html>'
),
"/info": '<html><body><p>Info</p><a href="/">zurueck</a></body></html>',
}
class Handler(BaseHTTPRequestHandler):
def _log(self):
auth = "ja" if self.headers.get("Authorization") else "nein"
with open(LOG, "a", encoding="utf-8") as fh:
fh.write("%s %s auth=%s\n" % (self.command, self.path, auth))
return auth == "ja"
def _answer(self):
has_auth = self._log()
if REQUIRE_AUTH and not has_auth:
self.send_response(401)
self.send_header("WWW-Authenticate", 'Basic realm="test"')
self.send_header("Content-Length", "0")
self.end_headers()
return
body = PAGES.get(self.path.split("?")[0], "<html><body>nicht gefunden</body></html>")
code = 200 if self.path.split("?")[0] in PAGES else 404
data = body.encode("utf-8")
self.send_response(code)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
if self.command != "HEAD":
self.wfile.write(data)
do_GET = do_POST = do_HEAD = do_PUT = do_DELETE = do_OPTIONS = _answer
def log_message(self, *args):
pass
HTTPServer(("0.0.0.0", PORT), Handler).serve_forever()