You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2014/02/11 01:18:09 UTC
svn commit: r1566885 - in /jackrabbit/oak/trunk: oak-auth-ldap/
oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/
oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/
oak-core/ oak-c...
Author: tripod
Date: Tue Feb 11 00:18:08 2014
New Revision: 1566885
URL: http://svn.apache.org/r1566885
Log:
OAK-516 Create LdapLoginModule based on ExternalLoginModule (wip)
Added:
jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java
jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginStandaloneTest.java
jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java
jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginWithRepoLoginTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
Removed:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestLoginModule.java
Modified:
jackrabbit/oak/trunk/oak-auth-ldap/pom.xml
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java
jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java
jackrabbit/oak/trunk/oak-core/pom.xml
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentity.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityRef.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalIDPManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/Tracker.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
Modified: jackrabbit/oak/trunk/oak-auth-ldap/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/pom.xml?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-auth-ldap/pom.xml Tue Feb 11 00:18:08 2014
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>oak-parent</artifactId>
- <version>0.16-SNAPSHOT</version>
+ <version>0.17-SNAPSHOT</version>
<relativePath>../oak-parent/pom.xml</relativePath>
</parent>
@@ -212,5 +212,13 @@
<version>1.5.5</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-core</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
</project>
Modified: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java (original)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentity.java Tue Feb 11 00:18:08 2014
@@ -86,7 +86,7 @@ public abstract class LdapIdentity imple
*/
@Nonnull
@Override
- public Iterable<? extends ExternalGroup> getGroups() {
+ public Iterable<? extends ExternalIdentityRef> getGroups() {
return Collections.emptyList();
}
Modified: jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java (original)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java Tue Feb 11 00:18:08 2014
@@ -573,9 +573,19 @@ public class LdapProviderConfig {
private String groupMemberAttribute = PARAM_GROUP_MEMBER_ATTRIBUTE;
- private final Identity userConfig = new Identity();
-
- private final Identity groupConfig = new Identity();
+ private final Identity userConfig = new Identity()
+ .setBaseDN(PARAM_USER_BASE_DN_DEFAULT)
+ .setExtraFilter(PARAM_USER_EXTRA_FILTER_DEFAULT)
+ .setIdAttribute(PARAM_USER_ID_ATTRIBUTE_DEFAULT)
+ .setMakeDnPath(PARAM_USER_MAKE_DN_PATH_DEFAULT)
+ .setObjectClasses(PARAM_USER_OBJECTCLASS_DEFAULT);
+
+ private final Identity groupConfig = new Identity()
+ .setBaseDN(PARAM_GROUP_BASE_DN_DEFAULT)
+ .setExtraFilter(PARAM_GROUP_EXTRA_FILTER_DEFAULT)
+ .setIdAttribute(PARAM_GROUP_NAME_ATTRIBUTE_DEFAULT)
+ .setMakeDnPath(PARAM_GROUP_MAKE_DN_PATH_DEFAULT)
+ .setObjectClasses(PARAM_GROUP_OBJECTCLASS_DEFAULT);
/**
* Returns the name of this provider configuration.
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java?rev=1566885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/InternalLdapServer.java Tue Feb 11 00:18:08 2014
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap;
+
+import java.io.File;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.directory.server.unit.AbstractServerTest;
+
+class InternalLdapServer extends AbstractServerTest {
+
+ public static final String GROUP_MEMBER_ATTR = "member";
+ public static final String GROUP_CLASS_ATTR = "groupOfNames";
+
+ public static final String ADMIN_PW = "secret";
+
+ public void setUp() throws Exception {
+ super.setUp();
+ doDelete = true;
+ }
+
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Override
+ protected void configureDirectoryService() throws Exception {
+ directoryService.setWorkingDirectory(new File("target", "apacheds"));
+ doDelete(directoryService.getWorkingDirectory());
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String addUser(String firstName, String lastName, String userId, String password)
+ throws Exception {
+ String cn = firstName + ' ' + lastName;
+ String dn = buildDn(cn, false);
+ StringBuilder entries = new StringBuilder();
+ entries.append("dn: ").append(dn).append('\n')
+ .append("objectClass: inetOrgPerson\n").append("cn: ").append(cn)
+ .append('\n').append("sn: ").append(lastName)
+ .append('\n').append("givenName:").append(firstName)
+ .append('\n').append("uid: ").append(userId)
+ .append('\n').append("userPassword: ").append(password).append("\n\n");
+ injectEntries(entries.toString());
+ return dn;
+ }
+
+ public String addGroup(String name) throws Exception {
+ String dn = buildDn(name, true);
+ StringBuilder entries = new StringBuilder();
+ entries.append("dn: ").append(dn).append('\n').append("objectClass: ")
+ .append(GROUP_CLASS_ATTR).append('\n').append(GROUP_MEMBER_ATTR)
+ .append(":\n").append("cn: ").append(name).append("\n\n");
+ injectEntries(entries.toString());
+ return dn;
+ }
+
+ public void addMember(String groupDN, String memberDN) throws Exception {
+ LdapContext ctxt = getWiredContext();
+ BasicAttributes attrs = new BasicAttributes();
+ attrs.put("member", memberDN);
+ ctxt.modifyAttributes(groupDN, DirContext.ADD_ATTRIBUTE, attrs);
+ }
+
+ public void removeMember(String groupDN, String memberDN) throws Exception {
+ LdapContext ctxt = getWiredContext();
+ BasicAttributes attrs = new BasicAttributes();
+ attrs.put("member", memberDN);
+ ctxt.modifyAttributes(groupDN, DirContext.REMOVE_ATTRIBUTE, attrs);
+ }
+
+ private static String buildDn(String name, boolean isGroup) {
+ StringBuilder dn = new StringBuilder();
+ dn.append("cn=").append(name).append(',');
+ if (isGroup) {
+ dn.append(ServerDNConstants.GROUPS_SYSTEM_DN);
+ } else {
+ dn.append(ServerDNConstants.USERS_SYSTEM_DN);
+ }
+ return dn.toString();
+ }
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginStandaloneTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginStandaloneTest.java?rev=1566885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginStandaloneTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginStandaloneTest.java Tue Feb 11 00:18:08 2014
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
+import org.junit.Ignore;
+
+@Ignore //ignore for the moment because "mvn test" runs into PermGen memory issues
+public class LdapLoginStandaloneTest extends LdapLoginTestBase {
+
+ @Override
+ protected Configuration getConfiguration() {
+ return new Configuration() {
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(String s) {
+ return new AppConfigurationEntry[]{
+ new AppConfigurationEntry(
+ ExternalLoginModule.class.getName(),
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ options)
+ };
+ }
+ };
+ }
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java?rev=1566885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginTestBase.java Tue Feb 11 00:18:08 2014
@@ -0,0 +1,371 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.login.LoginException;
+
+import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.api.AuthInfo;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapIdentityProvider;
+import org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapProviderConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalLoginModuleTestBase;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
+import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public abstract class LdapLoginTestBase extends ExternalLoginModuleTestBase {
+
+ protected static final InternalLdapServer LDAP_SERVER = new InternalLdapServer();
+
+ protected static final String USER_ID = "foobar";
+ protected static final String USER_PWD = "foobar";
+ protected static final String USER_FIRSTNAME = "Foo";
+ protected static final String USER_LASTNAME = "Bar";
+ protected static final String USER_ATTR = "givenName";
+ protected static final String USER_PROP = "profile/name";
+ protected static final String GROUP_PROP = "profile/member";
+ protected static final String GROUP_NAME = "foobargroup";
+
+ protected static String GROUP_DN;
+
+ protected static int CONCURRENT_LOGINS = 10;
+
+ //initialize LDAP server only once (fast, but might turn out to be not sufficiently flexible in the future)
+ protected static final boolean USE_COMMON_LDAP_FIXTURE = false;
+
+ protected final HashMap<String, Object> options = new HashMap<String, Object>();
+
+ protected UserManager userManager;
+
+ protected LdapIdentityProvider idp;
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ if (USE_COMMON_LDAP_FIXTURE) {
+ LDAP_SERVER.setUp();
+ createLdapFixture();
+ }
+ }
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ if (USE_COMMON_LDAP_FIXTURE) {
+ LDAP_SERVER.tearDown();
+ }
+ }
+
+ @Before
+ public void before() throws Exception {
+ super.before();
+
+ if (!USE_COMMON_LDAP_FIXTURE) {
+ LDAP_SERVER.setUp();
+ createLdapFixture();
+ }
+
+ UserConfiguration uc = securityProvider.getConfiguration(UserConfiguration.class);
+ userManager = uc.getUserManager(root, NamePathMapper.DEFAULT);
+ }
+
+ @After
+ public void after() throws Exception {
+
+ if (!USE_COMMON_LDAP_FIXTURE) {
+ LDAP_SERVER.tearDown();
+ }
+
+ try {
+ Authorizable a = userManager.getAuthorizable(USER_ID);
+ if (a != null) {
+ a.remove();
+ }
+ if (GROUP_DN != null) {
+ a = userManager.getAuthorizable(GROUP_DN);
+ if (a != null) {
+ a.remove();
+ }
+ }
+ root.commit();
+ } finally {
+ root.refresh();
+ super.after();
+ }
+ }
+
+ @Override
+ protected ExternalIdentityProvider createIDP() {
+ LdapProviderConfig cfg = new LdapProviderConfig()
+ .setName("ldap")
+ .setHostname("127.0.0.1")
+ .setPort(LDAP_SERVER.getPort())
+ .setBindDN(ServerDNConstants.ADMIN_SYSTEM_DN)
+ .setBindPassword(InternalLdapServer.ADMIN_PW)
+ .setGroupMemberAttribute(InternalLdapServer.GROUP_MEMBER_ATTR);
+
+ cfg.getUserConfig()
+ .setBaseDN(ServerDNConstants.USERS_SYSTEM_DN)
+ .setObjectClasses("inetOrgPerson");
+ cfg.getGroupConfig()
+ .setBaseDN(ServerDNConstants.GROUPS_SYSTEM_DN)
+ .setObjectClasses(InternalLdapServer.GROUP_CLASS_ATTR);
+
+ return new LdapIdentityProvider(cfg);
+ }
+
+ @Test
+ public void testLoginFailed() throws Exception {
+ try {
+ ContentSession cs = login(new SimpleCredentials(USER_ID, new char[0]));
+ cs.close();
+ fail("login failure expected");
+ } catch (LoginException e) {
+ // success
+ } finally {
+ assertNull(userManager.getAuthorizable(USER_ID));
+ }
+ }
+
+ @Test
+ public void testSyncCreateUser() throws Exception {
+ ContentSession cs = null;
+ try {
+ cs = login(new SimpleCredentials(USER_ID, USER_PWD.toCharArray()));
+
+ root.refresh();
+ Authorizable user = userManager.getAuthorizable(USER_ID);
+ assertNotNull(user);
+ assertTrue(user.hasProperty(USER_PROP));
+ Tree userTree = cs.getLatestRoot().getTree(user.getPath());
+ assertFalse(userTree.hasProperty(UserConstants.REP_PASSWORD));
+
+ assertNull(userManager.getAuthorizable(GROUP_DN));
+ } finally {
+ if (cs != null) {
+ cs.close();
+ }
+ options.clear();
+ }
+ }
+
+ @Test
+ public void testSyncCreateGroup() throws Exception {
+ ContentSession cs = null;
+ try {
+ cs = login(new SimpleCredentials(USER_ID, USER_PWD.toCharArray()));
+
+ root.refresh();
+ assertNull(userManager.getAuthorizable(USER_ID));
+ assertNull(userManager.getAuthorizable(GROUP_DN));
+ } finally {
+ if (cs != null) {
+ cs.close();
+ }
+ options.clear();
+ }
+ }
+
+ @Test
+ public void testSyncUpdate() throws Exception {
+ // create user upfront in order to test update mode
+ userManager.createUser(USER_ID, null);
+ root.commit();
+
+ ContentSession cs = null;
+ try {
+ cs = login(new SimpleCredentials(USER_ID, USER_PWD.toCharArray()));
+
+ root.refresh();
+ Authorizable user = userManager.getAuthorizable(USER_ID);
+ assertNotNull(user);
+ assertTrue(user.hasProperty(USER_PROP));
+ assertNull(userManager.getAuthorizable(GROUP_DN));
+ } finally {
+ if (cs != null) {
+ cs.close();
+ }
+ options.clear();
+ }
+ }
+
+ @Test
+ public void testLoginSetsAuthInfo() throws Exception {
+ ContentSession cs = null;
+ try {
+ SimpleCredentials sc = new SimpleCredentials(USER_ID, USER_PWD.toCharArray());
+ sc.setAttribute("attr", "val");
+
+ cs = login(sc);
+ AuthInfo ai = cs.getAuthInfo();
+
+ assertEquals(USER_ID, ai.getUserID());
+ assertEquals("val", ai.getAttribute("attr"));
+ } finally {
+ if (cs != null) {
+ cs.close();
+ }
+ }
+ }
+
+ @Test
+ public void testPrincipalsFromAuthInfo() throws Exception {
+ ContentSession cs = null;
+ try {
+ SimpleCredentials sc = new SimpleCredentials(USER_ID, USER_PWD.toCharArray());
+ sc.setAttribute("attr", "val");
+
+ cs = login(sc);
+ AuthInfo ai = cs.getAuthInfo();
+
+ root.refresh();
+ PrincipalProvider pp = getSecurityProvider().getConfiguration(PrincipalConfiguration.class).getPrincipalProvider(root, NamePathMapper.DEFAULT);
+ Set<? extends Principal> expected = pp.getPrincipals(USER_ID);
+ assertEquals(2, expected.size());
+ assertEquals(expected, ai.getPrincipals());
+
+ } finally {
+ if (cs != null) {
+ cs.close();
+ }
+ }
+ }
+
+ @Test
+ public void testPrincipalsFromAuthInfo2() throws Exception {
+ ContentSession cs = null;
+ try {
+ SimpleCredentials sc = new SimpleCredentials(USER_ID, USER_PWD.toCharArray());
+ sc.setAttribute("attr", "val");
+
+ cs = login(sc);
+ AuthInfo ai = cs.getAuthInfo();
+
+ root.refresh();
+ PrincipalProvider pp = getSecurityProvider().getConfiguration(PrincipalConfiguration.class).getPrincipalProvider(root, NamePathMapper.DEFAULT);
+ Set<? extends Principal> expected = pp.getPrincipals(USER_ID);
+ assertEquals(3, expected.size());
+ assertEquals(expected, ai.getPrincipals());
+
+ } finally {
+ if (cs != null) {
+ cs.close();
+ }
+ }
+ }
+
+ @Test
+ public void testReLogin() throws Exception {
+ ContentSession cs = null;
+ try {
+ cs = login(new SimpleCredentials(USER_ID, USER_PWD.toCharArray()));
+
+ root.refresh();
+ Authorizable user = userManager.getAuthorizable(USER_ID);
+ assertNotNull(user);
+ assertFalse(root.getTree(user.getPath()).hasProperty(UserConstants.REP_PASSWORD));
+
+ cs.close();
+ // login again
+ cs = login(new SimpleCredentials(USER_ID, USER_PWD.toCharArray()));
+ assertEquals(USER_ID, cs.getAuthInfo().getUserID());
+ } finally {
+ if (cs != null) {
+ cs.close();
+ }
+ options.clear();
+ }
+ }
+
+ @Ignore // FIXME
+ @Test
+ public void testConcurrentLogin() throws Exception {
+ concurrentLogin(false);
+ }
+
+ @Ignore // FIXME
+ @Test
+ public void testConcurrentLoginSameGroup() throws Exception {
+ concurrentLogin(true);
+ }
+
+ private void concurrentLogin(boolean sameGroup) throws Exception {
+ final List<Exception> exceptions = new ArrayList<Exception>();
+ List<Thread> workers = new ArrayList<Thread>();
+ for (int i = 0; i < CONCURRENT_LOGINS; i++) {
+ final String userId = "user-" + i;
+ final String pass = "secret";
+ String userDN = LDAP_SERVER.addUser(userId, "test", userId, pass);
+ if (sameGroup) {
+ LDAP_SERVER.addMember(GROUP_DN, userDN);
+ }
+ workers.add(new Thread(new Runnable() {
+ public void run() {
+ try {
+ login(new SimpleCredentials(
+ userId, pass.toCharArray())).close();
+ } catch (Exception e) {
+ exceptions.add(e);
+ }
+ }
+ }));
+ }
+ for (Thread t : workers) {
+ t.start();
+ }
+ for (Thread t : workers) {
+ t.join();
+ }
+ for (Exception e : exceptions) {
+ e.printStackTrace();
+ }
+ if (!exceptions.isEmpty()) {
+ throw exceptions.get(0);
+ }
+ }
+
+ protected static void createLdapFixture() throws Exception {
+ LDAP_SERVER.addMember(
+ GROUP_DN = LDAP_SERVER.addGroup(GROUP_NAME),
+ LDAP_SERVER.addUser(USER_FIRSTNAME, USER_LASTNAME, USER_ID, USER_PWD));
+ }
+}
Added: jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginWithRepoLoginTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginWithRepoLoginTest.java?rev=1566885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginWithRepoLoginTest.java (added)
+++ jackrabbit/oak/trunk/oak-auth-ldap/src/test/java/org/apache/jackrabbit/oak/security/authentication/ldap/LdapLoginWithRepoLoginTest.java Tue Feb 11 00:18:08 2014
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.security.authentication.ldap;
+
+import java.util.Collections;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
+import org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
+import org.junit.Ignore;
+
+@Ignore //ignore for the moment because "mvn test" runs into PermGen memory issues
+public class LdapLoginWithRepoLoginTest extends LdapLoginTestBase {
+
+ @Override
+ protected Configuration getConfiguration() {
+ return new Configuration() {
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(String s) {
+ return new AppConfigurationEntry[]{
+ new AppConfigurationEntry(
+ LoginModuleImpl.class.getName(),
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT,
+ Collections.<String, Object>emptyMap()),
+ new AppConfigurationEntry(
+ ExternalLoginModule.class.getName(),
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ options)
+ };
+ }
+ };
+ }
+}
Modified: jackrabbit/oak/trunk/oak-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/pom.xml?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core/pom.xml Tue Feb 11 00:18:08 2014
@@ -338,9 +338,9 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.directory.server</groupId>
- <artifactId>apacheds-server-unit</artifactId>
- <version>1.5.5</version>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
<scope>test</scope>
</dependency>
</dependencies>
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java Tue Feb 11 00:18:08 2014
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.security;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -43,9 +44,9 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncManager;
import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIDPManagerImpl;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager;
import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncManagerImpl;
import org.apache.jackrabbit.oak.spi.security.authentication.token.CompositeTokenConfiguration;
import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
@@ -57,6 +58,7 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.spi.security.user.AuthorizableNodeName;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAuthorizableActionProvider;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardRestrictionProvider;
@@ -114,16 +116,12 @@ public class SecurityProviderImpl implem
private ConfigurationParameters configuration;
- @Reference
- private ExternalIdentityProviderManager identityProviderManager;
-
- @Reference
- private SyncManager syncManager;
+ private Whiteboard whiteboard = new DefaultWhiteboard();
/**
* Default constructor used in OSGi environments.
*/
- public SecurityProviderImpl() {
+ protected SecurityProviderImpl() {
this(ConfigurationParameters.EMPTY);
}
@@ -140,8 +138,10 @@ public class SecurityProviderImpl implem
principalConfiguration = new PrincipalConfigurationImpl(this);
privilegeConfiguration = new PrivilegeConfigurationImpl();
tokenConfiguration = new TokenConfigurationImpl(this);
- identityProviderManager = new ExternalIDPManagerImpl();
- syncManager = new SyncManagerImpl();
+
+ // register non-OSGi managers
+ whiteboard.register(SyncManager.class, new SyncManagerImpl(whiteboard), Collections.emptyMap());
+ whiteboard.register(ExternalIdentityProviderManager.class, new ExternalIDPManagerImpl(whiteboard), Collections.emptyMap());
}
@Nonnull
@@ -188,10 +188,8 @@ public class SecurityProviderImpl implem
return (T) privilegeConfiguration;
} else if (TokenConfiguration.class == configClass) {
return (T) tokenConfiguration;
- } else if (ExternalIdentityProviderManager.class == configClass) {
- return (T) identityProviderManager;
- } else if (SyncManager.class == configClass) {
- return (T) syncManager;
+ } else if (Whiteboard.class == configClass) {
+ return (T) whiteboard;
} else {
throw new IllegalArgumentException("Unsupported security configuration class " + configClass);
}
@@ -199,7 +197,7 @@ public class SecurityProviderImpl implem
@Activate
protected void activate(ComponentContext context) throws Exception {
- Whiteboard whiteboard = new OsgiWhiteboard(context.getBundleContext());
+ whiteboard = new OsgiWhiteboard(context.getBundleContext());
authorizableActionProvider.start(whiteboard);
restrictionProvider.start(whiteboard);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentity.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentity.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentity.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentity.java Tue Feb 11 00:18:08 2014
@@ -65,7 +65,7 @@ public interface ExternalIdentity {
* @return the declared groups
*/
@Nonnull
- Iterable<? extends ExternalGroup> getGroups();
+ Iterable<? extends ExternalIdentityRef> getGroups();
/**
* Returns a map of properties of this external identity.
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityRef.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityRef.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityRef.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityRef.java Tue Feb 11 00:18:08 2014
@@ -101,4 +101,21 @@ public class ExternalIdentityRef {
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ExternalIdentityRef that = (ExternalIdentityRef) o;
+
+ if (!string.equals(that.string)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return string.hashCode();
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java Tue Feb 11 00:18:08 2014
@@ -44,7 +44,9 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncContext;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
@@ -151,6 +153,8 @@ public class DefaultSyncHandler implemen
}
} catch (RepositoryException e) {
throw new SyncException(e);
+ } catch (ExternalIdentityException e) {
+ throw new SyncException(e);
}
}
@@ -172,7 +176,8 @@ public class DefaultSyncHandler implemen
}
@CheckForNull
- private User createUser(ExternalUser externalUser) throws RepositoryException, SyncException {
+ private User createUser(ExternalUser externalUser)
+ throws RepositoryException, SyncException, ExternalIdentityException {
String password = externalUser.getPassword(); // todo: make configurable
Principal principal = new PrincipalImpl(externalUser.getPrincipalName());
User user = userManager.createUser(
@@ -186,7 +191,8 @@ public class DefaultSyncHandler implemen
}
@CheckForNull
- private Group createGroup(ExternalGroup externalGroup) throws RepositoryException, SyncException {
+ private Group createGroup(ExternalGroup externalGroup)
+ throws RepositoryException, SyncException, ExternalIdentityException {
Principal principal = new PrincipalImpl(externalGroup.getPrincipalName());
Group group = userManager.createGroup(
externalGroup.getId(),
@@ -196,25 +202,31 @@ public class DefaultSyncHandler implemen
return group;
}
- private void updateUser(ExternalUser externalUser, User user) throws RepositoryException, SyncException {
+ private void updateUser(ExternalUser externalUser, User user)
+ throws RepositoryException, SyncException, ExternalIdentityException {
syncAuthorizable(externalUser, user);
}
- private void syncAuthorizable(ExternalIdentity externalUser, Authorizable authorizable) throws RepositoryException, SyncException {
- for (ExternalGroup externalGroup : externalUser.getGroups()) {
- String groupId = externalGroup.getId();
- Group group;
- Authorizable a = userManager.getAuthorizable(groupId);
- if (a == null) {
- group = createGroup(externalGroup);
- } else {
- group = (a.isGroup()) ? (Group) a : null;
- }
+ private void syncAuthorizable(ExternalIdentity externalUser, Authorizable authorizable)
+ throws RepositoryException, SyncException, ExternalIdentityException {
+ for (ExternalIdentityRef externalGroupRef : externalUser.getGroups()) {
+ ExternalIdentity id = idp.getIdentity(externalGroupRef);
+ if (id instanceof ExternalGroup) {
+ ExternalGroup externalGroup = (ExternalGroup) id;
+ String groupId = externalGroup.getId();
+ Group group;
+ Authorizable a = userManager.getAuthorizable(groupId);
+ if (a == null) {
+ group = createGroup(externalGroup);
+ } else {
+ group = (a.isGroup()) ? (Group) a : null;
+ }
- if (group != null) {
- group.addMember(authorizable);
- } else {
- log.debug("No such group " + groupId + "; Ignoring group membership.");
+ if (group != null) {
+ group.addMember(authorizable);
+ } else {
+ log.debug("No such group " + groupId + "; Ignoring group membership.");
+ }
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalIDPManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalIDPManagerImpl.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalIDPManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalIDPManagerImpl.java Tue Feb 11 00:18:08 2014
@@ -16,48 +16,61 @@
*/
package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
import javax.annotation.Nonnull;
+import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager;
+import org.apache.jackrabbit.oak.spi.whiteboard.AbstractServiceTracker;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.osgi.service.component.ComponentContext;
/**
* {@code ExternalIDPManagerImpl} is used to manage registered external identity provider. This class automatically
* tracks the IDPs that are registered via OSGi but can also be used in non-OSGi environments by manually adding and
* removing the providers.
*/
-@Component
+@Component(immediate = true)
@Service
-public class ExternalIDPManagerImpl implements ExternalIdentityProviderManager {
+public class ExternalIDPManagerImpl extends AbstractServiceTracker<ExternalIdentityProvider> implements ExternalIdentityProviderManager {
+
+ /**
+ * Default constructor used by OSGi
+ */
+ public ExternalIDPManagerImpl() {
+ super(ExternalIdentityProvider.class);
+ }
- @Reference(
- name = "idpProvider",
- bind = "addProvider",
- unbind = "removeProvider",
- referenceInterface = ExternalIdentityProvider.class,
- cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
- policy = ReferencePolicy.DYNAMIC
- )
- final private Map<String, ExternalIdentityProvider> providers = new ConcurrentHashMap<String, ExternalIdentityProvider>();
+ /**
+ * Constructor used by non OSGi
+ * @param whiteboard the whiteboard
+ */
+ public ExternalIDPManagerImpl(Whiteboard whiteboard) {
+ super(ExternalIdentityProvider.class);
+ start(whiteboard);
+ }
- public void addProvider(ExternalIdentityProvider provider, final Map<String, Object> props) {
- providers.put(provider.getName(), provider);
+ @Activate
+ private void activate(ComponentContext ctx) {
+ start(new OsgiWhiteboard(ctx.getBundleContext()));
}
- public void removeProvider(ExternalIdentityProvider provider, final Map<String, Object> props) {
- providers.remove(provider.getName());
+ @Deactivate
+ private void deactivate() {
+ stop();
}
@Override
public ExternalIdentityProvider getProvider(@Nonnull String name) {
- return providers.get(name);
+ for (ExternalIdentityProvider provider: getServices()) {
+ if (name.equals(provider.getName())) {
+ return provider;
+ }
+ }
+ return null;
}
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java Tue Feb 11 00:18:08 2014
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
+import java.security.Principal;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -31,6 +32,7 @@ import org.apache.jackrabbit.oak.api.Com
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.AbstractLoginModule;
+import org.apache.jackrabbit.oak.spi.security.authentication.AuthInfoImpl;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager;
@@ -39,6 +41,8 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncManager;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,6 +84,11 @@ public class ExternalLoginModule extends
private ExternalUser externalUser;
/**
+ * Login credentials
+ */
+ private Credentials credentials;
+
+ /**
* Default constructor for the OSGIi LoginModuleFactory case and the default non-OSGi JAAS case.
*/
public ExternalLoginModule() {
@@ -102,14 +111,20 @@ public class ExternalLoginModule extends
options = ConfigurationParameters.of(osgiConfig, options);
}
+ Whiteboard whiteboard = getSecurityProvider().getConfiguration(Whiteboard.class);
+
String idpName = options.getConfigValue(PARAM_IDP_NAME, "");
if (idpName.length() == 0) {
log.error("External login module needs IPD name. Will not be used for login.");
} else {
- ExternalIdentityProviderManager idpMgr = getSecurityProvider().getConfiguration(ExternalIdentityProviderManager.class);
- idp = idpMgr.getProvider(idpName);
- if (idp == null) {
- log.error("No IDP found with name {}. Will not be used for login.", idpName);
+ ExternalIdentityProviderManager idpMgr = WhiteboardUtils.getService(whiteboard, ExternalIdentityProviderManager.class);
+ if (idpMgr == null) {
+ log.error("External login module needs IDPManager. Will not be used for login.");
+ } else {
+ idp = idpMgr.getProvider(idpName);
+ if (idp == null) {
+ log.error("No IDP found with name {}. Will not be used for login.", idpName);
+ }
}
}
@@ -117,10 +132,14 @@ public class ExternalLoginModule extends
if (syncHandlerName.length() == 0) {
log.error("External login module needs SyncHandler name. Will not be used for login.");
} else {
- SyncManager syncMgr = getSecurityProvider().getConfiguration(SyncManager.class);
- syncHandler = syncMgr.getSyncHandler(syncHandlerName);
- if (syncHandler == null) {
- log.error("No SyncHandler found with name {}. Will not be used for login.", idpName);
+ SyncManager syncMgr = WhiteboardUtils.getService(whiteboard, SyncManager.class);
+ if (syncMgr == null) {
+ log.error("External login module needs SyncManager. Will not be used for login.");
+ } else {
+ syncHandler = syncMgr.getSyncHandler(syncHandlerName);
+ if (syncHandler == null) {
+ log.error("No SyncHandler found with name {}. Will not be used for login.", syncHandlerName);
+ }
}
}
}
@@ -131,7 +150,7 @@ public class ExternalLoginModule extends
return false;
}
- Credentials credentials = getCredentials();
+ credentials = getCredentials();
if (credentials == null) {
log.debug("No credentials found for external login module. ignoring.");
return false;
@@ -201,7 +220,19 @@ public class ExternalLoginModule extends
context = syncHandler.createContext(idp, userManager, root);
context.sync(externalUser);
root.commit();
- return true;
+
+ Set<? extends Principal> principals = getPrincipals(externalUser.getId());
+ if (!principals.isEmpty()) {
+ if (!subject.isReadOnly()) {
+ subject.getPrincipals().addAll(principals);
+ subject.getPublicCredentials().add(credentials);
+ setAuthInfo(new AuthInfoImpl(externalUser.getId(), null, principals), subject);
+ } else {
+ log.debug("Could not add information to read only subject {}", subject);
+ }
+ return true;
+ }
+ return false;
} catch (SyncException e) {
throw new LoginException("User synchronization failed: " + e);
} catch (CommitFailedException e) {
@@ -217,5 +248,6 @@ public class ExternalLoginModule extends
protected void clearState() {
super.clearState();
externalUser = null;
+ credentials = null;
}
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java Tue Feb 11 00:18:08 2014
@@ -22,43 +22,62 @@ import java.util.concurrent.ConcurrentHa
import javax.annotation.Nonnull;
+import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncManager;
+import org.apache.jackrabbit.oak.spi.whiteboard.AbstractServiceTracker;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.osgi.service.component.ComponentContext;
/**
* {@code SyncManagerImpl} is used to manage registered sync handlers. This class automatically
* tracks the SyncHandlers that are registered via OSGi but can also be used in non-OSGi environments by manually
* adding and removing the handlers.
*/
-@Component
+@Component(immediate = true)
@Service
-public class SyncManagerImpl implements SyncManager {
+public class SyncManagerImpl extends AbstractServiceTracker<SyncHandler> implements SyncManager {
- @Reference(
- name = "syncHandler",
- bind = "addHandler",
- unbind = "removeHandler",
- referenceInterface = SyncHandler.class,
- cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
- policy = ReferencePolicy.DYNAMIC
- )
- final private Map<String, SyncHandler> handlers = new ConcurrentHashMap<String, SyncHandler>();
+ /**
+ * Default constructor used by OSGi
+ */
+ public SyncManagerImpl() {
+ super(SyncHandler.class);
+ }
+
+ /**
+ * Constructor used by non OSGi
+ * @param whiteboard the whiteboard
+ */
+ public SyncManagerImpl(Whiteboard whiteboard) {
+ super(SyncHandler.class);
+ start(whiteboard);
+ }
- public void addHandler(SyncHandler handler, final Map<String, Object> props) {
- handlers.put(handler.getName(), handler);
+ @Activate
+ private void activate(ComponentContext ctx) {
+ start(new OsgiWhiteboard(ctx.getBundleContext()));
}
- public void removeHandler(SyncHandler handler, final Map<String, Object> props) {
- handlers.remove(handler.getName());
+ @Deactivate
+ private void deactivate() {
+ stop();
}
@Override
public SyncHandler getSyncHandler(@Nonnull String name) {
- return handlers.get(name);
+ for (SyncHandler handler: getServices()) {
+ if (name.equals(handler.getName())) {
+ return handler;
+ }
+ }
+ return null;
}
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/Tracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/Tracker.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/Tracker.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/Tracker.java Tue Feb 11 00:18:08 2014
@@ -18,6 +18,10 @@ package org.apache.jackrabbit.oak.spi.wh
import java.util.List;
+import javax.annotation.CheckForNull;
+
+import com.google.common.base.Predicate;
+
/**
* Tracker for whiteboard services.
*/
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java Tue Feb 11 00:18:08 2014
@@ -19,14 +19,25 @@ package org.apache.jackrabbit.oak.spi.wh
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Collections.emptyMap;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
import org.apache.jackrabbit.oak.spi.commit.Observer;
public class WhiteboardUtils {
@@ -74,4 +85,83 @@ public class WhiteboardUtils {
.register(Observer.class, checkNotNull(observer), emptyMap());
}
+ /**
+ * Returns the currently available services from the whiteboard of the tracked type.
+ *
+ * Note that the underlying tracker is closed automatically.
+ *
+ * @param wb the whiteboard
+ * @param type the service type
+ * @return a list of services
+ */
+ @Nonnull
+ public static <T> List<T> getServices(@Nonnull Whiteboard wb, @Nonnull Class<T> type) {
+ return getServices(wb, type, null);
+ }
+
+ /**
+ * Returns the one of the currently available services from the whiteboard of the tracked type.
+ *
+ * Note that the underlying tracker is closed automatically.
+ *
+ * @return one service or {@code null}
+ */
+ @CheckForNull
+ public static <T> T getService(@Nonnull Whiteboard wb, @Nonnull Class<T> type) {
+ return getService(wb, type, null);
+ }
+
+ /**
+ * Returns the currently available services from the whiteboard of the tracked type. If {@code predicate} is
+ * not {@code null} the returned list is limited to the ones that match the predicate.
+ *
+ * Note that the underlying tracker is stopped automatically after the services are returned.
+ *
+ * @param wb the whiteboard
+ * @param type the service type
+ * @param predicate filtering predicate or {@code null}
+ * @return a list of services
+ */
+ @Nonnull
+ public static <T> List<T> getServices(@Nonnull Whiteboard wb, @Nonnull Class<T> type, @Nullable Predicate<T> predicate) {
+ Tracker<T> tracker = wb.track(type);
+ try {
+ if (predicate == null) {
+ return tracker.getServices();
+ } else {
+ return ImmutableList.copyOf(Iterables.filter(tracker.getServices(), predicate));
+ }
+ } finally {
+ tracker.stop();
+ }
+ }
+
+ /**
+ * Returns the one of the currently available services from the whiteboard of the tracked type. If {@code predicate} is
+ * not {@code null} only a service that match the predicate is returned.
+ *
+ * Note that the underlying tracker is closed automatically.
+ *
+ * @param wb the whiteboard
+ * @param type the service type
+ * @param predicate filtering predicate or {@code null}
+ * @return one service or {@code null}
+ */
+ @CheckForNull
+ public static <T> T getService(@Nonnull Whiteboard wb, @Nonnull Class<T> type, @Nullable Predicate<T> predicate) {
+ Tracker<T> tracker = wb.track(type);
+ try {
+ for (T service : tracker.getServices()) {
+ if (predicate == null || predicate.apply(service)) {
+ return service;
+ }
+ }
+ return null;
+ } finally {
+ tracker.stop();
+ }
+
+ }
+
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java?rev=1566885&r1=1566884&r2=1566885&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java Tue Feb 11 00:18:08 2014
@@ -17,20 +17,16 @@
package org.apache.jackrabbit.oak.spi.security.authentication.external;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
+
import javax.jcr.SimpleCredentials;
-import javax.security.auth.login.AppConfigurationEntry;
-import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginException;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.oak.AbstractSecurityTest;
import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
@@ -41,45 +37,29 @@ import static org.junit.Assert.fail;
/**
* ExternalLoginModuleTest...
*/
-public class ExternalLoginModuleTest extends AbstractSecurityTest {
+public class ExternalLoginModuleTest extends ExternalLoginModuleTestBase {
protected final HashMap<String, Object> options = new HashMap<String, Object>();
- private String userId;
- private Set<String> ids = new HashSet<String>();
-
- private UserManager userManager;
+ private String userId = "testUser";
@Before
public void before() throws Exception {
super.before();
-
- userId = TestLoginModule.externalUser.getId();
- ids.add(userId);
- for (ExternalGroup group : TestLoginModule.externalGroups) {
- ids.add(group.getId());
- }
- userManager = getUserManager(root);
}
@After
public void after() throws Exception {
- try {
- for (String id : ids) {
- Authorizable a = userManager.getAuthorizable(id);
- if (a != null) {
- a.remove();
- }
- }
- root.commit();
- } finally {
- root.refresh();
- super.after();
- }
+ super.after();
+ }
+
+ protected ExternalIdentityProvider createIDP() {
+ return new TestIdentityProvider();
}
@Test
public void testLoginFailed() throws Exception {
+ UserManager userManager = getUserManager(root);
try {
ContentSession cs = login(new SimpleCredentials("unknown", new char[0]));
cs.close();
@@ -93,71 +73,20 @@ public class ExternalLoginModuleTest ext
@Test
public void testSyncCreateUser() throws Exception {
- options.put(ExternalLoginModule.PARAM_SYNC_MODE, SyncMode.CREATE_USER);
-
+ UserManager userManager = getUserManager(root);
ContentSession cs = null;
try {
- cs = login(new SimpleCredentials(userId, new char[0]));
-
- root.refresh();
- for (String id : ids) {
- if (id.equals(userId)) {
- Authorizable a = userManager.getAuthorizable(id);
- assertNotNull(a);
- for (String prop : TestLoginModule.externalUser.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
- } else {
- assertNull(userManager.getAuthorizable(id));
- }
- }
- } finally {
- if (cs != null) {
- cs.close();
- }
- options.clear();
- }
- }
-
- @Test
- public void testSyncCreateGroup() throws Exception {
- options.put(ExternalLoginModule.PARAM_SYNC_MODE, SyncMode.CREATE_GROUP);
+ assertNull(userManager.getAuthorizable(userId));
- ContentSession cs = null;
- try {
cs = login(new SimpleCredentials(userId, new char[0]));
root.refresh();
- for (String id : ids) {
- assertNull(userManager.getAuthorizable(id));
- }
- } finally {
- if (cs != null) {
- cs.close();
- }
- options.clear();
- }
- }
- @Test
- public void testSyncCreateUserAndGroups() throws Exception {
- options.put(ExternalLoginModule.PARAM_SYNC_MODE, new String[]{SyncMode.CREATE_USER, SyncMode.CREATE_GROUP});
-
- ContentSession cs = null;
- try {
- cs = login(new SimpleCredentials(userId, new char[0]));
-
- root.refresh();
- for (String id : ids) {
- if (id.equals(userId)) {
- Authorizable a = userManager.getAuthorizable(id);
- assertNotNull(a);
- for (String prop : TestLoginModule.externalUser.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
- } else {
- assertNotNull(userManager.getAuthorizable(id));
- }
+ Authorizable a = userManager.getAuthorizable(userId);
+ assertNotNull(a);
+ ExternalUser user = idp.getUser(userId);
+ for (String prop : user.getProperties().keySet()) {
+ assertTrue(a.hasProperty(prop));
}
} finally {
if (cs != null) {
@@ -168,44 +97,30 @@ public class ExternalLoginModuleTest ext
}
@Test
- public void testSyncUpdate() throws Exception {
- options.put(ExternalLoginModule.PARAM_SYNC_MODE, SyncMode.UPDATE);
-
- // create user upfront in order to test update mode
- ExternalUser externalUser = TestLoginModule.externalUser;
- Authorizable user = userManager.createUser(externalUser.getId(), externalUser.getPassword());
- root.commit();
-
- ContentSession cs = null;
- try {
- cs = login(new SimpleCredentials(userId, new char[0]));
-
- root.refresh();
- for (String id : ids) {
- if (id.equals(userId)) {
- Authorizable a = userManager.getAuthorizable(id);
- assertNotNull(a);
- for (String prop : TestLoginModule.externalUser.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
- } else {
- assertNull(userManager.getAuthorizable(id));
- }
- }
- } finally {
- if (cs != null) {
- cs.close();
- }
- options.clear();
- }
+ @Ignore("group sync not implemented yet")
+ public void testSyncCreateGroup() throws Exception {
+// UserManager userManager = getUserManager(root);
+// ContentSession cs = null;
+// try {
+// cs = login(new SimpleCredentials(userId, new char[0]));
+//
+// root.refresh();
+// for (String id : ids) {
+// assertNull(userManager.getAuthorizable(id));
+// }
+// } finally {
+// if (cs != null) {
+// cs.close();
+// }
+// options.clear();
+// }
}
@Test
- public void testSyncUpdateAndGroups() throws Exception {
- options.put(ExternalLoginModule.PARAM_SYNC_MODE, new String[]{SyncMode.UPDATE, SyncMode.CREATE_GROUP});
-
+ public void testSyncUpdate() throws Exception {
// create user upfront in order to test update mode
- ExternalUser externalUser = TestLoginModule.externalUser;
+ UserManager userManager = getUserManager(root);
+ ExternalUser externalUser = idp.getUser(userId);
Authorizable user = userManager.createUser(externalUser.getId(), externalUser.getPassword());
root.commit();
@@ -214,64 +129,11 @@ public class ExternalLoginModuleTest ext
cs = login(new SimpleCredentials(userId, new char[0]));
root.refresh();
- for (String id : ids) {
- if (id.equals(userId)) {
- Authorizable a = userManager.getAuthorizable(id);
- assertNotNull(a);
- for (String prop : TestLoginModule.externalUser.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
- } else {
- assertNotNull(userManager.getAuthorizable(id));
- }
- }
- } finally {
- if (cs != null) {
- cs.close();
- }
- options.clear();
- }
- }
- @Test
- public void testDefaultSync() throws Exception {
- options.put(ExternalLoginModule.PARAM_SYNC_MODE, null);
-
- ContentSession cs = null;
- try {
- cs = login(new SimpleCredentials(userId, new char[0]));
-
- root.refresh();
- for (String id : ids) {
- if (id.equals(userId)) {
- Authorizable a = userManager.getAuthorizable(id);
- assertNotNull(a);
- for (String prop : TestLoginModule.externalUser.getProperties().keySet()) {
- assertTrue(a.hasProperty(prop));
- }
- } else {
- assertNotNull(userManager.getAuthorizable(id));
- }
- }
- } finally {
- if (cs != null) {
- cs.close();
- }
- options.clear();
- }
- }
-
- @Test
- public void testNoSync() throws Exception {
- options.put(ExternalLoginModule.PARAM_SYNC_MODE, "");
-
- ContentSession cs = null;
- try {
- cs = login(new SimpleCredentials(userId, new char[0]));
-
- root.refresh();
- for (String id : ids) {
- assertNull(userManager.getAuthorizable(id));
+ Authorizable a = userManager.getAuthorizable(userId);
+ assertNotNull(a);
+ for (String prop : externalUser.getProperties().keySet()) {
+ assertTrue(a.hasProperty(prop));
}
} finally {
if (cs != null) {
@@ -281,16 +143,4 @@ public class ExternalLoginModuleTest ext
}
}
- protected Configuration getConfiguration() {
- return new Configuration() {
- @Override
- public AppConfigurationEntry[] getAppConfigurationEntry(String s) {
- AppConfigurationEntry entry = new AppConfigurationEntry(
- TestLoginModule.class.getName(),
- AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
- options);
- return new AppConfigurationEntry[]{entry};
- }
- };
- }
}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java?rev=1566885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java Tue Feb 11 00:18:08 2014
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jackrabbit.oak.spi.security.authentication.external;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfig;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.junit.After;
+import org.junit.Before;
+
+/**
+ * ExternalLoginModuleTest...
+ */
+public abstract class ExternalLoginModuleTestBase extends AbstractSecurityTest {
+
+ protected final HashMap<String, Object> options = new HashMap<String, Object>();
+
+ private Set<String> ids = new HashSet<String>();
+
+ private Registration testIdpReg;
+
+ private Registration syncHandlerReg;
+
+ protected Whiteboard whiteboard;
+
+ protected ExternalIdentityProvider idp;
+
+ @Before
+ public void before() throws Exception {
+ super.before();
+ UserManager userManager = getUserManager(root);
+ Iterator<Authorizable> iter = userManager.findAuthorizables("jcr:primaryType", null);
+ while (iter.hasNext()) {
+ ids.add(iter.next().getID());
+ }
+ idp = createIDP();
+
+ whiteboard = getSecurityProvider().getConfiguration(Whiteboard.class);
+ testIdpReg = whiteboard.register(ExternalIdentityProvider.class, idp, Collections.<String, Object>emptyMap());
+
+ options.put(ExternalLoginModule.PARAM_SYNC_HANDLER_NAME, "default");
+ options.put(ExternalLoginModule.PARAM_IDP_NAME, idp.getName());
+
+ // set default sync config
+ setSyncConfig(new DefaultSyncConfig());
+ }
+
+ @After
+ public void after() throws Exception {
+ if (testIdpReg != null) {
+ testIdpReg.unregister();
+ testIdpReg = null;
+ }
+ idp = null;
+ setSyncConfig(null);
+
+ try {
+ UserManager userManager = getUserManager(root);
+ Iterator<Authorizable> iter = userManager.findAuthorizables("jcr:primaryType", null);
+ while (iter.hasNext()) {
+ ids.remove(iter.next().getID());
+ }
+ for (String id : ids) {
+ Authorizable a = userManager.getAuthorizable(id);
+ if (a != null) {
+ a.remove();
+ }
+ }
+ root.commit();
+ } finally {
+ root.refresh();
+ super.after();
+ }
+ }
+
+ protected abstract ExternalIdentityProvider createIDP();
+
+ protected void setSyncConfig(DefaultSyncConfig cfg) {
+ if (syncHandlerReg != null) {
+ syncHandlerReg.unregister();
+ syncHandlerReg = null;
+ }
+ if (cfg != null) {
+ syncHandlerReg = whiteboard.register(SyncHandler.class, new DefaultSyncHandler(cfg), Collections.<String, Object>emptyMap());
+ }
+ }
+
+ protected Configuration getConfiguration() {
+ return new Configuration() {
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(String s) {
+ AppConfigurationEntry entry = new AppConfigurationEntry(
+ ExternalLoginModule.class.getName(),
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+ options);
+ return new AppConfigurationEntry[]{entry};
+ }
+ };
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java?rev=1566885&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java Tue Feb 11 00:18:08 2014
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.spi.security.authentication.external;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Credentials;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.login.LoginException;
+
+/**
+ * ExternalLoginModuleImpl... TODO
+ */
+public class TestIdentityProvider implements ExternalIdentityProvider {
+
+ private final Map<String, TestGroup> externalGroups = new HashMap<String, TestGroup>();
+ private final Map<String, TestUser> externalUsers = new HashMap<String, TestUser>();
+
+
+ public TestIdentityProvider() {
+ addGroup(new TestGroup("a").withGroups("aa", "aaa"));
+ addGroup(new TestGroup("b").withGroups("a"));
+ addGroup(new TestGroup("c"));
+
+ addUser(new TestUser("testUser")
+ .withProperty("name", "Test User")
+ .withProperty("profile/name", "Public Name")
+ .withProperty("profile/age", 72)
+ .withProperty("./email", "test@testuser.com")
+ .withGroups("a", "b", "c")
+ );
+ }
+
+ private void addUser(TestIdentity user) {
+ externalUsers.put(user.getId(), (TestUser) user);
+ }
+
+ private void addGroup(TestIdentity group) {
+ externalGroups.put(group.getId(), (TestGroup) group);
+ }
+
+ @Nonnull
+ @Override
+ public String getName() {
+ return "test";
+ }
+
+ @Override
+ public ExternalIdentity getIdentity(@Nonnull ExternalIdentityRef ref) throws ExternalIdentityException {
+ return null;
+ }
+
+ @Override
+ public ExternalUser getUser(@Nonnull String userId) throws ExternalIdentityException {
+ return externalUsers.get(userId);
+ }
+
+ @Override
+ public ExternalUser authenticate(@Nonnull Credentials credentials) throws ExternalIdentityException, LoginException {
+ if (!(credentials instanceof SimpleCredentials)) {
+ return null;
+ }
+ SimpleCredentials creds = (SimpleCredentials) credentials;
+ ExternalUser user = getUser(creds.getUserID());
+ if (user != null) {
+ if (!new String(creds.getPassword()).equals(user.getPassword())) {
+ throw new LoginException("Invalid User/Password");
+ }
+ }
+ return user;
+ }
+
+ @Override
+ public ExternalGroup getGroup(@Nonnull String name) throws ExternalIdentityException {
+ return externalGroups.get(name);
+ }
+
+ private static class TestIdentity implements ExternalIdentity {
+
+ private final String userId;
+ private final ExternalIdentityRef id;
+
+ private final Set<ExternalIdentityRef> groups = new HashSet<ExternalIdentityRef>();
+ private final Map<String, Object> props = new HashMap<String, Object>();
+
+ private TestIdentity(String userId) {
+ this.userId = userId;
+ id = new ExternalIdentityRef(userId, "test");
+ }
+
+ @Override
+ public String getId() {
+ return userId;
+ }
+
+ @Override
+ public String getPrincipalName() {
+ return userId;
+ }
+
+ @Nonnull
+ @Override
+ public ExternalIdentityRef getExternalId() {
+ return id;
+ }
+
+ @Override
+ public String getIntermediatePath() {
+ return null;
+ }
+
+ @Override
+ public Iterable<ExternalIdentityRef> getGroups() {
+ return groups;
+ }
+
+ @Override
+ public Map<String, ?> getProperties() {
+ return props;
+ }
+
+ protected TestIdentity withProperty(String name, Object value) {
+ props.put(name, value);
+ return this;
+ }
+
+ protected TestIdentity withGroups(String ... grps) {
+ for (String grp: grps) {
+ groups.add(new ExternalIdentityRef(grp, "test"));
+ }
+ return this;
+ }
+ }
+
+ private static class TestUser extends TestIdentity implements ExternalUser {
+
+ private TestUser(String userId) {
+ super(userId);
+ }
+
+ @Override
+ public String getPassword() {
+ return "";
+ }
+
+ }
+
+ private static class TestGroup extends TestIdentity implements ExternalGroup {
+
+ private TestGroup(String userId) {
+ super(userId);
+ }
+
+ }
+}
\ No newline at end of file