3

Background

Plain old Java application, no web servers attached (not even JBoss), is using JPA to query a database.

Problem

The JDBC password is exposed in persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="PU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:postgresql:DATABASE"/>
      <property name="javax.persistence.jdbc.user" value="USERNAME"/>
      <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
      <property name="javax.persistence.jdbc.password" value="PASSWORD"/>
      <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
      <property name="hibernate.hbm2ddl.auto" value="validate"/>
    </properties>
  </persistence-unit>
</persistence>

Idea

It might be possible to instantiate a JNDI subcontext to set the password within the application's main method. This would possibly permit using a JTA data source:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
  <persistence-unit name="PU" transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>

Question

How would you externalize the password such that it no longer exists inside persistence.xml?

Note: persistence.xml is stored in a public repository, so it would be nice if the password wasn't screaming 'please hack me'. Instead, the JDBC connection information should be in a file that doesn't get checked into the repository.

Community
  • 1
  • 1
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
  • 1
    http://openjpa.208410.n2.nabble.com/How-to-encrypt-DB-password-in-persistence-xml-td2868212.html JNDI or pass the password from the app. – Tim Biegeleisen Jun 20 '16 at 04:52

1 Answers1

8

The password can be externalized by overriding the properties when instantiating the EntityManagerFactory:

  private EntityManagerFactory getEntityManagerFactory() {
    return Persistence.createEntityManagerFactory( getPersistenceUnitName(),
      getProperties() );
  }

  private Map getProperties() {
    Map result = new HashMap();

    // Read the properties from a file instead of hard-coding it here.
    // Or pass the password in from the command-line.
    result.put( "javax.persistence.jdbc.password", "PASSWORD" );

    return result;
  }
Community
  • 1
  • 1
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315