UnboundID LDAP SDK for Java 6.0.8

We have just released version 6.0.8 of the UnboundID LDAP SDK for Java. It is available for download from GitHub and SourceForge, and it is available in the Maven Central Repository.

Note that this is the last release for which the LDAP SDK source code will be maintained in both the GitHub and SourceForge repositories. The LDAP SDK was originally hosted in a subversion repository at SourceForge, but we switched to GitHub as the primary repository a few years ago. We have been relying on GitHub’s support for accessing git repositories via subversion to synchronize changes to the legacy SourceForge repository, but that support is being discontinued. The SourceForge project will continue to remain available for the discussion forum, mailing lists, and release downloads, but up-to-date source code will only be available on GitHub.

You can find the release notes for the 6.0.8 release (and all previous versions) at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but here’s a summary of the changes:

  • We added a DN.getDNRelativeToBaseDN method that can be used to retrieve the portion of DN that is relative to a given base DN (that is, the portion of a DN with the base DN stripped off). For example, if you provide it with a DN of “uid=test.user,ou=People,dc=example,dc=com” and a base DN of “dc=example,dc=com”, then the method will return “uid=test.user,ou=People”.
  • We added LDAPConnectionPool.getServerSet and LDAPThreadLocalConnectionPool.getServerSet methods that can be used to retrieve the server set that the connection pool uses to establish new connections for the pool.
  • We updated the Filter class to alternative methods with shorter names for constructing search filters from their individual components. For example, as an alternative to calling the Filter.createANDFilter method for constructing an AND search filter, you can now use Filter.and, and as an alternative to calling Filter.createEqualityFilter, you can now use Filter.equals. The older versions with longer method names will remain available for backward compatibility.
  • We added support for encrypted PKCS #8 private keys, which require a password to access the private key. The PKCS8PrivateKey class now provides methods for creating the encrypted PEM representation of the key, and the PKCS8PEMFileReader class now has the ability to read encrypted PEM files. We also updated the manage-certificates tool so that the export-private-key and import-certificate subcommands now support encrypted private keys.
  • We updated PassphraseEncryptedOutputStream to use a higher key factory iteration count by default. When using the strongest available 256-bit AES encryption, it now follows the latest OWASP recommendation of 600,000 PBKDF2 iterations. You can still programmatically explicitly specify the iteration count when creating a new output stream if desired, and we have also added system properties that can override the default iteration count without any code change.
  • We added a PassphraseEncryptedOutputStream constructor that allows you to provide a PassphraseEncryptedStreamHeader when creating a new instance of the output stream. This will reuse the secret key that was already derived for the provided stream header (although with newly generated initialization vector), which can be significantly faster than deriving a new secret key from the same passphrase.
  • We added a new ObjectTrio utility class that can be useful in cases where you need to reference three typed objects as a single object (for example, if you want a method to be able to return three objects without needing to define a new class that encapsulates those objects). This complements the existing ObjectPair class that supports two typed objects.
  • We updated the documentation to include RFC 9371 in the set of LDAP-related specifications. This RFC formalizes the process for requesting a private enterprise number (PEN) to use as the base object identifier (OID) for your own definitions (e.g., for use in defining custom attribute types or object classes). The OID-related documentation has also been updated to provide a link to the IANA site that you can use to request an official base OID for yourself or your organization.

Ping Identity Directory Server 9.2.0.0

We have just released version 9.2.0.0 of the Ping Identity Directory Server. See the release notes for a complete overview of changes, but here’s my summary:

Potential Backward Compatibility Issues

Summary of New Features and Enhancements for All Products

  • Added support for Java 17 [more information]
  • Added support for accessing external services through an HTTP proxy server [more information]
  • Added a Prometheus monitoring servlet extension [more information]
  • Added support for authenticating to Amazon AWS using an IRSA role [more information]
  • Added support for generating digital signatures with encryption settings definitions [more information]
  • Updated replace-certificate when running in interactive mode so that it can re-prompt for a certificate file if the initial file existed but did not contain valid certificate data

Summary of New Features and Enhancements for the Directory Server

  • Improved support for data security auditors [more information]
  • Added new secure, connectioncriteria, and requestcriteria access control keywords [more information]
  • Added support for defining resource limits for unauthenticated clients [more information]
  • Added Argon2i, Argon2d, and Argon2id password storage schemes to supplement the existing Argon2 scheme [more information]
  • Changed the default value of the replication-purge-obsolete-replicas global configuration property from false to true
  • Updated migrate-ldap-schema to support migrating attribute type definitions from Active Directory in spite of their non-standards-compliant format
  • Improved the usage text for the dsreplication enable command

Summary of New Features and Enhancements for the Directory Proxy Server

  • Exposed the maximum-attributes-per-add-request and maximum-modifications-per-modify-request properties in the global configuration

Summary of New Features and Enhancements for the Synchronization Server

  • Added support for synchronizing to SCIMv2 destinations [more information]
  • Added a sync-pipe-view tool that can display information about the set of sync pipes configured in the server
  • Added sync pipe monitor attributes related to account password policy state when synchronizing to a Ping Identity Directory Server

Summary of Bug Fixes

  • Fixed an issue that could cause replication protocol messages to be dropped, potentially resulting in paused replication
  • Fixed an issue in which a timeout could prevent adding servers to a large topology
  • Fixed an issue in which an unexpected error could cause a replication server to stop accepting new connections
  • Fixed an issue that prevented resource limits from being set properly for the topology administrator
  • Fixed an issue in which the dsreplication tool incorrectly handled DNs in a case-sensitive manner
  • Fixed an issue that could cause dsreplication enable to fail if there were any topology administrators without passwords
  • Fixed an issue that could cause a configured idle timeout to interfere with replica initialization
  • Fixed an issue that could prevent the server from generating an administrative alert when clearing an alarm that triggered an alert when it was originally raised
  • Fixed an issue that could cause degraded performance to a PingOne sync destination
  • Fixed an issue that could prevent users from changing their own passwords with the password modify extended operation if their account was in a “must change password” state and the request passed through the Directory Proxy Server
  • Fixed an issue in which dsconfig would always attempt to use simple authentication when applying changes to servers in a group, regardless of the type of authentication used when launching dsconfig
  • Fixed an issue that could cause certain kinds of Directory REST API requests to fail if they included the uniqueness request control
  • Fixed an issue in which an unclean shutdown could cause the server to create exploded index databases
  • Disabled the index cursor entry limit by default, which could cause certain types of indexed searches to be considered unindexed
  • Fixed an issue that could adversely affect performance in servers with a large number of virtual static groups

Removed Support for Incremental Backups

We have removed support for incremental backups. This feature was deprecated in the 8.3.0.0 release after repeated issues that could interfere with the ability to properly restore those backups. These issues do not affect full backups, which continue to be supported.

As an alternative to full or incremental backups, we recommend using LDIF exports, which are more useful and more portable than backups. They are also typically very compressible and can be taken more frequently than backups without consuming as much disk space. Further, the extract-data-recovery-log-changes tool can be used in conjunction with either LDIF exports or backups to replay changes recorded in the data recovery log since the time the LDIF export or backup was created.

Updated the Groovy Language Version

In order to facilitate support for Java 17, we have updated the library providing support for the Groovy scripting language from version 2.x to 3.x. While this should largely preserve backward compatibility, there may be some issues that could prevent existing Groovy scripted extensions from continuing to work without any problems.

The only compatibility issue that we have noticed is that the 3.x version of the Groovy support library cannot parse Java import statements that are broken up across multiple lines, like:

import java.util.concurrent.atomic.
            AtomicLong;

This was properly handled in Groovy 2.x, but the Groovy 3.x library does not appear to support this. To address the problem, you will need to update the script to put the entire import statement on a single line, like:

import java.util.concurrent.atomic.AtomicLong;

If you have any Groovy scripted extensions, we strongly recommend verifying them in a test environment before attempting to update production servers.

Java 17 Support

We have updated the server to support running on JVMs running Java version 17, which is the latest LTS release of the Java language. Java versions 8 and 11 also continue to be supported.

Note that Java 17 support is limited to the Directory Server, Directory Proxy Server, and Synchronization Server. Java 17 is not supported for the Metrics Engine, although it continues to be supported on Java 8 and 11.

The best way to enable Java 17 support is to have the JAVA_HOME environment variable set to the path of the Java 17 installation when installing the server using either the setup or manage-profile setup commands. It’s more complicated to switch to Java 17 for an existing instance that was originally set up on Java 8 or 11 because there are changes in the set of JVM arguments that should be used with Java 17. As such, if you want to switch to Java 17, then we recommend installing new instances and migrating the data to them.

By default, installations using Java 17 will use the garbage first garbage collection algorithm (G1GC), which is the same default as Java 11. We also support using the Z garbage collector (ZGC) on Java 17, although we have observed that it tends to consume a significantly greater amount of memory than the garbage first algorithm. While ZGC can exhibit better garbage collection performance than G1GC, if you wish to use it, we recommend configuring a smaller JVM heap size and thoroughly testing the server under load and at scale before enabling it in production environments.

HTTP Forward Proxy Support

We have updated several server components to provide support for issuing outbound HTTP and HTTPS requests through a proxy server. Updated components include:

  • The Amazon Key Manager cipher stream provider
  • The Amazon Secrets Manager cipher stream provider, passphrase provider, and password storage scheme
  • The Azure Key Vault cipher stream provider, passphrase provider, and password storage scheme
  • The PingOne pass-through authentication plugin
  • The PingOne sync source and destination
  • The Pwned Passwords password validator
  • The SCIMv1 sync destination
  • The SCIMv2 sync destination
  • The Twilio alert handler and OTP delivery mechanism
  • The UNBOUNDID-YUBIKEY-OTP SASL mechanism handler

To enable HTTP forward proxy support for any of these components, first, create an HTTP proxy external server configuration object with a command like:

dsconfig create-external-server \
     --server-name "Example HTTP Proxy Server" \
     --type http-proxy \
     --set server-host-name:proxy.example.com \
     --set server-port:3128

You can also optionally use the basic-authentication-username and basic-authentication-passphrase-provider properties if the HTTP proxy server requires authentication.

Once the HTTP proxy external server has been created, update the target component to reference that server. For example:

dsconfig set-password-validator-prop \
     --validator-name "Pwned Passwords" \
     --set "http-proxy-external-server:Example HTTP Proxy Server"

Prometheus Monitoring Servlet Extension

We have added support for a new HTTP servlet extension that can be used to expose certain server metrics in a format that can be consumed by Prometheus or other monitoring systems that support the OpenMetrics data format. To enable it, add the servlet extension to the desired HTTP connection handlers and either restart the server or disable and re-enable those connection handlers. For example:

dsconfig set-connection-handler-prop \
     --handler-name "HTTPS Connection Handler" \
     --add "http-servlet-extension:Prometheus Monitoring" \
     --set enabled:false

dsconfig set-connection-handler-prop \
     --handler-name "HTTPS Connection Handler" \
     --set enabled:true

By default, the server is preconfigured to expose a variety of metrics. You can customize this to remove metrics that you don’t care about, or to add additional metrics that we didn’t include by default. Any single-valued numeric monitor attribute can be exposed as a metric. You can also customize the set of labels included in metric definitions, on both a server-wide and per-metric basis.

Improved AWS Authentication Support

The server offers a number of components that can interact with Amazon Web Services components,
including:

  • A cipher stream provider that can use the Key Management Service
  • A cipher stream provider, passphrase provider, and password storage scheme that can use the Secrets Manager

In the past, you could authenticate to AWS using either a secret access key or using an IAM role that is associated with the EC2 instance or EKS container in which the server is running. In the 9.2.0.0 release, we’re introducing support for authenticating with an IRSA (IAM role for service accounts) role. We are also adding support for a default credentials provider chain that can attempt to automatically identify an appropriate authentication method for cases in which the server is running in an AWS environment, or in cases where information about a secret access key is available through either environment variables or Java system properties.

To use the new authentication methods, first create an AWS external server that specifies the desired value for the authentication-method property. Then, reference that external server when creating the desired component. For example:

dsconfig create-external-server \
     --server-name AWS \
     --type amazon-aws \
     --set authentication-method:irsa-role \
     --set aws-region-name:us-east-2

dsconfig create-cipher-stream-provider \
     --provider-name KMS \
     --type amazon-key-management-service \
     --set enabled:true \
     --set aws-external-server:AWS \
     --set kms-encryption-key-arn:this-is-the-key-arn

Data Security Auditor Improvements

The server offers a data security auditor framework that can be used to iterate across entries in a number of backends and examine them for potential security-related issues or items of note. In the past, we’ve offered auditors that can do the following:

  • Identify entries that define access control rules
  • Identify accounts that have been administratively disabled
  • Identify accounts that have passwords that are expired, are about to expire, or that have not been changed in longer than a given length of time
  • Identify accounts that are locked as a result of too many authentication failures, because it’s been too long since the user last authenticated, or because they did not choose a new password in a timely manner after an administrative reset.
  • Identify accounts with multiple passwords
  • Identify accounts with privileges assigned by real or virtual attributes
  • Identify accounts encoded with a variety of weak password storage schemes, including 3DES, AES, BASE64, BLOWFISH, CLEAR, MD5, RC4, or the default variant of the CRYPT scheme

In the 9.2 release, we’ve introduced support for several new types of data security auditors, including those that can do the following:

  • Identify accounts with account usability errors, warnings, and/or notices
  • Identify accounts that have an activation time in the future, an expiration time in the past, or an expiration time in the near future
  • Identify accounts that have passwords encoded with a deprecated password storage scheme
  • Identify accounts that have not authenticated in longer than a specified period of time, or that have not ever authenticated
  • Identify accounts that reference a nonexistent password policy
  • Identify entries that match a given search filter

We have also updated the Server SDK so that you can create your own data security auditors to use whatever logic you want.

In addition, we have updated the locked account data security auditor so that it can identify accounts that are locked as a result of attempting to authenticate with a password that fails password validator criteria, and we have updated the weakly encoded password data security auditor so that the following schemes are also considered weak: SMD5, SHA, SSHA, and the MD5 variant of the CRYPT scheme.

Finally, we’ve introduced support for a new audit data security recurring task that you can use to have the server automatically perform an audit on a regular basis.

New Access Control Keywords

We have introduced three new access control keywords.

The secure bind rule can be used to make access control decisions based on whether the client is using a secure connection (e.g., LDAPS or LDAP with StartTLS) to communicate with the server. Using a bind rule of secure="true" indicates that the ACI only applies to clients communicating with the server over a secure connection, while secure="false" indicates that the ACI only applies to clients communicating with the server over an insecure connection.

The connectioncriteria bind rule can be used to make access control decisions based on whether the client connection matches a specified set of connection criteria. The value of the bind rule can be either the name or the DN of the desired connection criteria.

The requestcriteria target can be used to make access control decisions based on whether the operation matches a specified set of request criteria. The value of the target can be either the name or the DN of the desired request criteria.

Note that because the Server SDK provides support for creating custom types of connection and request criteria, the introduction of these last two bind rules adds support for being able to define custom access control logic if the server’s existing access control framework doesn’t support what you want.

Resource Limits for Unauthenticated Clients

The server’s global configuration includes the following configuration properties that can be used to set default resource limits that will apply to all users that don’t have specific limits set for them:

  • size-limit — Specifies the maximum number of entries that can be returned for a search operation
  • time-limit — Specifies the maximum length of time the server should spend processing a search operation
  • idle-time-limit — Specifies the maximum length of time that a client connection may remain established without any operations in progress
  • lookthrough-limit — Specifies the maximum number of entries that the server can examine in the course of processing a search operation

These properties set global defaults for all clients, including those that aren’t authenticated. However, you may want to set lower limits for unauthenticated connections than for users that are authenticated. To make that easier to accomplish, we have added the following new additional properties that specifically apply to unauthenticated clients:

  • unauthenticated-size-limit
  • unauthenticated-time-limit
  • unauthenticated-idle-time-limit
  • unauthenticated-lookthrough-limit

By default, these properties don’t have any values, which will cause the server to inherit the value from the property that doesn’t specifically apply to unauthenticated clients (for example, if unauthenticated-size-limit is not set, then the server will use the size-limit value as the default for both authenticated and unauthenticated clients).

Improved Signature Generation

The server supports cryptographically signing log messages, backups, and LDIF exports. Previously, those signatures were always generated with MAC keys shared among other servers in the same topology. These keys are difficult to back up and restore, and the resulting signatures cannot be verified outside of the topology.
In the 9.2.0.0 release, we have updated the server so that it now generates digital signatures with encryption settings definitions. The server’s preferred definition will be used by default, but you can specify an alternative definition with the signing-encryption-settings-id property in the crypto manager configuration.

If digital signing is enabled but no encryption settings definitions are available, then a legacy topology key will continue to be used as a fallback.

Additional Argon2 Password Storage Schemes

The Argon2 key derivation function is a popular mechanism for encoding passwords, especially after it was selected as the winner of a password hashing competition in 2015. We introduced support for an ARGON2 password storage scheme in the 8.0.0.0 release.

There are actually three variants of the Argon2 algorithm:

  • Argon2i — Provides better protection against side-channel attacks. The existing ARGON2 scheme uses this variant.
  • Argon2d — Provides better protection against GPU-accelerated attacks.
  • Argon2id — Mixes the strategies used in the Argon2i and Argon2d variants to provide a degree of protection against both types of attacks.

In the 9.2.0.0 release, we are introducing three new password storage schemes, ARGON2I, ARGON2D, and ARGON2ID, which provide explicit support for each of these variants.

Note that if you want to use the Argon2 algorithm to encode passwords, and you need to run in an environment that contains pre-9.2.0.0 servers, then you should use the existing ARGON2 scheme. The newer schemes should only be used in environments containing only servers running version 9.2.0.0 or later.

SCIMv2 Sync Destination

The Synchronization Server has included support for SCIMv1 servers as a sync destination since the 3.2.2.0 release. This support relies on an XML-based configuration to map LDAP source attributes to SCIM destination attributes.

In the 9.2.0.0 release, we’re introducing support for SCIMv2 servers as a sync destination. For this destination, all of the necessary configuration is held in the server’s configuration framework, so there is no need for a separate file with mapping information. This implementation introduces several new types of configurable components, including:

  • HTTP authorization methods, which provide support for a variety of mechanisms for authenticating to HTTP-based services, including basic authentication and OAuth 2 bearer tokens (and in the latter case, you may configure either a static bearer token or have the server obtain one from an OAuth authorization server using the client_credentials grant type).
  • A SCIM2 external server, which provides the SCIM service URL, authorization method, and other settings to use when interacting with the SCIMv2 service.
  • SCIM2 attribute mappings, which describe how to generate SCIM attributes from the LDAP representation of a source entry.
  • SCIM2 endpoint mappings, which associate a set of attribute mappings with an endpoint in the SCIMv2 server.
  • The SCIM2 sync destination, which associates the SCIM2 external server and the SCIM2 endpoint mappings.

The documentation describes the process for configuring the Synchronization Server to synchronize changes to a SCIMv2 server. In addition, the config/sample-dsconfig-batch-files/configure-synchronization-to-scim2.dsconfig file provides an example that illustrates a set of changes that can be used to synchronize inetOrgPerson LDAP entries to urn:ietf:params:scim:schemas:core:2.0:UserM. SCIMv2 entries.

UnboundID LDAP SDK for Java 6.0.7

We have just released version 6.0.7 of the UnboundID LDAP SDK for Java. It is available for download from GitHub and SourceForge, and it is available in the Maven Central Repository. You can find the release notes at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but here’s a summary of the changes included in this version:

  • We fixed a bug in the SearchResultEntry.equals method that could prevent a SearchResultEntry from matching other types of Entry objects.
  • We fixed a bug in the Entry.applyModifications method that could cause it to fail with a NOT_ALLOWED_ON_RDN result if the provided entry was missing one or more of the attribute values used in its RDN.
  • We fixed a bug in the argument parser’s support for mutually dependent arguments with a set containing more than two arguments. Previously, the constraint would have been satisfied if at least two of the arguments were provided, rather than requiring all of them to be provided.
  • We added JSONObject methods for retrieving fields by name using case-insensitive matching (by default, JSON field names are treated in a case-sensitive manner). Because it is possible that a JSON object will have multiple fields with the same name when using case-insensitive matching, there are a few options for indicating how such conflicts should be handled, including only returning the first match, returning a map with all matching fields, or throwing an exception if there are multiple matches.
  • We updated the set of LDAP-related specifications to include the latest version of the draft-schmaus-kitten-sasl-ht proposal.

UnboundID LDAP SDK for Java 6.0.6

We have just released version 6.0.6 of the UnboundID LDAP SDK for Java. It is available for download from GitHub and SourceForge, and it is available in the Maven Central Repository. You can find the release notes at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but here’s a summary of the changes included in this version:

General Updates

  • We fixed an issue that could cause request failures when closing a connection operating in asynchronous mode with outstanding operations.
  • We fixed an issue that could interfere with the ability to get a default SSLContext on Java 17 when running in FIPS 140-2-compliant mode.
  • We updated LDAPConnectionOptions to add support for a new system property that can enable certificate hostname verification by default without any code changes.
  • We updated the LDAP command-line tool framework to add a new --verifyCertificateHostnames argument to enable hostname verification when performing TLS negotiation.
  • We improved the class-level Javadoc documentation for the SSLUtil class to provide a better overview of TLS protocol versions, TLS cipher suites, key managers, trust managers, and certificate hostname verification, and to provide better examples that illustrate best practices for establishing secure connections.
  • We fixed an issue in the JNDI compatibility support for controls, as well as extended requests and responses. Even though the implementation was based on the JNDI documentation, it appears that at least OpenJDK implementations do not abide by that documentation. The LDAP SDK is now compatible with the observed behavior rather than the documentation, although a system property can be used to revert to the former behavior.
  • We updated the SearchRequest class to add constructors that allow you to provide the search base DN with a DN object (as an alternative to existing constructors that allow you to specify it as a String).
  • We fixed an issue in the command-line tool framework in which an Error (for example, OutOfMemoryError) could cause the tool to report a NullPointerException rather than information about the underlying error.
  • We fixed an issue in the IA5 argument value validator that could allow it to accept argument values with non-ASCII characters.
  • We fixed an issue in the DNS hostname argument value validator that could prevent it from properly validating the last component of a fully qualified domain name, or the only component of an unqualified name.
  • We updated the identify-references-to-missing-entries tool to provide an option to generate an LDIF file with changes that can be used to remove identified references.
  • We updated the SelfSignedCertificateGenerator class to perform better validation for the subject alternative DNS names that it includes in a certificate.
  • We updated the manage-certificates generate-self-signed-certificate command to rename the --replace-existing-certificate argument to be --use-existing-key-pair. The former argument name still works, but it is hidden from the usage.
  • We included a native-image/resource-config.json file in the LDAP SDK jar file manifest, which can be used by the GraalVM native-image tool to ensure that appropriate resource files are included in the resulting image.

Updates Specific to Use With the Ping Identity Directory Server

  • * We updated the summarize-access-log tool to report on many more things, including the most common IP addresses for failed bind attempts, the most consecutive failed binds, information about work queue wait times, information about request and response controls, the number of components in search filters, and search filters that may indicate injection attempts.
  • We updated support for the audit data security administrative task to make it possible to specify the number and/or age of previous reports to retain.
  • We fixed issues that prevented specifying the criticality of the administrative operation and join request controls.

Ping Identity Directory Server 9.1.0.0

We have just released version 9.1.0.0 of the Ping Identity Directory Server and related products, including Directory Proxy Server, Synchronization Server, and Metrics Engine. See the release notes for a complete overview of changes, but here’s my summary:

Known Issues

  • When updating an 8.3 or 9.0 server to the 9.1 release, the Bouncy Castle library that the server uses for certain cryptographic processing will be updated. If it later becomes necessary to revert the update and return to the older version, the newer version of the Bouncy Castle libraries will remain in place. Although this will not cause any actual problems with the server, it may cause the server to log a message during startup about multiple versions of the library in the classpath.

Summary of New Features and Enhancements

  • Updated the Directory REST API to add support for a variety of request and response controls. [more information]
  • Added the ability to streamline the process for replacing a listener certificate if the new certificate is signed by the same issuer as the current certificate. [more information]
  • Updated the replace-certificate tool to make it possible to replace the server’s listener certificate even after it has expired. [more information]
  • Added support for sanitizing access log messages as they are logged. [more information]
  • Added support for generifying message strings in access and error log messages. [more information]
  • Updated the Synchronization Server to improve support for synchronizing changes to and from PingOne, including synchronizing using custom attributes, including multi-valued attributes and JSON-formatted attributes.
  • Improved the result that the server returns when using assured replication if it detects that the operation would ultimately be reverted as a result of a replication conflict.
  • Updated the sanitize-log tool so that its sanitization processing better aligns with the server’s new support for sanitized access logging. [more information]
  • Updated the summarize-access-log tool to support JSON-formatted access log files.
  • Added support for JSON-formatted controls in LDAP requests and responses. [more information]
  • Added a docker-pre-start-config command-line tool that can be used to speed up the startup process when running in a Docker container.
  • Updated manage-profile replace-profile to add a --skipValidation argument that can be used to skip the final validation process to reduce the time required for the update to complete.
  • Updated manage-profile generate-profile to add an --excludeSetupArguments argument that can generate a profile without the setup-arguments.txt file.
  • Improved the way that the Directory REST API processes PUT operations that alter an entry’s DN in conjunction with changes to other attributes in the entry.
  • Updated the active operation monitor provider to use millisecond precision in operation timestamps and to enable parsing the string representations of the operations using the LDAP SDK’s access log API.
  • Updated the status --fullVersion output to include the version of the collect-support-data tool.
  • Updated several libraries shipped with the server to improve functionality, address defects, and improve security.

Summary of Bug Fixes

  • Fixed an issue that could cause certain replication protocol messages to be dropped.
  • Fixed an issue that could cause a server to report missing changes and go into lockdown mode if it was restarted immediately after completing dsreplication initialize processing.
  • Fixed an issue that could prevent certain password policy functionality (including account status notification handlers) from being applied to an add operation in which an alternative policy should have been assigned using a virtual attribute rather than a real attribute.
  • Fixed an issue that could cause privileges assigned by virtual attribute to be overlooked in some cases (for example, when accessing topology-related functionality in the Admin Console).
  • Updated the server to create the esTokenizer.ping file if it does not exist but is needed. This file would not have been automatically created when upgrading a server with data encryption enabled from a pre-7.0 version to a later release with support for encrypted indexes.
  • Fixed an issue that could have incorrectly applied minimum and maximum password age constraints to users without a password.
  • Updated the JSON-formatted access logger to include the requester IP address field in disconnect, security negotiation, and client certificate log messages when appropriate.
  • Fixed an issue that prevented the server from refreshing monitor data used to detect and warn about upcoming certificate expiration. This could cause the server to continue to warn about an expiring certificate even after that certificate had been replaced. [more information]
  • Fixed issues that could prevent using the Amazon Secrets Manager, CyberArk Conjur, or HashiCorp Vault passphrase providers to obtain key and trust store PINs.
  • Fixed an issue that could cause the server to report a negative processing time in the access log for certain types of operations.
  • Updated the server to prevent inappropriate updates to the ds-pwp-modifiable-state-json operational attribute when the Modifiable Password Policy State plugin is not enabled.
  • Updated the server to prevent a user from updating their own password policy state using the ds-pwp-modifiable-state-json operational attribute.
  • Updated the server to prevent using the ds-pwp-modifiable-state-json attribute to alter a user’s password policy state in the same operation that also reset that user’s password.
  • Fixed an issue in which the dsreplication tool failed to properly normalize base DN values.
  • Fixed an issue that could prevent the Directory REST API from retrieving entries containing an attribute using the generalized time syntax whose value did not match an expected format.
  • Fixed an issue that could cause manage-profile replace-profile to fail with an error about merging configuration.
  • Updated manage-profile setup and manage-profile replace-profile to ensure that a pre-populated encryption settings database can only be provided in the post-setup files rather than in the pre-setup files, which fixes issues when using a customized cipher stream provider.
  • Updated the manage-topology add-server command to be more consistent when adding additional Synchronization Servers into a failover topology.
  • Fixed an issue in which the server could ignore certain indexes that it incorrectly believed to be redundant when evaluating search criteria.
  • Fixed an issue in which a SCIM request could return a less-appropriate error code in cases where an update violated a unique attribute constraint.
  • Fixed an issue that could cause the server to incorrectly reject a request containing a non-critical control that the requester was not allowed to use. The server will now process the operation as if that control had not been requested.
  • Fixed an issue that could allow the password policy state extended operation to create duplicate authentication failure time or grace login use time values in a user’s entry.
  • Fixed an issue that could adversely affect backward compatibility when attempting to use the legacy --useSSL or --useStartTLS arguments with the migrate-ldap-schema tool (as opposed to the newer arguments allowing you to independently specify security options for the source and target servers).
  • Fixed an issue that could prevent the server from generating an administrative alert to indicate that an outstanding alarm condition had been resolved.
  • Fixed an issue that could cause the server to report an internal error when attempting to obtain database statistics for a read-only backend.
  • Fixed an issue in the export-reversible-passwords tool that could cause it to report a timeout error when waiting for a response from the server.
  • Updated the export-reversible-passwords tool to automatically cancel an in-progress export if the tool used to invoke the export is terminated.
  • Fixed an issue that prevented the encode-password tool from working properly if the AES256 password storage scheme is enabled.
  • Updated the server to disable the index cursor entry limit by default, which is very unlikely to be needed and may interfere with the ability to effectively process certain requests.

Controls in the Directory REST API

It is now possible to use certain LDAP request and response controls through the Directory REST API. Controls should be provided as an array of JSON objects, and the following fields may be used in the JSON representation of the control:

  • oid — A mandatory string field that holds the object identifier for the control.
  • control-name — An optional string field that holds a user-friendly name for the control. Note that this is only intended for informational purposes and won’t be used in the course of actually decoding the control.
  • criticality — A mandatory Boolean field that indicates whether the control should be considered critical.
  • value-base64 — An optional string field whose values is the base64-encoded representation of the raw LDAP encoding for the value. This may be used for any type of control, including controls that the server supports but doesn’t offer a JSON-specific value encoding.
  • value-json — An optional JSON object field whose value contains zero or more fields that are specific to the type of control being represented.

At most one of the value-base64 and value-json fields may be present, and both may be omitted if the control doesn’t take a value.

For example, the following is a JSON representation of the Ping-proprietary join request control:

{ "oid":"1.3.6.1.4.1.30221.2.5.9",
  "control-name":"Join Request Control",
  "criticality":false,
  "value-json":{ "join-rule":{ "type":"dn",
                               "attribute":"manager" },
                 "base-dn-type":"use-custom-base-dn",
                 "base-dn-value":"ou=People,dc=example,dc=com",
                 "scope":"wholeSubtree",
                 "size-limit":10,
                 "attributes":[ "givenName",
                                "sn",
                                "cn",
                                "mail" ],
                 "require-match":false } }

For controls that take a value, the specific JSON encoding for that value varies from one control to another, and you should consult the documentation for a given control to understand how to properly encode and parse it.

Controls that may now be used in the Directory REST API include:

Improvements in Certificate Management

We have updated the replace-certificate tool and the corresponding support in the topology registry to add new options to make things easier when periodically replacing certificates, and especially listener certificates used for security communication with clients.

First, we have added a few new subcommands to the tool, including:

  • list-topology-registry-listener-certificates — Displays a list of the listener certificates associated with a specified instance in the topology registry.
  • list-topology-registry-inter-server-certificates — Displays a list of the inter-server certificates associated with a specific instance in the topology registry.
  • add-topology-registry-listener-certificate — Adds a new certificate to the set of listener certificates for a specified instance in the topology registry, but does not alter any certificate trust stores.

Next, we have updated the server’s use of topology registry listener certificates so that a server’s listener certificate may be trusted for inter-server communication if either the listener certificate itself or one of its issuers is found in the topology registry. Previously, the listener certificate itself was required to be present in the topology registry for that certificate to be trusted, but we have now added support for trusting issuer certificates. This makes it easier to an existing certificate with a new one signed by the same issuer because you can just update the key store without the need to update the topology registry, and there is less chance that a temporary communication problem between instances could arise if a server starts using a new listener certificate before the topology registry updates have propagated to all other instances in the topology.

If you decide to use this issuer-based trust, then there are two ways that you can get the issuer certificate into the topology registry:

  • Using the new replace-certificate add-topology-registry-listener-certificate command referenced above.
  • Using the replace-certificate replace-listener-certificate command with the new --topology-registry-update-type and --trust-store-update-type arguments, which make it possible to configure which certificate(s) in the trust chain will be added to the topology registry and the local trust store, respectively.

We also addressed an oversight in the replace-certificate replace-listener-certificate command that prevented it from being used to replace a listener certificate that had already expired, as the replace certificate tool would no longer trust that expired certificate and would therefore not establish a connection to the server to make the necessary updates. While we strongly recommend always replacing certificates before they actually expire, you can now use the --ignore-current-listener-certificate-validity-window argument to indicate that processing should proceed even if the presented listener certificate is outside its validity time frame. The listener certificate or one of its issuers must still be found in the topology registry.

Finally, we fixed an issue that prevented certificate information presented in the server’s monitor data from being updated. Since there is a gauge in place that uses this monitor information to warn about an upcoming certificate expiration, this bug prevented it from detecting when the certificate had been replaced, and the server would continue to warn about the upcoming expiration even after that certificate was no longer in use. That issue has been fixed, and certificate rotation should now be automatically detected.

Sanitizing Access Log Messages

The server’s access and error logs provide an invaluable resource for understanding how the server is used and for troubleshooting problems. However, they may also sometimes contain sensitive or personally identifiable information that you don’t want to have lying around on the filesystem. In the past, we have offered a sanitize-log tool that can be used to examine log files and produce a scrubbed copy that redacts or obscures potentially sensitive information, and that tool is still available (and improved). However, we have also added the ability to sanitize log messages as they are being written to help ensure that this information isn’t recorded in the logs in the first place.

For access logging, the new sanitization processing is based largely around log field syntaxes. Each log field is now associated with one of the following syntaxes:

  • String
  • Boolean
  • DN
  • Filter
  • Integer
  • Floating-point number
  • Generalized time
  • RFC 3339 timestamp
  • JSON object
  • Comma-delimited string list

We also offer a variety of sanitization types that may be used when determining how to handle a given log field, including:

  • preserve — The field will be included as-is, without any alteration or obfuscation.
  • omit — The field will be omitted from the log message entirely, without either the field name or its value present.
  • redact-entire-value — The field name will be included in the log message, but the entire value will be redacted such that all values for a given syntax will be the same. We actually try to preserve the original syntax when doing this when possible, using the following behavior:

    • String, Boolean, and string list fields will have their values replaced with the text “{REDACTED}”.
    • DN fields will have their values replaced with the text “redacted={REDACTED}”.
    • Filter fields will have their values replaced with the text “(redacted={REDACTED})”.
    • Integer fields will have their values replaced with the text “-999999999999999999”.
    • Floating-point fields will have their values replaced with the text “-999999.999999”.
    • Generalized time fields will have their values replaced with the text “99990101000000.000Z”.
    • RFC 3339 timestamp fields will have their values replaced with the text “9999-01-01T00:00:00.000Z”.
    • JSON object fields will have their values replaced with the text “{ "redacted":"{REDACTED}" }”.
  • redact-value-components — This behavior is similar to redact-entire-value, but it applies specifically to DN, filter, and JSON object values. In such cases, the redaction will be only applied to components within the value, rather than to the entire value itself. For DNs and filters, this means that only attribute values will be redacted while the rest of the text (including attribute names and punctuation) will be preserved, and for JSON objects it means that only field values will be redacted (and field names and punctuation will be preserved). For example, a DN of “uid=jdoe,ou=People,dc=example,dc=com” would become “uid={REDACTED},ou={REDACTED},dc={REDACTED},dc={REDACTED}”. You can optionally even configure this on a per-attribute or per-JSON-field basis, so that only certain attributes or fields (or all but a specified set of attributes or fields) will have their values redacted, and other attributes or fields will have their values preserved.
  • tokenize-entire-value — The field name will be included in the log message, but the value will be replaced with a token that is generated from the value but cannot be directly reversed back to its original value. This is similar to redaction, but different values will result in different tokens, and the same value will consistently result in the same token. This means that it’s possible to identify cases in which the same value appears across multiple log messages, even if you can’t tell what that value actually is. As with redaction, we attempt to preserve the original field syntax when possible, as follows:

    • String, Boolean, and string list fields will have their values tokenized with the text “{TOKENIZED:tokenValue}”, where tokenValue will be generated from the original value.
    • DN fields will have their values replaced with “tokenized={TOKENIZED:tokenValue}”.
    • Filter fields will have their values replaced with “(tokenized={TOKENIZED:tokenValue})”.
    • Integer fields will have their values replaced with a number that starts with “-999999999” and is followed by a sequence of nine additional digits generated from the original value.
    • Floating-point fields will have their values replaced with a number that starts with “-999999.” and is followed by a sequence of six additional digits generated from the original value.
    • Generalized time and RFC 3339 timestamp values will have their values replaced with a timestamp that uses the year 8888, but with other components of the timestamp generated from the original timestamp.
    • JSON object fields will have their values replaced with the text “{ "tokenized":"{TOKENIZED:tokenValue}" }”.
  • tokenize-value-components — This behavior is similar to redact-value-components, but the individual components will be tokenized rather than redacted. As with redact-value-components, this primarily applies to DNs, filters, and JSON objects.

The server now provides a log field syntax configuration object for each of the aforementioned syntaxes, and that object will include a default-behavior field that allows you to indicate that all values with that syntax should be treated in a given way. For example, if you configure the DN log field syntax with a default-behavior value of tokenize-value-components, then all DNs written to a text-formatted or JSON-formatted access log will automatically have their attribute values tokenized while the rest of the DN will remain intact.

For even more control over how individual log fields are treated, you can use log field behavior configuration objects. These objects allow you to choose the behavior to use on a field-by-field basis, and you can configure different behaviors for different loggers if desired.

If you’d rather still have access log messages written with all of the information intact, but still have the ability to sanitize those logs after the fact, then you can continue to use the sanitize-log tool to accomplish this, and we have updated this tool to provide improved behavior that is more closely aligned with the server’s support for sanitized logging. This includes:

  • It now knows about all predefined log fields that the server may use, and we have preselected default behaviors for each of those fields in a manner that we feel provides the best balance between privacy and usefulness.
  • It now uses the same syntax-aware redaction and tokenization logic that the server uses so that field values are more likely to conform to their original syntax.
  • You can customize the behavior that the tool exhibits on a per-syntax basis, or you can point it at a log field behavior configuration object.

Generified Log Message Strings

Sanitized logging and the sanitize-log tool provide very powerful mechanisms for removing or obscuring sensitive or identifiable information in log messages, but there are some access log fields that may have such a wide range of values that it’s not necessarily feasible to treat them in a “one size fits all” kind of way, especially while retaining the utility of that field. These kinds of fields include:

  • The diagnostic message that is returned to the client in an LDAP response.
  • An additional info message that is meant to be recorded in the access log for an operation but not returned to the client.
  • An authentication failure reason that is meant to explain why an authentication attempt failed.
  • A disconnect reason that is meant to provide the reason that a client connection was closed.

It’s possible that the values of these fields could occasionally include sensitive or identifiable information, but their content can also be very helpful in troubleshooting problems or understanding the server’s behavior in specific situations. As such, you would lose substantial benefit by configuring those fields to be redacted.

Further, while a field-based approach works well for sanitizing access log messages for the most part, it doesn’t really make any sense for error log messages, as the core content of an error log message appears in the same field for all messages.

To address these concerns, we have introduced the ability to log generified values of these strings, using the generify-message-strings-when-possible property in the configuration for each logger. If this property is set to true, then the server will log the generic format string for the associated message rather than the processed message that it would normally include.

For example, if a simple bind attempt fails because the target user doesn’t exist, the access log message for that operation might include an authentication failure reason like:

Unable to bind to the Directory Server as user uid=jdoe,ou=People,dc=example,dc=com because no such user exists in the server.

However, if the logger is configured to report the generic version of the message, then it would instead log:

Unable to bind to the Directory Server as user %s because no such user exists in the server.

The generic version of the message doesn’t specifically identify the user, thereby offering better privacy than the un-generified version, but at least it’s still useful enough to understand the reason that the authentication attempt failed.

JSON-Formatted LDAP Request and Response Controls

The Ping Identity Directory Server provides support for a very wide range of request and response controls. This includes not only standard controls defined in RFCs and Internet Drafts, but also many controls that we’ve defined ourselves for enhanced functionality. These controls can be easily accessed through the UnboundID LDAP SDK for Java, but they aren’t as readily available for use in applications written with other LDAP APIs, especially in languages that don’t run on the JVM. Even though the LDAP SDK documentation describes the format of the encoded values for these controls, generating or decoding those values may still be a substantial challenge, typically requiring a library for working with ASN.1 BER and knowing how to use it properly.

To help address that, we’ve introduced the ability to encode LDAP request controls as JSON objects, and to indicate that LDAP response controls should also be encoded as JSON objects. JSON is much easier to work with than ASN.1 BER across a variety of programming languages, and it doesn’t require as much expertise to understand how to properly generate or parse JSON objects.

The primary interface to this functionality is through the JSON-formatted request control, which has an OID of “1.3.6.1.4.1.30221.2.5.64” and a value that is the string representation of a JSON object that encapsulates the JSON representations of the request controls to send to the server (or you can omit the value if you don’t have any request controls to send but want all response controls to be returned using a JSON encoding). If the request includes a JSON-formatted request control, and if there are any response controls to be returned, then the server will return them in a JSON-formatted response control, which has an OID of “1.3.6.1.4.1.30221.2.5.65” and a value that uses the same format as the request control. Note that while you don’t need to use the UnboundID LDAP SDK for Java to generate or parse these controls, its Javadoc documentation (especially the documentation for the toJSONControl method for the controls in question) may be useful in understanding what fields may be used in these objects.

The value of a JSON-formatted request or response control is simply a JSON object that has a single controls field whose value is an array of the JSON objects that make up the individual request or response controls. For example, the following JSON object represents the encoded value for a JSON-formatted request control that embeds both a retain identity request control and a get authorization entry request control:

{ "controls":[
  { "oid":"1.3.6.1.4.1.30221.2.5.3",
    "control-name":"Retain Identity Request Control",
    "criticality":true },
  { "oid":"1.3.6.1.4.1.30221.2.5.6",
    "control-name":"Get Authorization Entry Request Control",
    "criticality":false,
    "value-json":{
      "include-authentication-entry":true,
      "include-authorization-entry":true,
      "attributes":[ "uid", "givenName", "sn", "cn", "mail" ] } } ] }

For controls that are supported in both LDAP and the Directory REST API, the JSON encoding that we use is the same in either case. However, the Directory Server supports a number of additional controls for LDAP requests and responses that it doesn’t currently support through the Directory REST API. In additional to all of the controls we currently support in the Directory REST API, we provide JSON encodings for each of the following additional controls in LDAP requests:

  • Account usable request and response controls
  • Administrative operation request control
  • Authorization identity request and response controls
  • Extended schema info request control
  • Get authorization entry request and response controls
  • Get backend set ID request and response controls
  • Get password policy state issues request and response controls
  • Get recent login history request and response controls
  • Get server ID request and response controls
  • Get user resource limits request and response controls
  • Hard delete request control
  • Override search limits request control
  • Password policy request and response controls
  • Replication repair request control
  • Retain identity request control
  • Return conflict entries request control
  • Route to backend set request control
  • Route to server request control
  • Server-side sort request and response controls
  • Simple paged results control
  • Soft delete request control
  • Soft-deleted entry access request control
  • Subentries request control
  • Subtree delete request control
  • Suppress operational attribute update request control
  • Undelete request control
  • Virtual list view request and response controls

UnboundID LDAP SDK for Java 6.0.5

We have just released version 6.0.5 of the UnboundID LDAP SDK for Java. It is available for download from GitHub and SourceForge, and it is available in the Maven Central Repository. You can find the release notes at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but here’s a summary of the changes included in this version:

General Updates:

  • We fixed an issue that could occasionally cause the LDAP SDK to hide the actual cause of a StartTLS failure by using information from a second, less useful exception.
  • We fixed an issue that could cause the ldifsearch tool to display a malformed message when the first unnamed trailing argument was expected to be a search filter but could not be parsed as a valid filter.
  • We improved support for validating and comparing values using the telephone number syntax. Previously, we used a loose interpretation of the specification, which would consider any printable string (including strings without any digits) to be valid, and would only ignore spaces and hyphens when comparing values. You can now configure varying levels of strictness (either programmatically or using system properties), including requiring at least one digit or strict conformance to the X.520 specification. You can also configure it to ignore all non-digit characters when comparing values, and this is now the default behavior.
  • We fixed a bug in which the ldapcompare tool did not properly close its output file if one was configured. The output file does get automatically closed when the tool exits so it’s not an issue when running ldapcompare from the command line, but this can cause problems if the tool is invoked programmatically from another application.
  • We fixed an issue with the tool properties file created using the --generatePropertiesFile argument in command-line tools that support it. The generated properties file did not properly escape backslash, carriage return, line feed, or form feed characters.

Updates Specific to Use With the Ping Identity Directory Server:

  • We added support for encoding controls to JSON objects, and for decoding JSON objects as controls. There is a generic JSON representation that will work for any type of control (in which the value is provided as the base64-encoded representation of the raw value used in the LDAP representation of the control), but most controls provided as part of the LDAP SDK also support a more user-friendly representation in which the components of the value are represented in a nested JSON object.
  • We added client-side support for a new JSON-formatted request control that can be used to send request controls to a Ping Identity Directory Server with the controls encoded as JSON objects rather than a raw LDAP representation. We also added support for a JSON-formatted response control that can be used to receive JSON-encoded response controls from the server.
  • We updated the ldapsearch and ldapmodify command-line tools to add a --useJSONFormattedRequestControls argument that will cause any request controls to be sent using a JSON-formatted request control, and it will cause any response controls returned by the server to be embedded in a JSON-formatted response control.
  • We fixed an issue with the way that the parallel-update tool created assured replication request controls when an explicit local or remote assurance level was specified. Previously, it would only specify a minimum assurance level without specifying a maximum level, which could cause the server to use a higher assurance level than requested by the client.
  • We updated the topology registry trust manager to allow trusting a certificate chain if either the peer certificate or any of its issuers is found in the server’s topology registry. Previously, it would only trust a certificate chain if the peer certificate itself was found in the topology registry, and having an issuer certificate was not sufficient. The former behavior is still available with a configuration option.
  • We updated the topology registry trust manager to make it possible to ignore the certificate validity window for peer and issuer certificates. The validity window is still respected by default, but if the trust manager is configured to ignore it, then a certificate chain may be trusted even if the peer or an issuer certificate is expired or not yet valid.

UnboundID LDAP SDK for Java 6.0.4

We have just released version 6.0.4 of the UnboundID LDAP SDK for Java. It is available for download from GitHub and SourceForge, and it is available in the Maven Central Repository. You can find the release notes at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but here’s a summary of the changes included in this version:

General Updates:

  • We fixed an issue with the Filter.matchesEntry method that could cause it to throw an exception rather than returning an appropriate Boolean result when evaluating an AND or an OR filter in which one of the nested elements used inappropriate matching (for example, if the assertion value did not conform to the syntax for the associated attribute type).
  • We fixed an issue with the way that decodeable controls are registered with the LDAP SDK. Under some circumstances, a thread could become blocked while attempting to create a new control.
  • We updated the JVM-default trust manager to properly check for the existence of a “jssecacerts” trust store file in accordance with the JSSE specification. It had previously only looked for a file named “cacerts”.
  • We updated the logic used to select the default set of supported cipher suites so that it will no longer exclude suites with names starting with “SSL_” by default on JVMs with a vendor string that includes “IBM”. IBM JVMs appear to use the “SSL_” prefix for some or all cipher suites, including those that are not associated with TLS protocols rather than a legacy SSL protocol. We also added a TLSCipherSuiteSelector.setAllowSSLPrefixedSuites method that can be used to override the default behavior.
  • We updated the LDIF reader to support reading modifications with attribute values read from a file referenced by URL. This was previously supported when reading LDIF entries or add change records, but it had been overlooked for LDIF modify change records.
  • We updated the LDIF reader so that it no longer generates comments attempting to clarify the contents of base64-encoded values if the value is longer than 1,000 bytes.
  • We updated the documentation to include the latest versions of the draft-behera-ldap-password-policy, draft-coretta-x660-ldap, and draft-ietf-kitten-scram-2fa specifications.

Updates Specific to Use With the Ping Identity Directory Server:

  • We added a new API for parsing access log messages generated by the server. The new API supports both text-formatted and JSON-formatted log messages, whereas the previous version only supported messages in the default text (“name=value”) format.
  • We updated the summarize-access-log tool (which can be used to perform basic analysis of server access log files) to add support for JSON-formatted log files.
  • We added support for retrieving and parsing X.509 certificate monitor entries.
  • We added client-side support for an administrative task that can cause the server to immediately refresh any cached certificate monitor data. The server will automatically refresh the cache every minute, but the task can be used to cause an immediate refresh.

Ping Identity Directory Server 9.0.0.0

We have just released version 9.0.0.0 of the Ping Identity Directory Server. The release notes provide a pretty comprehensive overview of what’s included, but here’s my summary.

Ping Identity Directory Server Products Do Not Use log4j

Recently, a very serious security issue (CVE-2021-44228) was identified in the Apache log4j library, which is used by many Java applications to provide logging support. None of the Ping Identity Directory Server, Directory Proxy Server, Synchronization Server, and Metrics Engine products make use of this library in any way, and it is not included as part of the server. Some of the libraries that we include with the server do have support for logging to log4j, but that functionality is not used, and the log4j library is not included as part of the server.

The standalone version of the Admin Console does include the log4j library, but it is included only as a transitive dependency of one of the other libraries used by the console, and the log4j library is not used in any way by the Admin Console. Because this vulnerability was disclosed very late in the release cycle for the Ping Identity server products, we have chosen to update to a non-vulnerable version of the library rather than remove it entirely, as that requires less testing. Again, even though the log4j library is included with the standalone Admin Console, it is not used in any way, so even if you are using an older version of the console with an older version of the log4j library, you are not vulnerable to the security issue.

The UnboundID LDAP SDK for Java does not include any third-party dependencies at all (other than a Java SE runtime environment at Java version 7 or later). It does not include or interact with log4j in any way.

Changes Affecting All Server Products

  • Added cipher stream providers for PKCS #11 tokens, Azure Key Vault, and CyberArk Conjur. [more information]
  • Added passphrase providers for Azure Key Vault and CyberArk Conjur. [more information]
  • Added password storage schemes for authenticating with passwords stored in external services, including AWS Secrets Manager, Azure Key Vault, CyberArk Conjur, and HashiCorp Vault. [more information]
  • Added extended operations for managing server certificates. [more information]
  • Added the ability to redact the values of sensitive configuration properties when constructing the dsconfig representation for a configuration change. [more information]
  • Included the original requester DN and client IP address in log messages for mirrored configuration changes. [more information]
  • Added TLS configuration properties for outbound connections. [more information]
  • Updated the Admin Console to support using PKCS #12 and BCFKS trust stores.
  • Updated the file servlet to support authenticating with OAuth 2.0 access tokens and OpenID Connect ID tokens, which makes it possible to download collect-support-data archives and server profiles generated through the Admin Console when authenticated with SSO.
  • Fixed an issue that could cause degraded performance and higher CPU utilization for some clients using TLSv1.3.
  • Fixed an issue that prevented the manage-profile replace-profile tool from working properly for servers running in FIPS 140-2-compliant mode.
  • Updated export-ldif to always base64-encode attribute values containing any ASCII control characters. Previously, only the null, line feed, and carriage return control characters caused values to be base64-encoded.
  • Fixed an issue in which some tools that operate on the server’s configuration did not use the correct matching rule for attribute types configured to use case-sensitive matching. If a config entry had an attribute with multiple values differing only in capitalization, all but one of the values could be lost.
  • Updated the Directory REST API to add support for attribute options.
  • Added the ability to recognize JVM builds from Eclipse Foundation, Eclipse Adoptium, and BellSoft.
  • Removed “-XX:RefDiscoveryPolicy=1” from the default set of options used to launch the JVM. In some cases, this option has been responsible for JVM crashes.

Changes Affecting the Directory Server

  • Added support for pluggable pass-through authentication. [more information]
  • Fixed an issue that could prevent authenticating with certain types of reversibly encrypted passwords that were encrypted on an instance that was subsequently removed from the topology. [more information]
  • Fixed an issue that prevented decoding the value of a proxied authorization v2 request control when the authorization identity had a specific length.
  • Fixed an issue that could cause sporadic failures when attempting to back up a backend with data encryption enabled. In such cases, the backup would likely succeed if re-attempted.
  • Added a replica-partial-backlog attribute to the replication summary monitor entry to provide information about how each replica contributes to the overall replication backlog.
  • Fixed an issue in which the server could use incorrect resource limit values (including size limit, time limit, lookthrough limit, and idle time limit) for users with custom limits who authenticated via pass-through authentication.
  • Fixed an issue in which the server did not properly update certain password policy state information for simple bind attempts targeting users without a password.
  • Fixed an issue in which the server may not handle other controls properly when processing an operation that includes the join request control. The server may have overlooked a control immediately following the join request control in the operation request, and it may have omitted appropriate non-join result controls from the response.
  • Fixed an issue in which a newly initialized server could go into lockdown mode with a warning about missing changes if it was restarted immediately after initialization completed.
  • Fixed an issue that could prevent changes applied to non-RDN attributes in the course of processing a modify DN operation from being replicated.
  • Fixed an issue that could prevent composed attribute values from being properly updated for operations that are part of a muti-update extended operation.
  • Improved performance for modify operations that need to update a composite index to add an entry ID to the middle of a very large ID set.
  • Added limits for the maximum number of attributes in an add request and the maximum number of modifications in a modify request. [more information]
  • Updated the dsreplication initialize-all command to support initializing multiple replicas in parallel.
  • Updated remove-defunct-server to add a --performLocalCleanup option that can be used to remove replication metadata from a server that is offline.
  • Added an option to the mirror virtual attribute provider to make it possible to bypass access control evaluation for the internal searches that it performs to retrieve data from other entries.
  • Fixed an issue in which an entry added with a createTimestamp attribute could lose the original formatting for that attribute when replicated to other servers.
  • Fixed an issue that could lead to long startup times in large topologies with data encryption enabled.
  • Updated the ldap-diff tool to add several new features. [more information]
  • Updated the migrate-ldap-schema tool to add several new features. [more information]

Changes Affecting the Directory Proxy Server

  • Fixed an issue that could cause certain internal operations initiated in the Directory Proxy Server to fail when forwarded to a backend Directory Server whose default password policy was configured in a way that interfered with the account used to authorize internal operations.
  • Improved the logic used to select the best error result to return to the client for operations broadcast to all backend sets. Previously, the server could have incorrectly returned a result indicating that the target entry did not exist when the operation failed for some other reason.
  • Updated the entry counter, hash DN, and round-robin placement algorithms to support excluding specific backend sets.

Changes Affecting the Synchronization Server

  • Added the ability to synchronize certain password policy state information from Active Directory to the Ping Identity Directory Server, including account disabled state and the password changed time.
  • Fixed an issue that could prevent synchronizing changes to entries that have multiple attributes with the same base attribute type but different sets of attribute options, particularly if any of the attributes have more values than the replace-all-attr-values limit defined in the associated Sync Class.
  • Added the ability to apply rate limiting when synchronizing changes to PingOne.
  • Fixed an issue in which the max-rate-per-second property was not properly applied when running the resync tool.

Changes Affecting the Metrics Engine

  • Fixed an issue that could prevent dashboard icons from being properly displayed.

New Cipher Stream Providers

The encryption settings database holds a set of definitions that include the keys used for data encryption. The encryption settings database is itself encrypted, and we use a component called a cipher stream provider for reading and writing that encrypted content. We already offered several cipher stream provider implementations, including:

  • Generate the encryption key with a passphrase read from a file.
  • Generate the encryption key with a passphrase provided interactively during server startup.
  • Protect the encryption key with AWS Key Management Service (KMS).
  • Generate the encryption key with a passphrase retrieved from AWS Secrets Manager.
  • Generate the encryption key with a passphrase retrieved from a HashiCorp Vault instance.
  • Use the Server SDK to develop your own custom cipher stream providers.

In the 9.0.0.0 release, we are introducing support for three new types of cipher stream providers:

  • Wrap the encryption key with a certificate read from a PKCS #11 token, like a Hardware Security Module (HSM). Note that because of the limitations in Java’s support for key wrapping, only certificates with RSA key pairs can be used for this purpose.
  • Generate the encryption key with a passphrase retrieved from Azure Key Vault.
  • Generate the encryption key with a passphrase retrieved from a CyberArk Conjur instance.

New Passphrase Providers

Passphrase providers offer a means of obtaining clear-text secrets that the server may need for things like accessing protected content in a certificate key store or authenticating to an external service. We already offered several passphrase provider implementations, including:

  • Read the secret from a file, which may optionally be encrypted with a key from the server’s encryption settings database.
  • Read the secret from an obscured value stored in the server’s configuration.
  • Read the secret from an environment variable.
  • Read the secret from AWS Secrets Manager.
  • Read the secret from a HashiCorp Vault instance.
  • Use the Server SDK to develop your own custom passphrase providers.

In the 9.0.0.0 release, we are introducing support for two new types of passphrase providers:

  • Read the secret from Azure Key Vault.
  • Read the secret from a CyberArk Conjur instance.

Password Storage Schemes for External Services

Password storage schemes are used to protect passwords held in the server. We already offered a variety of password storage schemes, including:

  • Schemes using salted 256-bit, 384-bit, and 512-bit SHA-2 digests. SHA-1 support is also available for legacy purposes, but is not recommended.
  • Schemes using more resource-intensive, brute-force-resistant algorithms like PBKDF2, bcrypt, scrypt, and Argon2.
  • A scheme that reversibly encrypts passwords with a 256-bit AES key obtained from the encryption settings database.
  • Schemes that reversibly encrypt passwords with legacy keys stored in the topology registry.

In the 9.0.0.0 release, we are introducing support for new password storage schemes that allow users to authenticate with passwords stored in external secret stores, including:

  • AWS Secrets Manager
  • Azure Key Vault
  • CyberArk Conjur
  • HashiCorp Vault

In these cases, the storage scheme is configured with the information needed to connect and authenticate to the external service, and the encoded representation of the password contains a JSON object with the information needed to identify the specific secret in that service to use as the password for the associated user.

These password storage schemes can be used to authenticate with both LDAP simple authentication and SASL mechanisms that use a password. However, these schemes are read-only: users can authenticate with a password stored in the associated external service, but password changes need to be made through that service rather than over LDAP.

Extended Operations for Certificate Management

We have added support for a set of extended operations that can be used to remotely manage certificates in server instances, including replacing listener and inter-server certificates and purging information about retired certificates from the topology registry. These operations are especially useful for managing certificates in instances running in Docker or in other cases where command-line access may not be readily available to run the replace-certificate tool.

When replacing certificates, the new key store can be obtained in several ways:

  • It can be read from a file that is already available to the server (for example, one that has been copied to the server or placed on a shared filesystem).
  • The raw bytes that make up the new key store file can be included directly in the extended request.
  • The individual certificates and private key can be provided in the extended request, in either PEM or DER form.

Many safeguards are in place to prevent these extended operations from being inappropriately used. These include:

  • The extended operation handler providing support for these operations is not enabled by default. It must be enabled before they can be used.
  • The extended operations will only be allowed over secure connections.
  • The extended operations can only be requested by a user with the permit-replace-certificate-request privilege. No users have this privilege by default (not even root users or topology administrators).
  • You can indicate which of the individual types of operations are allowed, and you can define connection and request criteria to further restrict the circumstances under which they may be used.
  • By default, it will only allow reading certificates from a file on the server filesystem. You have to specifically enable the option to allow providing the new certificate information from a remote client.
  • The server will generate administrative alerts for all successful and failed attempts to process these operations.

These extended operations can be invoked programmatically (support for them is included in the UnboundID LDAP SDK for Java). They can also be used through new subcommands in the replace-certificate command-line tool.

Redacting Sensitive Values in Configuration Changes

We have added a new redact-sensitive-values-in-config-logs global configuration property that can be used to indicate that the server should redact the values of sensitive configuration properties when generating the dsconfig representation for that configuration change, including the representation that is written to the config-audit.log file and included in alerts to notify administrators of the change.

By default, the values of sensitive configuration properties are obscured in a way that allows the server to obtain the clear-text value, but that is not readily apparent to an observer. This helps protect the values of these secrets while still allowing the config-audit.log file to be replayed. However, a determined user with access to this obfuscated representation may be able to determine the clear-text value that it represents.

If the redact-sensitive-values-in-config-logs property is set to true, then the values of sensitive configuration properties will be redacted rather than obscured. This prevents someone with access to the dsconfig representation of the change from being able to obtain the clear-text value of the secret, but it does mean that the config-audit.log file may no longer be replayable.

Original Requester Details for Mirrored Configuration Changes

When making configuration changes, log messages (including those written to the server’s access log and the config-audit.log file) include the DN of the user that requested the change and the IP address of the client system. However, for changes affecting mirrored configuration (including in the topology registry or cluster configuration), these values do not accurately reflect the DN and address of the original requester, but instead reflect either the details of an internal connection or of a connection from another server instance that has forwarded change to the topology master.

To address this, we have updated the server so that the DN and IP address of the original requester are included as part of changes to mirrored configuration. Records for these configuration changes that are written to config-audit.log and the server’s access log will now provide these values in the original-requester-dn and original-requester-ip fields.

New TLS Configuration Properties

We have updated the crypto manager configuration to add support for four new properties for configuring TLS communication:

  • outbound-ssl-protocol — Can be used to specify the set of TLS protocols that may be used for outbound connections (e.g., those used for pass-through authentication or for synchronization with remote servers).
  • outbound-ssl-cipher-suite — Can be used to specify the set of TLS cipher suites that may be used for outbound connections.
  • enable-sha-1-cipher-suites — Can be used to enable the use of TLS cipher suites that rely on the SHA-1 digest algorithm, which is no longer considered secure and is disabled by default.
  • enable-rsa-key-exchange-cipher-suites — Can be used to enable the use of TLS cipher suites that rely on the RSA key exchange algorithm, which does not provide support for forward secrecy and is disabled by default.

Pluggable Pass-Through Authentication

We have updated the Directory Server to add support for pluggable pass-through authentication. Previously, the server provided support for passing through simple bind attempts to another LDAP server or to PingOne. It is now possible to support pass-through authentication to other types of services, and the Server SDK has been updated to add support for creating custom pass-through authentication handlers.

This implementation includes an LDAP pass-through authentication handler that allows the new pluggable pass-through authentication plugin to be used as an alternative to the former LDAP-specific pass-through authentication plugin. The new implementation offers several advantages over the former one, including:

  • Better default configuration properties (especially for the override-local-password property).
  • The ability to indicate whether to attempt pass-through authentication for accounts in an usable password policy state (for example, those that are locked or that have expired passwords).
  • The ability to set timeouts for interaction with the external LDAP servers.
  • Improved diagnostic information about pass-through authentication attempts, including support for the password policy request control and password expired response control.
  • A new monitor entry with metrics about the processing performed by the plugin.

Preserving Secret Keys for Instances Removed From the Topology

Previously, when a server was removed from the topology (for example, by using the remove-defunct-server tool), secret keys associated with that instance could be lost. This is unlikely to cause any problems in most cases because these keys are no longer used for most purposes. However, it could be an issue if the server is configured to use a legacy password storage scheme that protects passwords with reversible encryption. These schemes encrypt passwords with keys from the topology registry, and if a server was removed from the topology, then keys specific to that instance were also removed. This could prevent remaining servers from being able to decrypt passwords that were initially encrypted by the instance that was removed. To address this, we now preserve any secret keys that are associated with an instance before removing that instance from the topology.

Affected password storage schemes include AES, Blowfish, RC4, and 3DES. The newer AES256 password storage scheme is not affected by this issue.

Size Limits for Add and Modify Requests

We have added new maximum-attributes-per-add-request and maximum-modifications-per-modify-request properties to the global configuration. The former can be used to limit the number of attributes that may be included in an add request, and the latter can be used to limit the number of modifications that may be included in a modify request. Neither of these properties affects the number of values that individual attributes may have.

These limits can help avoid potential denial-of-service attacks that use specially crafted add and modify requests. By default, add requests are limited to 1000 attributes, and modify requests are limited to 1000 modifications, which should be plenty for virtually all real-world use cases.

New ldap-diff Features

We have updated the ldap-diff tool to provide several new features. These include:

  • We have added an option to perform byte-for-byte comparisons when identifying differences. By default, the tool uses schema-aware matching, which may not flag differences in values that are logically equivalent but not identical (for example, values that differ only in capitalization for an attribute configured to use case-insensitive matching).
  • You can now use a properties file to provide default values for some or all of the command-line arguments.
  • We improved support for SASL authentication.

New migrate-ldap-schema Features

We have updated the migrate-ldap-schema tool to provide several new features. These include:

  • We have added more flexibility when securing communication with servers over TLS, including the ability to use different key and trust managers for the source and destination servers.
  • We have added support for SASL authentication.
  • We have added support for using a properties file to obtain default values for some or all of the command-line arguments.
  • We have added better validation for migrated attribute types and object classes.

UnboundID LDAP SDK for Java 6.0.3

We have just released version 6.0.3 of the UnboundID LDAP SDK for Java. It is available for download from GitHub and SourceForge, and it is available in the Maven Central Repository. You can find the release notes at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but here’s a summary of the changes included in this version:

General Updates:

  • We fixed an issue with the round-robin server set that could cause it to select some servers with a higher frequency than others in the event that one or more of the servers become unavailable.
  • We fixed a potential race condition that could leave a background Timer thread running if a connection was closed while waiting for a response to a request issued via the asynchronous API.
  • We fixed an issue in which the in-memory directory server could incorrectly include a matched DN in certain bind response messages.
  • We improved support for SSL/TLS debugging for SSLUtil operations when used in conjunction with the javax.net.debug system property.
  • We added methods to the JSONLDAPResultWriter class that can be used to encode entries, search result references, and LDAP results to JSON objects.
  • We added a CryptoHelper.inferKeyStoreType method that attempts to determine the key store type for a specified file that is expected to represent a JKS, PKCS #12, or BCFKS key store.
  • We added StaticUtils convenience methods for generating random bytes, integers, and strings, optionally using cryptographically secure random number generators.

Updates Specific to Use With the Ping Identity Directory Server:

  • We fixed an issue that could cause the manage-account tool to fail if it receives a response with an unrecognized password policy state operation type. This is most likely to occur when the tool is communicating with a version of the Ping Identity Directory Server that does not correspond to the version of the manage-account tool.
  • We added client-side support for new extended operations that can allow for remote management of certificates in Ping Identity Directory Server instances.
  • We updated the AuthenticationFailureReason class to add additional failure reason values related to pass-through authentication.
  • We updated the TaskManager class to add methods for using LDAPInterface objects (including connection pools or Server SDK internal connections) as an alternative to LDAPConnection objects when interacting with administrative tasks.

UnboundID LDAP SDK for Java 6.0.2

We have just released version 6.0.2 of the UnboundID LDAP SDK for Java. It is available for download from GitHub and SourceForge, and it is available in the Maven Central Repository. You can find the release notes at https://docs.ldap.com/ldap-sdk/docs/release-notes.html, but here’s a summary of the changes included in this version:

  • We fixed an issue in the JVM-default trust manager that could prevent it from properly trusting a certificate chain that should be considered valid through a cross-signed relationship, which may include certificates signed by the Let’s Encrypt service in some cases. Although the trust manager provided support for cross-signed certificates, that support would previously only be used if one or more of the certificates in the presented chain were outside of their current validity window.
  • We added the ability to use the tls-server-end-point channel binding type when authenticating with the GSSAPI SASL mechanism. This feature depends on the underlying JVM providing support for this channel binding type and will likely require Java 13 or later.
  • We fixed an issue in the in-memory directory server that could prevent it from returning search result references for smart referral entries within the scope of the search. It would previously only return references for smart referral entries that matched the search filter, but will now return references for any smart referral entry within the scope.
  • We updated the LDAP command-line tool framework to add a --defaultTrust argument that can be used to indicate that the tool should use a default set of non-interactive logic for determining whether to trust a presented certificate chain. This includes at least the JVM’s default trust store, but in tools that are part of a Ping Identity server installation, it may also include the server’s default trust store and the topology registry. This is the same logic that tools would previously use when invoked without any trust-related arguments, with the exception that it will not interactively prompt about whether to trust the presented chain if it cannot be trusted through any of the default mechanisms. As such, it is more suitable for use in scripts that are intended to run in non-interactive settings.