Wildfly - set datasource password at runtime

jboss eap 7 encrypt datasource password
jboss datasource configuration file
jboss eap 7 - datasource configuration example
wildfly datasource mysql
how to configure jndi in jboss 7
wildfly datasource configuration oracle
wildfly dynamic datasource
jboss datasource enabled

I am developing a server application using Jboss wildfly 8.1 and JPA Hibernate. The problem is, that the JPA datasource creditials have to be loaded at runtime (password). When the server starts, it connects to an encrypted storage where it retrieves password to real database. After that, it should establish connection to the real database.

I tried several things already: Lookup the datasource through JNDI and rebind it with actual DS. Lookup the entityManagerFactory through JNDI and rebind it with custom EntityManager.

but none of these work. Do you have idea how to solve it?

my config:

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0">
   <persistence-unit name="PERSISTENCE_UNIT" transaction-type="JTA">
      <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

      <jta-data-source>java:jboss/datasources/Datasource</jta-data-source>
      ...classes...

      <properties>
        <!-- Properties for Hibernate -->               
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        <property name="hibernate.hbm2ddl.auto" value="update"/>
        <property name="hibernate.show_sql" value="false"/>
        <property name="hibernate.format_sql" value="false"></property>
        <property name="hibernate.connection.useUnicode" value="true"/>
        <property name="hibernate.connection.characterEncoding" value="UTF-8"/>
        <property name="hibernate.connection.charSet" value="UTF-8"/>
        <property name="org.hibernate.flushMode" value="commit" /> <!-- THIS ONE IS IMPORTANT -->

        <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactory"/>
        <property name="jboss.entity.manager.jndi.name" value="java:/Manager1"/>
      </properties>      
   </persistence-unit>
</persistence>

datasource (defined in standalone.xml):

            <datasource jndi-name="java:jboss/datasources/Datasource" pool-name="DS" enabled="true" use-java-context="true">
                <connection-url>jdbc:mysql://localhost:3306/repository</connection-url>
                <connection-property name="useCompression">
                    false
                </connection-property>
                <connection-property name="logSlowQueries">
                    false
                </connection-property>
                <connection-property name="zeroDateTimeBehavior">
                    convertToNull
                </connection-property>
                <connection-property name="characterEncoding">
                    utf8
                </connection-property>
                <connection-property name="useUnicode">
                    true
                </connection-property>
                <connection-property name="connectionCollation">
                    utf8_unicode_ci
                </connection-property>
                <driver>mysql</driver>
                <security>
                    <user-name>user</user-name>
                    <password>TO_BE_DEFINED</password>
                </security>
            </datasource>

accessing entity manager:

@Stateless
@Local
public class GenericDataBean {

    @PersistenceContext(type=PersistenceContextType.TRANSACTION)
    private EntityManager em;

...
}

A possible solution for your problem is use a security domain for the datasource. In your case you must create custom login module responsible to load password from encrypted storage. Your configuration should be similar to.

Datasource:

<datasource ... >
   .....
   <security>
          <security-domain>EncryptedPassword</security-domain>
   </security>
</datasource>

Security Donain:

<security-domain name="EncryptedPassword">
    <authentication>
        <login-module code="com.example.EncryptedPasswordLoginModule" flag="required">
            <!-- list of options -->
            <module-option name="username" value="theusername"/>
            <module-option name="managedConnectionFactoryName" value="jboss.jca:service=LocalTxCM,name=DS"/>
        </login-module>
    </authentication>
</security-domain>

Login module implementation:

public class EncryptedPasswordLoginModule
    extends AbstractPasswordCredentialLoginModule{

    private String username;

    public void initialize(Subject subject, CallbackHandler handler, Map sharedState, Map options){
        super.initialize(subject, handler, sharedState, options);
        username = (String) options.get("username");
        if( username == null ){
            throw new IllegalArgumentException("The user name is a required option");
        }

    }   

    public boolean login() throws LoginException{
        if( super.login() == true )
            return true;

        super.loginOk = true;
        return true;
    }

   public boolean commit() throws LoginException{
        Principal principal = new SimplePrincipal(username);
        SubjectActions.addPrincipals(subject, principal);
        sharedState.put("javax.security.auth.login.name", username);
        try{
            char[] password = .... //code to load encrypted password;
            PasswordCredential cred = new PasswordCredential(username, password);
            cred.setManagedConnectionFactory(getMcf());
            SubjectActions.addCredentials(subject, cred);
        }
        catch(Exception e){
            throw new LoginException("Failed to load encrypted password: "+e.getMessage());
        }
        return true;
   }

   public boolean abort(){
        username = null;
        return true;
   }

   protected Principal getIdentity(){
      Principal principal = new SimplePrincipal(username);
      return principal;
   }

   protected Group[] getRoleSets() throws LoginException{
      Group[] empty = new Group[0];
      return empty;
   }
}

maybe this can help.

Data source configuration during runtime |JBoss.org Content , There is a system A that admins have access to and whre they put However when database username or password changes I have no idea  This tutorial explains 3 methods how to add a datasource to the application server Wildfly from Redhat. If you don't have Wildfly installed on your machine, you can follow my other posts: Windows: How to install WildFly on Windows Mac: How to install Wildfly on Mac Prerequisites Even if these steps are driver-agnostic, the example will use MySQL Connector…


How you are access the class SubjectActions? the class access modifier is default so it is throwing error at compile time error: class EncryptedPasswordLoginModule is public, should be declared in a file named EncryptedPasswordLoginModule.java

Chapter 15. Encrypting Data Source Passwords, Create an application authentication policy with the encrypted password. Configure the data source to use the application authentication policy. 15.1.1. Encrypt the  Within WildFly 18 for communication with the management interfaces and for other services exposed using Remoting where username / password authentication is used the use of Digest authentication is preferred over the use of HTTP Basic or SASL Plain so that we can avoid the sending of password in the clear over the network.


@javaguy this is my full class, hope it helps

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.resource.spi.security.PasswordCredential;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

/**
 * This is an Authentication module that fetches credentials from a file
 * This will be used in Cloud scenarios 
 * 
 */
public class FileLoginModule implements LoginModule {

    private static final Logger LOG = Logger.getLogger(MaterialLoginModule.class.getName());

    private Subject subject;
    private Map shared;
    private Map options;

    @Override
    public void initialize(Subject subject, CallbackHandler handler, Map<String, ?> shared, Map<String, ?> options) {
        this.subject = subject;
        this.shared = shared;
        this.options = options;

        LOG.log(Level.INFO, "Options: {0}", options);
    }

    @Override
    public boolean login() throws LoginException {

        try {
            String filePath = (String) this.options.get("creds");
            LOG.log(Level.FINE, "Fetching credentials from {0}", filePath);
            Path path = Paths.get(filePath);
            List<String> lines = Files.readAllLines(path);
            Iterator<String> it = lines.iterator();
            this.shared.put("user", it.hasNext() ? it.next() : "");
            this.shared.put("pass", it.hasNext() ? it.next().toCharArray() : null);
            return true;
        } catch (IOException e) {
            LOG.log(Level.SEVERE, e.getMessage(), e);
        }

        return false;
    }

    @Override
    public boolean commit() throws LoginException {
        subject.getPrivateCredentials().add(new PasswordCredential((String) this.shared.get("user"), (char[]) this.shared.get("pass")));
        LOG.log(Level.FINE, "Commiting...");
        return true;
    }

    @Override
    public boolean logout() throws LoginException {
        LOG.log(Level.INFO, "logging OUT {0}");
        return true;
    }

    @Override
    public boolean abort() throws LoginException {
        LOG.log(Level.INFO, "abort");
        return true;
    }
}

How to configure a Datasource with JBoss / WildFly, A datasource is defined into the datasources subsystem. Datasources in JBoss AS 7 are not defined anymore using -ds.xml file as you did for  Wildfly - set datasource password at runtime. I am developing a server application using Jboss wildfly 8.1 and JPA Hibernate. The problem is, that the JPA datasource creditials have to be loaded at runtime (password). When the server starts, it connects to an encrypted storage where it retrieves password to real database.


WildFly Datasource configuration, A collection of tutorials for Jboss and WildFly on Datasource In this tutorial we will learn how to configure connections to Databases using WildFly / JBoss AS 7 --driver-name=mysql --user-name=jboss --password=passwd. WildFly 18 is an exceptionally fast, lightweight and powerful implementation of the Jakarta Platform specifications. The state-of-the-art architecture built on the Modular Service Container enables services on-demand when your application requires them. The table below lists the technologies available in WildFly 18 server configuration profiles.


How to add a datasource to Wildfly – hotkey blog, steps in common: Add the JDBC Driver (a.k.a. Connector); Configure you datasource The runtime name is how is known to the server. This way you You can also configure the username, password and database name. Brian Stansberry Nov 14, 2019 WildFly 18.0.1 is released! WildFly 18.0.1 Final is now available for download. It’s been over a month since the WildFly 18 release and we had a number of important bug fixes and component upgrades ready to go so we decided to do a WildFly 18.0.1 release. Follow @WildFlyAS Tweets by @WildFlyAS.


Chapter 17. Encrypting Data Source Passwords JBoss Enterprise , 17.1.3. Configure the data source to use the application authentication policy. At run-time the application policy is bound to JNDI under the  The DATASOURCES declaration defines the prefix for our data source, in this case the prefix is DATABASE_SERVER. By using this definition, the WildFly S2I configuration scripts will pick up the database host name and port from the following variables: