EncryptingDataSourcePasswords

A simple login module for encrypting a datasource password

 

The org.jboss.resource.security.SecureIdentityLoginModule can be used to encrypt database passwords rather than using clear text passwords in the datasource configuration. It uses a hard-coded password to encrypt/decrypt the datasource password.

 

You can encrypt the datasource password using the SecureIdentityLoginModule main method by passing in the cleartext password, here shown as 'password':

 

Note: The example below was recently (21 June 2007) verified against JBoss AS 3.2.8.SP1, 4.0.0, 4.0.1sp1, 4.0.2, 4.0.3SP1, 4.0.4.GA, 4.0.5.GA, and 4.2.0.GA, using PostgreSQL 8.1.9-1, Sun JDK 1.5.0_11, and Fedora Core 6 (2.6.20-1.2952.fc6).

 

Second note: The JBoss 5.1 examples have been verified against JBoss AS 5.1.0 GA the 17 November 2009.

 

JBoss AS 3.2.x

 

From your JBoss 3.2.4 (or newer) home directory, invoke the secure identity login module like such:

[dward@dwardlinux jboss-3.2.8.SP1]$ java -cp lib/jboss-jmx.jar:lib/jboss-common.jar:server/default/deploy/jboss-jca.sar:server/default/lib/jbosssx.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

On Windows Operating System, use the following command

 

[dward@dwardlinux jboss-3.2.8.SP1]$ java -cp lib/jboss-jmx.jar;lib/jboss-common.jar;server/default/deploy/jboss-jca.sar;server/default/lib/jbosssx.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

JBoss AS 4.0.x or 4.2.x

 

From your JBoss 4.x home directory, invoke the secure identity login module like such:

 

[dward@dwardlinux jboss-4.0.5.GA]$ java -cp lib/jboss-common.jar:lib/jboss-jmx.jar:server/default/lib/jbosssx.jar:server/default/lib/jboss-jca.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

On Windows Operating System, use the following command

 

[dward@dwardlinux jboss-4.0.5.GA]$ java -cp lib/jboss-common.jar;lib/jboss-jmx.jar;server/default/lib/jbosssx.jar;server/default/lib/jboss-jca.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

JBoss AS 5.1.x

 

From your JBoss 5.x home directory, invoke the secure identity login module like such:

 

savas-ali-tokmens-macbook:jboss-5.1.0.GA alitokmen$ java -cp client/jboss-logging-spi.jar:common/lib/jbosssx.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

On Windows Operating System, use the following command

 

D:\JBoss\jboss-5.1.0.GA>java -cp client/jboss-logging-spi.jar;common/lib/jbosssx.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

JBoss AS 6.x

 

From your JBoss 6.x home directory, invoke the secure identity login module like such:

 

jboss-6.1.0.Final$ java -cp client/jboss-logging.jar:lib/jbosssx.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

On Windows Operating System, use the following command

 

D:\JBoss\jboss-6.1.0.Final>java -cp client/jboss-logging.jar;lib/jbosssx.jar org.jboss.resource.security.SecureIdentityLoginModule password
Encoded password: 5dfc52b51bd35553df8592078de921bc

 

The datasource -ds.xml should then not use the user-name and password settings, and instead specify the security-domain that maps to the login-config.xml entry for the SecureIdentityLoginModule config.

 

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
    <local-tx-datasource>
        <jndi-name>PostgresDS</jndi-name>
        <connection-url>jdbc:postgresql://127.0.0.1:5432/test?protocolVersion=2</connection-url>
        <driver-class>org.postgresql.Driver</driver-class>
        <min-pool-size>1</min-pool-size>
        <max-pool-size>20</max-pool-size>
        <!-- REPLACED WITH security-domain BELOW
        <user-name>admin</user-name>
        <password>password</password>
        -->
        <security-domain>EncryptDBPassword</security-domain>
        <metadata>
            <type-mapping>PostgreSQL 8.0</type-mapping>
        </metadata>
    </local-tx-datasource>
</datasources>

 

The login-config.xml entry for the EncryptDBPassword would look like:

<policy>
    <!-- Example usage of the SecureIdentityLoginModule -->
    <application-policy name="EncryptDBPassword">
        <authentication>
            <login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">
                <module-option name="username">admin</module-option>
                <module-option name="password">5dfc52b51bd35553df8592078de921bc</module-option>
                <module-option name="managedConnectionFactoryName">jboss.jca:name=PostgresDS,service=LocalTxCM</module-option>
            </login-module>
        </authentication>
    </application-policy>
</policy>

 

If you use a xa-datasource then the module-option name="managedConnectionFactoryName" should be:

<module-option name="managedConnectionFactoryName">jboss.jca:name=PostgresDS,service=XATxCM</module-option>

 

That's it!

 

A KeyStore based login module for encrypting a datasource password

 

The org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule is a login module for statically defining a data source username and password that uses a password that has been ecrypted by a JaasSecurityDomain. The base64 format of the data source password may be generated using the PBEUtils command:

 

 java -cp jbosssx.jar org.jboss.security.plugins.PBEUtils salt count
   domain-password data-source-password

 

The PBEUtils' command arguments are:

 

  • salt : the Salt attribute from the JaasSecurityDomain (MUST BE ONLY 8 characters long)

  • count : the IterationCount attribute from the JaasSecurityDomain

  • domain-password : the plaintext password that maps to the KeyStorePass attribute from the JaasSecurityDomain

  • data-source-password : the plaintext password for the data source that should be encrypted with the JaasSecurityDomain password

 

for example:

 

 java -cp jbosssx.jar org.jboss.security.plugins.PBEUtils abcdefgh 13 master ''
 Encoded password: E5gtGMKcXPP

 

A sample login-config.xml configuration entry would be:

 

 
 <application-policy name = "EncryptedHsqlDbRealm">
    <authentication>
       <login-module code = "org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule"
       flag = "required">
          <module-option name = "username">sa</module-option>
          <module-option name = "password">E5gtGMKcXPP</module-option>
          <module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=DefaultDS</module-option>
          <module-option name = "jaasSecurityDomain">jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</module-option>
       </login-module>
    </authentication>
 </application-policy>

 

The docs/examples/jca/hsqldb-encrypted-ds.xml illustrates that datasource configuration along with the JaasSecurityDomain configuration for the keystore:

 

<?xml version="1.0" encoding="UTF-8"?>

<!-- The Hypersonic embedded database JCA connection factory config
that illustrates the use of the JaasSecurityDomainIdentityLoginModule
to use encrypted password in the data source configuration. 

$Id: hsqldb-encrypted-ds.xml,v 1.1.2.1 2004/06/04 02:20:52 starksm Exp $ -->


<datasources>
   <local-tx-datasource>

      <!-- The jndi name of the DataSource, it is prefixed with java:/ -->
      <!-- Datasources are not available outside the virtual machine -->
      <jndi-name>DefaultDS</jndi-name>

      <!-- for tcp connection, allowing other processes to use the hsqldb
      database. This requires the org.jboss.jdbc.HypersonicDatabase mbean.
      <connection-url>jdbc:hsqldb:hsql://localhost:1701</connection-url>
      -->
      <!-- for totally in-memory db, not saved when jboss stops. 
      The org.jboss.jdbc.HypersonicDatabase mbean necessary
      <connection-url>jdbc:hsqldb:.</connection-url>
      -->
      <!-- for in-process persistent db, saved when jboss stops. The
      org.jboss.jdbc.HypersonicDatabase mbean is necessary for properly db shutdown
      -->
      <connection-url>jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB</connection-url>

      <!-- The driver class -->
      <driver-class>org.hsqldb.jdbcDriver</driver-class>

      <!--example of how to specify class that determines if exception means connection should be destroyed-->
      <!--exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyExceptionSorter</exception-sorter-class-name-->

      <!-- this will be run before a managed connection is removed from the pool for use by a client-->
      <!--<check-valid-connection-sql>select * from something</check-valid-connection-sql> -->

      <!-- The minimum connections in a pool/sub-pool. Pools are lazily constructed on first use -->
      <min-pool-size>5</min-pool-size>

      <!-- The maximum connections in a pool/sub-pool -->
      <max-pool-size>20</max-pool-size>

      <!-- The time before an unused connection is destroyed -->
      <!-- NOTE: This is the check period. It will be destroyed somewhere between 1x and 2x this timeout after last use -->
      <!-- TEMPORARY FIX! - Disable idle connection removal, HSQLDB has a problem with not reaping threads on closed connections -->
      <idle-timeout-minutes>0</idle-timeout-minutes>

      <!-- sql to call when connection is created
        <new-connection-sql>some arbitrary sql</new-connection-sql>
      -->

      <!-- sql to call on an existing pooled connection when it is obtained from pool 
         <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
      -->

      <!-- example of how to specify a class that determines a connection is valid before it is handed out from the pool
         <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.DummyValidConnectionChecker</valid-connection-checker-class-name>
      -->

      <!-- Whether to check all statements are closed when the connection is returned to the pool,
           this is a debugging feature that should be turned off in production -->
      <track-statements></track-statements>

      <!-- Use the getConnection(user, pw) for logins
        <application-managed-security></application-managed-security>
      -->

      <!-- Use the security domain defined in conf/login-config.xml -->
      <security-domain>EncryptedHsqlDbRealm</security-domain>

      <!-- This mbean can be used when using in process persistent hypersonic -->
      <depends>jboss:service=Hypersonic,database=localDB</depends>

      <!-- The datasource must depend on the mbean -->
      <depends>jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</depends>
   </local-tx-datasource>

   <!-- The JaasSecurityDomain used for encryption. Use the name
   "jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword"
   as the value of the JaasSecurityDomainIdentityLoginModule
   jaasSecurityDomain login module option in the EncryptedHsqlDbRealm
   login-config.xml section. Typically this service config should be in
   the conf/jboss-service.xml descriptor.
   The opaque master.password file could be created using: 
   java -cp jbosssx.jar org.jboss.security.plugins.FilePassword 12345678 17 master server.password

   The corresponding login-config.xml would look like:
    <application-policy name = "EncryptedHsqlDbRealm">
       <authentication>
          <login-module code = "org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule"
          flag = "required">
             <module-option name = "username">sa</module-option>
             <module-option name = "password">E5gtGMKcXPP</module-option>
             <module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=DefaultDS</module-option>
             <module-option name = "jaasSecurityDomain">jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</module-option>
          </login-module>
       </authentication>
    </application-policy>
    where the encrypted password was generated using:
     java -cp jbosssx.jar org.jboss.security.plugins.PBEUtils abcdefgh 13 master ''
     Encoded password: E5gtGMKcXPP
   -->
   <mbean code="org.jboss.security.plugins.JaasSecurityDomain"
      name="jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword">
      <constructor>
         <arg type="java.lang.String" value="ServerMasterPassword"></arg>
      </constructor>
      <!-- The opaque master password file used to decrypt the encrypted
      database password key -->
      <attribute name="KeyStorePass">{CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/server.password</attribute>
      <attribute name="Salt">abcdefgh</attribute>
      <attribute name="IterationCount">13</attribute>
   </mbean>

   <!-- This mbean can be used when using in process persistent db -->
   <mbean code="org.jboss.jdbc.HypersonicDatabase"
      name="jboss:service=Hypersonic,database=localDB">
      <attribute name="Database">localDB</attribute>
      <attribute name="InProcessMode">true</attribute>
   </mbean>
</datasources>

 

Addtional Link

JBoss Tip

 

 

Warnings

Remember to use the same salt and IterationCount in the MBean that was used during the password generation step. This has been explained in this blog tip.

 

Note

If you see this error:

 

Caused by: java.security.InvalidAlgorithmParameterException: Parameters missing
        at com.sun.crypto.provider.SunJCE_af.a(DashoA12275)
        at com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineInit(DashoA12275)
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.init(DashoA12275)
        at javax.crypto.Cipher.init(DashoA12275)
        at org.jboss.security.plugins.JaasSecurityDomain.decode(JaasSecurityDomain.java:325)
        at org.jboss.security.plugins.JaasSecurityDomain.decode64(JaasSecurityDomain.java:351)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
        ... 139 more

 

while starting a service that depends on the encrypted datasource it probably means that the mbean

 

(jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword)

 

is not yet started as a service. You need to include a:

 

<depends>

 

element to the datasource so that the mbean is started before the datasource.