Java en Production – L’audit

Après avoir abordé la gestion des fichiers de logs, nous continuons aujourd’hui la série « Applications Java prêtes pour la Production » avec l’audit.

Par audit, nous entendons l’audit des actions importantes réalisées sur une application.

Pourquoi auditer ?

Est-il vraiment utile de générer des informations d’audit dans nos applications ? Sans explications de juriste, quelques exemples suffiront à nous en convaincre :

  • Un site web de partage de photos doit pouvoir dire qui a uploadé quelle image, depuis quelle adresse IP et à quelle date.
  • L’application d’administration d’un site de e-commerce doit tracer toutes les modifications de prix pour empêcher un employé astucieux de baisser à 1 euro le prix de son téléphone préféré le temps de passer commande.

Pour revenir à des explications plus théoriques, les logs d’audit nous apportent :

  • les informations nécessaires à la justice en cas d’infraction,
  • la détection d’intrusions,
  • la reconstitution des événements en complément des logs d’exceptions pour aider au diagnostique de problèmes.

Nous nous placerons dans le cas le plus fréquent où nous ne développons pas d’outil pour consulter ces informations d’audit et où un accès direct au média de stockage (grep sur fichier texte, sql sur base de données, etc) suffit.

Que faut-il auditer ?

Dans un monde idéal, le contenu des messages serait défini avec les équipes de sécurité. En pratique, nous sommes assez seuls pour les choisir et il ne faut pas dramatiser. Si l’on ne prend pas le sujet à la légère, après quelques itérations, notre bon sens est le plus souvent suffisant.

Les éléments clefs à tracer sont :

  • L’heure exacte : il est essentiel que les serveurs soient à l’heure pour corréler les logs des différentes briques du système d’information. Le sujet est aujourd’hui censé être banal pour les équipes système (c.f. NTP) et nous pouvons demander le soutien des équipes sécurité pour obtenir gain de cause.
  • L’action réalisée : il s’agit souvent du nom de la méthode métier appelée.
  • L’identifiant et/ou la valeur des données métier sensibles manipulées : souvent les id ou le toString() des paramètres d’appel.
  • L’auteur de la manipulation : nom de l’utilisateur connecté et son adresse ip (pour plus de détails sur l’adresse ip : XForwardedFilter et Tomcat : Adresse IP de l’internaute, load balancer, reverse proxy et header Http X-Forwarded-For).
  • La description succincte des exceptions levées pour analyser les éventuelles attaques.

Pourquoi les logs d’accès des serveurs http ne suffisent pas ?

La première idée serait de se contenter des logs d’accès des serveurs web et des firewalls pour auditer les accès à nos applications ; nous n’aurions alors plus rien à faire.

Hélas, cela n’est pas suffisant car il manque dans les logs http des informations clefs :

  • Nous n’avons pas l’identité de l’appelant : on a bien l’adresse ip mais pas le login de l’utilisateur authentifié.
  • Nous n’avons pas les id passés en paramètre des opérations à auditer (sauf si on fait du REST) ; en SOAP, nous n’avons même pas le nom de l’opération !
  • Nous n’avons pas le détail des exceptions levées par l’application.

API : Framework de log vs. framework dédié

Dans un monde idéal, le framework d’audit ne devrait pas dépendre de la configuration des logs pour ne pas risquer qu’une mauvaise manipulation de ces configurations de logs ne le désactive.

En pratique, les frameworks de logs sont les briques les plus performantes et les plus matures pour traiter les besoins d’écriture d’audit et la probabilité de désactiver l’audit en faisant une mauvaise manipulation sur la configuration des logs est négligeable. Ces raisons nous amènent à utiliser SLF4J avec logback ou log4j pour gérer l’audit.

Nous encapsulerons tout de même le logger avec une couche légère packagée dans la librairie Xebia Spring Security Extras qui ajoutera au message l’identité de l’internaute et son adresse IP (via Spring Security). Cette librairie offre une gestion déclarative de l’audit avec une annotation @Audited, son aspect associé AuditAspect et une classe utilitaire Auditor. Nous ne rentrerons pas dans le débat annotations vs. code ; dans la majeure partie des projets, nous avons pu traiter la plupart de l’audit avec une annotation et seuls quelques cas ont nécessité de passer par du code.

Exemple de gestion de l’audit avec l’annotation @Audited :

@Audited(message = "transferMoney(#{args[0].accountNumber}, #{args[1].accountNumber}, #{args[3]})")
public void transferMoney(Account from, Account to, Amount amount) throws BusinessException { ... }

L’attribut message est un pattern supportant Spring Expression Language définissant l’entrée insérée dans le fichier d’audit ; la date, le nom de l’utilisateur, l’adresse ip et l’exception s’il y en a une sont ajoutés au message.

Fragment de configuration Spring Framework pour utiliser l’annotation @Audited :

<beans ...
   xmlns:security-extras="http://www.xebia.fr/schema/xebia-spring-security-extras"
   xsi:schemaLocation="...
        http://www.xebia.fr/schema/xebia-spring-security-extras http://www.xebia.fr/schema/security/xebia-spring-security-extras.xsd">

   <!-- enable Spring AOP --> 
   <aop:aspectj-autoproxy/>

  <!-- activate the AutitAspect --> 
  <security-extras:audit-aspect />
   ...
</beans>

Message d’audit généré :

... transferMoney(000652584515, 0000684651684, 187.53) by bdupont coming from 192.168.0.14
... transferMoney(000652584515, 0000684651684, 666666.00) threw '...BusinessException: debit amount greater than account balance' 
   by bdupont coming from 192.168.0.14

Exemple de gestion de l’audit avec l’utilitaire Auditor :

public void transferMoney(...) throws BusinessException {
   ...
   Auditor.audit("Tranfer '" + amount + "' from " + fromAccount + " to " + toAccount);
}

Message d’audit généré :

... Transfer '187.53 euros' from Account[000652584515] to Account[0000684651684] by bdupont coming from 192.168.0.14

L’entrée d’audit est ajoutée dans un fichier d’audit géré par le logger spécifique "fr.xebia.audit" (voir cet article pour la configuration du logger).

Tous les détails sur l’annotation @Audited sont sur @Audited Annotation.

Intégration du framework dans une application

Ce framework peut être intégré de différentes façons dans une application :

Stockage : fichier texte vs. base de données

Le stockage des entrées d’audit en base de données permet sûrement une recherche plus fine des données que sur des fichiers mais cela ajoute de la complexité (déploiement, exploitation, backup) ainsi que des risques de pannes et impacte les performances. Les approches JMS présentent des contraintes similaires et l’utilisation de systèmes de logs distants comme rsyslog présentent un défi de fiabilité. Ces difficultés sont accentuées lorsqu’une application génère de gros volumes de logs (plusieurs Go/jour).

Pour ces raisons, nous préférons stocker les messages d’audit dans un simple fichier. Les risques de saturation du système de fichiers sont assez facilement gérables par les équipes d’exploitation, les procédures d’archivage et de consultation très simples (gzip, scp, grep, etc) et il n’y a quasiment jamais de problème de performance, même avec des fichiers de quelques Go par jour.

Y-a-t-il un plus grand risque de perdre les données par de mauvaises manipulations ? Si une application est critique, les exploitants doivent déjà ne pas perdre les fichiers de log du système d’exploitation, des serveurs web et autres firewalls.

Pour la gestion des messages d’audit sous forme de fichier texte, nous aimons logback comme nous l’avons expliqué dans Java en Production – Les fichiers de logs mais il est aussi possible d’utiliser Log4j.

Exemple de configuration Logback pour gérer les messages d’audit émis sur le logger fr.xebia.audit :

<appender name="audit-file" class="ch.qos.logback.core.rolling.RollingFileAppender">
   <file>${LOGS_FOLDER}/my-application-audit.log</file>
   <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- rotate every day -->
      <fileNamePattern>/my-application-audit.%d{yyyyMMdd-HHmm}.log.zip</fileNamePattern>
   </rollingPolicy>
   <encoder>
      <!-- don't output the date or the logger name because the auditing framework handles this -->
      <pattern>%m %throwable{0}%n</pattern>
   </encoder>
</appender>
<!-- route the 'fr.xebia.audit' log messages to the audit-file -->
<logger name="fr.xebia.audit" additivity="false" level="TRACE">
   <appender-ref ref="audit-file" />
</logger>

Exemple équivalent avec log4j (le EnhancedPatternLayout requiert log4j 1.2.16) :

log4j.appender.auditfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.auditfile.datePattern='-'yyyyMMdd
log4j.appender.auditfile.file=${catalina.base}/logs/my-application-audit.log
log4j.appender.auditfile.layout=org.apache.log4j.EnhancedPatternLayout
log4j.appender.auditfile.layout.conversionPattern=%m %throwable{short}n

log4j.logger.fr.xebia.audit=INFO, auditfile

Que faire des logs d’audit après les avoir générées ?

Nous ne rentrerons pas plus dans les détails de la gestion des logs d’audit après leur génération par nos applications.

Ce sujet complexe présente aussi bien des aspects juridiques que de confidentialité ou encore de fiabilité. Schématiquement, on n’a pas le droit de garder indéfiniment des données personnelles, il faut restreindre leur consultation et empêcher leur modification et leur destruction par accident comme par malveillance.

Des professionnels de l’exploitation et de la sécurité sont beaucoup plus compétents que nous sur ce sujet :-).

Pour aller plus loin

Si le traitement de l’audit dans les applications vous a intéressé, nous avons aimé lire :

Synthèse

Nous avons vu aujourd’hui une façon simple de gérer l’audit d’applications java en reposant sur le framework de log de l’application (Logback voire Log4j) pour écrire les messages dans de simples fichiers texte avec une surcouche très légère composée d’une annotation @Audited et d’un utilitaire Auditor.

Historique
25/11/2010 : passage à la version 1.1.5 de la librarie xebia-spring-security-extras avec utilisation du namespace de configuration.
20/12/2011 : xebia-spring-security-extras : passage à la version 1.1.6 et aux URLs GitHub

Billets sur le même thème :

16 commentaires

  • Billet très intéressant. Vos sources sont aussi un exemple simple et clair de comment créer des annotations personnalisées avec AspectJ. Je ne m’étais jamais penché sur le sujet et cela a été instructif !

    Seb

  • @Sebastien,

    Merci pour vos encouragements.

    Nous avons aussi étés impressionnés par la productivité de Spring pour implémenter cette annotation :
    * La simplicité de @Around(value = "execution(* *(..)) && @annotation(audited)", argNames = "pjp,audited") pour indiquer à Spring AOP que nous voulons intercepter toutes les méthodes annotées par @Audited,
    * La simplicité du SpelExpressionParser fourni par Spring Expression Language pour évaluer notre expression en lui injectant les paramètres d’invocation de la méthode auditée.

    Cyrille (Xebia)

  • Article intéressant, comme souvent :)

    A noter que dans un monde JEE (sans Spring et le toin toin) pour la partie métier, une approche similaire peut être la création d’un interceptor d’audit sur les EJB; interceptor à utiliser du coup sur les ejb facade (qui devraient être les seuls points d’entrée des clients). Les logs HTTP permettent de faire le lien entre l’IP et le user loggé par l’interceptor, pour peu que le serveur applicatif logge les IP des utilisateurs qu’il authentifie.

    Arnaud Rolly, freelance JEE

  • @Arnaud,

    Merci pour vos encouragements. Je vous trouve un zest taquin à parler de « toin toin » Spring :-) .

    Pour mieux comprendre l’approche avec Java EE 5+,

    a) Je cerne bien l’annotation @javax.interceptor.Interceptors(Class[]) pour intercepter l’appel à mes méthodes métier et j’imagine @Interceptors(Auditor.class) mais je ne vois pas comment passer en paramètre de mon intercepteur Auditor.class le pattern du message que je veux émettre (2). Je trouverais dommage que toutes mes méthodes auditées soient traitées à la même enseigne façon « One Size Fits All » et de renoncer à mes beaux messages d’audit très expressifs.

    b) Pour ce qui est de l’expression language qui nous a bien simplifié la vie, le « Unified Expression Language » officiel semble très focalisé JSP et JSF (1) et, faute d’exemple référencé par Google, je penserais plutôt à Jakarta Commons-JEXL qui est notamment utilisé par Perf4j et qui m’a donnée grande satisfaction dans le passé (ie avant que j’homogénéise mes applications avec Spring EL).

    c) Pour les adresses IP, la corrélation des fichiers de logs (applications + access log) me semble délicate ; quelle jointure ai-je à ma disposition ? L’heure sera insuffisante en cas d’accès concurrent. J’imaginerais plutôt un ThreadLocal pour récupérer l’adresse ip via la requête http dans mes intercepteurs.

    Je suis ouvert à toute suggestion !

    Cyrille qui est bien content de placer le toin toin sur les serveurs J2EE 1.4 / JVM 1.5 de ses projets ;-)

    (1) javax.el javadoc : « Provides the API for the Unified Expression Language shared by the JSP 2.1 and JSF 1.2 technologies. »
    (2) cf Adam Bien : Interceptors (EJB 3) For Absolute Beginners – Or Pragmatic AOP in 2 Minutes (without XML :-))

  • Je suis effectivement un peu taquin, surtout envers Spring ;-)

    a) L’interceptor peut trés bien utiliser une annotation sur la méthode appelée pour extraire le pattern à utiliser, comme le @Audited de Spring (sauf qu’ici on peut avoir plusieurs annotations différentes spécifiques au projet, utile si les logs d’audit sont découpés en différentes « classes » avec chacune des données bien définies à enregistrer)

    c) Utiliser un ThreadLocal ne fonctionnera pas (ça peut « tomber en marche » dans certains cas) car il n’y a aucune garantie que le thread qui appelle l’EJB soit celui qui l’exécute (ex: un remote ejb sur une appli déployée sur un cluster). La jointure se fait ainsi:
    – log serveurs applicatif: IP -> utilisateur
    – log audit : utilisateur -> appel d’ejb
    Forcément, ce n’est pas utilisable dans le cas d’appli web sur le grand ‘ternet avec des parties publiques (mais dans ce cas là, on utilise rarement un « vrai » serveur applicatif et des EJB)

    Arnaud Rolly qui a supprimé des milliers de lignes de toin toin lors de sa dernière mission :p

  • @Arnaud,

    a) je vois mieux pour l’interceptor :

    Je garde mon annotation @Audited(message="bla bla bla") et j’ajoute une annotation @Interceptors.

    @Audited avec Spring Framework :

    @Audited(message = "transferMoney(#{args[0].accountNumber}, #{args[1].accountNumber}, #{args[3]})")
    public void transferMoney(Account from, Account to, Amount amount) throws BusinessException { ... }
    

    @Audited avec Java EE 5 :

    @Interceptors(AuditInterceptor.class)
    @Audited(message = "transferMoney(#{args[0].accountNumber}, #{args[1].accountNumber}, #{args[3]})")
    public void transferMoney(Account from, Account to, Amount amount) throws BusinessException { ... }
    

    Aspect d’audit avec Spring Framework :

    @Around(value = "execution(* *(..)) && @annotation(audited)", argNames = "pjp,audited")
    public Object logMessage(ProceedingJoinPoint pjp, Audited audited) throws Throwable {
      try {
         Object returned = pjp.proceed();
         String message = buildMessage(audited.message(), pjp.getThis(), pjp.getArgs(), returned, null);
         logger.info(message);
         return returned;
      } catch (Throwable t) {
         String message = buildMessage(audited.message(), pjp.getThis(), pjp.getArgs(), null, t);
         logger.warn(message);
         throw t;
      }
    }
    

    Interceptor d’audit avec Java EE 5 :

    @AroundInvoke
    public Object auditCall(InvocationContext context) throws Throwable {
       // Get @Audited annotation information
       Audited audited = context.getMethod().getAnnotation(Audited.class);   
       try {
          Object returned = context.proceed();
          String message = buildMessage(audited.message(), context.getTarget(), context.getParameters(), returned, null);
          logger.info(message);
          return returned;
       } catch (Throwable t) {
          String message = buildMessage(audited.message(), context.getTarget(), context.getParameters(), null, t);
          logger.warn(message);
          throw t;
       }
    }
    

    Les implémentations de l’annotation d’audit avec Spring Framework et Java EE 5 sont assez similaires ; Java EE 5 est un peu plus verbeux et un peu moins typé Spring Framework.

    c) Pour « ThreadLocal bien ou pas bien », je me limiterai à constater que c’est communément utilisé.
    Pour EJB container versus Servlet Container, j’ai le souvenir d’un évangéliste qui m’a un jour dit au JUG que ca n’avait pas d’importance. Je ne dois pas être au niveau car je souffre aujourd’hui même de problèmes de classloader sur une application J2EE 1.4.

    Pour le « vrai » serveur applicatif, je ne rentrerai pas dans un débat sans fin mais je constaterai :

    J’ai le souvenir d’avoir discuté avec des membre des Expert Group Java EE 5 et Java EE 6 d’une date réaliste de déploiement des versions Java EE 5 des serveurs des grands éditeurs (ie ce qu’on a dans beaucoup de DSI du CAC 40) : nous parlions de 2012 … alors que Spring 3 est utilisé ou utilisable sur quasiment tous les serveurs déployés. Nous avions aussi convenu que les premiers utilisateurs d’API Java EE 6 tourneraient sur Tomcat ou Jetty et le feraient avec JPA, JAX-WS et JAX-RS.

    « Pas de nom, pas de lieu, pas de date », je ne raconterai pas mes expériences sur le sujet en public :-).

    Par ailleurs, j’ai demandé à deux grands éditeurs d’In Memory Data Grid qui sont aussi très puissants sur les serveurs Java EE s’ils comptaient supporter ne serait-ce que l’assemblage des composants (CDI + Interceptors) dans leur grille. Réponse unanime : pas prévu dans l’agenda ; heureusement que j’ai le « toin toin » Spring Framework à ma disposition ;-).

    Cyrille qui compte supprimer des milliers de lignes de EJB 2, MDB & cie pour les remplacer par du lightweight Java.

  • Attention, l’annotation @Interceptors se place au niveau de la déclaration de classe, pas de méthode. Du coup, dans le code de l’intercepteur, il vaut mieux vérifier que l’annotation récupérée n’est pas nulle (on peut ne pas vouloir tout auditer)

    Arnaud Rolly, qui va replacer par du JEE 6 plein de code toin toin utilisé pour remplacer du code J2EE 1.4. L’informatique n’est qu’un cycle sans fin :)

  • @Arnaud

    Admis, alors que mon code « powered by Spring Framework AOP » est production ready avec seulement quelques lignes de « toin toin » technique, mon code Java EE 5 ressemblait plutôt à du Hello World de marchand de tapis ;-).

    Il manque :
    - La mise en cache de l’introspection de l’appel method.getAnnotation(Audited.class),
    - La protection contre l’absence de l’annotation @Audited ,
    - Probablement une moulinette pour vérifier que chaque annotation @Audited est associée avec un @Injectors(AuditInterceptor.class) et inversement.

    Voici une version un peu plus production ready mais pas encore très robuste de l’interceptor d’audit version Java EE :

       private final Map<Method, Audited> auditedAnnotationCache = new WeakHashMap<Method, Audited>();
    
    /**
     * Use a Map instead of of Set because there is no WeakHashSet in the JDK
     */
    private final Map<Method, Object> nonAnnotedMethodsCache = new WeakHashMap<Method, Object>();
    
    @AroundInvoke
    public Object auditCall(InvocationContext context) throws Throwable {
       // Get @Audited annotation (from cache if possible, skip audit if absent) 
       Method invokedMethod = context.getMethod();
       if (nonAnnotedMethodsCache.containsKey(invokedMethod)) {
          return context.proceed(); // not @audited, skip
       }
       Audited audited = auditedAnnotationCache.get(invokedMethod);
       if (audited == null) {
          audited = invokedMethod.getAnnotation(Audited.class);
          if (audited == null) {
             nonAnnotedMethodsCache.put(invokedMethod, null);
             return context.proceed(); // not @audited, skip
          } else {
             auditedAnnotationCache.put(invokedMethod, audited);
          }
       }
    
       try {
          Object returned = context.proceed();
          String message = buildMessage(audited.message(), context.getTarget(), context.getParameters(), returned, null);
          logger.info(message);
          return returned;
       } catch (Throwable t) {
          String message = buildMessage(audited.message(), context.getTarget(), context.getParameters(), null, t);
          logger.warn(message);
          throw t;
       }
    }
    

    Autant de « toin toin » technique pour un petit traitement métier, je préfère l’AOP by Spring Framework à celui de Java EE 5 ;-).

    Je suis ouvert à toute proposition plus élégante !

    On ne peut pas citer de nom mais je vous envie de travailler sur des data centers qui supportent déjà Java EE 6 en production ! Mon monde ne monte pas aussi vite de version de middleware … comme la plupart des grosses DSI et des gens qui ont des applications critiques :-).

    Cyrille

  • En 2010 j’ai mélangé du projet « de SSII » JEE 5 et du projet « de statup » JEE 6, j’avoue que c’est effectivement plaisant de pouvoir alterner et choisir ses missions sur des critères techniques :)

    Arnaud Rolly, freelance content.

  • Bonjour,

    Merci pour cet article fort intéressant ! Etant une entreprise spécialisée dans la traçabilité des opérations informatiques (log management), je me permets de vous joindre quelques pointeurs relatifs aux initiatives actuellement en cours dans le domaine. En effet, deux standards sont principalement en cours d’élaboration:
    * XDAS: Piloté par l’OpenGroup et ayant comme vocation la définition d’une structure de donnée uniforme ainsi qu’une taxonomie pour l’expression des messages d’audit
    * CEE: Piloté par le MITRE et le NIST et ayant comme vocation la définition d’un cadre général pour la génération des traces d’audit (recommandations, structure de données, taxonomie, format, etc.)

    L’objectif est d’unifier la manière d’exprimer ces informations d’audit (en gros, le String passé en paramètre à la méthode « Auditor.audit() » dans votre exemple ci-dessus).

    Des slides de présentation et une version « draft » du datamodel de l’XDAS (en cours d’élaboation) sont à disposition ici: http://xdas4j.codehaus.org/

    Meilleures salutations.

    J.Winteregg

  • Petit complément: Des informations complémentaires sont à disposition ici: http://www.netguardians.ch/index.php/resources/initiatives

  • @ Joël

    La bienséance vous défendait d’avoir l’orgueil de vous citer dans les pointeurs relatifs à XADS, c’est donc moi qui l’ajouterai ! Dana Gardner / Briefings Direct : XDAS standard aims to empower IT audit trails from across complex events, perhaps clouds avec Ian Dobson, director of the Security Forum for The Open Group et vous même, Joël Winteregg, CEO and co-founder of NetGuardians ; nous n’accueillons pas tous les jours sur notre blog des invités de Dana Gardner :-) .

    J’ai rapidement essayé d’implémenter notre exemple avec la librairie xads4j et, avec tout mon respect, je passerais par une couche intermédiaire (l’annotation @Audited, un builder, etc) pour factoriser la récupération des informations comme target (global à l’application) ou l’initiator (résolu à partir du contexte Spring Security) pour n’avoir qu’à préciser que l’action.

    Je vais profiter que vous êtes un professionnel de l’audit informatique et je me permettrais quelques questions liées à l’analyse [temps réel] des données d’audit.

    Comment aimez-vous stocker et aggréger les données d’audit ? Préférez vous stocker d’abord en local sur chaque machine (serveur d’application, serveur web, etc) puis seulement dans un deuxième temps envoyer au serveur centralisé d’audit ? Au contraire, osez-vous court circuiter le stockage local et uniquement envoyer le message au serveur centralisé ? Le cas échéant, quel mécanisme de communication fiable utilisez-vous pour être sur de ne perdre aucun message.
    Comment faites-vous pour consolider des gros volumes de traces d’audit sans risquer de pénaliser les systèmes audités ? Les cartes réseau d’administration sont-elles suffisantes ? Demandez vous des cartes réseau dédiées ?

    Les amateurs du stockage en base de données (plutôt qu’en fichier) avancent à juste titre la possibilité d’analyse quasi temps réel sur les données d’audit alors que les approches par fichiers imposent un délai pour que les traitements de centralisation intègrent ces fichiers. Quels délais d’intégration sont raisonnable dans le monde de l’audit ? Le temps réel semble très rarement nécessaire ? Cinq minutes présente des cas utilisation bien pratique, est-ce un délai raisonnable ?

    Quels format de stockage et de transport aimez-vous utiliser ? Nous voyions dans le domaine des communications inter-applications un foisonnement des formats de sérialisation comme Google Protocol Buffer, Apache Avro ou encore Thrift. Profitez-vous de ces innovations pour un sujet à aussi forte volumétrie que l’audit ?

    Le stockage et l’analyse de très gros volumes de données d’audit semble être un bon candidat aux scénarios des NoSQL (énorme volume de données partitionnables), est-ce une technologie qui suscite l’attention dans votre univers ?

    Cyrille

  • @Cyrille

    Notre librairie XDAS4J est actuellement très « brut de fonderie ». En effet, son utilisation n’est pas encore très user friendly. Une fois le standard défini, cette dernière sera travaillée afin de rendre son utilisation conviviale (helpers, IDE plugins, etc.) ainsi que son implémentation plus optimale (moins de création d’objets, etc.). Tous vos feedback à ce sujet son cependant bon à prendre. N’hésitez pas à nous solliciter sur l’une des listes en question: http://xdas4j.codehaus.org/mail-lists.html

    Concernant vos quelques questions, voici mon opinion en la matière:
    * Comment aimez-vous stocker et aggréger les données d’audit ?
    => Cela dépend généralement des besoins et des politiques de nos clients. La majeure partie d’entre eux conservent un logging local pour le court terme (rotation à quelques jours) et transmettent une copie des logs générés (à la génération du log) sur le collecteur distant.

    * quel mécanisme de communication fiable utilisez-vous pour être sur de ne perdre aucun message
    => Nous utilisons un peu tout ;-) Beaucoup d’appliances de sécurité (firewall, UTM, etc.) utilisent syslog (UDP), Windows du polling RPC, du polling JDBC (logs en BD), NFS pour des flat files, etc. En matière de fiabilité, je pense que du syslog over TCP serait intéressant (possible sur notre concentrateur de logs, mais pas officiellement supporté par log4j). Actuellement notre connecteur JDBC offre la meilleure fiabilité puisqu’il permet d’utiliser une base de données comme tampon. L’écriture et la lecture étant transactionnelle, l’intégrité des logs est garantie.

    * Comment faites-vous pour consolider des gros volumes de traces d’audit sans risquer de pénaliser les systèmes audités ?
    => La quantité n’est pas forcément synonyme de qualité. Nous essayons ainsi de filtrer un maximum de messages à la source (configuration adéquate des produits ou logiciels) afin d’être à même de remonter uniquement les traces pertinentes en matière de traçabilité ou de sécurité. D’où l’importance des standards en cours d’élaboration (unification des principes de logging)

    * Les cartes réseau d’administration sont-elles suffisantes ? Demandez vous des cartes réseau dédiées ?
    => Les systèmes audités ont généralement une carte réseau reliée à un VLAN de management. Ce dernier est généralement le segment idéal pour le transit des traces d’audit.

    * Quels délais d’intégration sont raisonnable dans le monde de l’audit ? Le temps réel semble très rarement nécessaire ? Cinq minutes présente des cas utilisation bien pratique, est-ce un délai raisonnable ?
    => Oui, un délai de 5 min est du quasi temps réel dans ce domaine ;-) De nombreux systèmes bufferisent des traces ou les génèrent à intervalle régulier. Un délai de 5 min est donc raisonnable pour de l’auditing. Cependant, dans des use cases orientés monitoring (proactivité), ce délai pourrait être certaines fois pénalisant. L’approche base de données n’est pas forcément synonyme de performances ou de réactivité. En effet, après le stockage de X Tera de logs, de simples requêtes d’agrégation prennent un certain temps… Des approches hybrides sont généralement les plus optimales. C’est notamment cette technologie qui a été développée au sein de NetGuardians.

    * Quels format de stockage et de transport aimez-vous utiliser ?
    => Actuellement, nous ne profitons pas vraiment des formats de stockage mentionnés. Pour les équipements IT du marché (SSL VPN, SAP, Cisco, etc.) nous n’avons pas vraiment le choix… Ces composants génèrent, au mieux, des traces syslog. Pour des composant logiciels (applications métiers Java, etc.) nous reposons généralement sur des bases de données tampon ou l’appender syslog de log4j. Un stockage compressé (zip) amène ensuite un très bon gain puisque les traces sont généralement assez répétitives (header uniforme, messages répétitifs, etc.)

    * Le stockage et l’analyse de très gros volumes de données d’audit semble être un bon candidat aux scénarios des NoSQL (énorme volume de données partitionnables), est-ce une technologie qui suscite l’attention dans votre univers ?
    => Oui, tout à fait. Ces technologies sont fortes intéressantes (sutout pour un stockage distribué). Nous avons notamment eu l’occasion d’étudier des bases de données vectorielles, du Map-Reduce (hadoop), etc.

    Cordialement,

    J.Winteregg

  • Article intéressant mais si je ne me trompe vous allez contre le commandement 9 de l’article suivant.
    http://blog.xebia.fr/2008/07/11/les-10-commandements-des-logs-applicatives/

  • @Stéphane,

    Merci d’avoir relevé la contradiction, vous nous avez pris en flagrant délit de « retournement de veste » :-).
    Nous nous sommes rendu compte que les risques de mauvaise manipulation du fichier de configuration du framework de logs et que développer une surcouche aux appenders du framework de log pour isoler les configurations représente rapidement une charge de travail très importante et dissuasive.

    Moralité, nous profitons du fichier de configuration des loggers même si ce n’est pas très orthodoxe et nous séparons les fichiers d’output : le fichier d’audit qui grossit en permanence est différent du fichier de logs qui ne bouge qu’en cas de dysfonctionnement.

    Nous allons mettre à jour le billet sur les dix commandements des logs.

    Cyrille

  • Le billet a été mis à jour pour référencer la version 1.1.5 de la librarie xebia-spring-security-extras qui permet désormais une configuration Spring par namespace XML <security-extras:audit-aspect /> et dont l’intégration Maven a été simplifiée par son déploiement sur la Maven Central Repository.

    Cyrille (Xebia)

Laisser un commentaire