mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 19:41:30 +00:00
Merge branch 'fix/m2-pr-f-scheduler-contextcheck-audit-closeout'
This commit is contained in:
@@ -6,6 +6,7 @@ run:
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- contextcheck
|
||||
- govet
|
||||
- staticcheck
|
||||
- unused
|
||||
|
||||
@@ -132,6 +132,15 @@ func (a *AuditMiddleware) Middleware(next http.Handler) http.Handler {
|
||||
path := r.URL.Path
|
||||
status := wrapped.statusCode
|
||||
|
||||
// Derive a detached context that preserves request-scoped values
|
||||
// (trace IDs, auth info carried via context keys) but is not cancelled
|
||||
// when the HTTP server finalizes the request. Using r.Context()
|
||||
// directly would cause the async audit write to observe ctx.Done()
|
||||
// as soon as the response completes; using context.Background() would
|
||||
// discard useful observability metadata. WithoutCancel gives us both
|
||||
// (M-2 / D-3).
|
||||
auditCtx := context.WithoutCancel(r.Context())
|
||||
|
||||
// Record audit event asynchronously (best-effort, don't block response).
|
||||
// SECURITY: We intentionally use r.URL.Path (not r.URL.String() or r.RequestURI)
|
||||
// to prevent query parameters from being recorded in the immutable audit trail.
|
||||
@@ -147,7 +156,7 @@ func (a *AuditMiddleware) Middleware(next http.Handler) http.Handler {
|
||||
go func() {
|
||||
defer a.wg.Done()
|
||||
if err := a.recorder.RecordAPICall(
|
||||
context.Background(),
|
||||
auditCtx,
|
||||
method,
|
||||
path,
|
||||
actor,
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@@ -78,10 +79,17 @@ func NewLogging(logger *slog.Logger) func(http.Handler) http.Handler {
|
||||
// Recovery middleware recovers from panics and returns a 500 error.
|
||||
func Recovery(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
requestID := getRequestID(r.Context())
|
||||
log.Printf("[%s] PANIC: %v", requestID, err)
|
||||
requestID := getRequestID(ctx)
|
||||
// Use slog.ErrorContext so the panic log carries the same
|
||||
// request-scoped trace/auth metadata as normal request logs
|
||||
// (M-2 / D-3 — preserve ctx propagation on the panic path).
|
||||
slog.ErrorContext(ctx, "panic recovered in HTTP handler",
|
||||
"request_id", requestID,
|
||||
"panic", fmt.Sprintf("%v", err),
|
||||
)
|
||||
http.Error(w, `{"error":"Internal Server Error"}`, http.StatusInternalServerError)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -547,7 +547,11 @@ func (c *Connector) solveAuthorizationsHTTP01(ctx context.Context, authzURLs []s
|
||||
return fmt.Errorf("failed to start challenge server: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
// Derive the challenge-server shutdown context from the parent ctx so
|
||||
// values (trace IDs, deadlines) propagate, but detach from its
|
||||
// cancellation so Shutdown always gets its full budget even when the
|
||||
// parent was cancelled (M-2 / D-3).
|
||||
shutdownCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 5*time.Second)
|
||||
defer cancel()
|
||||
_ = srv.Shutdown(shutdownCtx)
|
||||
c.logger.Debug("challenge server stopped")
|
||||
|
||||
Reference in New Issue
Block a user