Encrypt Sensitive Attributes in 389 Directory Server

Enable per-backend attribute encryption in 389 Directory Server with dsconf backend attr-encrypt, export and reimport with dsctl ldif2db --encrypted, verify LDAP access, and plan certificate and replication dependencies.

Published

Updated

Read time 11 min read

Reviewed byDeepak Prasad

389 Directory Server attribute encryption protecting telephoneNumber values at rest in the LMDB backend with TLS-wrapped encryption keys

Attribute encryption stores selected LDAP attribute values and their equality and presence index data in encrypted form inside the backend database. Authorized clients still receive plaintext over LDAP. The server decrypts values during reads. The protection target is data at rest on disk, not the LDAP wire protocol.

Typical candidates include personal or government identifiers:

text
telephoneNumber
employeeNumber
governmentIdentifier

Avoid uid as the main example. When uid is part of the entry DN, the value remains visible in the distinguished name even if you encrypt the attribute.

Before you start:

IMPORTANT
This guide covers per-backend encryption of selected attribute values and indexes at rest. It does not configure LDAP TLS (data in transit), general backup procedures, replication changelog encryption, or routine index tuning.

Tested on: Rocky Linux 10.2; 389 Directory Server 3.2.0.


Attribute encryption vs LDAP TLS

Protection Purpose
LDAP TLS or LDAPS Encrypts LDAP traffic between client and server
Attribute encryption Encrypts selected values in database files and indexes
Filesystem encryption Protects the complete disk or filesystem
ACI Controls which authenticated identities may read an attribute

Attribute encryption complements TLS and ACIs. TLS does not remove the need to protect stolen database files, and ACIs do not encrypt data stored on disk.


How 389 Directory Server encrypts attributes

Encryption is configured per backend (suffix), not for the whole instance at once.

Step What happens
Configuration You add attribute names with dsconf backend attr-encrypt --add-attr
Symmetric keys Directory Server generates symmetric encryption keys for the backend’s configured cipher and uses them to protect attributes enabled for encryption
Key wrapping Those keys are wrapped using the server TLS certificate public key
Reads and writes The server encrypts on write and decrypts on read for authorized LDAP clients
Indexes Equality and presence index values for encrypted attributes are encrypted too

If you lose the TLS private key that wraps the symmetric keys, encrypted data can become unrecoverable. Treat the certificate database and private key as part of your encryption recovery plan.


Choose attributes suitable for encryption

Attribute Encrypt? Reason
employeeNumber Yes Sensitive identifier stored only as a value
telephoneNumber Possibly Personal contact data
uid Usually no Often exposed in the entry DN
cn Usually no Frequently searched and commonly used in DNs
userPassword Not the main use case Passwords already use password-storage schemes

Attribute encryption supports equality and presence indexes. Test application searches on a lab copy before you encrypt production data. Substring or approximate matching may not apply to encrypted attributes the way operators expect.

This guide encrypts telephoneNumber on backend userroot for entries under ou=people,dc=example,dc=com.


Verify TLS and back up encryption keys

Attribute encryption requires TLS on the instance. Confirm security settings on ldap1:

bash
dsconf ldap1 security get

Sample output (trimmed):

output
nsslapd-security: on
nsslapd-secureport: 636

When nsslapd-security is on, you can configure encrypted attributes. Complete TLS setup, trust chains, and client trust configuration live in the TLS chapter.

Before you change encryption settings, back up:

  • The instance NSS certificate database under /etc/dirsrv/slapd-ldap1/
  • The server private key material referenced by that database
  • Any certificate database PIN or password file your deployment uses
  • A recoverable LDIF or database backup of the affected backend

Inspect currently encrypted attributes

List backends and suffixes to confirm the backend name:

bash
dsconf ldap1 backend suffix list

Sample output:

output
dc=example,dc=com (userroot)

Check whether any attributes are already encrypted on that backend:

bash
dsconf ldap1 backend attr-encrypt --list userroot

Sample output before configuration:

output
There are no encrypted attributes for this backend

You can pass the suffix DN (dc=example,dc=com) instead of userroot when the command accepts either form.


Export existing directory data

Export the backend while the instance is online. Use -E whenever you export data before enabling, disabling, or changing attribute encryption. That flag decrypts any already-encrypted attributes in the temporary LDIF so the file is consistent plaintext for reimport.

Write the LDIF under the instance ldif directory so the dirsrv user can create the file:

bash
dsconf ldap1 backend export -E -l /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-export.ldif userroot

Sample output:

output
The export task has finished successfully

The export task completes without printing the output path; the LDIF lands at the path you passed to -l.

Confirm sensitive values appear in plaintext in the export with grep:

bash
grep telephoneNumber /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-export.ldif

Sample output:

output
telephoneNumber: +1-555-0103
telephoneNumber: +1-555-0101

Treat the LDIF as sensitive. Restrict permissions and store it only long enough for the reimport workflow.


Enable encryption for an attribute

I'll add telephoneNumber to the encryption list for userroot:

bash
dsconf ldap1 backend attr-encrypt --add-attr telephoneNumber userroot

Sample output:

output
Successfully added encrypted attribute

Verify the configuration:

bash
dsconf ldap1 backend attr-encrypt --list userroot

Sample output:

output
dn: cn=telephoneNumber,cn=encrypted attributes,cn=userroot,cn=ldbm database,cn=plugins,cn=config
cn: telephoneNumber
nsEncryptionAlgorithm: AES

Enabling the configuration protects new writes, but values already stored in the backend files are not converted until you reimport the exported data.


Reimport existing data with encryption enabled

Confirm the export contains the full suffix before you stop the instance:

bash
grep -m1 '^dn: dc=example,dc=com$' /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-export.ldif

Sample output:

output
dn: dc=example,dc=com

Count the entries in the export:

bash
grep -c '^dn:' /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-export.ldif

The count should match the number of entries you expect for a complete backend export, not a partial subtree.

WARNING
dsctl ldif2db replaces the contents of the selected backend; it does not merge the LDIF with existing entries. Confirm that the export contains the complete suffix and keep a verified backup before continuing.

Stop the instance before offline import:

bash
dsctl ldap1 stop

Sample output:

output
Instance "ldap1" has been stopped

Import the export with encryption applied to configured attributes:

bash
dsctl ldap1 ldif2db --encrypted userroot /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-export.ldif

Sample output:

output
ldif2db successful

The --encrypted flag tells the import path to encrypt attributes listed in the backend encryption configuration.

Start the instance:

bash
dsctl ldap1 start

Sample output:

output
Instance "ldap1" has been started

Confirm the server is running:

bash
dsctl ldap1 status

Sample output:

output
Instance "ldap1" is running

Verify encrypted attribute access

Authorized LDAP clients should still receive plaintext values. Search for a user entry with ldapsearch:

bash
ldapsearch -LLL -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=user1,ou=people,dc=example,dc=com" telephoneNumber employeeNumber

Sample output:

output
dn: uid=user1,ou=people,dc=example,dc=com
telephoneNumber: +1-555-0101
employeeNumber: EMP-1001

The server decrypts telephoneNumber before returning it. employeeNumber remains unencrypted in this lab because only telephoneNumber was added to the encryption list.

Test an equality search against the encrypted attribute:

bash
ldapsearch -LLL -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -b "ou=people,dc=example,dc=com" "(telephoneNumber=+1-555-0101)" uid telephoneNumber

Sample output:

output
dn: uid=user1,ou=people,dc=example,dc=com
uid: user1
telephoneNumber: +1-555-0101

Equality matching remains supported for encrypted attributes. Configure an equality index when applications search the attribute regularly; otherwise, the server may perform an unindexed search.

You can verify the index configuration with:

bash
dsconf ldap1 backend index get --attr telephoneNumber userroot

Sample output (trimmed):

output
dn: cn=telephoneNumber,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
cn: telephoneNumber
nsIndexType: eq
nsIndexType: pres

Confirm encryption remains enabled:

bash
dsconf ldap1 backend attr-encrypt --list userroot

Verify that encryption is configured, the encrypted import completed successfully, and LDAP reads and equality searches still work. Do not inspect or modify raw LMDB files directly.

For LDAPS client tests, import the server CA into the client trust store as described in the TLS chapter. Self-signed lab certificates may require a one-off LDAPTLS_REQCERT=never only for local testing, not for production scripts.


Remove residual plaintext data

After a successful import and verification, reduce exposure from temporary plaintext copies:

  1. Delete the plaintext LDIF as soon as rollback is no longer required, and remove any snapshots, backups, or copied versions according to your data-retention process:
bash
shred -u /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-export.ldif

shred is a best-effort example only. It does not guarantee erasure on SSDs, copy-on-write filesystems, snapshots, or storage with remapped blocks. Red Hat notes that plaintext data can sometimes be recovered even after files are deleted.

  1. Stop the instance and remove the LMDB guardian page-pool file when it exists:
bash
dsctl ldap1 stop

Remove the guardian file that may still hold plaintext page-pool data:

bash
rm -f /var/lib/dirsrv/slapd-ldap1/db/guardian

Start ldap1 again after the guardian cleanup:

bash
dsctl ldap1 start

On some imports the guardian file may not be present; remove it only when the path exists.

  1. Plan for other plaintext surfaces called out in Red Hat documentation: process memory, swap space, older backups, and replication logs. Attribute encryption does not encrypt those areas automatically.

Encrypt additional attributes or multiple backends

Add each attribute separately on the backend that stores it:

bash
dsconf ldap1 backend attr-encrypt --add-attr employeeNumber userroot

Export the backend again with -E, then repeat the offline --encrypted import and verification for every attribute you add to a backend that already contains data.

When an instance serves multiple suffixes, configure encryption on each backend that holds the sensitive attribute. Enabling encryption on userroot does not encrypt attributes stored under a different backend.

Avoid encrypting every attribute. Encryption adds operational overhead and affects how you search and recover data.


Disable attribute encryption safely

Removing the configuration alone does not rewrite existing ciphertext back to plaintext in place. Export decrypted data, remove the setting, and reimport.

Export with decryption:

bash
dsconf ldap1 backend export -E -l /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-disable.ldif userroot

Remove the attribute from the encryption list:

bash
dsconf ldap1 backend attr-encrypt --del-attr telephoneNumber userroot

Sample output:

output
Successfully deleted encrypted attribute

Stop the instance and import without --encrypted:

bash
dsctl ldap1 stop

Import the decrypted LDIF into userroot:

bash
dsctl ldap1 ldif2db userroot /var/lib/dirsrv/slapd-ldap1/ldif/attr-encrypt-disable.ldif

Bring the instance back online:

bash
dsctl ldap1 start

Verify attr-encrypt --list reports no encrypted attributes and that LDAP searches return expected values.


Renew or replace the TLS certificate safely

Directory Server wraps attribute-encryption keys with the server TLS certificate. The impact depends on whether the private key changes.

Scenario Attribute-encryption impact
Certificate renewal with the same private key Lower risk; wrapped keys remain compatible
Certificate replacement with a new private key Wrapped symmetric-key entries in dse.ldif no longer match; requires the special workflow below

Before any certificate work, export affected backends with -E and back up the NSS database and private key.

Attribute encryption requires a special certificate-replacement workflow when the private key changes. After installing a certificate with a new private key:

  1. Export with -E (if not already done).
  2. Install the new certificate and private key. See certificate management (initial TLS setup remains in TLS, StartTLS, and LDAPS).
  3. Stop the instance.
  4. Edit /etc/dirsrv/slapd-ldap1/dse.ldif and remove the AES and 3DES wrapped-key entries for every backend. For example, remove cn=AES,cn=encrypted attribute keys,cn=userroot,cn=ldbm database,cn=plugins,cn=config and the matching cn=3DES,... entry. Red Hat warns that leaving any entry containing nsSymmetricKey in dse.ldif can prevent Directory Server from starting after key replacement.
  5. Reimport the decrypted LDIF with dsctl ldif2db --encrypted.
  6. Start the instance and verify LDAP reads and equality searches.

Follow the complete procedure in Red Hat Directory Server 13. Updating TLS certificates used for attribute encryption exactly; an incomplete key transition can prevent the server from starting.

If decryption fails after certificate replacement, restore the previous certificate database and private key from backup, or recover from a verified -E export.


Attribute encryption and replication

Keep these points in mind when replicas are involved:

  • Configure the same encrypted attributes on each replica backend that stores the data.
  • Protect replication connections with TLS between suppliers and consumers.
  • Attribute encryption does not encrypt every replication-related file on disk.
  • Encrypt replication changelogs separately when your threat model requires it. See the replication chapters for changelog settings.
  • Test replica initialization and encrypted imports on lab hosts such as ldap1.example.com and ldap2.example.com before production rollout.

Troubleshoot attribute encryption

Symptom Likely cause Fix
dsconf reports TLS is not configured nsslapd-security off or incomplete TLS setup Enable TLS per the TLS chapter; confirm with dsconf ldap1 security get
Existing values still appear unencrypted at rest Configuration enabled without reimport Export with -E and run dsctl ldif2db --encrypted while the instance is stopped
Server cannot decrypt attributes after certificate change New private key without wrapped-key cleanup in dse.ldif Follow the RHDS certificate-replacement workflow; remove AES/3DES nsSymmetricKey entries before reimport
Equality search slow or hits limits Unindexed search on encrypted attribute Add or confirm an equality index with dsconf backend index get; see indexing
Attribute value visible in the DN Value used as RDN component Choose a non-RDN attribute for encryption; DNs are always visible to clients
ldif2db fails Wrong backend name, LDIF path, permissions, or instance still running Confirm userroot, stop the instance, use a path readable by dirsrv, and add --encrypted when encryption is enabled
Export task permission denied Output path not writable by dirsrv Write LDIF files under /var/lib/dirsrv/slapd-ldap1/ldif/

What's Next


References


Summary

  1. Enable TLS and back up the certificate database and private key.
  2. Export existing backend data with -E to an LDIF file under the instance ldif directory.
  3. Enable encryption for the selected attribute with dsconf backend attr-encrypt --add-attr.
  4. Stop the instance and reimport with dsctl ldif2db --encrypted.
  5. Verify LDAP reads, equality searches, and attr-encrypt --list.
  6. Remove or protect plaintext LDIF exports and other residual plaintext surfaces.
  7. Preserve the TLS private key material required to recover encrypted data.

Frequently Asked Questions

1. Does attribute encryption replace LDAP TLS in 389 Directory Server?

No. TLS or LDAPS protects data in transit between client and server. Attribute encryption protects selected attribute values and their index data at rest inside the backend database files. Use both where the threat model requires it.

2. Can I encrypt uid or cn to hide values from the entry DN?

No. Values that appear in an entry RDN remain visible in the DN itself. Encrypt attributes such as telephoneNumber or employeeNumber that are stored only as attribute values.

3. Why must I reimport data after enabling attr-encrypt?

Enabling encryption in configuration protects new writes, but values already stored in the backend are not rewritten automatically. Export the backend and reimport with dsctl ldif2db --encrypted to convert existing values.

4. What happens if I lose the TLS private key after enabling attribute encryption?

Directory Server wraps attribute-encryption keys with the server TLS certificate. Without the matching private key and certificate database, encrypted attribute data can become unrecoverable. Back up the certificate database and private key before you enable encryption.

5. Does enabling encryption on one backend encrypt every suffix in the instance?

No. Attribute encryption is configured per backend or suffix. Repeat attr-encrypt configuration for each backend that stores the sensitive attribute.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …