Author: dj
Date: Thu Aug 18 14:22:59 2016
New Revision: 1756792

URL: http://svn.apache.org/viewvc?rev=1756792&view=rev
Log:
OAK-4679 : Backport OAK-4119, OAK-4101, OAK-4087 and OAK-4344
- backported OAK-4087

Added:
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncHandlerMapping.java
      - copied unchanged from r1746408, 
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncHandlerMapping.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleAutoMembershipTest.java
      - copied unchanged from r1746408, 
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleAutoMembershipTest.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/PrincipalProviderAutoMembershipTest.java
      - copied unchanged from r1746408, 
jackrabbit/oak/trunk/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/PrincipalProviderAutoMembershipTest.java
    
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/external/
      - copied from r1746408, 
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authentication/external/
    
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/
      - copied from r1743674, 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/
Removed:
    
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/defaultusersync.md
Modified:
    jackrabbit/oak/branches/1.4/   (props changed)
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalPrincipalConfiguration.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java
    
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java
    
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
    
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/usersync.md
    
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/principal/principalprovider.md
    jackrabbit/oak/branches/1.4/oak-run/pom.xml
    
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java
    
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
    
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java
    
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
    
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncAllExternalUsersTest.java
    
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncExternalUsersTest.java

Propchange: jackrabbit/oak/branches/1.4/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Aug 18 14:22:59 2016
@@ -1,3 +1,3 @@
 /jackrabbit/oak/branches/1.0:1665962
-/jackrabbit/oak/trunk:1733615,1733875,1733913,1733929,1734230,1734254,1734279,1734941,1735052,1735081,1735141,1735267,1735405,1735484,1735549,1735564,1735588,1735622,1735638,1735919,1735983,1736176,1737309-1737310,1737334,1737349,1737998,1738004,1738136,1738138,1738207,1738252,1738775,1738795,1738833,1738950,1738957,1738963,1739712,1739760,1739867,1739894,1739959-1739960,1740114,1740116,1740250,1740333,1740360,1740625-1740626,1740774,1740837,1740971,1741016,1741032,1741339,1741343,1742077,1742117,1742363,1742520,1742888,1742916,1743097,1743172,1743343,1744265,1744292,1744959,1745038,1745197,1745368,1746086,1746117,1746342,1746345,1746696,1746981,1747198,1747200,1747341-1747342,1747492,1747512,1748505,1748553,1748722,1748870,1749275,1749350,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1751871,1752198,1752202,1752273-1752274,1752438,1752447
 
,1752508,1752616,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755157,1756520,1756580
+/jackrabbit/oak/trunk:1733615,1733875,1733913,1733929,1734230,1734254,1734279,1734941,1735052,1735081,1735141,1735267,1735405,1735484,1735549,1735564,1735588,1735622,1735638,1735919,1735983,1736176,1737309-1737310,1737334,1737349,1737998,1738004,1738136,1738138,1738207,1738252,1738775,1738795,1738833,1738950,1738957,1738963,1739712,1739760,1739867,1739894,1739959-1739960,1740114,1740116,1740250,1740333,1740360,1740625-1740626,1740774,1740837,1740971,1741016,1741032,1741339,1741343,1742077,1742117,1742363,1742520,1742888,1742916,1743097,1743172,1743343,1743674,1744265,1744292,1744670,1744672,1744959,1745038,1745127,1745197,1745368,1746086,1746117,1746342,1746345,1746408,1746696,1746981,1747198,1747200,1747341-1747342,1747492,1747512,1748505,1748553,1748722,1748870,1749275,1749350,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1751871,1752198
 
,1752202,1752273-1752274,1752438,1752447,1752508,1752616,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755157,1756520,1756580
 /jackrabbit/trunk:1345480

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContext.java
 Thu Aug 18 14:22:59 2016
@@ -135,6 +135,11 @@ public class DynamicSyncContext extends
         }
     }
 
+    @Override
+    protected void applyMembership(@Nonnull Authorizable member, @Nonnull 
Set<String> groups) throws RepositoryException {
+        log.debug("Dynamic membership sync enabled => omit setting 
auto-membership for {} ", member.getID());
+    }
+
     /**
      * Recursively collect the principal names of the given declared group
      * references up to the given depth.

Modified: 
jackrabbit/oak/branches/1.4/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/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
 Thu Aug 18 14:22:59 2016
@@ -70,12 +70,12 @@ public class ExternalLoginModule extends
     /**
      * Name of the parameter that configures the name of the external identity 
provider.
      */
-    public static final String PARAM_IDP_NAME = "idp.name";
+    public static final String PARAM_IDP_NAME = 
SyncHandlerMapping.PARAM_IDP_NAME;
 
     /**
      * Name of the parameter that configures the name of the synchronization 
handler.
      */
-    public static final String PARAM_SYNC_HANDLER_NAME = "sync.handlerName";
+    public static final String PARAM_SYNC_HANDLER_NAME = 
SyncHandlerMapping.PARAM_SYNC_HANDLER_NAME;
 
     private ExternalIdentityProviderManager idpManager;
 

Modified: 
jackrabbit/oak/branches/1.4/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/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
 Thu Aug 18 14:22:59 2016
@@ -17,12 +17,12 @@
 package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
 
 import java.util.Hashtable;
-
 import javax.jcr.Repository;
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 import javax.security.auth.spi.LoginModule;
 
+import com.google.common.collect.ImmutableMap;
 import org.apache.felix.jaas.LoginModuleFactory;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -43,8 +43,6 @@ import org.osgi.service.component.Compon
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.ImmutableMap;
-
 /**
  * Implements a LoginModuleFactory that creates {@link ExternalLoginModule}s 
and allows to configure login modules
  * via OSGi config.
@@ -56,7 +54,7 @@ import com.google.common.collect.Immutab
         configurationFactory = true
 )
 @Service
-public class ExternalLoginModuleFactory implements LoginModuleFactory {
+public class ExternalLoginModuleFactory implements LoginModuleFactory, 
SyncHandlerMapping {
 
     private static final Logger log = 
LoggerFactory.getLogger(ExternalLoginModuleFactory.class);
 
@@ -92,14 +90,14 @@ public class ExternalLoginModuleFactory
             label = "Identity Provider Name",
             description = "Name of the identity provider (for example: 
'ldap')."
     )
-    public static final String PARAM_IDP_NAME = 
ExternalLoginModule.PARAM_IDP_NAME;
+    public static final String PARAM_IDP_NAME = 
SyncHandlerMapping.PARAM_IDP_NAME;
 
     @Property(
             value = "default",
             label = "Sync Handler Name",
             description = "Name of the sync handler."
     )
-    public static final String PARAM_SYNC_HANDLER_NAME = 
ExternalLoginModule.PARAM_SYNC_HANDLER_NAME;
+    public static final String PARAM_SYNC_HANDLER_NAME = 
SyncHandlerMapping.PARAM_SYNC_HANDLER_NAME;
 
     @Reference
     private SyncManager syncManager;
@@ -120,6 +118,7 @@ public class ExternalLoginModuleFactory
      */
     private Registration mbeanRegistration;
 
+    //----------------------------------------------------< SCR integration 
>---
     /**
      * Activates the LoginModuleFactory service
      * @param context the component context

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.java
 Thu Aug 18 14:22:59 2016
@@ -19,12 +19,14 @@ package org.apache.jackrabbit.oak.spi.se
 import java.security.Principal;
 import java.security.acl.Group;
 import java.text.ParseException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -54,6 +56,7 @@ import org.apache.jackrabbit.oak.api.Tre
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIdentityConstants;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
@@ -95,12 +98,18 @@ class ExternalGroupPrincipalProvider imp
 
     private final Root root;
     private final NamePathMapper namePathMapper;
+
     private final UserManager userManager;
+    private final AutoMembershipPrincipals autoMembershipPrincipals;
 
-    ExternalGroupPrincipalProvider(Root root, UserConfiguration uc, 
NamePathMapper namePathMapper) {
+    ExternalGroupPrincipalProvider(@Nonnull Root root, @Nonnull 
UserConfiguration uc,
+                                   @Nonnull NamePathMapper namePathMapper,
+                                   @Nonnull Map<String, String[]> 
autoMembershipMapping) {
         this.root = root;
         this.namePathMapper = namePathMapper;
+
         userManager = uc.getUserManager(root, namePathMapper);
+        autoMembershipPrincipals = new 
AutoMembershipPrincipals(autoMembershipMapping);
     }
 
     //--------------------------------------------------< PrincipalProvider 
>---
@@ -164,6 +173,15 @@ class ExternalGroupPrincipalProvider imp
     }
 
     //------------------------------------------------------------< private 
>---
+    @CheckForNull
+    private String getIdpName(@Nonnull Tree userTree) {
+        PropertyState ps = userTree.getProperty(REP_EXTERNAL_ID);
+        if (ps != null) {
+            return 
ExternalIdentityRef.fromString(ps.getValue(Type.STRING)).getProviderName();
+        } else {
+            return null;
+        }
+    }
 
     private Set<Group> getGroupPrincipals(@CheckForNull Authorizable 
authorizable) throws RepositoryException {
         if (authorizable != null && !authorizable.isGroup()) {
@@ -178,10 +196,14 @@ class ExternalGroupPrincipalProvider imp
         if (userTree.exists() && UserUtil.isType(userTree, 
AuthorizableType.USER) && userTree.hasProperty(REP_EXTERNAL_PRINCIPAL_NAMES)) {
             PropertyState ps = 
userTree.getProperty(REP_EXTERNAL_PRINCIPAL_NAMES);
             if (ps != null) {
+                // we have an 'external' user that has been synchronized with 
the dynamic-membership option
                 Set<Group> groupPrincipals = Sets.newHashSet();
                 for (String principalName : ps.getValue(Type.STRINGS)) {
                     groupPrincipals.add(new 
ExternalGroupPrincipal(principalName));
                 }
+
+                // add existing group principals as defined with the 
_autoMembership_ option.
+                
groupPrincipals.addAll(autoMembershipPrincipals.get(getIdpName(userTree)));
                 return groupPrincipals;
             }
         }
@@ -194,6 +216,10 @@ class ExternalGroupPrincipalProvider imp
      * {@link #REP_EXTERNAL_PRINCIPAL_NAMES} properties that match the given
      * name or name hint.
      *
+     * NOTE: ignore any principals listed in the {@link 
DefaultSyncConfig.User#autoMembership}
+     * because they are expected to exist in the system and thus will be found
+     * by another principal provider instance.
+     *
      * @param nameHint The principal name or name hint to be searched for.
      * @param exactMatch boolean flag indicating if the query should search for
      *                   exact matching.
@@ -409,4 +435,54 @@ class ExternalGroupPrincipalProvider imp
             return null;
         }
     }
+
+    private final class AutoMembershipPrincipals {
+
+        private final Map<String, String[]> autoMembershipMapping;
+        private final Map<String, Set<Group>> principalMap;
+
+        private AutoMembershipPrincipals(@Nonnull Map<String, String[]> 
autoMembershipMapping) {
+            this.autoMembershipMapping = autoMembershipMapping;
+            this.principalMap = new ConcurrentHashMap<String, 
Set<Group>>(autoMembershipMapping.size());
+        }
+
+        @Nonnull
+        private Collection<Group> get(@CheckForNull String idpName) {
+            if (idpName == null) {
+                return ImmutableSet.of();
+            }
+
+            Set<Group> principals;
+            if (!principalMap.containsKey(idpName)) {
+                String[] vs = autoMembershipMapping.get(idpName);
+                if (vs == null) {
+                    principals = ImmutableSet.of();
+                } else {
+                    ImmutableSet.Builder<Group> builder = 
ImmutableSet.builder();
+                    for (String groupId : autoMembershipMapping.get(idpName)) {
+                        try {
+                            Authorizable gr = 
userManager.getAuthorizable(groupId);
+                            if (gr != null && gr.isGroup()) {
+                                Principal grPrincipal = gr.getPrincipal();
+                                if (grPrincipal instanceof Group) {
+                                    builder.add((Group) grPrincipal);
+                                } else {
+                                    log.warn("Principal of group {} is not of 
type java.security.acl.Group -> Ignoring", groupId);
+                                }
+                            } else {
+                                log.warn("Configured auto-membership group {} 
does not exist -> Ignoring", groupId);
+                            }
+                        } catch (RepositoryException e) {
+                            log.debug("Failed to retrieved 'auto-membership' 
group with id {}", groupId, e);
+                        }
+                    }
+                    principals = builder.build();
+                }
+                principalMap.put(idpName, principals);
+            } else {
+                principals = principalMap.get(idpName);
+            }
+            return principals;
+        }
+    }
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalPrincipalConfiguration.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalPrincipalConfiguration.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalPrincipalConfiguration.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalPrincipalConfiguration.java
 Thu Aug 18 14:22:59 2016
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.oak.spi.se
 
 import java.security.Principal;
 import java.security.acl.Group;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -26,8 +28,11 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -46,6 +51,8 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncHandlerMapping;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalManagerImpl;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
@@ -54,6 +61,8 @@ import org.apache.jackrabbit.oak.spi.xml
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Implementation of the {@code PrincipalConfiguration} interface that provides
@@ -73,7 +82,10 @@ import org.osgi.util.tracker.ServiceTrac
 @Service({PrincipalConfiguration.class, SecurityConfiguration.class})
 public class ExternalPrincipalConfiguration extends ConfigurationBase 
implements PrincipalConfiguration {
 
+    private static final Logger log = 
LoggerFactory.getLogger(ExternalPrincipalConfiguration.class);
+
     private SyncConfigTracker syncConfigTracker;
+    private SyncHandlerMappingTracker syncHandlerMappingTracker;
 
     @SuppressWarnings("UnusedDeclaration")
     public ExternalPrincipalConfiguration() {
@@ -96,7 +108,7 @@ public class ExternalPrincipalConfigurat
     public PrincipalProvider getPrincipalProvider(Root root, NamePathMapper 
namePathMapper) {
         if (dynamicMembershipEnabled()) {
             UserConfiguration uc = 
getSecurityProvider().getConfiguration(UserConfiguration.class);
-            return new ExternalGroupPrincipalProvider(root, uc, 
namePathMapper);
+            return new ExternalGroupPrincipalProvider(root, uc, 
namePathMapper, syncConfigTracker.getAutoMembership());
         } else {
             return EmptyPrincipalProvider.INSTANCE;
         }
@@ -132,8 +144,13 @@ public class ExternalPrincipalConfigurat
     @Activate
     private void activate(BundleContext bundleContext, Map<String, Object> 
properties) {
         setParameters(ConfigurationParameters.of(properties));
-        syncConfigTracker = new SyncConfigTracker(bundleContext);
+        syncHandlerMappingTracker = new 
SyncHandlerMappingTracker(bundleContext);
+        syncHandlerMappingTracker.open();
+
+        syncConfigTracker = new SyncConfigTracker(bundleContext, 
syncHandlerMappingTracker);
         syncConfigTracker.open();
+
+
     }
 
     @SuppressWarnings("UnusedDeclaration")
@@ -142,6 +159,9 @@ public class ExternalPrincipalConfigurat
         if (syncConfigTracker != null) {
             syncConfigTracker.close();
         }
+        if (syncHandlerMappingTracker != null) {
+            syncHandlerMappingTracker.close();
+        }
     }
 
     //------------------------------------------------------------< private 
>---
@@ -196,11 +216,14 @@ public class ExternalPrincipalConfigurat
      */
     private static final class SyncConfigTracker extends ServiceTracker {
 
+        private final SyncHandlerMappingTracker mappingTracker;
+
         private Set<ServiceReference> enablingRefs = new 
HashSet<ServiceReference>();
         private boolean isEnabled = false;
 
-        public SyncConfigTracker(BundleContext context) {
+        public SyncConfigTracker(@Nonnull BundleContext context, @Nonnull 
SyncHandlerMappingTracker mappingTracker) {
             super(context, SyncHandler.class.getName(), null);
+            this.mappingTracker = mappingTracker;
         }
 
         @Override
@@ -234,5 +257,83 @@ public class ExternalPrincipalConfigurat
         private static boolean hasDynamicMembership(ServiceReference 
reference) {
             return 
PropertiesUtil.toBoolean(reference.getProperty(DefaultSyncConfigImpl.PARAM_USER_DYNAMIC_MEMBERSHIP),
 DefaultSyncConfigImpl.PARAM_USER_DYNAMIC_MEMBERSHIP_DEFAULT);
         }
+
+        private Map<String, String[]> getAutoMembership() {
+            Map<String, String[]> autoMembership = new HashMap<String, 
String[]>();
+            for (ServiceReference ref : enablingRefs) {
+                String syncHandlerName = 
PropertiesUtil.toString(ref.getProperty(DefaultSyncConfigImpl.PARAM_NAME), 
DefaultSyncConfigImpl.PARAM_NAME_DEFAULT);
+                String[] membership = 
PropertiesUtil.toStringArray(ref.getProperty(DefaultSyncConfigImpl.PARAM_GROUP_AUTO_MEMBERSHIP),
 new String[0]);
+
+                for (String idpName : 
mappingTracker.getIdpNames(syncHandlerName)) {
+                    String[] previous = autoMembership.put(idpName, 
membership);
+                    if (previous != null) {
+                        String msg = (Arrays.equals(previous, membership)) ? 
"Duplicate" : "Colliding";
+                        log.debug(msg + " auto-membership configuration for 
IDP '{}'; replacing previous values {} by {} defined by SyncHandler '{}'",
+                                idpName, Arrays.toString(previous), 
Arrays.toString(membership), syncHandlerName);
+                    }
+                }
+            }
+            return autoMembership;
+        }
+    }
+
+    /**
+     * {@code ServiceTracker} to detect any {@link SyncHandler} that has
+     * dynamic membership enabled.
+     */
+    private static final class SyncHandlerMappingTracker extends 
ServiceTracker {
+
+        private Map<ServiceReference, String[]> referenceMap = new 
HashMap<ServiceReference, String[]>();
+
+        public SyncHandlerMappingTracker(@Nonnull BundleContext context) {
+            super(context, SyncHandlerMapping.class.getName(), null);
+        }
+
+        @Override
+        public Object addingService(ServiceReference reference) {
+            addMapping(reference);
+            return super.addingService(reference);
+        }
+
+        @Override
+        public void modifiedService(ServiceReference reference, Object 
service) {
+            addMapping(reference);
+            super.modifiedService(reference, service);
+        }
+
+        @Override
+        public void removedService(ServiceReference reference, Object service) 
{
+            referenceMap.remove(reference);
+            super.removedService(reference, service);
+        }
+
+        private void addMapping(ServiceReference reference) {
+            String idpName = 
PropertiesUtil.toString(reference.getProperty(ExternalLoginModuleFactory.PARAM_IDP_NAME),
 null);
+            String syncHandlerName = 
PropertiesUtil.toString(reference.getProperty(ExternalLoginModuleFactory.PARAM_SYNC_HANDLER_NAME),
 null);
+
+            if (idpName != null && syncHandlerName != null) {
+                referenceMap.put(reference, new String[]{syncHandlerName, 
idpName});
+            } else {
+                log.warn("Ignoring SyncHandlerMapping with incomplete mapping 
of IDP '{}' and SyncHandler '{}'", idpName, syncHandlerName);
+            }
+        }
+
+        private Iterable<String> getIdpNames(@Nonnull final String 
syncHandlerName) {
+            return Iterables.filter(Iterables.transform(referenceMap.values(), 
new Function<String[], String>() {
+                        @Nullable
+                        @Override
+                        public String apply(@Nullable String[] input) {
+                            if (input != null && input.length == 2) {
+                                if (syncHandlerName.equals(input[0])) {
+                                    return input[1];
+                                } // else: different sync-handler
+                            } else {
+                                log.warn("Unexpected value of reference map. 
Expected String[] with length = 2");
+                            }
+                            return null;
+                        }
+                    }
+            ), Predicates.notNull());
+        }
     }
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalLoginModuleTestBase.java
 Thu Aug 18 14:22:59 2016
@@ -57,10 +57,10 @@ public abstract class ExternalLoginModul
 
         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());
-
         setSyncConfig(syncConfig);
+
+        options.put(ExternalLoginModule.PARAM_SYNC_HANDLER_NAME, 
syncConfig.getName());
+        options.put(ExternalLoginModule.PARAM_IDP_NAME, idp.getName());
     }
 
     @After

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
 Thu Aug 18 14:22:59 2016
@@ -92,7 +92,7 @@ public class TestIdentityProvider implem
     @Nonnull
     @Override
     public String getName() {
-        return "test";
+        return idpName;
     }
 
     @Override

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DynamicSyncContextTest.java
 Thu Aug 18 14:22:59 2016
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.spi.se
 
 import java.util.HashSet;
 import java.util.Set;
+import java.util.UUID;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.jcr.RepositoryException;
@@ -31,6 +32,7 @@ import com.google.common.collect.Iterabl
 import com.google.common.collect.Sets;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Root;
@@ -418,6 +420,21 @@ public class DynamicSyncContextTest exte
         assertFalse(r.hasPendingChanges());
     }
 
+    @Test
+    public void testAutoMembership() throws Exception {
+        Group gr = userManager.createGroup("group" + UUID.randomUUID());
+        r.commit();
+
+        syncConfig.user().setAutoMembership(gr.getID(), "non-existing-group");
+
+        SyncResult result = syncContext.sync(idp.getUser(USER_ID));
+        assertSame(SyncResult.Status.ADD, result.getStatus());
+
+        User u = userManager.getAuthorizable(USER_ID, User.class);
+        assertFalse(gr.isDeclaredMember(u));
+        assertFalse(gr.isMember(u));
+    }
+
     private static final class TestUserWithGroupRefs extends 
TestIdentityProvider.TestIdentity implements ExternalUser {
 
         private Iterable<ExternalIdentityRef> declaredGroupRefs;

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/AbstractPrincipalTest.java
 Thu Aug 18 14:22:59 2016
@@ -17,9 +17,11 @@
 package 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.principal;
 
 import java.security.Principal;
+import java.util.Set;
 import java.util.UUID;
 import javax.annotation.Nonnull;
 
+import com.google.common.collect.ImmutableMap;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
@@ -63,7 +65,9 @@ public abstract class AbstractPrincipalT
 
     @Nonnull
     PrincipalProvider createPrincipalProvider() {
-        return new ExternalGroupPrincipalProvider(root, 
getSecurityProvider().getConfiguration(UserConfiguration.class), 
NamePathMapper.DEFAULT);
+        Set<String> autoMembership = syncConfig.user().getAutoMembership();
+        return new ExternalGroupPrincipalProvider(root, 
getSecurityProvider().getConfiguration(UserConfiguration.class),
+                NamePathMapper.DEFAULT, ImmutableMap.of(idp.getName(), 
autoMembership.toArray(new String[autoMembership.size()])));
     }
 
     @Override

Modified: 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProviderTest.java
 Thu Aug 18 14:22:59 2016
@@ -53,7 +53,7 @@ import static org.junit.Assert.fail;
 
 public class ExternalGroupPrincipalProviderTest extends AbstractPrincipalTest {
 
-    private void syncWithMembership(@Nonnull ExternalUser externalUser, long 
depth) throws Exception {
+    void syncWithMembership(@Nonnull ExternalUser externalUser, long depth) 
throws Exception {
         DefaultSyncConfig sc = new DefaultSyncConfig();
         sc.user().setMembershipNestingDepth(depth);
 
@@ -68,7 +68,11 @@ public class ExternalGroupPrincipalProvi
         root.refresh();
     }
 
-    private Set<Principal> getDeclaredGroupPrincipals(@Nonnull String userId) 
throws ExternalIdentityException {
+    Set<Principal> getExpectedGroupPrincipals(@Nonnull String userId) throws 
Exception {
+        return getDeclaredGroupPrincipals(userId);
+    }
+
+    Set<Principal> getDeclaredGroupPrincipals(@Nonnull String userId) throws 
Exception {
         Set<Principal> principals = 
ImmutableSet.copyOf(Iterables.transform(idp.getUser(userId).getDeclaredGroups(),
 new Function<ExternalIdentityRef, Principal>() {
             @Nullable
             @Override
@@ -76,16 +80,24 @@ public class ExternalGroupPrincipalProvi
                 try {
                     return new 
PrincipalImpl(idp.getIdentity(input).getPrincipalName());
                 } catch (ExternalIdentityException e) {
-                    fail(e.getMessage());
-                    return null;
+                    throw new RuntimeException(e);
                 }
-            }
-
-            ;
+            };
         }));
         return principals;
     }
 
+    void collectExpectedPrincipals(Set<Principal> grPrincipals, @Nonnull 
Iterable<ExternalIdentityRef> declaredGroups, long depth) throws Exception {
+        if (depth <= 0) {
+            return;
+        }
+        for (ExternalIdentityRef ref : declaredGroups) {
+            ExternalIdentity ei = idp.getIdentity(ref);
+            grPrincipals.add(new PrincipalImpl(ei.getPrincipalName()));
+            collectExpectedPrincipals(grPrincipals, ei.getDeclaredGroups(), 
depth - 1);
+        }
+    }
+
     @Test
     public void testGetPrincipalLocalUser() throws Exception {
         
assertNull(principalProvider.getPrincipal(getTestUser().getPrincipal().getName()));
@@ -233,7 +245,7 @@ public class ExternalGroupPrincipalProvi
         Authorizable user = getUserManager(root).getAuthorizable(USER_ID);
         assertNotNull(user);
 
-        Set<Principal> expected = getDeclaredGroupPrincipals(USER_ID);
+        Set<Principal> expected = getExpectedGroupPrincipals(USER_ID);
 
         Set<? extends Principal> principals = 
principalProvider.getGroupMembership(user.getPrincipal());
         assertEquals(expected, principals);
@@ -274,17 +286,6 @@ public class ExternalGroupPrincipalProvi
         assertEquals(expectedGrPrincipals, principals);
     }
 
-    private void collectExpectedPrincipals(Set<Principal> grPrincipals, 
@Nonnull Iterable<ExternalIdentityRef> declaredGroups, long depth) throws 
ExternalIdentityException {
-        if (depth <= 0) {
-            return;
-        }
-        for (ExternalIdentityRef ref : declaredGroups) {
-            ExternalIdentity ei = idp.getIdentity(ref);
-            grPrincipals.add(new PrincipalImpl(ei.getPrincipalName()));
-            collectExpectedPrincipals(grPrincipals, ei.getDeclaredGroups(), 
depth - 1);
-        }
-    }
-
     @Test
     public void testGetGroupMembershipExternalGroup() throws Exception {
         Authorizable group = 
getUserManager(root).getAuthorizable("secondGroup");
@@ -313,7 +314,7 @@ public class ExternalGroupPrincipalProvi
     @Test
     public void testGetPrincipalsExternalUser() throws Exception {
         Set<? extends Principal> principals = 
principalProvider.getPrincipals(USER_ID);
-        assertEquals(getDeclaredGroupPrincipals(USER_ID), principals);
+        assertEquals(getExpectedGroupPrincipals(USER_ID), principals);
     }
 
     @Test

Modified: 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/externalloginmodule.md
 Thu Aug 18 14:22:59 2016
@@ -64,7 +64,7 @@ if the user is not yet present in the lo
 check the credentials with the external system during the `login()` method.
 
 The details of the default user/group synchronization mechanism are described 
in section
-[User and Group Synchronization : The Default 
Implementation](defaultusersync.html)
+[User and Group Synchronization : The Default 
Implementation](external/defaultusersync.html)
 
 ##### Supported Credentials
 

Modified: 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/usersync.md
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/usersync.md?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/usersync.md
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/authentication/usersync.md
 Thu Aug 18 14:22:59 2016
@@ -51,7 +51,7 @@ for the following tasks:
 Oak 1.0 provides a default implementation of the user synchronization API that 
allow
 to plug additional `SyncHandler` implementations. 
 
-Default implementation is described in section [User and Group Synchronization 
: The Default Implementation](defaultusersync.html).
+Default implementation is described in section [User and Group Synchronization 
: The Default Implementation](external/defaultusersync.html).
 
 ### Pluggability
 

Modified: 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/principal/principalprovider.md
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/principal/principalprovider.md?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/principal/principalprovider.md
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-doc/src/site/markdown/security/principal/principalprovider.md
 Thu Aug 18 14:22:59 2016
@@ -79,7 +79,7 @@ principals on the IDP but relies on a pe
 the names of these external principals are synchronized to based on a 
configurable
 expiration time.
 
-See section [User and Group Synchronization : The Default 
Implementation](../authentication/defaultusersync.html)
+See section [User and Group Synchronization : The Default 
Implementation](../authentication/external/defaultusersync.html)
 for additional details.
 
 Since Oak 1.5.3

Modified: jackrabbit/oak/branches/1.4/oak-run/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-run/pom.xml?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.4/oak-run/pom.xml (original)
+++ jackrabbit/oak/branches/1.4/oak-run/pom.xml Thu Aug 18 14:22:59 2016
@@ -282,6 +282,11 @@
       <version>${project.version}</version>
     </dependency>
     <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>oak-auth-external</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.tomcat</groupId>
       <artifactId>tomcat-jdbc</artifactId>
       <version>7.0.64</version>
@@ -407,6 +412,12 @@
       <optional>true</optional>
     </dependency>
 
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
     <!-- Findbugs annotations -->
     <dependency>
       <groupId>com.google.code.findbugs</groupId>

Modified: 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java
 Thu Aug 18 14:22:59 2016
@@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
 /**
  * Abstract base class for individual performance benchmarks.
  */
-abstract class AbstractTest<T> extends Benchmark implements CSVResultGenerator 
{
+public abstract class AbstractTest<T> extends Benchmark implements 
CSVResultGenerator {
 
     /**
      * A random string to guarantee concurrently running tests don't overwrite

Modified: 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1756792&r1=1756791&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
 Thu Aug 18 14:22:59 2016
@@ -32,6 +32,9 @@ import joptsimple.OptionParser;
 import joptsimple.OptionSet;
 import joptsimple.OptionSpec;
 import org.apache.commons.io.FileUtils;
+import 
org.apache.jackrabbit.oak.benchmark.authentication.external.ExternalLoginTest;
+import 
org.apache.jackrabbit.oak.benchmark.authentication.external.SyncAllExternalUsersTest;
+import 
org.apache.jackrabbit.oak.benchmark.authentication.external.SyncExternalUsersTest;
 import org.apache.jackrabbit.oak.benchmark.wikipedia.WikipediaImport;
 import org.apache.jackrabbit.oak.fixture.JackrabbitRepositoryFixture;
 import org.apache.jackrabbit.oak.fixture.OakFixture;
@@ -128,6 +131,10 @@ public class BenchmarkRunner {
                 .defaultsTo(Boolean.FALSE);
         OptionSpec<String> supportedPaths = parser.accepts("supportedPaths", 
"Supported paths in composite setup.")
                 
.withOptionalArg().ofType(String.class).withValuesSeparatedBy(',');
+        OptionSpec<Boolean> dynamicMembership = 
parser.accepts("dynamicMembership", "Enable dynamic membership handling during 
synchronisation of external users.")
+                
.withOptionalArg().ofType(Boolean.class).defaultsTo(Boolean.FALSE);
+        OptionSpec<String> autoMembership = parser.accepts("autoMembership", 
"Ids of those groups a given external identity automatically become member of.")
+                
.withOptionalArg().ofType(String.class).withValuesSeparatedBy(',');
         OptionSpec<String> nonOption = parser.nonOptions();
         OptionSpec help = parser.acceptsAll(asList("h", "?", "help"), "show 
help").forHelp();
         OptionSet options = parser.parse(args);
@@ -341,7 +348,12 @@ public class BenchmarkRunner {
                 wikipedia.value(options),
                 flatStructure.value(options),
                 report.value(options), withStorage.value(options)),
-            new ReplicaCrashResilienceTest()
+            new ReplicaCrashResilienceTest(),
+
+            // benchmarks for oak-auth-external
+            new ExternalLoginTest(numberOfUsers.value(options), 
numberOfGroups.value(options), expiration.value(options), 
dynamicMembership.value(options), autoMembership.values(options)),
+            new SyncAllExternalUsersTest(numberOfUsers.value(options), 
numberOfGroups.value(options), expiration.value(options), 
dynamicMembership.value(options), autoMembership.values(options)),
+            new SyncExternalUsersTest(numberOfUsers.value(options), 
numberOfGroups.value(options), expiration.value(options), 
dynamicMembership.value(options), autoMembership.values(options), 
batchSize.value(options))
         };
 
         Set<String> argset = Sets.newHashSet(nonOption.values(options));

Modified: 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java?rev=1756792&r1=1743674&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java
 Thu Aug 18 14:22:59 2016
@@ -33,6 +33,8 @@ import javax.security.auth.login.Configu
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.Oak;
 import org.apache.jackrabbit.oak.benchmark.AbstractTest;
 import org.apache.jackrabbit.oak.fixture.JcrCreator;
@@ -52,30 +54,44 @@ import org.apache.jackrabbit.oak.spi.sec
 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.basic.DefaultSyncConfig;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncConfigImpl;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIDPManagerImpl;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncHandlerMapping;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncManagerImpl;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.principal.ExternalPrincipalConfiguration;
+import 
org.apache.jackrabbit.oak.spi.security.principal.CompositePrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
+import org.apache.sling.testing.mock.osgi.context.OsgiContextImpl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Base benchmark test for external authentication.
  *
  * The setup currently defines the following configuration options:
  *
- * - {@code numberofUsers} : number of user accounts that are 'known' to the 
IDP
- * - {@code numberofGroups}: number of groups 'known' to the IDP and equally 
used to define the membershipSize of each user.
+ * - {@code numberOfUsers} : number of user accounts that are 'known' to the 
IDP
+ * - {@code numberOfGroups}: number of groups 'known' to the IDP and equally 
used to define the membershipSize of each user.
  * - {@code expirationTime}: expiration time as set with
  *   {@link DefaultSyncConfig.Authorizable#setExpirationTime(long)}, used for 
both users and groups
  * - {@code dynamicMembership}: boolean flag to enable dynamic membership (see 
OAK-4101)
  *
  * Note: by default the {@link 
DefaultSyncConfig.User#setMembershipNestingDepth(long)}
  * is set to 1 and each user will become member of each of the groups as 
defined
- * by {@code numberofGroups}.
+ * by {@code numberOfGroups}.
  */
 abstract class AbstractExternalTest extends AbstractTest {
 
     private static final String PATH_PREFIX = "pathPrefix";
+
+    private final Random random = new Random();
+    private final ExternalPrincipalConfiguration 
externalPrincipalConfiguration = new ExternalPrincipalConfiguration();
+
     final DefaultSyncConfig syncConfig = new DefaultSyncConfig();
     final SyncHandler syncHandler = new DefaultSyncHandler(syncConfig);
 
@@ -84,19 +100,23 @@ abstract class AbstractExternalTest exte
     SyncManagerImpl syncManager;
     ExternalIdentityProviderManager idpManager;
 
-    private final Random random = new Random();
-
-    protected AbstractExternalTest(int numberofUsers, int numberofGroups, long 
expTime, boolean dynamicMembership) {
-        idp = new TestIdentityProvider(numberofUsers, numberofGroups);
-        
syncConfig.user().setMembershipNestingDepth(1).setExpirationTime(expTime).setPathPrefix(PATH_PREFIX);
-        
syncConfig.group().setExpirationTime(expTime).setPathPrefix(PATH_PREFIX);
-        // TODO OAK-4101 : 
syncConfig.user().setDynamicMembership(dynamicMembership);
+    protected AbstractExternalTest(int numberOfUsers, int numberOfGroups,
+                                   long expTime, boolean dynamicMembership,
+                                   @Nonnull List<String> autoMembership) {
+        idp = new TestIdentityProvider(numberOfUsers, numberOfGroups);
+        syncConfig.user()
+                .setMembershipNestingDepth(1)
+                .setDynamicMembership(dynamicMembership)
+                .setAutoMembership(autoMembership.toArray(new 
String[autoMembership.size()]))
+                .setExpirationTime(expTime).setPathPrefix(PATH_PREFIX);
+        syncConfig.group()
+                .setExpirationTime(expTime).setPathPrefix(PATH_PREFIX);
     }
 
     protected abstract Configuration createConfiguration();
 
     protected String getRandomUserId() {
-        int index = random.nextInt(((TestIdentityProvider) idp).numberofUsers);
+        int index = random.nextInt(((TestIdentityProvider) idp).numberOfUsers);
         return "u" + index;
     }
 
@@ -112,6 +132,19 @@ abstract class AbstractExternalTest exte
         super.run(iterable, concurrencyLevels);
     }
 
+    @Override
+    protected void beforeSuite() throws Exception {
+        Set<String> autoMembership = syncConfig.user().getAutoMembership();
+        if (!autoMembership.isEmpty()) {
+            Session s = loginAdministrative();
+            UserManager userManager = ((JackrabbitSession) s).getUserManager();
+            for (String groupId : autoMembership) {
+                userManager.createGroup(groupId, new PrincipalImpl(groupId), 
PATH_PREFIX);
+            }
+            s.save();
+        }
+    }
+
     /**
      * Remove any user/group accounts that have been synchronized into the 
repo.
      *
@@ -146,6 +179,27 @@ abstract class AbstractExternalTest exte
                     whiteboard.register(ExternalIdentityProvider.class, idp, 
Collections.emptyMap());
                     whiteboard.register(SyncHandler.class, syncHandler, 
Collections.emptyMap());
 
+                    // assert proper init of the 
'externalPrincipalConfiguration' if dynamic membership is enabled
+                    if (syncConfig.user().getDynamicMembership()) {
+                        OsgiContextImpl context = new OsgiContextImpl();
+
+                        // register the ExternalPrincipal configuration in 
order to have it's
+                        // activate method invoked.
+                        
context.registerInjectActivateService(externalPrincipalConfiguration);
+
+                        // now register the sync-handler with the dynamic 
membership config
+                        // in order to enable dynamic membership with the 
external principal configuration
+                        Map props = ImmutableMap.of(
+                                
DefaultSyncConfigImpl.PARAM_USER_DYNAMIC_MEMBERSHIP, 
syncConfig.user().getDynamicMembership(),
+                                
DefaultSyncConfigImpl.PARAM_GROUP_AUTO_MEMBERSHIP, 
syncConfig.user().getAutoMembership());
+                        context.registerService(SyncHandler.class, 
WhiteboardUtils.getService(whiteboard, SyncHandler.class), props);
+
+                        Map shMappingProps = ImmutableMap.of(
+                                SyncHandlerMapping.PARAM_IDP_NAME, 
idp.getName(),
+                                SyncHandlerMapping.PARAM_SYNC_HANDLER_NAME, 
syncConfig.getName());
+                        context.registerService(SyncHandlerMapping.class, new 
SyncHandlerMapping() {}, shMappingProps);
+                    }
+
                     SecurityProvider sp = new 
TestSecurityProvider(ConfigurationParameters.EMPTY);
                     return new Jcr(oak).with(sp);
                 }
@@ -158,25 +212,24 @@ abstract class AbstractExternalTest exte
     private final class TestSecurityProvider extends SecurityProviderImpl {
         public TestSecurityProvider(@Nonnull ConfigurationParameters 
configuration) {
             super(configuration);
-            //  TODO: enable once OAK-4104 is commited
-            //            PrincipalConfiguration principalConfiguration = 
getConfiguration(PrincipalConfiguration.class);
-            //            if (!(principalConfiguration instanceof 
CompositePrincipalConfiguration)) {
-            //                throw new IllegalStateException();
-            //            } else {
-            //                PrincipalConfiguration defConfig = 
checkNotNull(((CompositePrincipalConfiguration) 
principalConfiguration).getDefaultConfig());
-            //                bindPrincipalConfiguration((new 
ExternalPrincipalConfiguration(this)));
-            //                bindPrincipalConfiguration(defConfig);
-            //            }
+            PrincipalConfiguration principalConfiguration = 
getConfiguration(PrincipalConfiguration.class);
+            if (!(principalConfiguration instanceof 
CompositePrincipalConfiguration)) {
+                throw new IllegalStateException();
+            } else {
+                PrincipalConfiguration defConfig = 
checkNotNull(((CompositePrincipalConfiguration) 
principalConfiguration).getDefaultConfig());
+                bindPrincipalConfiguration(externalPrincipalConfiguration);
+                bindPrincipalConfiguration(defConfig);
+            }
         }
     }
 
     private final class TestIdentityProvider implements 
ExternalIdentityProvider {
 
-        private final int numberofUsers;
+        private final int numberOfUsers;
         private final int membershipSize;
 
-        private TestIdentityProvider(int numberofUsers, int membershipSize) {
-            this.numberofUsers = numberofUsers;
+        private TestIdentityProvider(int numberOfUsers, int membershipSize) {
+            this.numberOfUsers = numberOfUsers;
             this.membershipSize = membershipSize;
         }
 
@@ -219,8 +272,8 @@ abstract class AbstractExternalTest exte
         @Nonnull
         @Override
         public Iterator<ExternalUser> listUsers() {
-            Set<ExternalUser> all = new HashSet<>();
-            for (long i = 0; i < numberofUsers; i++) {
+            Set<ExternalUser> all = new HashSet<ExternalUser>();
+            for (long i = 0; i < numberOfUsers; i++) {
                 all.add(new TestUser(i));
             }
             return all.iterator();
@@ -229,7 +282,7 @@ abstract class AbstractExternalTest exte
         @Nonnull
         @Override
         public Iterator<ExternalGroup> listGroups() {
-            Set<ExternalGroup> all = new HashSet<>();
+            Set<ExternalGroup> all = new HashSet<ExternalGroup>();
             for (long i = 0; i < membershipSize; i++) {
                 all.add(new TestGroup(i));
             }
@@ -238,7 +291,7 @@ abstract class AbstractExternalTest exte
 
         Iterable<ExternalIdentityRef> getDeclaredGroupRefs(String userId) {
             if (userId.charAt(0) == 'u') {
-                Set<ExternalIdentityRef> groupRefs = new HashSet<>();
+                Set<ExternalIdentityRef> groupRefs = new 
HashSet<ExternalIdentityRef>();
                 for (long i = 0; i < membershipSize; i++) {
                     groupRefs.add(new ExternalIdentityRef("g"+ i, 
idp.getName()));
                 }

Modified: 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java?rev=1756792&r1=1743674&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
 Thu Aug 18 14:22:59 2016
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.benchmark.authentication.external;
 
+import java.util.List;
+import javax.annotation.Nonnull;
 import javax.jcr.SimpleCredentials;
 import javax.security.auth.login.AppConfigurationEntry;
 import javax.security.auth.login.Configuration;
@@ -34,8 +36,9 @@ import org.apache.jackrabbit.oak.spi.sec
  */
 public class ExternalLoginTest extends AbstractExternalTest {
 
-    public ExternalLoginTest(int numberofUsers, int numberofGroups, long 
expTime, boolean dynamicMembership) {
-        super(numberofUsers, numberofGroups, expTime, dynamicMembership);
+    public ExternalLoginTest(int numberOfUsers, int numberOfGroups, long 
expTime,
+                             boolean dynamicMembership, @Nonnull List<String> 
autoMembership) {
+        super(numberOfUsers, numberOfGroups, expTime, dynamicMembership, 
autoMembership);
     }
 
     @Override

Modified: 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncAllExternalUsersTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncAllExternalUsersTest.java?rev=1756792&r1=1743674&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncAllExternalUsersTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncAllExternalUsersTest.java
 Thu Aug 18 14:22:59 2016
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.benchmark.authentication.external;
 
+import java.util.List;
+import javax.annotation.Nonnull;
 import javax.security.auth.login.Configuration;
 
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
@@ -30,8 +32,9 @@ public class SyncAllExternalUsersTest ex
 
     private SynchronizationMBean bean;
 
-    public SyncAllExternalUsersTest(int numberofUsers, int membershipSize, 
long expTime, boolean dynamicMembership) {
-        super(numberofUsers, membershipSize, expTime, dynamicMembership);
+    public SyncAllExternalUsersTest(int numberOfUsers, int membershipSize, 
long expTime,
+                                    boolean dynamicMembership, @Nonnull 
List<String> autoMembership) {
+        super(numberOfUsers, membershipSize, expTime, dynamicMembership, 
autoMembership);
     }
 
     @Override

Modified: 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncExternalUsersTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncExternalUsersTest.java?rev=1756792&r1=1743674&r2=1756792&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncExternalUsersTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.4/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/SyncExternalUsersTest.java
 Thu Aug 18 14:22:59 2016
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.benchmark.authentication.external;
 
+import java.util.List;
+import javax.annotation.Nonnull;
 import javax.security.auth.login.Configuration;
 
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
@@ -33,9 +35,10 @@ public class SyncExternalUsersTest exten
     private final int batchSize;
     private SynchronizationMBean bean;
 
-    public SyncExternalUsersTest(int numberofUsers, int membershipSize, long 
expTime,
-                                 boolean dynamicMembership, int batchSize) {
-        super(numberofUsers, membershipSize, expTime, dynamicMembership);
+    public SyncExternalUsersTest(int numberOfUsers, int membershipSize, long 
expTime,
+                                 boolean dynamicMembership, @Nonnull 
List<String> autoMembership,
+                                 int batchSize) {
+        super(numberOfUsers, membershipSize, expTime, dynamicMembership, 
autoMembership);
         this.batchSize = batchSize;
     }
 


Reply via email to