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:
@@ -39,6 +39,9 @@ services:
|
|||||||
# Environment variables for the application
|
# Environment variables for the application
|
||||||
environment:
|
environment:
|
||||||
- DEV_MODE=true
|
- 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
|
# Application configuration
|
||||||
# - PORT=8080
|
# - PORT=8080
|
||||||
# - ENVIRONMENT=development
|
# - ENVIRONMENT=development
|
||||||
|
|||||||
+36
-1
@@ -2,7 +2,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.dcntrlized.org/Dcntrlized/KeepNote/db"
|
"git.dcntrlized.org/Dcntrlized/KeepNote/db"
|
||||||
@@ -13,6 +16,7 @@ import (
|
|||||||
"git.dcntrlized.org/Dcntrlized/KeepNote/middleware"
|
"git.dcntrlized.org/Dcntrlized/KeepNote/middleware"
|
||||||
"git.dcntrlized.org/dcntrlized/dcntrlized-auth/authclient"
|
"git.dcntrlized.org/dcntrlized/dcntrlized-auth/authclient"
|
||||||
"git.dcntrlized.org/dcntrlized/dcntrlized-auth/authproxy"
|
"git.dcntrlized.org/dcntrlized/dcntrlized-auth/authproxy"
|
||||||
|
"git.dcntrlized.org/dcntrlized/dcntrlized-auth/tlsutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -70,5 +74,36 @@ func main() {
|
|||||||
|
|
||||||
handler := middleware.LoggingMiddleware(middleware.CorsMiddleware(mux))
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user