OpenLiberty / open-liberty

Open Liberty is a highly composable, fast to start, dynamic application server runtime environment
https://openliberty.io
Eclipse Public License 2.0
1.15k stars 592 forks source link

Consistent handling of environment variable keystore_password #14777

Open skedi opened 4 years ago

skedi commented 4 years ago

Describe the bug

In configuring a keystore in server.xml, we recognized that the environment variable keystore_password is not handled as it is described generally for environment variables in the open liberty reference for server configuration ( https://openliberty.io/docs/20.0.0.11/reference/config/server-configuration-overview.html ):

For example, if you enter ${my.env.var} in the server.xml file, it looks for environment variables with the following names: my.env.var my_env_var MY_ENV_VAR

Open liberty accepts this environment variable under windows regardless of whether it is written uppercase or lower-case. On an unixoid system only lower-case gets accepted.

Steps to Reproduce

Provide a keystore with a custom password Configure this keystore in server.xml and do not set a password for this keystore in server.xml Start open liberty through maven with liberty:dev goal and configure the openliberty-runtime with true and provide a KEYSTORE_PASSWORD environment variable with the keystore custom password Here an example:

<plugin>
                    <groupId>io.openliberty.tools</groupId>
                    <artifactId>liberty-maven-plugin</artifactId>
                    <configuration>
                        <assemblyArtifact>
                            <groupId>io.openliberty</groupId>
                            <artifactId>openliberty-runtime</artifactId>
                            <version>${version.openliberty-runtime}</version>
                            <type>zip</type>
                        </assemblyArtifact>
                        <serverName>${server.name}</serverName>
                        <configFile>${project.build.directory}/server.xml</configFile>
                        <looseApplication>true</looseApplication>
                        <packageFile>${package.file}</packageFile>
                        <include>${packaging.type}</include>
                        <noPassword>true</noPassword>
                        <bootstrapProperties>
                            <default_http_port>${http.port}</default_http_port>
                            <default_https_port>${https.port}</default_https_port>
                        </bootstrapProperties>
                        <applications>${project.build.finaName}</applications>
                        <copyDependencies>
                            <location>lib/global</location>
                            <dependency>
                                <groupId>com.h2database</groupId>
                                <artifactId>h2</artifactId>
                            </dependency>
                            <dependency>
                                <groupId>${productiv.jdbc.driver.groupid}</groupId>
                                <artifactId>${productiv.jdbc.driver.artifactid}</artifactId>
                            </dependency>
                        </copyDependencies>
                        <clean>true</clean>
                        <cleanApps>true</cleanApps>
                        <cleanDropins>true</cleanDropins>
                    </configuration>
</plugin>

Expected behavior

Regardless through which notation (keystore.password, KEYSTORE_PASSWORD, keystore_password, etc. ) the environment variable keystore password gets provided, open liberty opens the provided keystore in the server.xml with the set password.

Diagnostic information:

Openliberty 20.0.0.x Java Version: AdoptOpenJdk 11 on Openj9 or Hotspot server.xml configuration:


<server description="Service Liberty">
    <featureManager>
        <feature>cdi-2.0</feature>
        <feature>concurrent-1.0</feature>       
        <feature>ejbLite-3.2</feature>
        <feature>jaxrs-2.1</feature>
        <feature>jpaContainer-2.2</feature>
        <feature>mpConfig-1.4</feature>
        <feature>mpHealth-2.2</feature>
        <feature>mpJwt-1.1</feature>
        <feature>mpMetrics-2.3</feature>
        <feature>mpRestClient-1.4</feature>
        <feature>transportSecurity-1.0</feature>
    </featureManager>

    <managedExecutorService
        jndiName="service/schedule/timer">
        <contextService>
            <jeeMetadataContext />
            <classloaderContext />
        </contextService>
    </managedExecutorService>

    <keyStore id="defaultKeyStore" updateTrigger="polled"
        location="${liberty.security}/key.p12">
    </keyStore>

    <keyStore id="defaultTrustStore" updateTrigger="polled"
        location="${liberty.security}/trustStore.p12" />

    <ssl id="ssl" keyStoreRef="defaultKeyStore"
        clientAuthenticationSupported="true" trustStoreRef="defaultTrustStore"
        trustDefaultCerts="true" verifyHostname="true" />

    <sslDefault sslRef="ssl" />

    <applicationManager autoExpand="true" />

    <httpEndpoint host="*" httpPort="${default_http_port}"
        httpsPort="${default_https_port}" id="defaultHttpEndpoint" />

    <mpMetrics authentication="false" />

    <application location="${project.build.finalName}.war"
        context-root="/" />

    <library id="jdbcDriverLibrary">
        <fileset caseSensitive="false" dir="${server.config.dir}/lib/global"
            includes="${datasource_jdbc_driver_jar}" />
    </library>

    <dataSource id="defaultDataSource"
        jndiName="jdbc/serviceDatasource" 
        queryTimeout="20m" >
        <jdbcDriver
            javax.sql.DataSource="${datasource_jdbc_javax_sql_datasource}"
            libraryRef="jdbcDriverLibrary">
        </jdbcDriver>
        <properties URL="${datasource_jdbc_url}"
            user="${datasource_jdbc_user}" password="${datasource_jdbc_password}" />
    </dataSource>

    <transaction totalTranLifetimeTimeout="20m" />

    <mpJwt id="jwtUserConsumer"
        userNameAttribute="preferred_username"
        audiences="${list(jwt_audiences)}" sslRef="ssl" />

</server>
NottyCode commented 4 years ago

Looks like the security code is calling System.getenv for keystore_password rather than going through the config runtime which should solve this. The code is here:

https://github.com/OpenLiberty/open-liberty/blob/b1af3030244fcec13c62dbd6b6493794c848d55b/dev/com.ibm.ws.ssl/src/com/ibm/ws/ssl/config/WSKeyStore.java#L304

It should be possible to update the metatype for the attribute to have ibm:variable="keystore_password" which should cause the variable to be used if it isn't explicitly configured and provide the expected behaviour. That would mean removing the callback code form WSKeyStore. Alternatively using the VariableRegistry should result in the desired behaviour.