Added: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md?rev=1695223&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md (added) +++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md Tue Aug 11 07:41:07 2015 @@ -0,0 +1,61 @@ +<!-- + 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. +--> + +Implementations of the PrincipalProvider Interface +-------------------------------------------------------------------------------- + +Oak contains by default the following implementations of the `PrincipalProvider` +interface: + +### org.apache.jackrabbit.oak.security.principal.PrincipalProviderImpl + +This is the default implementation of the `PrincipalProvider`, which makes use +of the fact that `Authorizable`s as defined by the Jackrabbit user management +API are always paired with a `Principal`. + +The implementation is not tied to a particular user management implementation +and doesn't need to be rewritten if the security setup would be configured with +different implementation of `UserConfiguration`. + +### org.apache.jackrabbit.oak.security.user.UserPrincipalProvider + +The introduction of the optional `UserConfiguration.getUserPrincipalProvider` +extension allows for an optimized variant of the default principal provider, which +is reading principal information from user and group accounts always paired with +a `Principal` instance. + +This extension allows for a provider based implementation details of the user +management implementation it is associated with, offering the ability to optimize +the principal lookup without having to use regular Jackrabbit user management +API calls and the associated overhead in terms of user/group object creation. + +While the implementation is located along with the user management implementation +present in Oak this provider implementation should not be considered being +part of the user management API implementation. + +Another benefit of this optimized implementation is the ability to specifically +cache the results of the principal resolution in order to improve login performance. +See section [Caching Results of Principal Resolution](cache.html) for further details. + +### org.apache.jackrabbit.oak.spi.security.principal.CompositePrincipalProvider + +This implementation is a simple wrapper implementation that combines different +principals from different source providers. It is used in +`CompositePrincipalConfiguration` held by the default `SecurityProvider` to +collect all configured/plugged principal configurations i.e. the various +implementations of principal management. +
Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user.md URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user.md?rev=1695223&r1=1695222&r2=1695223&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user.md (original) +++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user.md Tue Aug 11 07:41:07 2015 @@ -295,14 +295,20 @@ as of OAK 1.0: | `PARAM_PASSWORD_MAX_AGE` | int | 0 | | `PARAM_PASSWORD_INITIAL_CHANGE` | boolean | false | | `PARAM_PASSWORD_HISTORY_SIZE` | int (upper limit: 1000) | 0 | +| `PARAM_CACHE_EXPIRATION` | long | 0 | | | | | The following configuration parameters present with the default implementation in Jackrabbit 2.x are no longer supported and will be ignored: -* 'compatibleJR16' -* 'autoExpandTree' -* 'autoExpandSize' -* 'groupMembershipSplitSize' +* `compatibleJR16` +* `autoExpandTree` +* `autoExpandSize` +* `groupMembershipSplitSize` + +The optional `cacheExpiration` configuration option listed above is discussed in +detail in section [Caching Results of Principal Resolution](principal/cache.html). +It is not related to user management s.str. but affects the implementation +specific `PrincipalProvider` implementation exposed by `UserConfiguration.getUserPrincipalProvider`. ### Pluggability Copied: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportCacheTest.java (from r1692462, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportHistoryTest.java) URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportCacheTest.java?p2=jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportCacheTest.java&p1=jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportHistoryTest.java&r1=1692462&r2=1695223&rev=1695223&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportHistoryTest.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportCacheTest.java Tue Aug 11 07:41:07 2015 @@ -23,6 +23,7 @@ import org.apache.jackrabbit.oak.spi.sec import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -30,7 +31,7 @@ import static org.junit.Assert.assertTru * and pw-history content: test that the history is imported irrespective of the * configuration. */ -public class UserImportHistoryTest extends AbstractImportTest { +public class UserImportCacheTest extends AbstractImportTest { @Override protected String getTargetPath() { @@ -43,10 +44,10 @@ public class UserImportHistoryTest exten } /** - * @since Oak 1.3.3 + * @since Oak 1.3.4 */ @Test - public void testImportUserWithPwdHistory() throws Exception { + public void testImportUserWithCache() throws Exception { // import user String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<sv:node sv:name=\"y\" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\" xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:fn_old=\"http://www.w3.org/2004/10/xpath-functions\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\" xmlns:rep=\"internal\" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\">" + @@ -62,24 +63,24 @@ public class UserImportHistoryTest exten " <sv:property sv:name=\"rep:principalName\" sv:type=\"String\">" + " <sv:value>yPrincipal</sv:value>" + " </sv:property>" + - " <sv:node sv:name=\"" + UserConstants.REP_PWD + "\">" + + " <sv:node sv:name=\"rep:cache\">" + " <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\">" + - " <sv:value>" + UserConstants.NT_REP_PASSWORD + "</sv:value>" + + " <sv:value>rep:Cache</sv:value>" + " </sv:property>" + - " <sv:property sv:name=\"" + UserConstants.REP_PWD_HISTORY + "\" sv:type=\"String\" sv:multiple=\"true\">" + - " <sv:value>{sha1}8efd86fb78a56a5145ed7739dcb00c78581c5375</sv:value>" + + " <sv:property sv:name=\"rep:expiration\" sv:type=\"Long\">" + + " <sv:value>123456789</sv:value>" + + " </sv:property>" + + " <sv:property sv:name=\"rep:groupPrincipalNames\" sv:type=\"String\" sv:multiple=\"true\">" + + " <sv:value>\"testGroup\"</sv:value>" + " </sv:property>" + " </sv:node>" + "</sv:node>"; doImport(USERPATH, xml); + getImportSession().save(); Authorizable authorizable = getUserManager().getAuthorizable("y"); Node userNode = getImportSession().getNode(authorizable.getPath()); - assertTrue(userNode.hasNode(UserConstants.REP_PWD)); - - Node pwdNode = userNode.getNode(UserConstants.REP_PWD); - assertTrue(pwdNode.hasProperty(UserConstants.REP_PWD_HISTORY)); - assertEquals("{sha1}8efd86fb78a56a5145ed7739dcb00c78581c5375", pwdNode.getProperty(UserConstants.REP_PWD_HISTORY).getString()); + assertFalse(userNode.hasNode("rep:cache")); } } Modified: jackrabbit/oak/trunk/oak-run/run_concurrent_login.sh URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/run_concurrent_login.sh?rev=1695223&r1=1695222&r2=1695223&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-run/run_concurrent_login.sh (original) +++ jackrabbit/oak/trunk/oak-run/run_concurrent_login.sh Tue Aug 11 07:41:07 2015 @@ -16,10 +16,11 @@ # limitations under the License. # TITLE=LoginTest -BENCH="LoginWithMembersTest LoginWithMembershipTest" # LoginTest LoginLogoutTest LoginGetRootLogoutTest" +BENCH="LoginWithMembershipTest" #LoginWithMembersTest LoginWithMembershipTest LoginTest LoginLogoutTest LoginGetRootLogoutTest" USER="user" # admin anonymous" USE_TOKEN=false # true HASH_ITERATIONS="-1" +EXPIRATION="200000" NO_GROUPS="1 10 100 1000" USE_NESTED_GROUPS=true # false RUNTIME=5 @@ -38,6 +39,7 @@ echo "Profiling: $PROFILE" >> $LOG echo "User: $USER" >> $LOG echo "Run with Token: $USE_TOKEN" >> $LOG echo "Hash Iterations: $HASH_ITERATIONS" >> $LOG +echo "Cache Expiration: $EXPIRATION" >> $LOG echo "Number of Groups: $NO_GROUPS" >> $LOG echo "Use Nested Groups: $USE_NESTED_GROUPS" >> $LOG @@ -53,7 +55,8 @@ for bm in $BENCH echo "Executing benchmarks as user: $USER with $noGroups groups (nested = $USE_NESTED_GROUPS) on $fix" | tee -a $LOG echo "-----------------------------------------------------------" | tee -a $LOG rm -rf target/Jackrabbit-* target/Oak-Tar-* - cmd="java -Xmx2048m -Dprofile=$PROFILE -Druntime=$RUNTIME -Dwarmup=10 -jar target/oak-run-*-SNAPSHOT.jar benchmark --noIterations $HASH_ITERATIONS --runWithToken $USE_TOKEN --numberOfGroups $noGroups --nestedGroups $USE_NESTED_GROUPS --csvFile $LOG --concurrency $THREADS --runAsUser $USER --report false $bm $fix" + # cmd="java -Xmx2048m -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 -Dprofile=$PROFILE -Druntime=$RUNTIME -Dwarmup=10 -jar target/oak-run-*-SNAPSHOT.jar benchmark --noIterations $HASH_ITERATIONS --runWithToken $USE_TOKEN --expiration $EXPIRATION --numberOfGroups $noGroups --nestedGroups $USE_NESTED_GROUPS --csvFile $LOG --concurrency $THREADS --runAsUser $USER --report false $bm $fix" + cmd="java -Xmx2048m -Dprofile=$PROFILE -Druntime=$RUNTIME -Dwarmup=10 -jar target/oak-run-*-SNAPSHOT.jar benchmark --noIterations $HASH_ITERATIONS --runWithToken $USE_TOKEN --expiration $EXPIRATION --numberOfGroups $noGroups --nestedGroups $USE_NESTED_GROUPS --csvFile $LOG --concurrency $THREADS --runAsUser $USER --report false $bm $fix" echo $cmd $cmd done Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java?rev=1695223&r1=1695222&r2=1695223&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java (original) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java Tue Aug 11 07:41:07 2015 @@ -16,8 +16,6 @@ */ package org.apache.jackrabbit.oak.benchmark; -import java.util.Collections; -import java.util.Map; import javax.jcr.Credentials; import javax.jcr.GuestCredentials; import javax.jcr.Repository; @@ -27,7 +25,6 @@ import javax.jcr.SimpleCredentials; import javax.jcr.security.Privilege; import javax.security.auth.login.Configuration; -import com.google.common.collect.ImmutableMap; import org.apache.jackrabbit.api.JackrabbitSession; import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials; import org.apache.jackrabbit.api.security.user.Authorizable; @@ -54,20 +51,27 @@ abstract class AbstractLoginTest extends public final static int COUNT = 1000; public final static String USER = "user"; public final static int DEFAULT_ITERATIONS = -1; + public final static long NO_CACHE = -1; private String runAsUser; private boolean runWithToken; private int noIterations; + private long expiration; public AbstractLoginTest() { this("admin", false, DEFAULT_ITERATIONS); } public AbstractLoginTest(String runAsUser, boolean runWithToken, int noIterations) { + this(runAsUser, runWithToken, noIterations, NO_CACHE); + } + + public AbstractLoginTest(String runAsUser, boolean runWithToken, int noIterations, long expiration) { super(); this.runAsUser = runAsUser; this.runWithToken = runWithToken; this.noIterations = noIterations; + this.expiration = expiration; } @Override @@ -102,15 +106,23 @@ abstract class AbstractLoginTest extends @Override protected Repository[] createRepository(RepositoryFixture fixture) throws Exception { - if (noIterations != -1) { + if (noIterations != -1 || expiration > 0) { if (fixture instanceof OakRepositoryFixture) { - final String configName = (runWithToken) ? TokenConfiguration.NAME : UserConfiguration.NAME; return ((OakRepositoryFixture) fixture).setUpCluster(1, new JcrCreator() { @Override public Jcr customize(Oak oak) { - Map<String, Integer> map = Collections.singletonMap(UserConstants.PARAM_PASSWORD_HASH_ITERATIONS, noIterations); - ConfigurationParameters conf = ConfigurationParameters.of(map); - SecurityProvider sp = new SecurityProviderImpl(ConfigurationParameters.of(ImmutableMap.of(configName, conf))); + ConfigurationParameters conf; + ConfigurationParameters iterations = ConfigurationParameters.of(UserConstants.PARAM_PASSWORD_HASH_ITERATIONS, noIterations); + ConfigurationParameters cache = ConfigurationParameters.of("cacheExpiration", expiration); + if (runWithToken) { + conf = ConfigurationParameters.of( + TokenConfiguration.NAME, iterations, + UserConfiguration.NAME, cache); + } else { + conf = ConfigurationParameters.of( + UserConfiguration.NAME, ConfigurationParameters.of(iterations, cache)); + } + SecurityProvider sp = new SecurityProviderImpl(conf); return new Jcr(oak).with(sp); } }); Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1695223&r1=1695222&r2=1695223&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java (original) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java Tue Aug 11 07:41:07 2015 @@ -92,6 +92,8 @@ public class BenchmarkRunner { .withOptionalArg().ofType(Boolean.class).defaultsTo(Boolean.FALSE); OptionSpec<Integer> noIterations = parser.accepts("noIterations", "Change default 'passwordHashIterations' parameter.") .withOptionalArg().ofType(Integer.class).defaultsTo(AbstractLoginTest.DEFAULT_ITERATIONS); + OptionSpec<Long> expiration = parser.accepts("expiration", "Expiration time (e.g. principal cache.") + .withOptionalArg().ofType(Long.class).defaultsTo(AbstractLoginTest.NO_CACHE); OptionSpec<Integer> numberOfGroups = parser.accepts("numberOfGroups", "Number of groups to create.") .withOptionalArg().ofType(Integer.class).defaultsTo(LoginWithMembershipTest.NUMBER_OF_GROUPS_DEFAULT); OptionSpec<Boolean> nestedGroups = parser.accepts("nestedGroups", "Use nested groups.") @@ -182,11 +184,13 @@ public class BenchmarkRunner { runWithToken.value(options), noIterations.value(options), numberOfGroups.value(options), - nestedGroups.value(options)), + nestedGroups.value(options), + expiration.value(options)), new LoginWithMembersTest( runWithToken.value(options), noIterations.value(options), - numberOfGroups.value(options)), + numberOfGroups.value(options), + expiration.value(options)), new NamespaceTest(), new NamespaceRegistryTest(), new ReadPropertyTest(), Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java?rev=1695223&r1=1695222&r2=1695223&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java (original) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java Tue Aug 11 07:41:07 2015 @@ -39,8 +39,8 @@ public class LoginWithMembersTest extend private final int numberOfMembers; - public LoginWithMembersTest(boolean runWithToken, int noIterations, int numberOfMembers) { - super(USER, runWithToken, noIterations); + public LoginWithMembersTest(boolean runWithToken, int noIterations, int numberOfMembers, long expiration) { + super(USER, runWithToken, noIterations, expiration); this.numberOfMembers = numberOfMembers; } Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java?rev=1695223&r1=1695222&r2=1695223&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java (original) +++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java Tue Aug 11 07:41:07 2015 @@ -42,8 +42,8 @@ public class LoginWithMembershipTest ext private final int numberOfGroups; private final boolean nestedGroups; - public LoginWithMembershipTest(boolean runWithToken, int noIterations, int numberOfGroups, boolean nestedGroups) { - super(USER, runWithToken, noIterations); + public LoginWithMembershipTest(boolean runWithToken, int noIterations, int numberOfGroups, boolean nestedGroups, long expiration) { + super(USER, runWithToken, noIterations, expiration); this.numberOfGroups = numberOfGroups; this.nestedGroups = nestedGroups;
