From 55053284a91de860a4189f5d169efb856ee82ce0 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 12 Sep 2011 16:00:46 +0000
Subject: [PATCH] Issue OPENDJ-262: Implement pass through authentication (PTA)
---
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java | 139 +++++++++++++++++++++++++++++++++++++++++++++-
opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java | 2
2 files changed, 136 insertions(+), 5 deletions(-)
diff --git a/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java b/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
index d02d685..dbd18eb 100644
--- a/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
+++ b/opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
@@ -1279,7 +1279,7 @@
// There's a potential, but benign, race condition here: other threads
// could jump in and rotate through the list before we return the
// connection factory.
- return newNextIndex;
+ return oldNextIndex;
}
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
index 6766d55..a41f31c 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyTestCase.java
@@ -284,8 +284,6 @@
{
builder.append("GetLDAPConnectionFactoryEvent(");
builder.append(hostPort);
- builder.append(", ");
- builder.append(options);
builder.append(')');
return builder;
}
@@ -2839,9 +2837,142 @@
- // TODO: connection pooling
- // TODO: load balancing
// TODO: fail-over
+ // TODO: retry search/bind on error
+ // TODO: detect when servers come back online
+
+ /**
+ * Tests load balancing across 3 servers.
+ *
+ * @throws Exception
+ * If an unexpected exception occurred.
+ */
+ @Test(enabled = true)
+ public void testLoadBalancing() throws Exception
+ {
+ // Mock configuration.
+ final LDAPPassThroughAuthenticationPolicyCfg cfg = mockCfg()
+ .withPrimaryServer(phost1).withPrimaryServer(phost2)
+ .withPrimaryServer(phost3)
+ .withMappingPolicy(MappingPolicy.MAPPED_SEARCH)
+ .withMappedAttribute("uid").withBaseDN("o=ad");
+
+ // Create all the events.
+ final MockProvider provider = new MockProvider();
+
+ // First of all the connection factories are created.
+ final GetLDAPConnectionFactoryEvent fe1 = new GetLDAPConnectionFactoryEvent(
+ phost1, cfg);
+ final GetLDAPConnectionFactoryEvent fe2 = new GetLDAPConnectionFactoryEvent(
+ phost2, cfg);
+ final GetLDAPConnectionFactoryEvent fe3 = new GetLDAPConnectionFactoryEvent(
+ phost3, cfg);
+ provider.expectEvent(fe1).expectEvent(fe2).expectEvent(fe3);
+
+ // Get connection for phost1, then search, then bind.
+ final GetConnectionEvent ceSearch1 = new GetConnectionEvent(fe1);
+ final GetConnectionEvent ceBind1 = new GetConnectionEvent(fe1);
+ provider
+ .expectEvent(ceSearch1)
+ .expectEvent(
+ new SimpleBindEvent(ceSearch1, searchBindDNString,
+ "searchPassword", ResultCode.SUCCESS))
+ .expectEvent(
+ new SearchEvent(ceSearch1, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString))
+ .expectEvent(ceBind1)
+ .expectEvent(
+ new SimpleBindEvent(ceBind1, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Get connection for phost2, then search, then bind.
+ final GetConnectionEvent ceSearch2 = new GetConnectionEvent(fe2);
+ final GetConnectionEvent ceBind2 = new GetConnectionEvent(fe2);
+ provider
+ .expectEvent(ceSearch2)
+ .expectEvent(
+ new SimpleBindEvent(ceSearch2, searchBindDNString,
+ "searchPassword", ResultCode.SUCCESS))
+ .expectEvent(
+ new SearchEvent(ceSearch2, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString))
+ .expectEvent(ceBind2)
+ .expectEvent(
+ new SimpleBindEvent(ceBind2, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Get connection for phost3, then search, then bind.
+ final GetConnectionEvent ceSearch3 = new GetConnectionEvent(fe3);
+ final GetConnectionEvent ceBind3 = new GetConnectionEvent(fe3);
+ provider
+ .expectEvent(ceSearch3)
+ .expectEvent(
+ new SimpleBindEvent(ceSearch3, searchBindDNString,
+ "searchPassword", ResultCode.SUCCESS))
+ .expectEvent(
+ new SearchEvent(ceSearch3, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString))
+ .expectEvent(ceBind3)
+ .expectEvent(
+ new SimpleBindEvent(ceBind3, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Repeat again using cached connection to phost1: search, then bind.
+ provider.expectEvent(
+ new SearchEvent(ceSearch1, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString)).expectEvent(
+ new SimpleBindEvent(ceBind1, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Repeat again using cached connection to phost2: search, then bind.
+ provider.expectEvent(
+ new SearchEvent(ceSearch2, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString)).expectEvent(
+ new SimpleBindEvent(ceBind2, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Repeat again using cached connection to phost3: search, then bind.
+ provider.expectEvent(
+ new SearchEvent(ceSearch3, "o=ad", SearchScope.WHOLE_SUBTREE,
+ "(uid=aduser)", adDNString)).expectEvent(
+ new SimpleBindEvent(ceBind3, adDNString, userPassword,
+ ResultCode.SUCCESS));
+
+ // Connections should be cached until the policy is finalized.
+
+ // Obtain policy and state.
+ final LDAPPassThroughAuthenticationPolicyFactory factory = new LDAPPassThroughAuthenticationPolicyFactory(
+ provider);
+ assertTrue(factory.isConfigurationAcceptable(cfg, null));
+ final AuthenticationPolicy policy = factory.createAuthenticationPolicy(cfg);
+
+ // Cycle twice through the LB pool.
+ for (int i = 0; i < 6; i++)
+ {
+ final AuthenticationPolicyState state = policy
+ .createAuthenticationPolicyState(userEntry);
+ assertEquals(state.getAuthenticationPolicy(), policy);
+
+ // Perform authentication.
+ assertTrue(state.passwordMatches(ByteString.valueOf(userPassword)));
+
+ state.finalizeStateAfterBind();
+ }
+
+ // Cached connections should be closed when the policy is finalized.
+ provider.expectEvent(new CloseEvent(ceSearch1));
+ provider.expectEvent(new CloseEvent(ceSearch2));
+ provider.expectEvent(new CloseEvent(ceSearch3));
+ provider.expectEvent(new CloseEvent(ceBind1));
+ provider.expectEvent(new CloseEvent(ceBind2));
+ provider.expectEvent(new CloseEvent(ceBind3));
+
+ // Tear down and check final state.
+ policy.finalizeAuthenticationPolicy();
+ provider.assertAllExpectedEventsReceived();
+ }
+
+
MockPolicyCfg mockCfg()
{
--
Gitblit v1.10.0