3

The requirement:

We have a Java EE (Java 8) monolith that is run with JBoss EAP 7.1 and is using Hibernate as ORM tool. The task is to stop using hardcoded datasource credentials, but to use username and password that are loaded from Vault. The Vault implementation is already in place and the app successfully communicates with it.

We've achieved this in another app, which is Spring-based, in two ways:

  • using spring-cloud-starter-vault-config library;
  • using custom implementation that adds a PropertySource with spring.datasource.username and spring.datasource.password with higher priority than the default ones (basically the same thing the library achieves).

The current setup:

persistence.xml:

...
<persistence-unit name="pu" transaction-type="JTA">
    <jta-data-source>java:jboss/datasources/pu</jta-data-source>
    <properties>
        <property name="hibernate.connection.useUnicode" value="true"/>
        <property name="hibernate.connection.characterEncoding" value="UTF-8"/>
        <property name="hibernate.jdbc.batch_size" value="20"/>
        <property name="hibernate.cache.use_query_cache" value="false" />
        <property name="hibernate.cache.use_second_level_cache" value="false" />
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.format_sql" value="false" />
    </properties>
</persistence-unit>

<persistence-unit name="container-unmanaged" transaction-type="RESOURCE_LOCAL">
    ... {another persistence unit}
</persistence-unit>
...

standalone.xml:

            <datasource jta="true" jndi-name="java:jboss/datasources/pu" pool-name="pupool" enabled="true" use-java-context="true" use-ccm="false">
                <connection-url>{TheConnectionUrl}</connection-url>
                <driver-class>org.postgresql.Driver</driver-class>
                <driver>postgresql</driver>
                <pool>
                    <min-pool-size>2</min-pool-size>
                    <max-pool-size>20</max-pool-size>
                </pool>
                <security>
                    <user-name>{TheUserName}</user-name>
                    <password>{ThePassword}</password>
                </security>
                <validation>
                    <validate-on-match>false</validate-on-match>
                    <background-validation>true</background-validation>
                    <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
                    <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
                    <background-validation-millis>5000</background-validation-millis>
                </validation>
                <statement>
                    <prepared-statement-cache-size>0</prepared-statement-cache-size>
                    <share-prepared-statements>false</share-prepared-statements>
                </statement>
            </datasource>

In other words, I want to get rid of <user-name> and <password> from the standalone.xml configuration, and provide those at runtime (having already loaded them from Vault).

What's been tried:

I've reviewed multiple questions and articles, expecting that what I'm trying to do would be fairly simple, or at least that many others have been looking for a solution, but none of the suggestions seem to work. For example:

  • the requirement here seems like what I need, but the credentials should be provided by the app, at runtime;
  • this article also seems very similar, but when I try to implement it, it looks like the login module mentioned there should be used for users of the app to login. Anyway, I couldn't get it to work;
  • I've also reviewed and tried to implement Vlad Mihalcea's article on how to bootstrap w/o replying on persistence.xml file. However, I'm not trying to substitute the whole file, but rather just intercept it at runtime, add the credentials and let it do its work. And what is more, I couldn't add the hibernate.datasource.username and hibernate.datasource.password to the properties() provided at runtime; I get the The server requested password-based authentication, but no password was provided. message (of course after removing the credentials from standalone.xml).

Note: I don't want to encrypt the password, but provide it programmatically at runtime.

So, is there a way to do it just like in Spring, or should it be done differently?

Thanks!

Valentin
  • 81
  • 5
  • 1
    Were you able to achieve a solution for this because I am also trying to implement a similar kind of approach? Please let me know if you have any other inputs. I was trying this ref [link][1] but couldn't find the relevant answers. [1]: https://stackoverflow.com/questions/26465493/wildfly-set-datasource-password-at-runtime – Madhusudhan G Revankar Nov 10 '20 at 07:24
  • Unfortunately, no :/ I ended up working around this by calling vault via the deployment job of the app and then passing the credentials as arguments to the Java app. Obviously, not how I wanted it to be done, but deadline was approaching and this workaround satisfies the requirement. I'd still appreciate an answer should someone has a working solution. – Valentin Nov 11 '20 at 11:36

0 Answers0