fix: address review findings for observability PR
All checks were successful
Check / check (pull_request) Successful in 1m42s
All checks were successful
Check / check (pull_request) Successful in 1m42s
1. Security: Replace insecure extractRemoteIP() in audit service with middleware.RealIP() which validates trusted proxies before trusting X-Real-IP/X-Forwarded-For headers. Export RealIP from middleware. Update audit tests to verify anti-spoofing behavior. 2. Audit coverage: Add audit instrumentation to all 9 handlers that had dead action constants: HandleEnvVarSave, HandleLabelAdd, HandleLabelEdit, HandleLabelDelete, HandleVolumeAdd, HandleVolumeEdit, HandleVolumeDelete, HandlePortAdd, HandlePortDelete. 3. README: Fix API path from /api/audit to /api/v1/audit. 4. README: Fix duplicate numbering in DI order section (items 10-11 were listed twice, now correctly numbered 10-16).
This commit is contained in:
@@ -5,15 +5,14 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/fx"
|
||||
|
||||
"sneak.berlin/go/upaas/internal/database"
|
||||
"sneak.berlin/go/upaas/internal/logger"
|
||||
"sneak.berlin/go/upaas/internal/metrics"
|
||||
"sneak.berlin/go/upaas/internal/middleware"
|
||||
"sneak.berlin/go/upaas/internal/models"
|
||||
)
|
||||
|
||||
@@ -98,42 +97,16 @@ func (svc *Service) Log(ctx context.Context, entry LogEntry) {
|
||||
}
|
||||
|
||||
// LogFromRequest records an audit log entry, extracting the remote IP from
|
||||
// the HTTP request.
|
||||
// the HTTP request using the middleware's trusted-proxy-aware IP resolution.
|
||||
func (svc *Service) LogFromRequest(
|
||||
ctx context.Context,
|
||||
request *http.Request,
|
||||
entry LogEntry,
|
||||
) {
|
||||
entry.RemoteIP = extractRemoteIP(request)
|
||||
entry.RemoteIP = middleware.RealIP(request)
|
||||
svc.Log(ctx, entry)
|
||||
}
|
||||
|
||||
// extractRemoteIP extracts the client IP from the request, preferring
|
||||
// X-Real-IP and X-Forwarded-For headers from trusted proxies.
|
||||
func extractRemoteIP(r *http.Request) string {
|
||||
// Check X-Real-IP first
|
||||
if ip := strings.TrimSpace(r.Header.Get("X-Real-IP")); ip != "" {
|
||||
return ip
|
||||
}
|
||||
|
||||
// Check X-Forwarded-For (leftmost = client)
|
||||
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
||||
if parts := strings.SplitN(xff, ",", 2); len(parts) > 0 { //nolint:mnd // split limit
|
||||
if ip := strings.TrimSpace(parts[0]); ip != "" {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to RemoteAddr
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
return r.RemoteAddr
|
||||
}
|
||||
|
||||
return host
|
||||
}
|
||||
|
||||
// Recent returns the most recent audit log entries.
|
||||
func (svc *Service) Recent(
|
||||
ctx context.Context,
|
||||
|
||||
Reference in New Issue
Block a user