Exposer les logs de manière sécurisée avec Spring Boot

Cet article décrit de manière concise la mise en oeuvre et la configuration d’outils permettant l’exploitation en production des fichiers de logs. Pour une explication détaillée de ces composants et leur utilisation, merci de vous référer aux documentations en bas de cet article.

Spring Boot offre un panel d’outils très intéressants pour la mise en production et le suivi applicatif. Ce qui nous intéresse ici plus particulièrement c’est la gestion des logs et la manière de pouvoir les consulter facilement et de manière sécurisée depuis un appel HTTP. Pour cela nous allons nous aider de deux composants:

  • Le framework de logging LogBack pour la gestion des logs de sortie
  • L’outil de monitoring et de management Actuator

LogBack

Initialisation

LogBack est nativement incorporé dans Spring Boot via la dépendance spring-boot-starter, elle même incorporée dans toute dépendance de type starter. Logback utilise SLF4J (Simple Logging Facade for Java) comme interface native et s’implémente de la manière suivante dans une classe Java:

package com.ingeniance.appformation.controller;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/api")
public class LoggingController {
 
    Logger logger = LoggerFactory.getLogger(this.getClass());
 
    @RequestMapping("/")
    public String index() {
        logger.trace("A TRACE Message");
        logger.debug("A DEBUG Message");
        logger.info("An INFO Message");
        logger.warn("A WARN Message");
        logger.error("An ERROR Message");
 
        return "This is a logging example controller.";
    }
}

Vous pouvez maintenant retrouver toutes ces informations dans votre console à l’exécution de votre application Java.

Passons maintenant à l’étape suivante qui est d’externaliser vers un fichier le résultat de ces logs.

Configuration

LogBack incorpore un fichier de configuration qui peut utiliser les propriétés de l’environnement de Spring. Pour cela il suffit d’avoir dans notre classpath un fichier nommé de la manière suivante : logback-spring.xml. Il faut ensuite ajouter dans notre application.propeties les éléments suivants :

logging:
  path: logs
  file: ${logging.path}/myapplication.log
  level:
    root: WARN
    org.springframework.web: ERROR
    com.ingeniance: TRACE
    org.hibernate: ERROR
  pattern:
    console: "%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable"
    file: "%d %p %C{1.} [%t] %m%n"

L’élément important à retenir ici est la définition de logging.file qui indique à Spring Boot de gérer un fichier de log.

  • level définit le niveau de log pour chaque dépendance listée.
  • pattern permet d’appliquer un format d’affichage des logs pour chaque support de sortie ainsi qu’une colorisation syntaxique dans le cas d’une sortie Console.

Notre sortie Console aura cette fois l’allure suivante :

Vous pouvez remarquer l’utilisation des paramètres Spring pour injecter le path dans logging.file.

Spring Boot offre également de définir un niveau de log par défaut, surchargeable par ceux définit dans notre application.properties. Il suffit de déclarer l’injection de la ressource suivante dans notre fichier logback-spring.xml.

<include resource="org/springframework/boot/logging/logback/base.xml"/>

Pour notre besoin final, nous devons pouvoir paramétrer des logs pouvant être archivés via une rolling policy et suivant un format et des règles bien précises. Notre fichier logback-spring.xml aura alors la forme suivante:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
 
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
        </layout>
    </appender>
 
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>${FILE_LOG_PATTERN}</Pattern>
        </encoder>
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily and when the file reaches 5 MegaBytes -->
            <fileNamePattern>${LOG_PATH}/archived/apt_%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>5MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- keep 30 days' worth of history -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
</configuration>

Attention cependant, dans notre cas nous utilisons application.properties pour définir un certain nombre de paramètres dont notamment logging.file. Vous allez retrouver dans de nombreux tutoriaux le path du fichier de log à placer dans votre fichier logback-spring.xml de la manière suivante :

<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>myapplication.log</file>
...

Ceci est à proscrire si vous ne voulez pas générer un conflit de déclaration entre application.properties et le fichier de configuration de Logback.

Nous n’avons survolé qu’une petite partie des possibilités offertes par Logback, mais vous avez également la possibilité de définir des niveaux de logs en fonction des environnements, ou plus finement en fonction des dépendances par type de sortie.

Actuator

Maintenant que nous avons un fichier de logs maintenu dans notre application, il serait appréciable de pouvoir le consulter depuis notre environnement de production dans le cas où un bug applicatif aurait été détecté. Spring Boot dispose d’un outil de monitoring nommé Actuator. Dans notre cas, il va nous servir à exposer le contenu de nos fichiers de logs depuis une requête HTTP sécurisée.

Initialisation

Vous devez dans un premier temps importer la dépendance d’Actuator. Sous Maven importez la dépendance starter de la manière suivante :

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

Actuator met à disposition tout un tas de services définis par des endpoints et accessibles par défaut depuis l’URL: http://localhost:<port>/actuator/<endpoint>. Le endpoint qui nous intéresse est logfile qui affiche le fichier de logs défini depuis la propriété logging.file.

Depuis application.properties ajoutez la configuration suivante :

endpoints:
  enabled: false
  logfile:
    enabled: true
management:
    context-path: /management
    security:
        enabled: false
        roles: ROLE_ADMIN

Plusieurs notions sont abordées ici.

  • endpoints.enabled désactive l’ensemble des endpoints d’Actuator, évitant ainsi l’affichage d’informations sensibles.
  • endpoints.logfile.enabled permet en revanche d’activer uniquement celui-ci.
  • management.context-path permet de modifier l’URL par défaut par celle-ci: http://localhost:<port>/management/<endpoint>.
  • management.security.enabled permet de désactiver la gestion de sécurité par Actuator et permet de la déporter vers celle utilisée par notre application.
  • management.security.roles permet d’ajouter des rôles supplémentaires pour l’accès aux endpoints. Par défaut, le rôle définit est ACTUATOR.

Faites attention cependant car la configuration spécifiée précédemment est celle sous Spring Boot 1.X. Dans le cas de Spring Boot 2.X, un remaniement des paramètres est à prévoir :

management:
    endpoint:
        logfile:
            enabled: true
    endpoints:
        enabled-by-default: false
        web:
            base-path: /management
            exposure:
                include: "*"
    security:
        enabled: false
        roles: ROLE_ADMIN

Sécurisation

Actuator est maintenant configuré et permet d’afficher depuis une URL notre fichier de logs. Nous avons ajouté un rôle d’administration et indiqué la prise en main de la sécurité par un composant externe. Pour surcharger les règles d’accès à notre application il suffit d’ajouter un @Bean de type WebSecurityConfigurerAdapter et d’ajouter @Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER) pour surcharger les règles de sécurité d’Actuator (ce dernier point n’est plus nécessaire sous Spring Boot 2.X).

@Configuration
@EnableWebSecurity
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
    }
}

Nous indiquons ainsi que toute personne essayant d’accéder à l’URL http://localhost:<port>/management/ doit posséder un rôle de type ADMIN.

Conclusion

Vous avez vu dans cet article:

  • Le moyen de mettre en place des loggings au sein d’une application Java.
  • D’améliorer l’affichage dans la Console et de modifier le niveau de vos logs par dépendance.
  • D’externaliser et d’archiver de manière efficace les logs à l’aide de LogBack.
  • D’installer Actuator pour consulter les logs depuis un appel HTTP de manière sécurisée.

Ressources

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.