diff --git a/cmd/secheaders-devserver/main.go b/cmd/secheaders-devserver/main.go new file mode 100644 index 0000000..bb699a6 --- /dev/null +++ b/cmd/secheaders-devserver/main.go @@ -0,0 +1,40 @@ +// secheaders-devserver dient der manuellen/e2e-Verifikation von API-08 +// (Pruefung 2: CSP blockiert Inline-Script) mit einem echten Browser. +// Zwei Pfade: /protected (mit Middleware) und /unprotected (ohne) — beide +// liefern dieselbe Seite mit einem Inline-Script, das ein DOM-Element +// aendert. Ein echter Browser zeigt den Unterschied. +package main + +import ( + "log" + "net/http" + + "gitea.perlbach24.de/scripte/nexarch/internal/secheaders" +) + +const page = ` + +
BLOCKED
+ +` + +func servePage(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html; charset=utf-8") + _, _ = w.Write([]byte(page)) +} + +func main() { + cfg := secheaders.DefaultConfig() + mux := http.NewServeMux() + // SetHeaders statt Middleware: dieser lokale Demo-Server laeuft ohne + // TLS-Terminierung, der HTTPS-Redirect-Teil von Middleware wuerde hier + // in eine Endlosschleife fuehren (siehe secheaders.go-Dokumentation). + mux.HandleFunc("/protected", func(w http.ResponseWriter, r *http.Request) { + secheaders.SetHeaders(cfg, w) + servePage(w, r) + }) + mux.HandleFunc("/unprotected", servePage) + + log.Println("secheaders-devserver listening on :8086") + log.Fatal(http.ListenAndServe(":8086", mux)) +} diff --git a/internal/secheaders/secheaders.go b/internal/secheaders/secheaders.go index 4d91fb4..a15ebfd 100644 --- a/internal/secheaders/secheaders.go +++ b/internal/secheaders/secheaders.go @@ -83,18 +83,25 @@ func Middleware(cfg Config, next http.HandlerFunc) http.HandlerFunc { return } - w.Header().Set("Content-Security-Policy", cfg.ContentSecurityPolicy) - w.Header().Set("Strict-Transport-Security", cfg.hstsValue()) - w.Header().Set("X-Frame-Options", cfg.FrameOptions) - w.Header().Set("Referrer-Policy", cfg.ReferrerPolicy) - if cfg.ContentTypeNoSniff { - w.Header().Set("X-Content-Type-Options", "nosniff") - } - + SetHeaders(cfg, w) next(w, r) } } +// SetHeaders setzt die Baseline-Header direkt, OHNE die HTTPS-Redirect- +// Pruefung von Middleware — nuetzlich fuer lokale Entwicklungs-/ +// Demo-Umgebungen ohne TLS-Terminierung (siehe cmd/secheaders-devserver) +// und fuer Aufrufer, die den Redirect selbst schon anderweitig sicherstellen. +func SetHeaders(cfg Config, w http.ResponseWriter) { + w.Header().Set("Content-Security-Policy", cfg.ContentSecurityPolicy) + w.Header().Set("Strict-Transport-Security", cfg.hstsValue()) + w.Header().Set("X-Frame-Options", cfg.FrameOptions) + w.Header().Set("Referrer-Policy", cfg.ReferrerPolicy) + if cfg.ContentTypeNoSniff { + w.Header().Set("X-Content-Type-Options", "nosniff") + } +} + // isSecure erkennt TLS direkt ODER ueber den ueblichen Reverse-Proxy-Header // (X-Forwarded-Proto) — der Core-Dienst laeuft in der Praxis hinter einem // TLS-terminierenden Proxy, sieht r.TLS also nie direkt gesetzt.