lift / framework

Lift Framework
http://liftweb.net
Apache License 2.0
1.27k stars 278 forks source link

Lift4: Support for Env Vars in configuration #2011

Open dpp opened 1 year ago

dpp commented 1 year ago

Lift's properties/configuration mechanism is based on named files. However, this means storing secrets (e.g., DB credentials, etc.) in files and potentially checking those files into source control systems. Yikes!!

The industry is moving to using Env Vars for configuration/secrets.

The proposal is to extend Lift's configuration system to support referencing Env Vars from configuration files (Rust has an env!(...) macro.

Thus if a line in a configuration file looks like:

foo.bar.baz=env!("VAR_NAME")

Lift's configuration system will read the env var and if the env var isn't define, the config system will throw an exception which will halt the Lift boot cycle.

andreak commented 1 year ago

Many projects use Spring Boot and use its properties-loading mechanism.; It'd be nice if we could weave in some kind of interop with Spring Boot's properties.

dpp commented 1 year ago

Do you have a pointer to the Spring Boot properties package? Lemme see if I can do something with reflection so if it's there, it'll be used.

andreak commented 1 year ago

We inject Spring's org.springframework.core.env.Environment in Boot:

@Configurable
class Boot extends VisenaLoggable {

    @Resource(name = "origoDecoratorProvider")
    val decoratorProvider: ExecutionTaskDecoratorProvider = null
    @Resource(name = "liftSchedulerExecutor")
    val liftSchedulerExecutor: ExecutorService = null
    @Resource
    val springEnvironment: Environment = null

    def boot(): Unit = {

....
....
        LiftRules.ajaxRetryCount = Full(springEnvironment.getProperty("ajax.retryCount", classOf[Int]))

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/env/Environment.html

We use AspectJ's META-INF/aop.xml to configure how Spring should process "non-Spring managed classes":

<aspectj>
    <weaver options="-verbose -showWeaveInfo -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler">
        <!--
        Only weave @Configurable stuff
        -->
        <include within="@org.springframework.beans.factory.annotation.Configurable no.officenet.origo..*"/>
        <include within="@org.springframework.beans.factory.annotation.Configurable com.visena..*"/>
        <include within="@org.springframework.beans.factory.annotation.Configurable bootstrap.liftweb.Boot"/>
    </weaver>

</aspectj>
lvitaly commented 1 year ago

Maybe it is worth supporting different config providers? For example, lightbend/config supports env variable out of the box.

dpp commented 1 year ago

I am suggesting a very simple extension to the existing Props mechanism that allows injection of environment variables into properties.

There's nothing in Lift that defaults to using the Props system... it's mostly stand-alone.

If there are other properties systems that are used with other systems, why not use those natively in the Lift app rather than trying to wrap Props (which is simple and dumb by design) around them?