Home > Software engineering >  How to reload Logback SSL appenders Keystore/Truststore without restarting the application?
How to reload Logback SSL appenders Keystore/Truststore without restarting the application?

Time:01-21

I Want to be able to reload the Keystore/Trustore of the SSL appenders of the Logback without restarting the application. This is done because when the certificates expire you don't have to restart the application.

I've tried using JVMs default keystore/trustore, but it seems that the appender only reads the keystore/trustore once. the expected result is reloading the keystore/trustore without restarting the application.

CodePudding user response:

Added an endpoint for that, simply getting the appender from the context stopping and then starting again does the trick.

package com.gabrieljuliao.kubelogger.controllers;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Objects;

@RestController
@RequestMapping("/LogbackSSLSocketAppender")
public class LogbackSSLSocketAppenderController {

    @GetMapping("/restart/{loggerName}/{appenderName}")
    public ResponseEntity<?> restartSSLContext(@PathVariable("loggerName") String loggerName, @PathVariable String appenderName){
        LoggerContext ctx = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger logger = ctx.getLogger(loggerName);
        Appender<ILoggingEvent> appender = logger.getAppender(appenderName);

        if (Objects.nonNull(appender)) {
            logger.info("Stopping, and detaching  appender");
            appender.stop();
            logger.detachAppender(appenderName);
            try {
                logger.info("Attaching, and starting appender");
                logger.addAppender(appender);
                appender.start();
            } catch (Exception e) {
                logger.error("Error starting appender: "   e.getMessage(), e);
                return ResponseEntity.status(500).build();
            }
            return ResponseEntity.ok().build();
        }
        logger.info("Appender not found");
        return ResponseEntity.notFound().build();
    }
}

CodePudding user response:

If you are using Logstash Logback Encoder use the code below, just change the appender class to whatever logstash appender you want, don't forget to change the downcast if required. Check the parent to whom to downcast to.

package com.gabrieljuliao.kubelogger.controllers;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import net.logstash.logback.appender.AbstractLogstashTcpSocketAppender;
import net.logstash.logback.appender.LogstashTcpSocketAppender;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Objects;

@RestController
@RequestMapping(value = "/LogstashTcpSocketAppender", produces = MediaType.APPLICATION_JSON_VALUE)
public class LogstashTcpSocketAppenderController {
    Logger logger = (Logger) LoggerFactory.getLogger(LogstashTcpSocketAppenderController.class);

    @GetMapping("/restart/{loggerName}/{appenderName}")
    public ResponseEntity<?> restartSSLContext(@PathVariable("loggerName") String loggerName, @PathVariable String appenderName) {

        LoggerContext ctx = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger logger = ctx.getLogger(loggerName);
        LogstashTcpSocketAppender appender = castToLogstashTcpSocketAppender(logger.getAppender(appenderName));

        if (Objects.nonNull(appender)) {
            logger.info("Stopping, and detaching  appender");
            appender.stop();
            logger.detachAppender(appenderName);

            // force recreation of ssl context.
            appender.setSocketFactory(null);

            try {
                logger.info("Attaching, and starting appender");
                logger.addAppender(appender);
                appender.start();
            } catch (Exception e) {
                logger.error("Error starting appender: "   e.getMessage(), e);
                return ResponseEntity.status(500).build();
            }
            return ResponseEntity.ok().build();
        }

        logger.info("Appender not found");
        return ResponseEntity.notFound().build();
    }

    private LogstashTcpSocketAppender castToLogstashTcpSocketAppender(Appender<ILoggingEvent> appender) {
        if (appender instanceof AbstractLogstashTcpSocketAppender<?, ?>) {
            AbstractLogstashTcpSocketAppender<?, ?> abstractLogstashTcpSocketAppender = (AbstractLogstashTcpSocketAppender<?, ?>) appender;
            if (abstractLogstashTcpSocketAppender instanceof LogstashTcpSocketAppender) {
                return (LogstashTcpSocketAppender) abstractLogstashTcpSocketAppender;
            }
        }
        return null;
    }
}
  • Related