diff --git a/docker-compose.debug.yaml b/docker-compose.debug.yaml index 5285275..b97eae6 100644 --- a/docker-compose.debug.yaml +++ b/docker-compose.debug.yaml @@ -39,6 +39,9 @@ services: # Environment variables for the application environment: - DEV_MODE=true + # Security theme M2 §2: dev escape hatch — keep the listener plaintext + # so the RN client (direct mode) and hot reload work without certs. + - INSECURE_INTERNAL=1 # Application configuration # - PORT=8080 # - ENVIRONMENT=development diff --git a/src/main.go b/src/main.go index b235c96..cb27ffc 100644 --- a/src/main.go +++ b/src/main.go @@ -2,7 +2,10 @@ package main import ( "context" + "crypto/tls" + "net" "net/http" + "os" "strings" "git.dcntrlized.org/Dcntrlized/KeepNote/db" @@ -13,6 +16,7 @@ import ( "git.dcntrlized.org/Dcntrlized/KeepNote/middleware" "git.dcntrlized.org/dcntrlized/dcntrlized-auth/authclient" "git.dcntrlized.org/dcntrlized/dcntrlized-auth/authproxy" + "git.dcntrlized.org/dcntrlized/dcntrlized-auth/tlsutil" ) func main() { @@ -70,5 +74,36 @@ func main() { handler := middleware.LoggingMiddleware(middleware.CorsMiddleware(mux)) - http.ListenAndServe(":8080", handler) + // Security theme M2 §2: the service's listener requires a CA-issued client + // cert (Maestro's identity) so only Maestro can drive actions (T4) and the + // peer edge is encrypted. INSECURE_INTERNAL=1 keeps the dev fleet plaintext. + tlsCfg, err := tlsutil.ServerConfig() + if err != nil { + logger.Error("TLS setup failed: %v", err) + os.Exit(1) + } + if tlsCfg == nil { + logger.Info("KeepNote listening plaintext on :8080 (INSECURE_INTERNAL dev mode)") + if err := http.ListenAndServe(":8080", handler); err != nil { + logger.Error("HTTP server failed: %v", err) + os.Exit(1) + } + return + } + + logger.Info("KeepNote listening on :8080 (mTLS, ClientAuth=RequireAndVerify)") + if err := serveTLS(":8080", tlsCfg, handler); err != nil { + logger.Error("HTTPS server failed: %v", err) + os.Exit(1) + } +} + +// serveTLS runs an HTTPS listener with the given mTLS config. +func serveTLS(addr string, cfg *tls.Config, handler http.Handler) error { + ln, err := net.Listen("tcp", addr) + if err != nil { + return err + } + tlsLn := tls.NewListener(ln, cfg) + return http.Serve(tlsLn, handler) }