Author: tripod
Date: Wed Mar 12 01:15:05 2014
New Revision: 1576555
URL: http://svn.apache.org/r1576555
Log:
OAK-516 Create LdapLoginModule based on ExternalLoginModule (wip)
Added:
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncedIdentity.java
jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/
jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/generate_ldif.pl
(with props)
jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/users.csv
Modified:
jackrabbit/oak/trunk/oak-auth-external/pom.xml
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
Modified: jackrabbit/oak/trunk/oak-auth-external/pom.xml
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/pom.xml?rev=1576555&r1=1576554&r2=1576555&view=diff
==============================================================================
Binary files - no diff available.
Modified:
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java?rev=1576555&r1=1576554&r2=1576555&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java
(original)
+++
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java
Wed Mar 12 01:15:05 2014
@@ -34,6 +34,16 @@ public interface SyncContext {
boolean sync(@Nonnull ExternalIdentity identity) throws SyncException;
/**
+ * Synchronizes an authorizable with the corresponding external identity
with the repository based on the respective
+ * configuration.
+ *
+ * @param id the id of the authorizable
+ * @return {@code true} if the given identity was synced; {@code false}
for no change.
+ * @throws SyncException if an error occurrs
+ */
+ boolean sync(@Nonnull String id) throws SyncException;
+
+ /**
* Closes this context and releases any resources bound to it. Note that
an implementation must not commit the
* {@link org.apache.jackrabbit.oak.api.Root} passed during the creation
call. This is the responsibility of the
* application.
Modified:
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java?rev=1576555&r1=1576554&r2=1576555&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
(original)
+++
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
Wed Mar 12 01:15:05 2014
@@ -16,7 +16,9 @@
*/
package org.apache.jackrabbit.oak.spi.security.authentication.external;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.oak.api.Root;
@@ -55,4 +57,12 @@ public interface SyncHandler {
@Nonnull UserManager userManager,
@Nonnull Root root) throws SyncException;
+ /**
+ * Tries to find the identity with the given authorizable id or name.
+ * @param userManager the user manager
+ * @param id the id or name of the authorizable
+ * @return a synced identity object or {@code null}
+ */
+ @CheckForNull
+ SyncedIdentity findIdentity(@Nonnull UserManager userManager, @Nonnull
String id) throws RepositoryException;
}
\ No newline at end of file
Added:
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncedIdentity.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncedIdentity.java?rev=1576555&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncedIdentity.java
(added)
+++
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncedIdentity.java
Wed Mar 12 01:15:05 2014
@@ -0,0 +1,53 @@
+/*
+ * 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 javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+/**
+ * Represents a synchronized identity managed by a {@link SyncHandler}.
+ */
+public interface SyncedIdentity {
+
+ /**
+ * Returns the internal id or name of the corresponding authorizable.
+ * @return the id.
+ */
+ @Nonnull
+ String getId();
+
+ /**
+ * Returns the external reference of this identity.
+ * @return the reference or {@code null}
+ */
+ @CheckForNull
+ ExternalIdentityRef getExternalIdRef();
+
+ /**
+ * Checks if this identity represents a group.
+ * @return {@code true} if group.
+ */
+ boolean isGroup();
+
+ /**
+ * Returns the time when this identity was last synced or a value less or
equal to 0 if it was never synced.
+ * @return the time when this identity was last synced.
+ */
+ long lastSynced();
+}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java?rev=1576555&r1=1576554&r2=1576555&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
(original)
+++
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
Wed Mar 12 01:15:05 2014
@@ -59,6 +59,7 @@ import org.apache.jackrabbit.oak.spi.sec
import
org.apache.jackrabbit.oak.spi.security.authentication.external.SyncContext;
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.SyncedIdentity;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -118,12 +119,18 @@ public class DefaultSyncHandler implemen
config = DefaultSyncConfig.of(cfg);
}
+ /**
+ * {@inheritDoc}
+ */
@Nonnull
@Override
public String getName() {
return config.getName();
}
+ /**
+ * {@inheritDoc}
+ */
@Nonnull
@Override
public SyncContext createContext(@Nonnull ExternalIdentityProvider idp,
@Nonnull UserManager userManager, @Nonnull Root root)
@@ -131,6 +138,28 @@ public class DefaultSyncHandler implemen
return new ContextImpl(idp, userManager, root);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SyncedIdentity findIdentity(@Nonnull UserManager userManager,
@Nonnull String id)
+ throws RepositoryException {
+ Authorizable auth = userManager.getAuthorizable(id);
+ if (auth == null) {
+ return null;
+ }
+ ExternalIdentityRef ref = getIdentityRef(auth);
+ Value[] lmValues = auth.getProperty(REP_LAST_SYNCED);
+ long lastModified = -1;
+ if (lmValues != null && lmValues.length > 0) {
+ lastModified = lmValues[0].getLong();
+ }
+ return new SyncedIdentityImpl(id, ref, auth.isGroup(), lastModified);
+ }
+
+ /**
+ * Internal implementation of the sync context
+ */
private class ContextImpl implements SyncContext {
private final ExternalIdentityProvider idp;
@@ -192,11 +221,73 @@ public class DefaultSyncHandler implemen
throw new IllegalArgumentException("identity must be user
or group but was: " + identity);
}
if (log.isDebugEnabled()) {
- log.debug("sync({}) {}", identity.getId(),
timer.getString());
+ log.debug("sync({}) -> {} {}", new Object[]{
+ identity.getExternalId().getString(),
identity.getId(), timer.getString()
+ });
+ }
+ return ret;
+ } catch (RepositoryException e) {
+ throw new SyncException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean sync(@Nonnull String id) throws SyncException {
+ try {
+ DebugTimer timer = new DebugTimer();
+ boolean ret = false;
+ // find authorizable
+ Authorizable auth = userManager.getAuthorizable(id);
+ if (auth == null) {
+ return false;
+ }
+ // check if we need to deal with this authorizable
+ ExternalIdentityRef ref = getIdentityRef(auth);
+ if (ref == null ||
!idp.getName().equals(ref.getProviderName())) {
+ return false;
+ }
+
+ if (auth instanceof Group) {
+ Group group = (Group) auth;
+ ExternalGroup external = idp.getGroup(id);
+ timer.mark("retrieve");
+ if (external == null) {
+ if (group.getDeclaredMembers().hasNext()) {
+ log.info("won't remove local group with members:
{}", id);
+ } else {
+ auth.remove();
+ log.debug("removing authorizable '{}' that no
longer exists on IDP {}", id, idp.getName());
+ timer.mark("remove");
+ ret = true;
+ }
+ } else {
+ ret = syncGroup(external, group);
+ timer.mark("sync");
+ }
+ } else {
+ ExternalUser external = idp.getUser(id);
+ timer.mark("retrieve");
+ if (external == null) {
+ auth.remove();
+ log.debug("removing authorizable '{}' that no longer
exists on IDP {}", id, idp.getName());
+ timer.mark("remove");
+ ret = true;
+ } else {
+ ret = syncUser(external, (User) auth);
+ timer.mark("sync");
+ }
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("sync({}) -> {} {}", new Object[]{id,
ref.getString(), timer.getString()});
}
return ret;
} catch (RepositoryException e) {
throw new SyncException(e);
+ } catch (ExternalIdentityException e) {
+ throw new SyncException(e);
}
}
@@ -346,7 +437,7 @@ public class DefaultSyncHandler implemen
declaredExternalGroups.put(grp.getID(), grp);
}
}
- timer.mark("existing");
+ timer.mark("reading");
for (ExternalIdentityRef ref: externalGroups) {
log.debug("- processing membership {}", ref.getId());
@@ -564,20 +655,31 @@ public class DefaultSyncHandler implemen
* @return {@code true} if same IDP.
*/
private boolean isSameIDP(@Nullable Authorizable auth) throws
RepositoryException {
- if (auth == null) {
- return false;
- }
- Value[] v = auth.getProperty(REP_EXTERNAL_ID);
- if (v == null || v.length == 0) {
- return false;
- }
- ExternalIdentityRef ref =
ExternalIdentityRef.fromString(v[0].getString());
- return idp.getName().equals(ref.getProviderName());
+ ExternalIdentityRef ref = getIdentityRef(auth);
+ return ref != null && idp.getName().equals(ref.getProviderName());
}
}
/**
+ * Retrieves the external identity ref from the authorizable
+ * @param auth the authorizable
+ * @return the ref
+ * @throws RepositoryException if an error occurs
+ */
+ @CheckForNull
+ private static ExternalIdentityRef getIdentityRef(@Nullable Authorizable
auth) throws RepositoryException {
+ if (auth == null) {
+ return null;
+ }
+ Value[] v = auth.getProperty(REP_EXTERNAL_ID);
+ if (v == null || v.length == 0) {
+ return null;
+ }
+ return ExternalIdentityRef.fromString(v[0].getString());
+ }
+
+ /**
* Robust relative path concatenation.
* @param paths relative paths
* @return the concatenated path
@@ -604,4 +706,43 @@ public class DefaultSyncHandler implemen
}
return result.length() == 0 ? null : result.toString();
}
+
+ private static class SyncedIdentityImpl implements SyncedIdentity {
+
+ private final String id;
+
+ private final ExternalIdentityRef ref;
+
+ private final boolean isGroup;
+
+ private final long lastSynced;
+
+ private SyncedIdentityImpl(String id, ExternalIdentityRef ref, boolean
isGroup, long lastSynced) {
+ this.id = id;
+ this.ref = ref;
+ this.isGroup = isGroup;
+ this.lastSynced = lastSynced;
+ }
+
+ @Nonnull
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public ExternalIdentityRef getExternalIdRef() {
+ return ref;
+ }
+
+ @Override
+ public boolean isGroup() {
+ return false;
+ }
+
+ @Override
+ public long lastSynced() {
+ return lastSynced;
+ }
+ }
}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1576555&r1=1576554&r2=1576555&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
(original)
+++
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
Wed Mar 12 01:15:05 2014
@@ -21,7 +21,9 @@ import java.util.Collections;
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nonnull;
import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
@@ -41,6 +43,7 @@ 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.security.authentication.external.SyncedIdentity;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
import org.slf4j.Logger;
@@ -162,7 +165,28 @@ public class ExternalLoginModule extends
return false;
}
+ // remember userID as we need this so often
+ final String userId = credentials instanceof SimpleCredentials ?
((SimpleCredentials) credentials).getUserID() : null;
try {
+ SyncedIdentity sId = null;
+ if (userId != null) {
+ sId = syncHandler.findIdentity(getUserManager(), userId);
+ // if there exists an authorizable with the given userid but
is not an external one or if it belongs to
+ // another IDP, we just ignore it.
+ if (sId != null) {
+ if (sId.getExternalIdRef() == null) {
+ log.debug("ignoring local user: {}", sId.getId());
+ return false;
+ }
+ if
(!sId.getExternalIdRef().getProviderName().equals(idp.getName())) {
+ if (log.isDebugEnabled()) {
+ log.debug("ignoring foreign identity: {}
(idp={})", sId.getExternalIdRef().getString(), idp.getName());
+ }
+ return false;
+ }
+ }
+ }
+
externalUser = idp.authenticate(credentials);
if (externalUser != null) {
log.debug("IDP {} returned valid user {}", idp.getName(),
externalUser);
@@ -178,26 +202,38 @@ public class ExternalLoginModule extends
return true;
} else {
if (log.isDebugEnabled()) {
- if (credentials instanceof SimpleCredentials) {
- log.debug("IDP {} returned null for simple creds of
{}", idp.getName(), ((SimpleCredentials) credentials).getUserID());
+ if (userId != null) {
+ log.debug("IDP {} returned null for simple creds of
{}", idp.getName(), userId);
} else {
log.debug("IDP {} returned null for {}",
idp.getName(), credentials);
}
}
+
+ if (sId != null) {
+ // invalidate the user if it exists as synced variant
+ log.debug("local user exists for '{}'. re-validating.",
sId.getId());
+ validateUser(sId.getId());
+ }
+ return false;
}
} catch (ExternalIdentityException e) {
- log.error("Error while authenticating credentials {} with {}", new
Object[]{credentials, idp.getName(), e});
+ log.error("Error while authenticating '{}' with {}", new Object[]{
+ userId == null ? credentials : userId, idp.getName(), e
+ });
return false;
} catch (LoginException e) {
- log.debug("IDP {} throws login exception for {}", new Object[]
{idp.getName(), credentials, e});
+ log.debug("IDP {} throws login exception for '{}': {}", new
Object[] {
+ idp.getName(), userId == null ? credentials : userId,
e.getMessage()
+ });
throw e;
- } catch (SyncException e) {
- log.debug("SyncHandler {} throws sync exception for {}", new
Object[] {idp.getName(), credentials, e});
+ } catch (Exception e) {
+ log.debug("SyncHandler {} throws sync exception for '{}'", new
Object[] {
+ syncHandler.getName(), userId == null ? credentials :
userId, e
+ });
LoginException le = new LoginException("Error while syncing
user.");
le.initCause(e);
throw le;
}
- return false;
}
@Override
@@ -231,7 +267,7 @@ public class ExternalLoginModule extends
* @param user the external user
* @throws SyncException if an error occurs
*/
- private void syncUser(ExternalUser user) throws SyncException {
+ private void syncUser(@Nonnull ExternalUser user) throws SyncException {
SyncContext context = null;
try {
Root root = getRoot();
@@ -242,9 +278,15 @@ public class ExternalLoginModule extends
if (userManager == null) {
throw new SyncException("Cannot synchronize user. userManager
== null");
}
+ DebugTimer timer = new DebugTimer();
context = syncHandler.createContext(idp, userManager, root);
context.sync(user);
+ timer.mark("sync");
root.commit();
+ timer.mark("commit");
+ if (log.isDebugEnabled()) {
+ log.debug("syncUser({}) {}", user.getId(), timer.getString());
+ }
} catch (CommitFailedException e) {
throw new SyncException("User synchronization failed during
commit.", e);
} finally {
@@ -254,6 +296,39 @@ public class ExternalLoginModule extends
}
}
+ /**
+ * Initiates synchronization of a possible remove user
+ * @param id the user id
+ */
+ private void validateUser(@Nonnull String id) throws SyncException {
+ SyncContext context = null;
+ try {
+ Root root = getRoot();
+ if (root == null) {
+ throw new SyncException("Cannot synchronize user. root ==
null");
+ }
+ UserManager userManager = getUserManager();
+ if (userManager == null) {
+ throw new SyncException("Cannot synchronize user. userManager
== null");
+ }
+ DebugTimer timer = new DebugTimer();
+ context = syncHandler.createContext(idp, userManager, root);
+ context.sync(id);
+ timer.mark("sync");
+ root.commit();
+ timer.mark("commit");
+ if (log.isDebugEnabled()) {
+ log.debug("validateUser({}) {}", id, timer.getString());
+ }
+ } catch (CommitFailedException e) {
+ throw new SyncException("User synchronization failed during
commit.", e);
+ } finally {
+ if (context != null) {
+ context.close();
+ }
+ }
+
+ }
//------------------------------------------------< AbstractLoginModule
>---
@Override
Modified:
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java?rev=1576555&r1=1576554&r2=1576555&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
(original)
+++
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
Wed Mar 12 01:15:05 2014
@@ -42,7 +42,7 @@ import org.apache.jackrabbit.oak.spi.sec
public class ExternalLoginModuleFactory implements LoginModuleFactory {
@Property(
- intValue = 150,
+ intValue = 50,
label = "JAAS Ranking",
description = "Specifying the ranking (i.e. sort order) of this
login module entry. The entries are sorted " +
"in a descending order (i.e. higher value ranked
configurations come first)."
Modified:
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java?rev=1576555&r1=1576554&r2=1576555&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
(original)
+++
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTest.java
Wed Mar 12 01:15:05 2014
@@ -19,11 +19,14 @@ package org.apache.jackrabbit.oak.spi.se
import java.util.HashMap;
import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
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.api.ContentSession;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@@ -144,6 +147,7 @@ public class ExternalLoginModuleTest ext
UserManager userManager = getUserManager(root);
ExternalUser externalUser = idp.getUser(userId);
Authorizable user = userManager.createUser(externalUser.getId(), null);
+ user.setProperty("rep:externalId", new ValueFactoryImpl(root,
NamePathMapper.DEFAULT).createValue(externalUser.getExternalId().getString()));
root.commit();
ContentSession cs = null;
Added: jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/generate_ldif.pl
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/generate_ldif.pl?rev=1576555&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/generate_ldif.pl
(added)
+++ jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/generate_ldif.pl
Wed Mar 12 01:15:05 2014
@@ -0,0 +1,199 @@
+#!/usr/bin/perl
+#
+# 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.
+#
+
+#
+# script to generate a LDIF with 66 primary groups and 17,576 unique users.
+# There are additional 100 secondary groups, where indirectly all users are
member of.
+# Each user is a member of about 6 or 7 groups.
+# The largest groups contain about 20% of the users (~3,500 users)
+# The users all have the same password "password"
+#
+# The oak-users.csv file contains all of the users. Here is an example of the
data from this CSV:
+#
+# 3997,T0F9D,Told Xyla
+# 3998,U0F9E,Upshove Xerasia
+# 3999,V0F9F,Verve Xenicus
+# 4000,W0FA0,Wharf Xiphiid
+# 4001,X0FA1,Xyletic Xenial
+# 4002,Y0FA2,Yean Xylonic
+# 4003,Z0FA3,Zimocca Xylenol
+# 4004,A0FA4,Agnail Yukian
+# 4005,B0FA5,Boolian Yapman
+#
+# The columns are:
+# <sequential-number>,<user-id>,<users-full-name>
+#
+# Group membership for each user is based on the sequential number and the
first letters of the first and last full-name.
+# The first letter of the names defined the user as being in groups
"has_<letter>" for each part of the full name
+# Each user is part of groups:
+# <modulus>_of_five
+# <modulus>_of_seven
+# <modulus>_of_eleven
+# <modulus>_of_seventeen
+#
+# According to the user's <sequential-number> so that <modulus> =
<sequential-number> % 5, 7, 11 and 17.
+# For example, uid=T0F9D (sequential-number=3997) is a member of groups
two_of_five, zero_of_seven,
+# four_of_eleven and two_of_seventeen
+#
+# Alas, there is no seven_of_nine.
+#
+
+%allgroups = ();
+
+$base = "o=oak,dc=apache,dc=org";
+
+# 0,A0000,Adeem Anend
+# 1,B0001,Brenda Abashed
+
+@digits = ( "zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine",
+ "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
"sixteen",
+ "seventeen", "eighteen", "nineteen" );
+
+sub n_of_m {
+ local ( $num, $mod ) = @_;
+ local $n, $g;
+ $n = $num % $mod;
+ $g = @digits[$n] . "_of_" . @digits[$mod];
+ return $g;
+}
+
+sub do_group {
+ local ( $group ) = @_;
+
+ unless (defined($allgroups{$group})) {
+ $mod = <<"DONE";
+# define group $group
+dn: cn=$group,ou=Groups,$base
+changetype: add
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: $group
+uniquemember: cn=$name,ou=Users,$base
+
+DONE
+ print $mod;
+ } else {
+
+ $mod = <<"DONE";
+# modify group $group
+dn: cn=$group,ou=Groups,$base
+changetype: modify
+add: uniquemember
+uniquemember: cn=$name,ou=Users,$base
+
+DONE
+
+ print $mod;
+}
+ $allgroups{$group} .= $uid;
+}
+
+print <<"DONE";
+dn: ou=Groups,$base
+objectclass: top
+objectclass: organizationalUnit
+ou: groups
+
+dn: ou=Users,$base
+objectclass: top
+objectclass: organizationalUnit
+ou: Users
+
+dn: cn=admin,$base
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+objectclass: top
+uid: admin
+cn: Administrator
+displayName: Administrator
+givenName: Administrator
+sn: Administrator
+description: Administrator of test company
+mail: admin\@oak.example.org
+userPassword: password
+
+DONE
+
+while (<>) {
+ chomp;
+ $_ =~ s/\s+$//;
+
+ @fields = split /,/;
+
+ $num = @fields[0];
+ $id = lc @fields[1];
+ $name = @fields[2];
+ $name =~ /^([^ ]+)\s+([^ ]+)$/;
+ $fname = $1;
+ $lname = $2;
+
+
+$g = &n_of_m($num, 5);
+$g = $g.",".&n_of_m($num, 7);
+$g = $g.",".&n_of_m($num, 11);
+$g = $g.",".&n_of_m($num, 17);
+
+$fname =~/^(\w)/; $l1 = $1; $l1 =~ y/A-Z/a-z/;
+$lname =~/^(\w)/; $l2 = $1; $l2 =~ y/A-Z/a-z/;
+$g = $g.",has_$l1";
+$g = $g.",has_$l2" unless ($l1 eq $l2);
+
+# print "num=$num id=$id name=$name fname=$fname lname=$lname groups=$g\n";
+
+ $ldif = <<"DONE";
+# $num,$id,$name
+# groups: $g
+#
+dn: cn=$name,ou=Users, $base
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+objectclass: top
+uid: $id
+cn: $name
+displayName: $name
+givenName: $fname
+sn: $lname
+description: $name is a test user with groups $g
+mail: $id\@oak.example.org
+userPassword: password
+
+DONE
+
+ print $ldif;
+
+ foreach $i (split /,/, $g) {
+ do_group($i);
+ }
+}
+
+foreach my $i (1..100) {
+print <<"DONE";
+
+dn: cn=dummy_$i,ou=Groups,$base
+changetype: add
+objectclass: top
+objectclass: groupOfUniqueNames
+cn: dummy_$i
+DONE
+
+ foreach my $i ('a'..'z') {
+ print "uniquemember: cn=has_$i,ou=Groups,$base\n"
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-auth-external/src/test/scripts/generate_ldif.pl
------------------------------------------------------------------------------
svn:executable = *