ulisesbocchio / jasypt-spring-boot

Jasypt integration for Spring boot
MIT License
2.92k stars 523 forks source link

StandardEncryptableEnvironment not working with logback-spring.xml and SMTPAppender #398

Closed sbklahr closed 3 months ago

sbklahr commented 3 months ago

I'm using jasypt-spring-boot-starter:3.0.5 and spring-boot:3.3.2. As stated in the documentation I'm supposed to use StandardEncryptableEnvironment to get Spring properties replacement in logback-spring.xml.

Here is my setup:

@SpringBootApplication
public class MyApp {

    public static void main(final String[] args) {
        new SpringApplicationBuilder()
                .environment(new StandardEncryptableEnvironment())
                .sources(MyApp.class).run(args);
    }
}

logback-spring.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <springProperty name="smtpHost" source="smtp.host" defaultValue="not-set"/>
    <springProperty name="smtpUsername" source="smtp.username" defaultValue="not-set"/>
    <springProperty name="smtpPassword" source="smtp.password" defaultValue="not-set"/>

    <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <smtpHost>${smtpHost}</smtpHost>
        <username>${smtpUsername}</username>
        <password>${smtpPassword}</password>
        ...
    </appender>

    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="EMAIL"/>
        </root>
    </springProfile>

</configuration>

application.yml:

smtp:
  host: myhost
  username: myusername
  password: ENC(......)

When I start I get the following error:

Logging system failed to initialize using configuration from 'null'
java.lang.IllegalStateException: Logback configuration error detected: 
ERROR in ch.qos.logback.core.model.util.VariableSubstitutionsHelper@3e37aa90 - Problem while parsing [${smtpPassword}] java.lang.IllegalArgumentException: All tokens consumed but was expecting "}"
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.reportConfigurationErrorsIfNecessary(LogbackLoggingSystem.java:282)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:260)
    at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:81)
    at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:61)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:193)
    at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:332)
    at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
    at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
    at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
    at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
    at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:370)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:330)
    at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:149)
    at org.MyApp.main(MyApp.java:28)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
    Suppressed: java.lang.IllegalArgumentException: All tokens consumed but was expecting "}"
        at ch.qos.logback.core.subst.Parser.expectNotNull(Parser.java:160)
        at ch.qos.logback.core.subst.Parser.expectCurlyRight(Parser.java:165)
        at ch.qos.logback.core.subst.Parser.T(Parser.java:93)
        at ch.qos.logback.core.subst.Parser.E(Parser.java:58)
        at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
        at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
        at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
        at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
        at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
        at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
        at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
        at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
        at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
        at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
        at ch.qos.logback.core.subst.Parser.parse(Parser.java:54)
        at ch.qos.logback.core.subst.NodeToStringTransformer.tokenizeAndParseString(NodeToStringTransformer.java:59)
        at ch.qos.logback.core.subst.NodeToStringTransformer.handleVariable(NodeToStringTransformer.java:102)
        at ch.qos.logback.core.subst.NodeToStringTransformer.compileNode(NodeToStringTransformer.java:77)
        at ch.qos.logback.core.subst.NodeToStringTransformer.transform(NodeToStringTransformer.java:64)
        at ch.qos.logback.core.subst.NodeToStringTransformer.substituteVariable(NodeToStringTransformer.java:52)
        at ch.qos.logback.core.util.OptionHelper.substVars(OptionHelper.java:112)
        at ch.qos.logback.core.model.util.VariableSubstitutionsHelper.subst(VariableSubstitutionsHelper.java:52)
        at ch.qos.logback.core.model.processor.ModelInterpretationContext.subst(ModelInterpretationContext.java:166)
        at ch.qos.logback.core.model.processor.ImplicitModelHandler.doBasicProperty(ImplicitModelHandler.java:105)
        at ch.qos.logback.core.model.processor.ImplicitModelHandler.handle(ImplicitModelHandler.java:86)
        at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:241)
        at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253)
        at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253)
        at ch.qos.logback.core.model.processor.DefaultProcessor.traversalLoop(DefaultProcessor.java:90)
        at ch.qos.logback.core.model.processor.DefaultProcessor.process(DefaultProcessor.java:106)
        at ch.qos.logback.core.joran.GenericXMLConfigurator.processModel(GenericXMLConfigurator.java:216)
        at org.springframework.boot.logging.logback.SpringBootJoranConfigurator.processModel(SpringBootJoranConfigurator.java:133)
        at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:178)
        at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:123)
        at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:66)
        at org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LogbackLoggingSystem.java:292)
        at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:254)
        at org.springframework.boot.logging.logback.LogbackLoggingSystem.withLoggingSuppressed(LogbackLoggingSystem.java:472)
        at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:248)
        ... 25 more

The properties smtpHost and smtpUsername are properly resolved. Only the encoded password smtpPassword is not properly resolved.

sbklahr commented 3 months ago

The problem seems to be related only to Spring Boot or Logback and not to Jasypt. The problem occurred as I had a curly brace in smtpPassword.