com.nimbusds.openid.connect.provider.spi.claims.ldap.Configuration Maven / Gradle / Ivy
package com.nimbusds.openid.connect.provider.spi.claims.ldap;
import java.util.Properties;
import com.nimbusds.common.config.*;
import com.nimbusds.common.ldap.FilterTemplate;
import com.thetransactioncompany.util.PropertyParseException;
import com.thetransactioncompany.util.PropertyRetriever;
import com.unboundid.ldap.sdk.DN;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.SearchScope;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* LDAP claims source configuration. It is typically derived from a Java key /
* value properties file. The configuration is stored as public fields which
* become immutable (final) after their initialisation.
*
* Example configuration properties:
*
*
* op.ldapClaimsSource.enable = true
*
* op.ldapClaimsSource.attributeMap = /WEB-INF/ldapClaimsMap.json
*
* op.ldapClaimsSource.server.url = ldap://localhost:1389 ldap://remotehost:1389
* op.ldapClaimsSource.server.selectionAlgorithm = FAILOVER
* op.ldapClaimsSource.server.connectTimeout = 1000
* op.ldapClaimsSource.server.security = STARTTLS
* op.ldapClaimsSource.server.trustSelfSignedCerts = true
* op.ldapClaimsSource.server.connectionPoolSize = 10
* op.ldapClaimsSource.server.connectionPoolMaxWaitTime = 250
* op.ldapClaimsSource.server.connectionMaxAge = 0
*
* op.ldapClaimsSource.directory.user.dn = cn=Directory Manager
* op.ldapClaimsSource.directory.user.password = secret
*
* op.ldapClaimsSource.directory.baseDN = ou=people,dc=wonderland,dc=net
* op.ldapClaimsSource.directory.scope = ONE
* op.ldapClaimsSource.directory.filter = (uid=%u)
*
* op.ldapClaimsSource.customTrustStore.enable = false
* op.ldapClaimsSource.customTrustStore.file =
* op.ldapClaimsSource.customTrustStore.password =
* op.ldapClaimsSource.customTrustStore.type =
*
* op.ldapClaimsSource.customKeyStore.enable = false
* op.ldapClaimsSource.customKeyStore.file =
* op.ldapClaimsSource.customKeyStore.password =
* op.ldapClaimsSource.customKeyStore.type =
*
*/
public final class Configuration implements LoggableConfiguration {
/**
* The default properties prefix.
*/
public static final String DEFAULT_PREFIX = "op.ldapClaimsSource.";
/**
* Directory store details.
*/
public static class Directory implements LoggableConfiguration {
/**
* The directory user credentials. Should have read permission
* to the directory tree containing the user entries.
*
* Property keys: [prefix]user.*
*/
public final DirectoryUser user;
/**
* The base distinguished name (DN) of the directory branch
* where the user entries are stored.
*
*
Property key: [prefix]baseDN
*/
public final DN baseDN;
/**
* The search scope for the user entries with respect to the
* specified base DN.
*
*
Property key: [prefix]scope
*/
public final SearchScope scope;
/**
* The search filter to retrieve the user entries. The "%u"
* placeholder will be substituted with the subject identifier.
*
*
Property key: [prefix]filter
*/
public final FilterTemplate filter;
/**
* Creates a new directory store details instance from the
* specified properties.
*
* @param prefix The properties prefix. Must not be
* {@code null}.
* @param props The properties. Must not be {@code null}.
*
* @throws PropertyParseException On a missing or invalid
* property.
*/
public Directory(final String prefix, final Properties props)
throws PropertyParseException {
user = new DirectoryUser(prefix + "user.", props);
PropertyRetriever pr = new PropertyRetriever(props);
String dnString = pr.getString(prefix + "baseDN");
try {
baseDN = new DN(dnString);
} catch (LDAPException e) {
throw new PropertyParseException("Invalid base DN: " + e.getMessage(),
prefix + "baseDN",
dnString);
}
String scopeString = pr.getString(prefix + "scope");
if (scopeString.equalsIgnoreCase("BASE"))
scope = SearchScope.BASE;
else if (scopeString.equalsIgnoreCase("ONE"))
scope = SearchScope.ONE;
else if (scopeString.equalsIgnoreCase("SUB"))
scope = SearchScope.SUB;
else if (scopeString.equalsIgnoreCase("SUBORDINATES"))
scope = SearchScope.SUBORDINATE_SUBTREE;
else
throw new PropertyParseException("Invalid search scope",
prefix + "scope",
scopeString);
String filterString = pr.getString(prefix + "filter");
try {
filter = new FilterTemplate(filterString);
} catch (IllegalArgumentException e) {
throw new PropertyParseException("Invalid filter template: " + e.getMessage(),
prefix + "filter",
filterString);
}
}
@Override
public void log() {
Logger log = LogManager.getLogger("MAIN");
user.log();
log.info("LDAP claims source: Base DN: {}", baseDN.toString());
log.info("LDAP claims source: Search scope: {}", scope);
log.info("LDAP claims source: Filter: {}", filter);
}
}
/**
* Enables / disables the LDAP claims source. Disabled by default.
*
*
Property key: [prefix]enable
*/
public final boolean enable;
/**
* The LDAP attribute map definition. Can be the file name of a
* resource relative to the web application root, or a direct JSON
* object representation of the attribute map, optionally BASE-64
* encoded to ease passing the JSON string as a Java system property.
*
*
Defaults to {@link LDAPClaimsSource#MAP_FILE_PATH}.
*
*
Property key: [prefix]attributeMap
*/
public final String attributeMap;
/**
* The LDAP server connection details.
*/
public final LDAPServerConnectionPoolDetails server;
/**
* The directory store details.
*/
public final Directory directory;
/**
* The custom trust store details.
*/
public final CustomTrustStoreConfiguration customTrustStore;
/**
* The custom key store details.
*/
public final CustomKeyStoreConfiguration customKeyStore;
/**
* Creates a new LDAP claims source configuration from the specified
* properties.
*
* @param props The properties. Must not be {@code null}.
*
* @throws ConfigurationException On a missing or invalid property.
*/
public Configuration(final Properties props)
throws ConfigurationException {
PropertyRetriever pr = new PropertyRetriever(props);
try {
enable = pr.getOptBoolean(DEFAULT_PREFIX + "enable", false);
if (! enable) {
attributeMap = null;
server = null;
directory = null;
customTrustStore = null;
customKeyStore = null;
return;
}
attributeMap = pr.getOptString(DEFAULT_PREFIX + "attributeMap", LDAPClaimsSource.MAP_FILE_PATH);
server = new LDAPServerConnectionPoolDetails(DEFAULT_PREFIX + "server.", props);
directory = new Directory(DEFAULT_PREFIX + "directory.", props);
customTrustStore = new CustomTrustStoreConfiguration(DEFAULT_PREFIX + "customTrustStore.", props);
customKeyStore = new CustomKeyStoreConfiguration(DEFAULT_PREFIX + "customKeyStore.", props);
} catch (PropertyParseException e) {
throw new ConfigurationException(e.getMessage() + ": Property: " + e.getPropertyKey());
}
}
/**
* Logs the configuration details at INFO level. Properties that may
* adversely affect security are logged at WARN level.
*/
@Override
public void log() {
Logger log = LogManager.getLogger("MAIN");
log.info("[CSLDAP0000] LDAP claims source configuration:");
log.info("[CSLDAP0001] LDAP claims source enabled: {}", enable);
if (! enable) {
return;
}
log.info("[CSLDAP0005] LDAP attribute map: {}", attributeMap);
server.log();
directory.log();
customTrustStore.log();
customKeyStore.log();
}
}