From f3612b1aa023f12906a71cb12c6ca1cae12aa5dd Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 22 Mar 2013 13:01:05 +0000
Subject: [PATCH] Partial fix for OPENDJ-694: Implement HTTP BASIC authentication
---
opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json | 23 ++++++-
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Context.java | 8 ++
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java | 35 +++++++++--
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthorizationPolicy.java | 42 ++++++++++++++
opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Config.java | 30 +++++----
opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java | 11 +++
6 files changed, 120 insertions(+), 29 deletions(-)
diff --git a/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java b/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java
index 011afac..782bacd 100644
--- a/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java
+++ b/opendj3/opendj-rest2ldap-servlet/src/main/java/org/forgerock/opendj/rest2ldap/servlet/Rest2LDAPConnectionFactoryProvider.java
@@ -28,6 +28,7 @@
import org.forgerock.json.resource.ConnectionFactory;
import org.forgerock.json.resource.Resources;
import org.forgerock.json.resource.Router;
+import org.forgerock.opendj.rest2ldap.AuthorizationPolicy;
import org.forgerock.opendj.rest2ldap.Rest2LDAP;
import org.forgerock.opendj.rest2ldap.Rest2LDAP.Builder;
@@ -77,8 +78,13 @@
final JsonValue configuration = new JsonValue(content);
// Parse the authorization configuration.
+ final AuthorizationPolicy authzPolicy =
+ configuration.get("servlet").get("authorizationPolicy").required().asEnum(
+ AuthorizationPolicy.class);
final String proxyAuthzTemplate =
configuration.get("servlet").get("proxyAuthzIdTemplate").asString();
+
+ // Parse the connection factory if present.
final String ldapFactoryName =
configuration.get("servlet").get("ldapConnectionFactory").asString();
final org.forgerock.opendj.ldap.ConnectionFactory ldapFactory;
@@ -96,8 +102,9 @@
for (final String mappingUrl : mappings.keys()) {
final JsonValue mapping = mappings.get(mappingUrl);
final CollectionResourceProvider provider =
- Rest2LDAP.builder().connectionFactory(ldapFactory).useProxiedAuthorization(
- proxyAuthzTemplate).configureMapping(mapping).build();
+ Rest2LDAP.builder().connectionFactory(ldapFactory).authorizationPolicy(
+ authzPolicy).proxyAuthzIdTemplate(proxyAuthzTemplate)
+ .configureMapping(mapping).build();
router.addRoute(mappingUrl, provider);
}
return Resources.newInternalConnectionFactory(router);
diff --git a/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json b/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json
index fe6c9d4..14645cc 100644
--- a/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json
+++ b/opendj3/opendj-rest2ldap-servlet/src/main/webapp/opendj-rest2ldap-servlet.json
@@ -100,19 +100,32 @@
"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
+ // 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.
+ // Specifies how LDAP authorization should be performed. The method
+ // must be one of:
+ //
+ // "none" - use connections acquired from the LDAP connection
+ // factory. Don't use proxied authorization, and don't
+ // use cached pre-authenticated connections,
+ // "reuse" - use the connection obtained during LDAP
+ // authentication. If no connection was passed through
+ // the authorization will fail,
+ // "proxy" - use proxied authorization with an authorization ID
+ // derived from the "proxyAuthzIdTemplate". Proxied
+ // authorization will only be used if there is no
+ // pre-authenticated connection available.
+ "authorizationPolicy" : "none",
+
+ // The AuthzID template which will be used for proxied authorization.
// 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}",
+ "proxyAuthzIdTemplate" : "dn:{dn}",
// The REST APIs and their LDAP attribute mappings.
"mappings" : {
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthorizationPolicy.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthorizationPolicy.java
new file mode 100644
index 0000000..cb7d0fb
--- /dev/null
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthorizationPolicy.java
@@ -0,0 +1,42 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2013 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.rest2ldap;
+
+/**
+ * The policy which should be for performing authorization.
+ */
+public enum AuthorizationPolicy {
+ /**
+ * Use connections acquired from the LDAP connection factory. Don't use
+ * proxied authorization, and don't use cached pre-authenticated
+ * connections.
+ */
+ NONE,
+
+ /**
+ * Use the connection obtained during LDAP authentication. If no connection
+ * was passed through the authorization will fail.
+ */
+ REUSE,
+
+ /**
+ * Use proxied authorization with an authorization ID derived from the
+ * proxied authorization ID template. Proxied authorization will only be
+ * used if there is no pre-authenticated connection available.
+ */
+ PROXY;
+}
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Config.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Config.java
index f8f2c54..cbabe03 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Config.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Config.java
@@ -25,14 +25,17 @@
final class Config {
private final ConnectionFactory factory;
private final DecodeOptions options;
+ private final AuthorizationPolicy authzPolicy;
private final AuthzIdTemplate proxiedAuthzTemplate;
private final ReadOnUpdatePolicy readOnUpdatePolicy;
private final Schema schema;
Config(final ConnectionFactory factory, final ReadOnUpdatePolicy readOnUpdatePolicy,
- final AuthzIdTemplate proxiedAuthzTemplate, final Schema schema) {
+ final AuthorizationPolicy authzPolicy, final AuthzIdTemplate proxiedAuthzTemplate,
+ final Schema schema) {
this.factory = factory;
this.readOnUpdatePolicy = readOnUpdatePolicy;
+ this.authzPolicy = authzPolicy;
this.proxiedAuthzTemplate = proxiedAuthzTemplate;
this.schema = schema;
this.options = new DecodeOptions().setSchema(schema);
@@ -61,12 +64,22 @@
}
/**
+ * Returns the authorization policy which should be used for performing LDAP
+ * operations.
+ *
+ * @return The authorization policy which should be used for performing LDAP
+ * operations.
+ */
+ AuthorizationPolicy getAuthorizationPolicy() {
+ return authzPolicy;
+ }
+
+ /**
* Returns the authorization ID template which should be used when proxied
* authorization is enabled.
*
* @return The authorization ID template which should be used when proxied
- * authorization is enabled, or {@code null} if proxied
- * authorization is disabled.
+ * authorization is enabled.
*/
AuthzIdTemplate getProxiedAuthorizationTemplate() {
return proxiedAuthzTemplate;
@@ -93,15 +106,4 @@
Schema schema() {
return schema;
}
-
- /**
- * Returns {@code true} if the proxied authorization should be used for
- * authorizing LDAP requests.
- *
- * @return {@code true} if the proxied authorization should be used for
- * authorizing LDAP requests.
- */
- boolean useProxiedAuthorization() {
- return proxiedAuthzTemplate != null;
- }
}
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Context.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Context.java
index 4136956..f6c9579 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Context.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Context.java
@@ -205,7 +205,10 @@
Context(final Config config, final ServerContext context) {
this.config = config;
this.context = context;
- if (context.containsContext(AuthenticatedConnectionContext.class)) {
+
+ // Re-use the pre-authenticated connection if available and the authorization policy allows.
+ if (config.getAuthorizationPolicy() != AuthorizationPolicy.NONE
+ && context.containsContext(AuthenticatedConnectionContext.class)) {
final Connection connection =
context.asContext(AuthenticatedConnectionContext.class).getConnection();
this.preAuthenticatedConnection = connection != null ? wrap(connection) : null;
@@ -265,7 +268,8 @@
* cached connection since cached connections are supposed to have been
* pre-authenticated and therefore do not require proxied authorization.
*/
- if (preAuthenticatedConnection == null && config.useProxiedAuthorization()) {
+ if (preAuthenticatedConnection == null
+ && config.getAuthorizationPolicy() == AuthorizationPolicy.PROXY) {
if (context.containsContext(SecurityContext.class)) {
try {
final SecurityContext securityContext =
diff --git a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
index b69da29..9a7bed6 100644
--- a/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
+++ b/opendj3/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
@@ -71,6 +71,7 @@
private ConnectionFactory factory;
private MVCCStrategy mvccStrategy;
private NameStrategy nameStrategy;
+ private AuthorizationPolicy authzPolicy = AuthorizationPolicy.NONE;
private AuthzIdTemplate proxiedAuthzTemplate;
private ReadOnUpdatePolicy readOnUpdatePolicy = CONTROLS;
private AttributeMapper rootMapper;
@@ -105,13 +106,30 @@
if (rootMapper == null) {
throw new IllegalStateException("No mappings provided");
}
- if (proxiedAuthzTemplate != null && factory == null) {
- throw new IllegalStateException(
- "No connection factory specified for use with proxied authorization");
+ switch (authzPolicy) {
+ case NONE:
+ if (factory == null) {
+ throw new IllegalStateException(
+ "A connection factory must be specified when the authorization policy is 'none'");
+ }
+ break;
+ case PROXY:
+ if (proxiedAuthzTemplate == null) {
+ throw new IllegalStateException(
+ "Proxied authorization enabled but no template defined");
+ }
+ if (factory == null) {
+ throw new IllegalStateException(
+ "A connection factory must be specified when using proxied authorization");
+ }
+ break;
+ case REUSE:
+ // This is always ok.
+ break;
}
return new LDAPCollectionResourceProvider(baseDN, rootMapper, nameStrategy,
- mvccStrategy, new Config(factory, readOnUpdatePolicy, proxiedAuthzTemplate,
- schema), additionalLDAPAttributes);
+ mvccStrategy, new Config(factory, readOnUpdatePolicy, authzPolicy,
+ proxiedAuthzTemplate, schema), additionalLDAPAttributes);
}
/**
@@ -302,7 +320,12 @@
return useEtagAttribute(ad(attribute));
}
- public Builder useProxiedAuthorization(final String template) {
+ public Builder authorizationPolicy(final AuthorizationPolicy policy) {
+ this.authzPolicy = ensureNotNull(policy);
+ return this;
+ }
+
+ public Builder proxyAuthzIdTemplate(final String template) {
this.proxiedAuthzTemplate = template != null ? new AuthzIdTemplate(template) : null;
return this;
}
--
Gitblit v1.10.0