| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- package server
- import (
- "context"
- "net"
- "net/http"
- "strings"
- "time"
- "vocat/internal/store"
- )
- // recordAudit writes one security-relevant event to the audit trail. Failures
- // are logged but never block the request being audited.
- func (s *Server) recordAudit(
- ctx context.Context,
- actor string,
- action string,
- entityType string,
- entityID string,
- outcome string,
- remoteAddr string,
- ) {
- if s.store == nil {
- return
- }
- _, err := s.store.AppendAuditEvent(ctx, store.AuditEvent{
- Actor: actor,
- Action: action,
- EntityType: entityType,
- EntityID: entityID,
- Outcome: outcome,
- RemoteAddr: remoteAddr,
- CreatedAt: time.Now().UTC(),
- })
- if err != nil {
- s.logger.Warn("write audit event failed", "action", action, "error", err)
- }
- }
- // audit records an event for an already-authenticated request, resolving the
- // actor from the session and the source address from the raw connection (proxy
- // headers are deliberately not trusted for the audit trail).
- func (s *Server) audit(r *http.Request, action string, entityType string, entityID string, outcome string) {
- actor := ""
- if s.auth != nil {
- if cookie, err := r.Cookie(sessionCookieName); err == nil && cookie.Value != "" {
- if session, authErr := s.auth.Authenticate(r.Context(), cookie.Value); authErr == nil {
- actor = session.Principal.Username
- }
- }
- }
- s.recordAudit(r.Context(), actor, action, entityType, entityID, outcome, requestRemoteHost(r))
- }
- // auditAuth records an authentication event where no session exists yet (the
- // actor is the username that was attempted).
- func (s *Server) auditAuth(r *http.Request, username string, outcome string) {
- s.recordAudit(r.Context(), username, "auth.login", "session", username, outcome, requestRemoteHost(r))
- }
- func requestRemoteHost(r *http.Request) string {
- host, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr))
- if err != nil {
- return strings.TrimSpace(r.RemoteAddr)
- }
- return host
- }
|