Unencrypted ldap.adminpassword property in postgres database

Hi everyone,

I’d appreciate some help regarding OpenLdap bind password encryption.
I’m working on a Kubernetes pod-based, touchless deployment of Openfire (using version 4.7.5). I configure OpenLdap via the openfire.xml file, but for some reason, the ldap.adminpassword ends up stored in the database in plain text.

Here’s an overview of what happens during the Openfire deployment process—after the PostgreSQL database pod is up, but before Openfire’s first startup:

  1. The original openfire.xml and security.xml files are deleted, and my custom-configured versions (provided via a ConfigMap) are copied into /etc/openfire.
  2. The database schema is checked and loaded if needed.
  3. Openfire is started using the startup.jar file.

The OpenLDAP bind password is specified via the ldap.adminPassword property, but for some reason it’s not being encrypted when saved to the database.

My openfire.xml includes the following:

<jive>
  <ldap>
    <adminPassword>password</adminPassword>
  </ldap>
</jive>

And in security.xml, I’ve also listed this property for encryption:

<security>
  <encrypt>
    <property>
      <name>database.defaultProvider.username</name>
      <name>database.defaultProvider.password</name>
      <name>ldap.adminpassword</name>
    </property>
  </encrypt>
</security>

Could you please help me figure out how to ensure the ldap.adminpassword gets stored in the database in encrypted form?

Thanks in advance for any help

Hi Miklos!

Going through an entire Kubernetes setup is a bit more effort than what I have available right now, but I do think that I can be of some help.

  1. In your security.xml example, it is important to use the exact casing of the property name.

    You have:

    <name>ldap.adminpassword</name>
    

    This needs to be:

    <name>ldap.adminPassword</name>
    

    Note that difference in the letter P.

  2. When testing this, I found a problem in Openfire (I’m using the latest development version, which is currently a snapshot that will become release 5.1.0). Openfire fails to startup successfully, with the configuration that you’re trying to have.

    I have documented this problem as OF-3175.

I am working on a fix for this problem, which I think is ready to be merged. With this fix, when I use this content for openfire.xml:

<?xml version="1.0" encoding="UTF-8"?>
<jive>
  <adminConsole>
      <port>9090</port>
      <securePort>9091</securePort>
  </adminConsole>
  <connectionProvider>
    <className>org.jivesoftware.database.EmbeddedConnectionProvider</className>
  </connectionProvider>
  <ldap>
      <host>127.0.0.1</host>
      <port>10389</port>
      <baseDN>dc=planetexpress,dc=com</baseDN>
      <adminDN>cn=admin,dc=planetexpress,dc=com</adminDN>
      <adminPassword>GoodNewsEveryone</adminPassword>
      <sslEnabled>false</sslEnabled>
  </ldap>
  <autosetup>
      <run>true</run>
      <locale>en</locale>
      <xmpp>
          <auth>
              <anonymous>true</anonymous>
          </auth>
          <domain>example.org</domain>
          <fqdn>example.org</fqdn>
      </xmpp>
      <database>
          <mode>embedded</mode>
      </database>
      <admin>
          <email>admin@example.com</email>
          <password>admin</password>
      </admin>
  </autosetup>
</jive>

and this content for security.xml:

<?xml version="1.0" encoding="UTF-8"?>
<security>
  <encrypt>
    <algorithm>Blowfish</algorithm>
    <key>
       <current />
    </key>
    <property>
      <name>database.defaultProvider.username</name>
      <name>database.defaultProvider.password</name>
      <name>ldap.adminPassword</name>
    </property>
  </encrypt>  

Then, after startup of Openfire, the openfire.xml file gets modified like this:

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

<jive> 
  <adminConsole> 
    <port>9090</port>  
    <securePort>9091</securePort> 
  </adminConsole>  
  <connectionProvider> 
    <className>org.jivesoftware.database.EmbeddedConnectionProvider</className> 
  </connectionProvider>  
  <ldap> 
    <host>127.0.0.1</host>  
    <port>10389</port>  
    <baseDN>dc=planetexpress,dc=com</baseDN>  
    <adminDN>cn=admin,dc=planetexpress,dc=com</adminDN>  
    <adminPassword encrypted="true" iv="gejFrZByxi1LdgROGMgwQA==">a3604dcda1d170a6db7d317168c960c9c84f48e520eb1f7da3ce1793e7e1149cb6a6167d48d24662cc703917968c6>
    <sslEnabled>false</sslEnabled> 
  </ldap>  
  <setup>true</setup> 
  <locale>en</locale> 
  <fqdn>example.org</fqdn>
</jive>

and the database gets modified like this (the password is added as a plaintext value, then removed, then re-added as an encrypted value):

COMMIT
INSERT INTO OFPROPERTY VALUES('ldap.host','127.0.0.1',0,NULL)
COMMIT
INSERT INTO OFPROPERTY VALUES('ldap.port','10389',0,NULL)
COMMIT
INSERT INTO OFPROPERTY VALUES('ldap.baseDN','dc=planetexpress,dc=com',0,NULL)
COMMIT
INSERT INTO OFPROPERTY VALUES('ldap.adminDN','cn=admin,dc=planetexpress,dc=com',0,NULL)
COMMIT
INSERT INTO OFPROPERTY VALUES('ldap.adminPassword','GoodNewsEveryone',0,NULL)
COMMIT
DELETE FROM OFPROPERTY WHERE NAME='ldap.adminPassword'
INSERT INTO OFPROPERTY VALUES('ldap.adminPassword','f5a477a06c079be474f57626b1064b3872d6815ef9fb5924ae0d8b4b12a63f46bc077a4edc15327a3a01f882bcc80c2e',1,'+XDIoI+ClAIFNFBESIexqA==')
COMMIT
INSERT INTO OFPROPERTY VALUES('ldap.sslEnabled','false',0,NULL)
COMMIT

I believe that this shows that your problem is addressed.

Hello Guus,
Thank you very much for the quick response.
I will test what you suggested in a few days and report back on the results.

Hello Guus,
I tested the configuration you recommended and came to the following:If I use embedded database, the encryption works fine, but if I use a Postgres database, the ldap admin password is still saved as plain text at the end of the deployment. The only change I made to the openfire.xml configuration was that I had to remove the database part from the autosetup part because the deployment could not find the database provider only if the database part was used outside of the autosetup.

<?xml version="1.0" encoding="UTF-8"?>
<jive>
  <adminConsole>
	<port>{{ .Values.openfire.adminConsole.httpPort }}</port>
	<securePort>{{ .Values.openfire.adminConsole.httpsPort }}</securePort>
  </adminConsole>
  <connectionProvider>
	<className>org.jivesoftware.database.DefaultConnectionProvider</className>
  </connectionProvider>

  <database>
	<defaultProvider>
	  <driver>org.postgresql.Driver</driver>
	  <serverURL>jdbc:postgresql://{{ include "openfire.fullname" . }}-postgres:5432/openfire</serverURL>
	  <username>openfire</username>
	  <password>${DB_PASSWORD}</password>
	  <testSQL>select 1</testSQL>
	  <testBeforeUse>false</testBeforeUse>
	  <testAfterUse>false</testAfterUse>
	  <minConnections>5</minConnections>
	  <maxConnections>25</maxConnections>
	  <connectionTimeout>1.0</connectionTimeout>
	</defaultProvider>
  </database>

  <autosetup>
	  <run>true</run>
	  <locale>en</locale>
	  <xmpp>
		  <auth>
			  <anonymous>true</anonymous>
		  </auth>
		  <domain>testopenfire.services</domain>
		  <fqdn>chat.testopenfire.services</fqdn>
	  </xmpp>
	  <admin>
		  <email>admin@example.com</email>
		  <password>admin</password>
	  </admin>
  </autosetup>

  <provider>
	<user>
	  <className>org.jivesoftware.openfire.ldap.LdapUserProvider</className>
	</user>
	<group>
	  <className>org.jivesoftware.openfire.ldap.LdapGroupProvider</className>
	  <groupBasedAdminProvider>
		<groupName>{{ .Values.ldap.adminGroup }}</groupName>
	  </groupBasedAdminProvider>
	</group>
	<auth>
	  <className>org.jivesoftware.openfire.ldap.LdapAuthProvider</className>
	</auth>
	<admin>
	  <className>org.jivesoftware.openfire.admin.GroupBasedAdminProvider</className>
	</admin>
  </provider>
  <ldap>
	<host>{{ .Values.ldap.host }}</host>
	<port>{{ .Values.ldap.port }}</port>
	<usernameField>cn</usernameField>
	<baseDN>{{ .Values.ldap.baseDN }}</baseDN>
	<nameField>cn</nameField>
	<searchFilter>(&amp;(objectClass=inetOrgPerson)(cn={0}))</searchFilter>
	<groupNameField>cn</groupNameField>
	<adminPassword>${LDAP_PASSWORD}</adminPassword>
	<groupMemberField>member</groupMemberField>
	<groupDescriptionField>description</groupDescriptionField>
	<posixMode>false</posixMode>
	<groupSearchFilter>(objectClass=groupOfNames)</groupSearchFilter>
	<adminDN>{{ .Values.ldap.adminDN }}</adminDN>
	<connectionProtocol>{{ .Values.ldap.connectionProtocol }}</connectionProtocol>
	<connectionPoolEnabled>{{ .Values.ldap.connectionPoolEnabled }}</connectionPoolEnabled>
	<sslEnabled>{{ .Values.ldap.sslEnabled }}</sslEnabled>
	<startTlsEnabled>{{ .Values.ldap.startTlsEnabled }}</startTlsEnabled>
  </ldap>
</jive>

and the security.xml

<?xml version="1.0" encoding="UTF-8"?>
<security>
  <encrypt>
	<algorithm>Blowfish</algorithm>
	<key>
	  <current></current>
	</key>
	<property>
	  <name>database.defaultProvider.username</name>
	  <name>database.defaultProvider.password</name>
	  <name>ldap.adminPassword</name>
	</property>
  </encrypt>
</security>

Plain text ldap admin password is: 0GnNNNMJ6pQTxsIW
The following Postgres log shows that Openfire encrypts the ldap.adminPassword, but for some reason it updates it again with the plain text password after encryption, so it ends up remaining in the database in plain text format.

2026-02-16 19:20:51.736 UTC [110] DETAIL:  parameters: $1 = 'ldap.adminPassword', $2 = '0GnNNNMJ6pQTxsIW', $3 = '0', $4 = NULL
2026-02-16 19:20:51.736 UTC [110] LOG:  execute S_1: INSERT INTO ofProperty(name, propValue, encrypted, iv) VALUES($1,$2,$3,$4)
2026-02-16 19:20:51.736 UTC [110] DETAIL:  parameters: $1 = 'ldap.adminPassword', $2 = '0GnNNNMJ6pQTxsIW', $3 = '0', $4 = NULL
2026-02-16 19:20:51.736 UTC [110] LOG:  duration: 0.092 ms
2026-02-16 19:20:51.742 UTC [110] LOG:  duration: 3.043 ms  parse <unnamed>: UPDATE ofProperty SET propValue=$1, encrypted=$2, iv=$3 WHERE name=$4
2026-02-16 19:20:51.742 UTC [110] LOG:  duration: 0.114 ms  bind <unnamed>: UPDATE ofProperty SET propValue=$1, encrypted=$2, iv=$3 WHERE name=$4
2026-02-16 19:20:51.742 UTC [110] DETAIL:  parameters: $1 = 'f9639af92b2f895acc4e4ec8dad33cf455b10d3ee9eaeeddfd0cca8acf862c4159f1c73933530d716d6e409a5ad8184b', $2 = '1', $3 = 'gno1Vz5i3TGB3UrUxcAdkA==', $4 = 'ldap.adminPassword'
2026-02-16 19:20:51.742 UTC [110] LOG:  execute <unnamed>: UPDATE ofProperty SET propValue=$1, encrypted=$2, iv=$3 WHERE name=$4
2026-02-16 19:20:51.742 UTC [110] DETAIL:  parameters: $1 = 'f9639af92b2f895acc4e4ec8dad33cf455b10d3ee9eaeeddfd0cca8acf862c4159f1c73933530d716d6e409a5ad8184b', $2 = '1', $3 = 'gno1Vz5i3TGB3UrUxcAdkA==', $4 = 'ldap.adminPassword'
2026-02-16 19:20:51.745 UTC [110] LOG:  duration: 2.195 ms
2026-02-16 19:20:51.764 UTC [110] LOG:  duration: 0.100 ms  parse <unnamed>: UPDATE ofProperty SET propValue=$1, encrypted=$2, iv=$3 WHERE name=$4
2026-02-16 19:20:51.764 UTC [110] LOG:  duration: 0.105 ms  bind <unnamed>: UPDATE ofProperty SET propValue=$1, encrypted=$2, iv=$3 WHERE name=$4
2026-02-16 19:20:51.764 UTC [110] DETAIL:  parameters: $1 = '0GnNNNMJ6pQTxsIW', $2 = '0', $3 = NULL, $4 = 'ldap.adminPassword'
2026-02-16 19:20:51.764 UTC [110] LOG:  execute <unnamed>: UPDATE ofProperty SET propValue=$1, encrypted=$2, iv=$3 WHERE name=$4
2026-02-16 19:20:51.764 UTC [110] DETAIL:  parameters: $1 = '0GnNNNMJ6pQTxsIW', $2 = '0', $3 = NULL, $4 = 'ldap.adminPassword'
2026-02-16 19:20:51.764 UTC [110] LOG:  duration: 0.082 ms

My code does not contain any sql commands, Openfire is only configured via xml files.

Based on what I wrote, do you have any ideas on where I should go next?
Thank you in advance for your help.

Miklos