Copied: jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/principal/principalprovider.md (from r1695223, jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md) URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/principal/principalprovider.md?p2=jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/principal/principalprovider.md&p1=jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md&r1=1695223&r2=1756777&rev=1756777&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/principal/principalprovider.md (original) +++ jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/principal/principalprovider.md Thu Aug 18 13:15:22 2016 @@ -21,7 +21,7 @@ Implementations of the PrincipalProvider Oak contains by default the following implementations of the `PrincipalProvider` interface: -### org.apache.jackrabbit.oak.security.principal.PrincipalProviderImpl +### [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 @@ -31,17 +31,17 @@ The implementation is not tied to a part 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 +### [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. +extension (since Oak 1.3.4) allows for an optimized variant of the default +principal provider, which is reading principal information from user and group +accounts using generic user management API. _Note:_ every single user/group +exposes a `Principal` instance through the call `Authorizable.getPrincipal()` -This extension allows for a provider based implementation details of the user +This extension allows for a provider based on 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. +the principal lookup 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 @@ -51,7 +51,7 @@ Another benefit of this optimized implem 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 +### [CompositePrincipalProvider] This implementation is a simple wrapper implementation that combines different principals from different source providers. It is used in @@ -59,3 +59,33 @@ principals from different source provide collect all configured/plugged principal configurations i.e. the various implementations of principal management. +Custom `PrincipalProvider` implementations may be used to combine principals from +different source i.e. detaching principal management from the user management, +where principals are backed by an existing user/group account. + +### [ExternalGroupPrincipalProvider] + +Implementation of the `PrincipalProvider` interface that exposes _external_ principals +of type `java.security.acl.Group`. _External_ refers to the fact that these +principals are defined and managed by an external identity provider in contrast to +the default implementation that represents principals native to the repository. +This implies that the principals known and exposed by this provider implementation +does not expect principals to be backed by an authorizable group. As such they +can only be retrieved using Jackrabbit Principal Management API but not with +User Management calls. + +For performance reasons the `ExternalGroupPrincipalProvider` doesn't lookup +principals on the IDP but relies on a persisted cache inside the repository where +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) +for additional details. + +Since Oak 1.5.3 + +<!-- references --> +[PrincipalProviderImpl]: /oak/docs/apidocs/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.html +[CompositePrincipalProvider]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/principal/CompositePrincipalProvider.html +[UserPrincipalProvider]: /oak/docs/apidocs/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.html +[ExternalGroupPrincipalProvider]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/principal/ExternalGroupPrincipalProvider.html
Modified: jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user.md URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user.md?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user.md (original) +++ jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user.md Thu Aug 18 13:15:22 2016 @@ -18,16 +18,14 @@ User Management -------------------------------------------------------------------------------- -<a href="jcr_api"/> -### JCR API +### JCR User Management JCR itself doesn't come with a dedicated user management API. The only method related and ultimately used for user management tasks is `Session.getUserID()`. Therefore an API for user and group management has been defined as part of the extensions present with Jackrabbit API. -<a name="jackrabbit_api"/> -### Jackrabbit API +### Jackrabbit User Management API The Jackrabbit API provides the user management related extensions that are missing in JCR. The relevant interfaces are defined in the @@ -41,26 +39,225 @@ missing in JCR. The relevant interfaces - `QueryBuilder` - `Query` -<a name="api_extensions"/> -### API Extensions +### Oak User Management Implementation + +The default user management implementation stores user/group information in the +content repository. In contrast to Jackrabbit 2.x, which by default used a single, +dedicated workspace for user/group data, this data will as of Oak 1.0 be stored +separately for each JCR workspace. + +Consequently the `UserManager` associated with the editing sessions, performs +all actions with this editing session. This corresponds to the behavior as defined +the alternative implementation present with Jackrabbit 2.x ((see Jackrabbit 2.x `UserPerWorkspaceUserManager`). + +#### General +* The Oak implementation is build on the Oak API. This allows for double usage as + extension to the JCR API as well as within the Oak layer (aka SPI). +* The `UserManager` is always associated with the same JCR workspace as the editing + `Session` from which the class has been obtained. +* Changes made to the user management API are always transient and require `Session#save()` to be persisted. +* In case of any failure during user management related write operations the API + consumer is in charge of specifically revert pending or invalid transient modifications + or calling `Session#refresh(false)`. + +#### Differences wrt Jackrabbit 2.x + +A summary of all changes with respect to the former implementation present with +Jackrabbit 2.x is present in the corresponding [section](user/differences.html). + +#### Built-in Users and Special Groups + +The setup of builtin user and group accounts is triggered by the configured `WorkspaceInitializer` +associated with the user management configuration (see Configuration section below). + +The default user management implementation in OAK comes with an initializer that +creates the following builtin user accounts: + +##### Administrator +The admin user is always being created. The ID of this user is retrieved from the +user configuration parameter `PARAM_ADMIN_ID`, which defaults to `admin`. + +As of OAK 1.0 however the administrator user might be created without initial +password forcing the application to set the password upon start (see `PARAM_OMIT_ADMIN_PW` +configuration parameter). + +##### Anonymous User +In contrast to Jackrabbit 2.x the anonymous (or guest) user is optional. Creation +will be skipped if the value of the `PARAM_ANONYMOUS_ID` configuration parameter +is `null` or empty. + +Note, that the anonymous user will always be created without specifying a password +in order to prevent regular login with `SimpleCredentials`. +The proper way to obtain a guest session is: + + Repository#login(new GuestCredentials(), wspName); + +See section [Authentication](authentication.html) for further information about +guest login. + +##### Everyone Group + +The default user management implementation in Oak contains special handling for +the optional group that represents _everyone_, which is marked by the reserved +name [everyone] and corresponds to the `EveryonePrincipal`. + +This special group always contains all Authorizable as member and cannot be edited +with user management API. As of OAK this fact is consistently reflected in all +group membership related methods. See also [Principal Management](principal.html). + +#### Reading Authorizables + +##### Handling of the Authorizable ID +* As of Oak the node type definition of `rep:Authorizable` defines a new property `rep:authorizableId` which is intended to store the ID of a user or group. +* The default implementation comes with a dedicated property index for `rep:authorizableId` which asserts the uniqueness of that ID. +* `Authorizable#getID` returns the string value contained in `rep:authorizableID` and for backwards compatibility falls back on the node name in case the ID property is missing. +* The name of the authorizable node is generated based on a configurable implementation of the `AuthorizableNodeName` interface (see configuration section below). By default it uses the ID as name hint and includes a conversion to a valid JCR node name. + +##### equals() and hashCode() +The implementation of `Object#equals()` and `Object#hashCode()` for user and +groups slightly differs from Jackrabbit 2.x. It no longer relies on the _sameness_ +of the underlaying JCR node but only compares IDs and the user manager instance. + +#### Creating Authorizables +* The `rep:password` property is no longer defined to be mandatory. Therefore a new user might be created without specifying a password. Note however, that `User#changePassword` does not allow to remove the password property. +* `UserManager#createGroup(Principal)` will no longer generate a groupID in case the principal name collides with an existing user or group ID. This has been considered redundant as the Jackrabbit API in the mean time added `UserManager#createGroup(String groupID)`. +* Since OAK is designed to scale with flat hierarchies the former configuration options `autoExpandTree` and `autoExpandSize` are no longer supported. + +#### Query + +See section [Searching Users and Groups](user/query.html) for details. + +#### Group Membership + +See section [Group Membership](user/membership.html) for details. + +#### Autosave Behavior +Due to the nature of the UserManager (see above) we decided to drop the auto-save +behavior in the default implementation present with OAK. Consequently, + +* `UserManager#autoSave(boolean)` throws `UnsupportedRepositoryOperationException` +* `UserManager#isAutoSave()` always returns `false` + +See also `PARAM_SUPPORT_AUTOSAVE` below; while this should not be needed if +application code has been written against the Jackrabbit API (and thus testing if +auto-save mode is enabled or not) this configuration option can be used as last resort. + + +#### User/Group Representation in the Repository +The following block lists the built-in node types related to user management tasks: + + [rep:Authorizable] > mix:referenceable, nt:hierarchyNode + abstract + + * (nt:base) = nt:unstructured VERSION + - rep:principalName (STRING) protected mandatory + - rep:authorizableId (STRING) protected /* @since oak 1.0 */ + - * (UNDEFINED) + - * (UNDEFINED) multiple + + [rep:Group] > rep:Authorizable, rep:MemberReferences + + rep:members (rep:Members) = rep:Members multiple protected VERSION /* @deprecated */ + + rep:membersList (rep:MemberReferencesList) = rep:MemberReferencesList protected COPY + + /** @since oak 1.0 */ + [rep:MemberReferences] + - rep:members (WEAKREFERENCE) protected multiple < 'rep:Authorizable' + + /** @since oak 1.0 */ + [rep:MemberReferencesList] + + * (rep:MemberReferences) = rep:MemberReferences protected COPY + + /** @deprecated since oak 1.0 */ + [rep:Members] + orderable + + * (rep:Members) = rep:Members protected multiple + - * (WEAKREFERENCE) protected < 'rep:Authorizable' + +<a name="validation"/> +##### Validation + +The consistency of this content structure is asserted by a dedicated `UserValidator`. +The corresponding errors are all of type `Constraint` with the following codes: + +| Code | Message | +|-------------------|----------------------------------------------------------| +| 0020 | Admin user cannot be disabled | +| 0021 | Invalid jcr:uuid for authorizable (creation) | +| 0022 | Changing Id, principal name after creation | +| 0023 | Invalid jcr:uuid for authorizable (mod) | +| 0024 | Password may not be plain text | +| 0025 | Attempt to remove id, principalname or pw | +| 0026 | Mandatory property rep:principalName missing | +| 0027 | The admin user cannot be removed | +| 0028 | Attempt to create outside of configured scope | +| 0029 | Intermediate folders not rep:AuthorizableFolder | +| 0030 | Missing uuid for group (check for cyclic membership) | +| 0031 | Cyclic group membership | +| 0032 | Attempt to set password with system user | +| 0033 | Attempt to add rep:pwd node to a system user | + + +#### XML Import +As of Oak 1.0 user and group nodes can be imported both with Session and Workspace +import. Other differences compared to Jackrabbit 2.x: + +* Importing an authorizable to another tree than the configured user/group node will only failed upon save (-> see `UserValidator` during the `Root#commit`). With Jackrabbit 2.x core it used to fail immediately. +* The `BestEffort` behavior is now also implemented for the import of impersonators (was missing in Jackrabbit /2.x). + +### API Extensions The Oak project introduces the following user management related public interfaces and classes: -- `AuthorizableType`: ease handling with the different authorizable types. -- `AuthorizableAction` and `AuthorizableActionProvider`: see [Authorizable Actions](user/authorizableaction.html) for details. -- `AuthorizableNodeName`: see section [Authorizable Node Name Generation](user/authorizablenodename.html). -- `GroupAction` (via `AuthorizableActionProvider`): see [Group Actions](user/groupaction.html) for details. -- `UserAuthenticationFactory`: see sections [pluggability](user/default.html#pluggability) -and [user authentication](authentication/default.html#user_authentication) for additional details. +#### Authorizable Actions + +The former internal Jackrabbit interface `AuthorizableAction` has been slightly +adjusted to match Oak requirements and is now part of the public Oak SPI interfaces. +In contrast to Jackrabbit-core the AuthorizableAction(s) now operate directly on +the Oak API, which eases the handling of implementation specific tasks such as +writing protected items. + +See section [Authorizable Actions](user/authorizableaction.html) for further +details and examples. + +#### Node Name Generation -<a href="utilities"/> -### Utilities +The default user management implementation with Oak 1.0 allows to specify how +the name of a new authorizable node is being generated. + +See section [Authorizable Node Name](user/authorizablenodename.html) for further +details and examples. + +#### Password Expiry and Force Initial Password Change + +Since Oak 1.1.0 the default user management and authentication implementation +provides password expiry and initial password change. + +By default these features are disabled. The corresponding configuration options +are + +- `PARAM_PASSWORD_MAX_AGE`: number of days until the password expires. +- `PARAM_PASSWORD_INITIAL_CHANGE`: boolean flag to enable this feature. + +See section [Password Expiry and Force Initial Password Change](user/expiry.html) +for details. + +#### Password History + +Since Oak 1.3.3 the default user management implementation provides password +history support. + +By default this feature is disabled. The corresponding configuration option is + +- `PARAM_PASSWORD_HISTORY_SIZE`: number of changed passwords to remember. + +See section [Password History](user/history.html) for details. + +#### Utilities `org.apache.jackrabbit.oak.spi.security.user.*` +- `AuthorizableType` : Ease handling with the different authorizable types. - `UserConstants` : Constants (NOTE: OAK names/paths) -- `UserIdCredentials` : Simple credentials implementation that might be used for `User.getCredentials' without exposing pw information. `org.apache.jackrabbit.oak.spi.security.user.util.*` @@ -70,53 +267,82 @@ and [user authentication](authentication function for password generation. - `UserUtil` : Utilities related to general user management tasks. -<a href="default_implementation"/> -### Oak User Management Implementation - -The behavior of the default user management implementation is described in section -[User Management: The Default Implementation](user/default.html). -<a name="configuration"/> ### Configuration -The Oak user management comes with a dedicated entry point called [UserConfiguration]. -This class is responsible for passing configuration options to the implementation -and provides the following two methods: +The following user management specific methods are present with the [UserConfiguration] +as of OAK 1.0: -- `getUserManager(Root, NamePathMapper)`: get a new `UserManager` instance -- `getUserPrincipalProvider(Root, NamePathMapper)`: optional method that allows for optimized principal look-up from user/group accounts (since Oak 1.3.4). +* getUserManager: Obtain a new user manager instance -#### Configuration Parameters +#### Configuration Parameters supported by the default implementation -The supported configuration options of the default implementation are described in the corresponding [section](user/default.html#configuration). +| Parameter | Type | Default | +|-------------------------------------|---------|----------------------------------------------| +| `PARAM_ADMIN_ID` | String | "admin" | +| `PARAM_OMIT_ADMIN_PW` | boolean | false | +| `PARAM_ANONYMOUS_ID` | String | "anonymous" (nullable) | +| `PARAM_USER_PATH` | String | "/rep:security/rep:authorizables/rep:users" | +| `PARAM_GROUP_PATH` | String | "/rep:security/rep:authorizables/rep:groups" | +| `PARAM_DEFAULT_DEPTH` | int | 2 | +| `PARAM_PASSWORD_HASH_ALGORITHM` | String | "SHA-256" | +| `PARAM_PASSWORD_HASH_ITERATIONS` | int | 1000 | +| `PARAM_PASSWORD_SALT_SIZE` | int | 8 | +| `PARAM_AUTHORIZABLE_NODE_NAME` | AuthorizableNodeName | AuthorizableNodeName#DEFAULT | +| `PARAM_AUTHORIZABLE_ACTION_PROVIDER`| AuthorizableActionProvider | DefaultAuthorizableActionProvider | +| `PARAM_SUPPORT_AUTOSAVE` | boolean | false | +| `PARAM_IMPORT_BEHAVIOR` | String ("abort", "ignore", "besteffort") | "ignore" | +| `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` + +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`. -<a name="pluggability"/> ### Pluggability -The default security setup as present with Oak 1.0 is able to have the default -user management implementation replaced as follows: +The default security setup as present with Oak 1.0 is able to provide custom +implementation on various levels: -The complete user management implementation can be changed by plugging a different -`UserConfiguration` implementations. In OSGi-base setup this is achieved by making -the configuration a service which must take precedence over the default. -In a non-OSGi-base setup the custom configuration must be exposed by the -`SecurityProvider` implementation. - -Alternatively the default user management implementation can be extended and -adjusted using various means. See the corresponding [section](user/default.html#pluggability) -for further details. +1. The complete user management implementation can be changed by plugging a different + `UserConfiguration` implementations. In OSGi-base setup this is achieved by making + the configuration a service. In a non-OSGi-base setup the custom configuration + must be exposed by the `SecurityProvider` implementation. +2. Within the default user management implementation the following parts can be + change/extended at runtime by providing corresponding OSGi services or passing + appropriate configuration parameters exposing the custom implementations: + - `AuthorizableActionProvider`: Defines the authorizable actions, see [Authorizable Actions](user/authorizableaction.html). + - `AuthorizableNodeName`: Defines the generation of the authorizable node names + in case the user management implementation stores user information in the repository. + See [Authorizable Node Name Generation](user/authorizablenodename.html). -<a name="further_reading"/> ### Further Reading - [Differences wrt Jackrabbit 2.x](user/differences.html) -- [User Management : The Default Implementation](user/default.html) - - [Group Membership](user/membership.html) - - [Authorizable Actions](user/authorizableaction.html) - - [Authorizable Node Name](user/authorizablenodename.html) - - [Password Expiry and Force Initial Password Change](user/expiry.html) - - [Password History](user/history.html) +- [Group Membership](user/membership.html) +- [Authorizable Actions](user/authorizableaction.html) +- [Authorizable Node Name](user/authorizablenodename.html) - [Searching Users and Groups](user/query.html) +- [Password Expiry and Force Initial Password Change](user/expiry.html) +- [Password History](user/history.html) <!-- hidden references --> +[everyone]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/principal/EveryonePrincipal.html#NAME [UserConfiguration]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/user/UserConfiguration.html +[OAK-118]: https://issues.apache.org/jira/browse/OAK-118 +[OAK-482]: https://issues.apache.org/jira/browse/OAK-482 +[OAK-793]: https://issues.apache.org/jira/browse/OAK-793 +[OAK-949]: https://issues.apache.org/jira/browse/OAK-949 +[OAK-1183]: https://issues.apache.org/jira/browse/OAK-1183 + Modified: jackrabbit/oak/branches/1.2/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java (original) +++ jackrabbit/oak/branches/1.2/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/xml/ImporterImpl.java Thu Aug 18 13:15:22 2016 @@ -469,7 +469,9 @@ public class ImporterImpl implements Imp // process properties importProperties(tree, propInfos, false); - parents.push(tree); + if (tree.exists()) { + parents.push(tree); + } } Modified: jackrabbit/oak/branches/1.2/oak-parent/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-parent/pom.xml?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-parent/pom.xml (original) +++ jackrabbit/oak/branches/1.2/oak-parent/pom.xml Thu Aug 18 13:15:22 2016 @@ -433,7 +433,7 @@ <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.testing.osgi-mock</artifactId> - <version>1.2.0</version> + <version>1.3.0</version> <scope>test</scope> <exclusions> <!-- Need to exclude it due to SLING-4470 --> Modified: jackrabbit/oak/branches/1.2/oak-run/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/pom.xml?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/pom.xml (original) +++ jackrabbit/oak/branches/1.2/oak-run/pom.xml Thu Aug 18 13:15:22 2016 @@ -277,6 +277,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> Modified: jackrabbit/oak/branches/1.2/oak-run/run_concurrent_login.sh URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/run_concurrent_login.sh?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/run_concurrent_login.sh (original) +++ jackrabbit/oak/branches/1.2/oak-run/run_concurrent_login.sh Thu Aug 18 13:15:22 2016 @@ -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/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java (original) +++ jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java Thu Aug 18 13:15:22 2016 @@ -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; @@ -55,20 +52,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 @@ -103,15 +107,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); oak.with(sp); return new Jcr(oak); } Modified: jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java (original) +++ jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractTest.java Thu Aug 18 13:15:22 2016 @@ -39,7 +39,7 @@ import org.apache.jackrabbit.oak.fixture /** * 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.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java (original) +++ jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java Thu Aug 18 13:15:22 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.OakRepositoryFixture; @@ -90,10 +93,14 @@ 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.") .withOptionalArg().ofType(Boolean.class).defaultsTo(false); + OptionSpec<Integer> batchSize = parser.accepts("batchSize", "Batch size before persisting operations.") + .withOptionalArg().ofType(Integer.class).defaultsTo(1); OptionSpec<Integer> itemsToRead = parser.accepts("itemsToRead", "Number of items to read") .withRequiredArg().ofType(Integer.class).defaultsTo(1000); OptionSpec<Integer> concurrency = parser.accepts("concurrency", "Number of test threads.") @@ -172,11 +179,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(), @@ -287,7 +296,12 @@ public class BenchmarkRunner { wikipedia.value(options), flatStructure.value(options), report.value(options), withStorage.value(options), withServer.value(options)), - new FindAuthorizableWithScopeTest(numberOfUsers.value(options), setScope.value(options)) + new FindAuthorizableWithScopeTest(numberOfUsers.value(options), setScope.value(options)), + + // benchmarks for oak-auth-external + new ExternalLoginTest(numberOfUsers.value(options), numberOfGroups.value(options), expiration.value(options), false), + new SyncAllExternalUsersTest(numberOfUsers.value(options), numberOfGroups.value(options), expiration.value(options), false), + new SyncExternalUsersTest(numberOfUsers.value(options), numberOfGroups.value(options), expiration.value(options), false, batchSize.value(options)) }; Set<String> argset = Sets.newHashSet(nonOption.values(options)); Modified: jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java (original) +++ jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembersTest.java Thu Aug 18 13:15:22 2016 @@ -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/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java?rev=1756777&r1=1756776&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java (original) +++ jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/LoginWithMembershipTest.java Thu Aug 18 13:15:22 2016 @@ -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; Modified: jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java?rev=1756777&r1=1743674&r2=1756777&view=diff ============================================================================== --- jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java (original) +++ jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/AbstractExternalTest.java Thu Aug 18 13:15:22 2016 @@ -55,9 +55,14 @@ import org.apache.jackrabbit.oak.spi.sec 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.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.user.UserConstants; import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; +import static com.google.common.base.Preconditions.checkNotNull; + /** * Base benchmark test for external authentication. * @@ -88,9 +93,12 @@ abstract class AbstractExternalTest exte 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); + syncConfig.user() + .setMembershipNestingDepth(1) + .setDynamicMembership(dynamicMembership) + .setExpirationTime(expTime).setPathPrefix(PATH_PREFIX); + syncConfig.group() + .setExpirationTime(expTime).setPathPrefix(PATH_PREFIX); } protected abstract Configuration createConfiguration(); @@ -158,15 +166,14 @@ 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((new ExternalPrincipalConfiguration(this))); + bindPrincipalConfiguration(defConfig); + } } } @@ -219,7 +226,7 @@ abstract class AbstractExternalTest exte @Nonnull @Override public Iterator<ExternalUser> listUsers() { - Set<ExternalUser> all = new HashSet<>(); + Set<ExternalUser> all = new HashSet<ExternalUser>(); for (long i = 0; i < numberofUsers; i++) { all.add(new TestUser(i)); } @@ -229,7 +236,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 +245,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())); }