M2 §2: require a CA-issued client cert on the HTTP listener (mTLS)

Serve the listener over TLS with ClientAuth=RequireAndVerifyClientCert
trusting the instance CA (shared tlsutil.ServerConfig): only Maestro can
drive actions (T4), and the peer edge is encrypted. INSECURE_INTERNAL=1
(dev debug compose) keeps the listener plaintext for the RN client's
direct mode and hot reload.
This commit is contained in:
2026-08-16 01:14:06 +01:00
parent 39b6c642be
commit 73c09132b3
2 changed files with 39 additions and 1 deletions
+3
View File
@@ -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
+36 -1
View File
@@ -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)
}