From a9edb3548b0b5794eefc4a02fb9d274ed70588a8 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 21 Mar 2013 18:04:28 +0000
Subject: [PATCH] Partial fix for OPENDJ-694: Implement HTTP BASIC authentication
---
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplate.java | 83 +++++++---
opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json | 281 +++++++++++++++++++++++-----------
opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java | 12 +
opendj-sdk/opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplateTest.java | 12 +
opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java | 55 +-----
5 files changed, 270 insertions(+), 173 deletions(-)
diff --git a/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java b/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java
index ba36044..011afac 100644
--- a/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java
+++ b/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java
@@ -21,6 +21,7 @@
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
+import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;
import org.forgerock.json.fluent.JsonValue;
import org.forgerock.json.resource.CollectionResourceProvider;
@@ -36,54 +37,14 @@
*/
public final class Rest2LDAPConnectionFactoryProvider {
private static final String INIT_PARAM_CONFIG_FILE = "config-file";
- private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+ private static final ObjectMapper JSON_MAPPER = new ObjectMapper().configure(
+ JsonParser.Feature.ALLOW_COMMENTS, true);
/**
* Returns a JSON resource connection factory configured using the
* configuration file named in the {@code config-file} Servlet
- * initialization parameter. The configuration file should have the
- * following JSON structure excluding the C-like comments:
- *
- * <pre>
- * {
- * // LDAP connection factory configurations.
- * "ldapConnectionFactories" : {
- * "default" : {
- * // See Rest2LDAP.configureConnectionFactory(JsonValue, String)
- * },
- * "root" : {
- * ...
- * }
- * },
- *
- * // This is optional.
- * "authorization" : {
- * // The LDAP connection factory which should be used for LDAP operations, or
- * // re-use cached connection from authentication filter if not present.
- * "ldapConnectionFactory" : "root",
- *
- * // The optional authorization ID template to use if proxied authorization is
- * // to be performed.
- * "proxyAuthzIdTemplate" : "dn:uid={uid},ou=people,dc=example,dc=com"
- * },
- *
- * // The LDAP mappings
- * "mappings" : {
- * "/users" : {
- * // The LDAP mapping for /users - Rest2LDAP.Builder.configureMapping(JsonValue).
- * "baseDN" : "ou=people,dc=example,dc=com",
- *
- * ...
- * },
- * "/groups" : {
- * // The LDAP mapping for /groups - Rest2LDAP.Builder.configureMapping(JsonValue).
- * "baseDN" : "ou=groups,dc=example,dc=com",
- *
- * ...
- * }
- * }
- * }
- * </pre>
+ * initialization parameter. See the sample configuration file for a
+ * detailed description of its content.
*
* @param config
* The Servlet configuration.
@@ -117,9 +78,9 @@
// Parse the authorization configuration.
final String proxyAuthzTemplate =
- configuration.get("authorization").get("proxyAuthzIdTemplate").asString();
+ configuration.get("servlet").get("proxyAuthzIdTemplate").asString();
final String ldapFactoryName =
- configuration.get("authorization").get("ldapConnectionFactory").asString();
+ configuration.get("servlet").get("ldapConnectionFactory").asString();
final org.forgerock.opendj.ldap.ConnectionFactory ldapFactory;
if (ldapFactoryName != null) {
ldapFactory =
@@ -131,7 +92,7 @@
// Create the router.
final Router router = new Router();
- final JsonValue mappings = configuration.get("mappings").required();
+ final JsonValue mappings = configuration.get("servlet").get("mappings").required();
for (final String mappingUrl : mappings.keys()) {
final JsonValue mapping = mappings.get(mappingUrl);
final CollectionResourceProvider provider =
diff --git a/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json b/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json
index cae4009..fe6c9d4 100644
--- a/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json
+++ b/opendj-sdk/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json
@@ -1,17 +1,33 @@
{
+ // The array of connection factories which will be used by the Rest2LDAP
+ // Servlet and authentication filter.
"ldapConnectionFactories" : {
+ // Unauthenticated connections used for performing bind requests.
"default" : {
- "primaryLDAPServers" : [
+ "connectionPoolSize" : 10,
+ "heartBeatIntervalSeconds" : 30,
+
+ // The preferred load-balancing pool.
+ "primaryLDAPServers" : [
{
"hostname" : "localhost",
"port" : 1389
}
],
- "connectionPoolSize" : 10,
- "heartBeatIntervalSeconds" : 30
+ // The fail-over load-balancing pool (optional).
+ "secondaryLDAPServers" : [
+ // Empty.
+ ]
},
+
+ // Authenticated connections which will be used for searches during
+ // authentication and proxied operations (if enabled). This factory
+ // will re-use the server "default" configuration.
"root" : {
"inheritFrom" : "default",
+
+ // Defines how authentication should be performed. Only "simple"
+ // authentication is supported at the moment.
"authentication" : {
"simple" : {
"bindDN" : "cn=directory manager",
@@ -20,104 +36,179 @@
}
}
},
-
- "authorization" : {
- "ldapConnectionFactory" : "root"
+
+ // The Rest2LDAP authentication filter configuration. The filter will be
+ // disabled if the configuration is not present. Upon successful
+ // authentication the filter will create a security context containing the
+ // following principals:
+ //
+ // "dn" - the DN of the user if known (may not be the case for sasl-plain)
+ // "id" - the username used for authentication.
+ "authenticationFilter" : {
+ // Indicates whether the filter should allow HTTP BASIC authentication.
+ "supportHTTPBasicAuthentication" : true,
+
+ // Indicates whether the filter should allow alternative authentication
+ // and, if so, which HTTP headers it should obtain the username and
+ // password from.
+ "supportAltAuthentication" : true,
+ "altAuthenticationUsernameHeader" : "X-OpenIDM-Username",
+ "altAuthenticationPasswordHeader" : "X-OpenIDM-Password",
+
+ // Indicates whether the authenticated LDAP connection should be cached
+ // for use within the Rest2LDAP Servlet for subsequent LDAP operations.
+ // If this is set to true then the Servlet will not need its own LDAP
+ // connection factory and will also not need to use proxied
+ // authorization.
+ "reuseAuthenticatedConnection" : true,
+
+ // Specifies how LDAP authentications should be performed. The method
+ // must be one of:
+ //
+ // "simple" - the username is an LDAP DN
+ // "sasl-plain" - the username is an authzid which will be
+ // substituted into the "saslAuthzIdTemplate" using
+ // %s substitution
+ // "search+simple" - the user's DN will be resolved by performing an
+ // LDAP search using a filter constructed by
+ // substituting the username into the
+ // "searchFilterTemplate" using %s substitution.
+ "method" : "simple",
+
+ // The connection factory which will be exclusively used for
+ // authenticating users using LDAP bind operations.
+ "bindLDAPConnectionFactory" : "default",
+
+ // The SASL AuthzID template which will be used for "sasl-plain"
+ // authentication.
+ "saslAuthzIdTemplate" : "dn:uid=%s,ou=people,dc=example,dc=com",
+
+ // The connection factory which will be used for performing LDAP
+ // searches to locate users when "search+simple" authentication is
+ // enabled.
+ "searchLDAPConnectionFactory" : "root",
+
+ // The search parameters to use for "search+simple" authentication.
+ "searchBaseDN" : "ou=people,dc=example,dc=com",
+ "searchScope" : "sub", // Or "one".
+ "searchFilterTemplate" : "(&(objectClass=inetOrgPerson)(uid=%s))"
+
+ // TODO: support for HTTP sessions?
},
- "mappings" : {
- "/users" : {
- "baseDN" : "ou=people,dc=example,dc=com",
- "readOnUpdatePolicy" : "controls",
- "additionalLDAPAttributes" : [
- {
- "type" : "objectClass",
- "values" : [
- "top",
- "person",
- "organizationalPerson",
- "inetOrgPerson"
- ]
+ // The Rest2LDAP Servlet configuration.
+ "servlet" : {
+ // The connection factory which will be used for performing LDAP
+ // operations. Pre-authenticated connections passed through from the
+ // authentication filter see "reuseAuthenticatedConnection") will be
+ // used in preference to this factory. Specifically, a connection
+ // factory does not need to be configured if a connection will always
+ // be passed on from the filter, which may not always be the case
+ // if the filter is configured to use HTTP sessions.
+ "ldapConnectionFactory" : "root",
+
+ // The AuthzID template which will be used for proxied authorization. If
+ // no template is specified then proxied authorization will be disabled.
+ // The template should contain fields which are expected to be found in
+ // the security context create during authentication, e.g. "dn" and "id".
+
+ // "proxyAuthzIdTemplate" : "dn:{dn}",
+
+ // The REST APIs and their LDAP attribute mappings.
+ "mappings" : {
+ "/users" : {
+ "baseDN" : "ou=people,dc=example,dc=com",
+ "readOnUpdatePolicy" : "controls",
+ "additionalLDAPAttributes" : [
+ {
+ "type" : "objectClass",
+ "values" : [
+ "top",
+ "person",
+ "organizationalPerson",
+ "inetOrgPerson"
+ ]
+ }
+ ],
+ "namingStrategy" : {
+ "strategy" : "clientDNNaming",
+ "dnAttribute" : "uid"
+ },
+ "etagAttribute" : "etag",
+ "attributes" : {
+ "schemas" : { "constant" : [ "urn:scim:schemas:core:1.0" ] },
+ "_id" : { "simple" : { "ldapAttribute" : "uid", "isSingleValued" : true, "isRequired" : true, "writability" : "createOnly" } },
+ "_rev" : { "simple" : { "ldapAttribute" : "etag", "isSingleValued" : true, "writability" : "readOnly" } },
+ "userName" : { "simple" : { "ldapAttribute" : "mail", "isSingleValued" : true, "writability" : "readOnly" } },
+ "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "isRequired" : true } },
+ "name" : { "object" : {
+ "givenName" : { "simple" : { "ldapAttribute" : "givenName", "isSingleValued" : true } },
+ "familyName" : { "simple" : { "ldapAttribute" : "sn", "isSingleValued" : true, "isRequired" : true } }
+ } },
+ "manager" : { "reference" : {
+ "ldapAttribute" : "manager",
+ "baseDN" : "ou=people,dc=example,dc=com",
+ "primaryKey" : "uid",
+ "mapper" : { "object" : {
+ "_id" : { "simple" : { "ldapAttribute" : "uid", "isSingleValued" : true, "isRequired" : true } },
+ "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "writability" : "readOnlyDiscardWrites" } }
+ } }
+ } },
+ "groups" : { "reference" : {
+ "ldapAttribute" : "isMemberOf",
+ "baseDN" : "ou=groups,dc=example,dc=com",
+ "writability" : "readOnly",
+ "primaryKey" : "cn",
+ "mapper" : { "object" : {
+ "_id" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true } }
+ } }
+ } },
+ "contactInformation" : { "object" : {
+ "telephoneNumber" : { "simple" : { "ldapAttribute" : "telephoneNumber", "isSingleValued" : true } },
+ "emailAddress" : { "simple" : { "ldapAttribute" : "mail", "isSingleValued" : true } }
+ } },
+ "meta" : { "object" : {
+ "created" : { "simple" : { "ldapAttribute" : "createTimestamp", "isSingleValued" : true, "writability" : "readOnly" } },
+ "lastModified" : { "simple" : { "ldapAttribute" : "modifyTimestamp", "isSingleValued" : true, "writability" : "readOnly" } }
+ } }
}
- ],
- "namingStrategy" : {
- "strategy" : "clientDNNaming",
- "dnAttribute" : "uid"
},
- "etagAttribute" : "etag",
- "attributes" : {
- "schemas" : { "constant" : [ "urn:scim:schemas:core:1.0" ] },
- "_id" : { "simple" : { "ldapAttribute" : "uid", "isSingleValued" : true, "isRequired" : true, "writability" : "createOnly" } },
- "_rev" : { "simple" : { "ldapAttribute" : "etag", "isSingleValued" : true, "writability" : "readOnly" } },
- "userName" : { "simple" : { "ldapAttribute" : "mail", "isSingleValued" : true, "writability" : "readOnly" } },
- "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "isRequired" : true } },
- "name" : { "object" : {
- "givenName" : { "simple" : { "ldapAttribute" : "givenName", "isSingleValued" : true } },
- "familyName" : { "simple" : { "ldapAttribute" : "sn", "isSingleValued" : true, "isRequired" : true } }
- } },
- "manager" : { "reference" : {
- "ldapAttribute" : "manager",
- "baseDN" : "ou=people,dc=example,dc=com",
- "primaryKey" : "uid",
- "mapper" : { "object" : {
- "_id" : { "simple" : { "ldapAttribute" : "uid", "isSingleValued" : true, "isRequired" : true } },
- "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "writability" : "readOnlyDiscardWrites" } }
+ "/groups" : {
+ "baseDN" : "ou=groups,dc=example,dc=com",
+ "readOnUpdatePolicy" : "controls",
+ "additionalLDAPAttributes" : [
+ {
+ "type" : "objectClass",
+ "values" : [
+ "top",
+ "groupOfUniqueNames"
+ ]
+ }
+ ],
+ "namingStrategy" : {
+ "strategy" : "clientDNNaming",
+ "dnAttribute" : "cn"
+ },
+ "etagAttribute" : "etag",
+ "attributes" : {
+ "schemas" : { "constant" : [ "urn:scim:schemas:core:1.0" ] },
+ "_id" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "isRequired" : true, "writability" : "createOnly" } },
+ "_rev" : { "simple" : { "ldapAttribute" : "etag", "isSingleValued" : true, "writability" : "readOnly" } },
+ "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "isRequired" : true, "writability" : "readOnly" } },
+ "members" : { "reference" : {
+ "ldapAttribute" : "uniqueMember",
+ "baseDN" : "dc=example,dc=com",
+ "primaryKey" : "uid",
+ "mapper" : { "object" : {
+ "_id" : { "simple" : { "ldapAttribute" : "uid", "isSingleValued" : true, "isRequired" : true } },
+ "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "writability" : "readOnlyDiscardWrites" } }
+ } }
+ } },
+ "meta" : { "object" : {
+ "created" : { "simple" : { "ldapAttribute" : "createTimestamp", "isSingleValued" : true, "writability" : "readOnly" } },
+ "lastModified" : { "simple" : { "ldapAttribute" : "modifyTimestamp", "isSingleValued" : true, "writability" : "readOnly" } }
} }
- } },
- "groups" : { "reference" : {
- "ldapAttribute" : "isMemberOf",
- "baseDN" : "ou=groups,dc=example,dc=com",
- "writability" : "readOnly",
- "primaryKey" : "cn",
- "mapper" : { "object" : {
- "_id" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true } }
- } }
- } },
- "contactInformation" : { "object" : {
- "telephoneNumber" : { "simple" : { "ldapAttribute" : "telephoneNumber", "isSingleValued" : true } },
- "emailAddress" : { "simple" : { "ldapAttribute" : "mail", "isSingleValued" : true } }
- } },
- "meta" : { "object" : {
- "created" : { "simple" : { "ldapAttribute" : "createTimestamp", "isSingleValued" : true, "writability" : "readOnly" } },
- "lastModified" : { "simple" : { "ldapAttribute" : "modifyTimestamp", "isSingleValued" : true, "writability" : "readOnly" } }
- } }
- }
- },
- "/groups" : {
- "baseDN" : "ou=groups,dc=example,dc=com",
- "readOnUpdatePolicy" : "controls",
- "additionalLDAPAttributes" : [
- {
- "type" : "objectClass",
- "values" : [
- "top",
- "groupOfUniqueNames"
- ]
}
- ],
- "namingStrategy" : {
- "strategy" : "clientDNNaming",
- "dnAttribute" : "cn"
- },
- "etagAttribute" : "etag",
- "attributes" : {
- "schemas" : { "constant" : [ "urn:scim:schemas:core:1.0" ] },
- "_id" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "isRequired" : true, "writability" : "createOnly" } },
- "_rev" : { "simple" : { "ldapAttribute" : "etag", "isSingleValued" : true, "writability" : "readOnly" } },
- "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "isRequired" : true, "writability" : "readOnly" } },
- "members" : { "reference" : {
- "ldapAttribute" : "uniqueMember",
- "baseDN" : "dc=example,dc=com",
- "primaryKey" : "uid",
- "mapper" : { "object" : {
- "_id" : { "simple" : { "ldapAttribute" : "uid", "isSingleValued" : true, "isRequired" : true } },
- "displayName" : { "simple" : { "ldapAttribute" : "cn", "isSingleValued" : true, "writability" : "readOnlyDiscardWrites" } }
- } }
- } },
- "meta" : { "object" : {
- "created" : { "simple" : { "ldapAttribute" : "createTimestamp", "isSingleValued" : true, "writability" : "readOnly" } },
- "lastModified" : { "simple" : { "ldapAttribute" : "modifyTimestamp", "isSingleValued" : true, "writability" : "readOnly" } }
- } }
}
}
}
diff --git a/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplate.java b/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplate.java
index 07fccaf..50e5472 100644
--- a/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplate.java
+++ b/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplate.java
@@ -37,11 +37,57 @@
* <code>u:{uid}@{realm}.example.com</code>.
*/
final class AuthzIdTemplate {
+ private static interface Impl {
+ String formatAsAuthzId(AuthzIdTemplate t, Object[] templateVariables, Schema schema)
+ throws ResourceException;
+ }
+
+ private static final Impl DN_IMPL = new Impl() {
+
+ @Override
+ public String formatAsAuthzId(final AuthzIdTemplate t, final Object[] templateVariables,
+ final Schema schema) throws ResourceException {
+ final String authzId = String.format(Locale.ENGLISH, t.formatString, templateVariables);
+ try {
+ // Validate the DN.
+ DN.valueOf(authzId.substring(3), schema);
+ } catch (final IllegalArgumentException e) {
+ throw new ForbiddenException(
+ "The request could not be authorized because the required security principal "
+ + " was not a valid LDAP DN");
+ }
+ return authzId;
+ }
+ };
+
+ private static final Pattern DN_PATTERN = Pattern.compile("^dn:\\{[^}]+\\}$");
+
+ private static final Impl DN_TEMPLATE_IMPL = new Impl() {
+
+ @Override
+ public String formatAsAuthzId(final AuthzIdTemplate t, final Object[] templateVariables,
+ final Schema schema) throws ResourceException {
+ return "dn:" + DN.format(t.dnFormatString, schema, templateVariables).toString();
+ }
+
+ };
+
private static final Pattern KEY_RE = Pattern.compile("\\{([^}]+)\\}");
+ private static final Impl UID_TEMPLATE_IMPL = new Impl() {
+
+ @Override
+ public String formatAsAuthzId(final AuthzIdTemplate t, final Object[] templateVariables,
+ final Schema schema) throws ResourceException {
+ return String.format(Locale.ENGLISH, t.formatString, templateVariables);
+ }
+
+ };
+
private final String dnFormatString;
private final String formatString;
private final List<String> keys = new ArrayList<String>();
+ private final Impl pimpl;
private final String template;
AuthzIdTemplate(final String template) {
@@ -57,10 +103,16 @@
keys.add(matcher.group(1));
}
matcher.appendTail(buffer);
-
- this.template = template;
this.formatString = buffer.toString();
- this.dnFormatString = template.startsWith("dn:") ? formatString.substring(3) : null;
+ this.template = template;
+
+ if (template.startsWith("dn:")) {
+ this.pimpl = DN_PATTERN.matcher(template).matches() ? DN_IMPL : DN_TEMPLATE_IMPL;
+ this.dnFormatString = formatString.substring(3);
+ } else {
+ this.pimpl = UID_TEMPLATE_IMPL;
+ this.dnFormatString = null;
+ }
}
@Override
@@ -70,29 +122,8 @@
String formatAsAuthzId(final Map<String, Object> principals, final Schema schema)
throws ResourceException {
- if (isDNTemplate()) {
- final String dn = formatAsDN(principals, schema).toString();
- final StringBuilder builder = new StringBuilder(dn.length() + 3);
- builder.append("dn:");
- builder.append(dn);
- return builder.toString();
- } else {
- final String[] values = getPrincipalsForFormatting(principals);
- return String.format(Locale.ENGLISH, formatString, (Object[]) values);
- }
- }
-
- DN formatAsDN(final Map<String, Object> principals, final Schema schema)
- throws ResourceException {
- if (!isDNTemplate()) {
- throw new IllegalStateException();
- }
- final String[] values = getPrincipalsForFormatting(principals);
- return DN.format(dnFormatString, schema, (Object[]) values);
- }
-
- boolean isDNTemplate() {
- return dnFormatString != null;
+ final String[] templateVariables = getPrincipalsForFormatting(principals);
+ return pimpl.formatAsAuthzId(this, templateVariables, schema);
}
private String[] getPrincipalsForFormatting(final Map<String, Object> principals)
diff --git a/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java b/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
index 11f43c4..b69da29 100644
--- a/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
+++ b/opendj-sdk/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
@@ -660,10 +660,14 @@
// Parse secondary data center(s).
final JsonValue secondaryLDAPServers = configuration.get("secondaryLDAPServers");
final ConnectionFactory secondary;
- if (secondaryLDAPServers.isList() && secondaryLDAPServers.size() != 0) {
- secondary =
- parseLDAPServers(secondaryLDAPServers, bindRequest, connectionPoolSize,
- heartBeatIntervalSeconds);
+ if (secondaryLDAPServers.isList()) {
+ if (secondaryLDAPServers.size() > 0) {
+ secondary =
+ parseLDAPServers(secondaryLDAPServers, bindRequest, connectionPoolSize,
+ heartBeatIntervalSeconds);
+ } else {
+ secondary = null;
+ }
} else if (!secondaryLDAPServers.isNull()) {
throw new IllegalArgumentException("Invalid secondaryLDAPServers configuration");
} else {
diff --git a/opendj-sdk/opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplateTest.java b/opendj-sdk/opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplateTest.java
index 7376fce..b2e8897 100644
--- a/opendj-sdk/opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplateTest.java
+++ b/opendj-sdk/opendj3/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplateTest.java
@@ -49,6 +49,12 @@
map("uid", "test.user", "realm", "test+cn=quoting")
},
{
+ // Should not perform DN quoting.
+ "dn:{dn}",
+ "dn:uid=test.user,ou=acme,dc=example,dc=com",
+ map("dn", "uid=test.user,ou=acme,dc=example,dc=com")
+ },
+ {
"u:{uid}@{realm}.example.com",
"u:test.user@acme.example.com",
map("uid", "test.user", "realm", "acme")
@@ -82,6 +88,11 @@
map("uid", "test.user")
},
{
+ // Malformed DN.
+ "dn:{dn}",
+ map("dn", "uid")
+ },
+ {
"u:{uid}@{realm}.example.com",
map("uid", "test.user")
},
@@ -105,7 +116,6 @@
},
};
// @formatter:on
-
}
@Test(dataProvider = "invalidTemplates", expectedExceptions = IllegalArgumentException.class)
--
Gitblit v1.10.0