Files
metacrypt/internal/server/server.go
Kyle Isom 5c5d7e184e Fix ECDH zeroization, add audit logging, and remediate high findings
- Fix #61: handleRotateKey and handleDeleteUser now zeroize stored
  privBytes instead of calling Bytes() (which returns a copy). New
  state populates privBytes; old references nil'd for GC.
- Add audit logging subsystem (internal/audit) with structured event
  recording for cryptographic operations.
- Add audit log engine spec (engines/auditlog.md).
- Add ValidateName checks across all engines for path traversal (#48).
- Update AUDIT.md: all High findings resolved (0 open).
- Add REMEDIATION.md with detailed remediation tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:04:39 -07:00

88 lines
2.2 KiB
Go

// Package server implements the HTTP server for Metacrypt.
package server
import (
"context"
"crypto/tls"
"fmt"
"log/slog"
"net/http"
"sync"
"time"
"github.com/go-chi/chi/v5"
"google.golang.org/grpc"
internacme "git.wntrmute.dev/kyle/metacrypt/internal/acme"
"git.wntrmute.dev/kyle/metacrypt/internal/audit"
"git.wntrmute.dev/kyle/metacrypt/internal/auth"
"git.wntrmute.dev/kyle/metacrypt/internal/config"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
"git.wntrmute.dev/kyle/metacrypt/internal/policy"
"git.wntrmute.dev/kyle/metacrypt/internal/seal"
)
// Server is the Metacrypt HTTP server.
type Server struct {
cfg *config.Config
seal *seal.Manager
auth *auth.Authenticator
policy *policy.Engine
engines *engine.Registry
audit *audit.Logger
httpSrv *http.Server
grpcSrv *grpc.Server
logger *slog.Logger
acmeHandlers map[string]*internacme.Handler
version string
acmeMu sync.Mutex
}
// New creates a new server.
func New(cfg *config.Config, sealMgr *seal.Manager, authenticator *auth.Authenticator,
policyEngine *policy.Engine, engineRegistry *engine.Registry, auditLog *audit.Logger, logger *slog.Logger, version string) *Server {
s := &Server{
cfg: cfg,
seal: sealMgr,
auth: authenticator,
policy: policyEngine,
engines: engineRegistry,
audit: auditLog,
logger: logger,
version: version,
}
return s
}
// Start starts the HTTPS server.
func (s *Server) Start() error {
r := chi.NewRouter()
r.Use(s.loggingMiddleware)
s.registerRoutes(r)
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS13,
}
s.httpSrv = &http.Server{
Addr: s.cfg.Server.ListenAddr,
Handler: r,
TLSConfig: tlsCfg,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
}
s.logger.Info("starting server", "addr", s.cfg.Server.ListenAddr)
err := s.httpSrv.ListenAndServeTLS(s.cfg.Server.TLSCert, s.cfg.Server.TLSKey)
if err != nil && err != http.ErrServerClosed {
return fmt.Errorf("server: %w", err)
}
return nil
}
// Shutdown gracefully shuts down the server.
func (s *Server) Shutdown(ctx context.Context) error {
return s.httpSrv.Shutdown(ctx)
}