Module Audit

Module de tracabilite automatique - middleware HTTP, behavior MediatR, SignalR et persistance

Module Audit

Le module Audit assure la tracabilite complete de toutes les actions effectuees dans l'API. Il collecte les evenements d'audit depuis deux sources (middleware HTTP et behavior MediatR), les persiste en base de donnees et les diffuse en temps reel via SignalR.

Architecture du module

mermaid
flowchart TB
    subgraph BuildingBlocks
        MW[AuditHttpMiddleware<br/>Middleware HTTP]
        BH[AuditCommandBehavior<br/>Pipeline MediatR]
        EM[AuditEmitter<br/>IAuditEmitter]
    end

    subgraph Module Audit
        CE[ConsumeAuditEvent<br/>INotificationHandler]
        WR[AuditLogWriter<br/>IAuditLogWriter]
        DB[(AuditContext<br/>schema: audit)]
        HB[AuditHub<br/>SignalR]
    end

    MW -->|AuditEventV1| EM
    BH -->|AuditEventV1| EM
    EM -->|MediatR Notification| CE
    CE -->|WriteAsync| WR
    WR -->|Persistance| DB
    WR -->|Broadcast| HB
    HB -->|Temps reel| Admin[Admin Dashboard]

Sources d'evenements d'audit

AuditHttpMiddleware (BuildingBlocks)

Le middleware HTTP intercepte toutes les requetes entrantes et produit un evenement d'audit contenant :

  • Methode et route : GET, POST, etc. avec le template de route
  • Codes de reponse : classification automatique (Success, Failure, Denied, Noop)
  • Corps de requete/reponse : capture optionnelle avec tronquage configurable
  • Duree de traitement : en millisecondes
  • Contexte : IP, User-Agent, correlation ID, trace ID, span ID
  • Classification : Activity, Security (401/403), Exception (500+)

Le middleware est configurable via AuditHttpMiddlewareOptions :

  • Enabled : activer/desactiver le middleware
  • CaptureBodies : capturer les corps de requete/reponse
  • MaxBodyBytes : taille maximale des corps captures
  • ExcludedPaths : chemins exclus de l'audit (health checks, swagger, etc.)
  • AllowedContentTypes : types MIME autorises pour la capture de corps

AuditCommandBehavior (BuildingBlocks)

Le behavior MediatR intercepte toutes les commandes (ICommand<T>) et produit un evenement d'audit :

  • Seules les commandes sont auditees (pas les queries)
  • Les commandes avec l'attribut [SkipAudit] sont ignorees
  • Le nom d'action est derive du nom de la commande (LoginCommand -> login)
  • Le nom du module est infere depuis le namespace
  • L'ID d'entite est extrait automatiquement depuis les proprietes Id ou *Id
  • En cas d'echec, l'exception est capturee sans interrompre sa propagation

Entite AuditLog

L'entite principale du module, persistee dans le schema audit :

ProprieteTypeDescription
IdGuidIdentifiant unique de l'evenement
OccurredAtUtcDateTimeMoment ou l'action s'est produite
ReceivedAtUtcDateTimeMoment de reception par le module
ModuleNamestringModule source (identity, messaging, http)
ActionNamestringNom de l'action (login, register, http.post.api.v1.identity.auth.login)
EventTypestringType (activity, security, exception)
EntityTypestringType d'entite affectee
EntityIdstringIdentifiant de l'entite
ActorUserIdGuid?Utilisateur qui a effectue l'action
ActorTypestring?Type d'acteur (user, system)
ResultstringResultat (success, failure, denied, noop)
Reasonstring?Raison en cas d'echec
SeveritystringSeverite (business, security, infrastructure)
TenantIdstring?Identifiant du tenant
IpAddressstring?Adresse IP source
UserAgentstring?User-Agent du client
CorrelationIdstring?Identifiant de correlation
RequestIdstring?Identifiant de requete
TraceIdstring?Trace ID OpenTelemetry
SpanIdstring?Span ID OpenTelemetry
Tagsstring[]Tags (authentication, authorization)
MetadataJsonstringMetadonnees JSON (methode HTTP, status code, duree, etc.)
TokenFingerprintSha256string?Empreinte du token JWT
SourcestringSource de l'evenement (command, http, system)
PayloadJsonstringPayload JSON (corps de requete/reponse, parametres de commande)
VersionintVersion du format d'evenement

Services

IAuditLogWriter / AuditLogWriter

Service responsable de la persistance et de la diffusion des evenements :

public interface IAuditLogWriter
{
    Task WriteAsync(AuditEventV1 auditEvent, CancellationToken cancellationToken);
}

L'implementation AuditLogWriter :

  1. Convertit l'AuditEventV1 en entite AuditLog
  2. Persiste en base via AuditContext
  3. Enregistre les metriques (evenement persiste, echec, latence)
  4. Diffuse le log via SignalR vers le groupe audit-admins

En cas d'echec de la diffusion SignalR, un warning est logue mais l'evenement est deja persiste.

AuditHub (SignalR)

Hub SignalR pour la diffusion en temps reel des evenements d'audit :

  • Route : /hubs/audit
  • Autorisation : [Authorize] - seuls les utilisateurs avec le role Admin peuvent se connecter
  • Groupe : audit-admins
  • Evenement : AuditLogInserted - envoye a chaque nouvel evenement d'audit
[Authorize]
internal sealed class AuditHub(ILogger<AuditHub> logger) : Hub
{
    public override async Task OnConnectedAsync()
    {
        bool isAdmin = Context.User?.IsInRole(IdentityConstant.Role.Admin) ?? false;
        if (!isAdmin)
        {
            Context.Abort();
            return;
        }
        await Groups.AddToGroupAsync(Context.ConnectionId, GroupName);
    }
}

Configuration SignalR :

  • MaximumReceiveMessageSize : 16 Ko
  • MaximumParallelInvocationsPerClient : 1
  • ClientTimeoutInterval : 60 secondes
  • KeepAliveInterval : 15 secondes

Features d'administration

FeatureTypeDescription
GetAuditLogsQueryListe paginee des logs d'audit
GetAuditLogByIdQueryDetail d'un log par ID
GetAuditLogsByCorrelationQueryLogs par correlation ID
GetAuditLogsByTraceQueryLogs par trace ID OpenTelemetry
GetAuditSummaryQueryResume statistique des evenements
GetExceptionAuditLogsQueryLogs de type exception uniquement
GetSecurityAuditLogsQueryLogs de type securite uniquement
ConsumeAuditEventHandlerConsommation des notifications MediatR

DbContext

public sealed class AuditContext : AppDbContextBase
{
    public DbSet<AuditLog> AuditLogs => Set<AuditLog>();

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.ApplyConfigurationsFromAssembly(typeof(AuditContext).Assembly);
        builder.ToSnakeCaseTables();
    }
}

Le schema utilise la convention snake_case pour les noms de tables et colonnes.

Metriques

Le module expose des metriques OpenTelemetry via AuditMetrics :

  • audit.event.persisted : nombre d'evenements persistes avec succes
  • audit.event.failed : nombre d'echecs de persistance
  • audit.write.latency : latence d'ecriture en millisecondes
  • audit.http.body.capture.skipped : nombre de captures de corps ignorees

Infrastructure partagee (BuildingBlocks/Auditing)

Le dossier BuildingBlocks/Auditing/ contient toute l'infrastructure d'audit reutilisable :

ComposantDescription
AuditEventV1Record immutable representant un evenement d'audit
AuditHttpMiddlewareMiddleware ASP.NET Core pour l'audit HTTP
AuditCommandBehaviorPipeline behavior MediatR pour l'audit des commandes
AuditEmitter / IAuditEmitterEmission des evenements via MediatR
AuditContext / IAuditContextProviderFournisseur du contexte d'execution
AuditSeverityClassifierClassification de la severite
AuditMaskingServiceMasquage des donnees sensibles
AuditMetricsMetriques OpenTelemetry
AuditActionAttributeAttribut pour nommer les actions
SkipAuditAttributeAttribut pour exclure de l'audit
EntityChangeAuditSaveChangesInterceptorIntercepteur EF Core pour les changements d'entites
TokenFingerprintProviderExtraction de l'empreinte du token JWT
EnumsActivityKind, AuditActorType, AuditEventType, AuditLevel, AuditResult, AuditTag, SecurityAction