Author: angela
Date: Wed Oct 28 16:37:04 2020
New Revision: 1882944
URL: http://svn.apache.org/viewvc?rev=1882944&view=rev
Log:
OAK-9051 : Enhance oak-exercise for Principal base authorization
Added:
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased_evaluation.md
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/AbstractPrincipalBasedTest.java
(with props)
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L1_IntroductionTest.java
(with props)
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L2_AccessControlManagementTest.java
(with props)
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L3_PermissionEvaluationTest.java
(with props)
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L4_DisabledAggregationFilterTest.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased.md
jackrabbit/oak/trunk/oak-exercise/pom.xml
Modified:
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased.md
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased.md?rev=1882944&r1=1882943&r2=1882944&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased.md
(original)
+++
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased.md
Wed Oct 28 16:37:04 2020
@@ -163,8 +163,8 @@ looking up effective policies by princip
If a given set of principals is supported by the configured
`FilterProvider/Filter` implementation, the principal-based
authorization model will contribute an implementation of
`AggregatedPermissionProvider` to the composite. Whether or not
-access will be granted depends on the aggregated providers and their ranking,
the composition type and whether or not an
-`AggregationFilter` is defined for the setup (see also section [Combining
Multiple Authorization Models](composite.html) for details).
+access will be granted depends on the aggregated providers and their ranking,
the composition type and the presence of an
+`AggregationFilter` (see also section [Combining Multiple Authorization
Models](composite.html) for details).
If the set of principals is not supported an `EmptyPermissionProvider` will be
returned and the model will be ignored
altogether. It follows that in this case permission evaluation delegated to
other authorization modules configured in the
@@ -192,7 +192,7 @@ The inheritance model only takes the ite
start at the target item and search up the item hierarchy for a matching
entry. An entry is considered matching if it is
defined for any of the principals in the given set, applies to the target item
and grants the specified permissions.
-##### Allowed if Granted
+##### Evaluation Shortcut
As soon as an entry matches the target item and grants the requested
permission the evaluation will stop. As this
model only supports allowing entries there exists no particular requirement to
maintain and handle the order of
@@ -230,7 +230,7 @@ limit the scope of the principal-based a
- the set of principals must not be empty and must only contain
`SystemUserPrincipal`s
- each `SystemUserPrincipal` must be associated with a location in the
repository (i.e. must be `ItemBasedPrincipal` when
obtained through principal management API).
-- all principals must additionally be located below the path configured with
`FilterProviderImpl` (see [below](#configuration)
+- all principals must additionally be located below the path configured with
`FilterProviderImpl` (see section [Configuration](#configuration))
So, if this implementation is enabled the principal-based authorization will
only take effect for `SystemUserPrincipal`s
that are created below the configured path. As soon as a given `Subject` or
set of principals contains principals that
@@ -246,6 +246,12 @@ interface that stops the aggregation of
`PrincipalBasedPermissionProvider` takes effect (i.e. the mandatory
`FilterProvider` will handle a given set of principals).
The `AggregationFilter` can be enabled by setting the corresponding flag with
the module [configuration](#configuration).
+<a name="details_examples"></a>
+#### Examples
+
+See [Permission Evaluation with Principal-Based
Authorization](principalbased_evaluation.html) for examples illustrating
+an authorization setup including principal-based authorization and how it
handles different principals.
+
<a name="representation"></a>
### Representation in the Repository
Added:
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased_evaluation.md
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased_evaluation.md?rev=1882944&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased_evaluation.md
(added)
+++
jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/authorization/principalbased_evaluation.md
Wed Oct 28 16:37:04 2020
@@ -0,0 +1,137 @@
+<!--
+ 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.
+-->
+
+Permission Evaluation with Principal-Based Authorization
+--------------------------------------------------------------------------------
+
+The examples below describe permission evaluation based on an authorization
setup with the following characteristices:
+
+ FilterProviderImpl:
+ - Path: "/home/users/system/supported"
+
+ CompositeAuthorizationConfiguration (CompositionType=AND):
+
+ PrincipalBasedAuthorizationConfiguration
+ - FilterProvider: reference to FilterProviderImpl as configured above
(default implementation)
+ - Enable AggregationFilter: true
+ - Ranking: 500
+
+ AuthorizationConfigurationImpl
+ - Ranking: 100
+
+The following principals will be used in various combinations:
+
+ Principals not supported by the configured 'FilterProvider'
+
+ - GroupPrincipal: 'testgroup'
+ - Principal: 'user'
+ - SystemUserPrincipal: 'service-A' with path /home/users/system/45
+
+ Principals supporeted by the configured 'FilterProvider'
+
+ - SystemUserPrincipal: 'service-B' with path
/home/users/system/supported/featureB/11
+ - SystemUserPrincipal: 'service-C' with path
/home/users/system/supported/featureC/C1
+
+The following access control setup has been defined:
+
+ grant access using regular path-based ac-management calls
+ i.e. 'AccessControlManager.getApplicablePolicies(String)' or
'AccessControlManager.getPolicies(String))'
+
+ - 'testgroup': /content [jcr:read, jcr:readAccessControl]
+ - 'service-A': /content [jcr:versionManagement]
+ - 'service-B': /content [jcr:read, jcr:modifyProperties]
+
+ grant access using principal-based ac-management calls (only possible for
supported principals)
+ i.e. 'JackrabbitAccessControlManager.getApplicablePolicies(Principal)' or
'AccessControlManager.getPolicies(Principal))'
+
+ - 'service-B': /content [jcr:read, jcr:nodeTypeManagement]
+ - 'service-C': /content [jcr:read, jcr:lockManagement]
+
+##### Example 1: Subject with principals _'user'_, _'testgroup'_
+Since neither 'user' nor 'testgroup' is a system-user-princial supported by
principal-based authorization,
+principal-based permission evaluation is omitted.
+
+Result: the Session is granted `jcr:read`, `jcr:readAccessControl` at /content.
+
+##### Example 2: Subject with principals _'service-A'_, _'testgroup'_
+Since neither 'service-A' nor 'testgroup' is supported by principal-based
authorization,
+principal-based permission evaluation is omitted.
+
+Result: the Session is granted `jcr:read`, `jcr:readAccessControl`,
`jcr:versionManagement` at /content.
+
+##### Example 3: Subject with principals _'service-B'_, _'testgroup'_
+Since 'testgroup' is not supported by principal-based authorization,
principal-based permission evaluation is omitted
+and only path-based access control setup take effect.
+
+Result: the Session is granted
`jcr:read`,`jcr:readAccessControl`,`jcr:modifyProperties` at /content.
+
+##### Example 4: Subject with principals _'service-A'_, _'service-B'_
+Since 'service-A' is not supported by principal-based authorization,
principal-based permission evaluation is omitted
+and only path-based access control setup take effect.
+
+Result: the Session is granted
`jcr:read`,`jcr:modifyProperties`,`jcr:versionManagement` at /content.
+
+##### Example 5: Subject with principals _'service-B'_
+'service-B' is supported by principal-based authorization and no unsupported
principal is present in the Subject.
+Therefore, principal-based permission evaluation takes effect. Since the
`AggregationFilter` is enabled in the configuration
+describedf above, permission evaluation stops and does not continue evaluating
path-based permissions.
+
+Result: the Session is granted `jcr:read`, `jcr:nodeTypeManagement` at
/content.
+
+NOTE:
+If `AggregationFilter` was disabled _both_ permission providers would be used
for the evaluation.
+The result then depends on the `CompositionType`:
+
+| `AggregationFilter` | `CompositionType.AND` | `CompositionType.OR` |
+|---------------------|-----------------------|----------------------|
+| enabled | `jcr:read`, `jcr:nodeTypeManagement` | `jcr:read`,
`jcr:nodeTypeManagement` |
+| disabled | `jcr:read` | `jcr:read`,
`jcr:modifyProperties`, `jcr:nodeTypeManagement` |
+
+##### Example 6: Subject with principals _'service-C'_
+'service-C' is supported by principal-based authorization and no unsupported
principal is present in the Subject.
+Therefore, principal-based permission evaluation takes effect. Since the
`AggregationFilter` is enabled in the configuration
+described above, permission evaluation stops and does not continue evaluating
path-based permissions.
+
+Result: the Session is granted `jcr:read`, `jcr:lockManagement` at /content.
+
+NOTE:
+If `AggregationFilter` was disabled _both_ permission providers would be used
for the evaluation.
+The result then depends on the `CompositionType`:
+
+| `AggregationFilter` | `CompositionType.AND` | `CompositionType.OR` |
+|---------------------|-----------------------|----------------------|
+| enabled | `jcr:read`, `jcr:lockManagement` | `jcr:read`,
`jcr:lockManagement` |
+| disabled | - | `jcr:read`, `jcr:lockManagement` |
+
+##### Example 6: Subject with principals _'service-B'_, _'service-C'_
+Both 'service-B' is supported by principal-based authorization and no
unsupported principal is present in the Subject.
+Therefore, principal-based permission evaluation takes effect. Since the
`AggregationFilter` is enabled in the configuration
+described above, permission evaluation stops and does not continue evaluating
path-based permissions.
+
+Result: the Session is granted `jcr:read`, `jcr:nodeTypeManagement`,
`jcr:lockManagement` at /content.
+
+NOTE:
+If `AggregationFilter` was disabled _both_ permission providers would be used
for the evaluation.
+The result then depends on the `CompositionType`:
+
+| `AggregationFilter` | `CompositionType.AND` | `CompositionType.OR` |
+|---------------------|-----------------------|----------------------|
+| enabled | `jcr:read`, `jcr:nodeTypeManagement`,
`jcr:lockManagement` | `jcr:read`, `jcr:nodeTypeManagement`,
`jcr:lockManagement` |
+| disabled | `jcr:read` | `jcr:read`,
`jcr:modifyProperties`, `jcr:nodeTypeManagement`, `jcr:lockManagement` |
+
+
+
Modified: jackrabbit/oak/trunk/oak-exercise/pom.xml
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/pom.xml?rev=1882944&r1=1882943&r2=1882944&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-exercise/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-exercise/pom.xml Wed Oct 28 16:37:04 2020
@@ -121,6 +121,11 @@
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-authorization-principalbased</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-commons</artifactId>
<version>${jackrabbit.version}</version>
</dependency>
@@ -205,9 +210,20 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-store-composite</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.testing.osgi-mock</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Added:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/AbstractPrincipalBasedTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/AbstractPrincipalBasedTest.java?rev=1882944&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/AbstractPrincipalBasedTest.java
(added)
+++
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/AbstractPrincipalBasedTest.java
Wed Oct 28 16:37:04 2020
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package
org.apache.jackrabbit.oak.exercise.security.authorization.principalbased;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
+import
org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.composite.MountInfoProviderService;
+import
org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.security.internal.SecurityProviderHelper;
+import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregationFilter;
+import
org.apache.jackrabbit.oak.spi.security.authorization.principalbased.FilterProvider;
+import
org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.FilterProviderImpl;
+import
org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.PrincipalBasedAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Rule;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+abstract class AbstractPrincipalBasedTest extends AbstractSecurityTest {
+
+ @Rule
+ public final OsgiContext context = new OsgiContext();
+
+ private Group gr;
+ private final Map<String, User> systemUsers = new HashMap<>();
+
+ private final PrincipalBasedAuthorizationConfiguration
principalBasedAuthorizationConfiguration = new
PrincipalBasedAuthorizationConfiguration();
+
+ @Override
+ public void after() throws Exception {
+ try {
+ if (gr != null) {
+ gr.remove();
+ }
+ for (User u : systemUsers.values()) {
+ u.remove();
+ }
+ root.commit();
+ } finally {
+ super.after();
+ }
+ }
+
+ @Override
+ protected SecurityProvider initSecurityProvider() {
+ // principal-based authorization is designed for osgi-setup.
+ // injecting the configuration into the security provider needs a some
workarounds....
+ FilterProvider filterProvider = getFilterProvider();
+ context.registerInjectActivateService(filterProvider,
Collections.singletonMap("path", getSupportedPath()));
+ context.registerInjectActivateService(new MountInfoProviderService());
+ ConfigurationParameters params =
ConfigurationParameters.of(CompositeConfiguration.PARAM_RANKING, 500,
"enableAggregationFilter", enableAggregationFilter());
+
context.registerInjectActivateService(principalBasedAuthorizationConfiguration,
params);
+
+ SecurityProvider sp = super.initSecurityProvider();
+ SecurityProviderHelper.updateConfig(sp,
principalBasedAuthorizationConfiguration, AuthorizationConfiguration.class);
+ if (enableAggregationFilter()) {
+ AggregationFilter aggregationFilter =
context.getService(AggregationFilter.class);
+ ((CompositeAuthorizationConfiguration)
sp.getConfiguration(AuthorizationConfiguration.class)).withAggregationFilter(aggregationFilter);
+ }
+ return sp;
+ }
+
+ @NotNull
+ @Override
+ protected ConfigurationParameters getSecurityConfigParameters() {
+ return ConfigurationParameters.of("authorizationCompositionType",
getCompositionType().toString());
+ }
+
+ @NotNull
+ CompositeAuthorizationConfiguration.CompositionType getCompositionType() {
+ return CompositeAuthorizationConfiguration.CompositionType.AND;
+ }
+
+ @NotNull
+ FilterProvider getFilterProvider() {
+ return new FilterProviderImpl();
+ }
+
+ boolean enableAggregationFilter() {
+ return true;
+ }
+
+ @NotNull
+ String getSupportedPath() {
+ return PathUtils.concat(UserConstants.DEFAULT_USER_PATH,
getSupportedIntermediatePath());
+ }
+
+ @NotNull
+ String getSupportedIntermediatePath() {
+ return
PathUtils.concatRelativePaths(UserConstants.DEFAULT_SYSTEM_RELATIVE_PATH,
"supported");
+ }
+
+ @NotNull
+ Principal getRegularUserPrincipal() throws Exception {
+ return getTestUser().getPrincipal();
+ }
+
+ @NotNull
+ Principal getGroupPrincipal() throws Exception {
+ if (gr == null) {
+ gr = getUserManager(root).createGroup("groupId");
+ root.commit();
+ }
+ return gr.getPrincipal();
+ }
+
+ @NotNull
+ Principal getSystemUserPrincipal(@NotNull String name, @Nullable String
intermediatePath) throws Exception {
+ User su;
+ if (systemUsers.containsKey(name)) {
+ su = systemUsers.get(name);
+ } else {
+ su = getUserManager(root).createSystemUser(name, intermediatePath);
+ root.commit();
+ systemUsers.put(name, su);
+ }
+ return su.getPrincipal();
+ }
+
+ @NotNull
+ PrincipalBasedAuthorizationConfiguration
getPrincipalBasedAuthorizationConfiguration() {
+ return principalBasedAuthorizationConfiguration;
+ }
+
+ @Nullable
+ static PrincipalAccessControlList
getApplicablePrincipalAccessControlList(@NotNull JackrabbitAccessControlManager
acMgr, @NotNull Principal principal) throws Exception {
+ Set<JackrabbitAccessControlPolicy> applicable =
ImmutableSet.copyOf(acMgr.getApplicablePolicies(principal));
+ PrincipalAccessControlList acl = (PrincipalAccessControlList)
Iterables.find(applicable, accessControlPolicy -> accessControlPolicy
instanceof PrincipalAccessControlList, null);
+ return acl;
+ }
+
+ @NotNull
+ ContentSession getTestSession(@NotNull Principal... principals) throws
Exception {
+ Subject subject = new Subject(true, ImmutableSet.copyOf(principals),
ImmutableSet.of(), ImmutableSet.of());
+ return Subject.doAsPrivileged(subject,
(PrivilegedExceptionAction<ContentSession>) () ->
getContentRepository().login(null, null), null);
+ }
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/AbstractPrincipalBasedTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L1_IntroductionTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L1_IntroductionTest.java?rev=1882944&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L1_IntroductionTest.java
(added)
+++
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L1_IntroductionTest.java
Wed Oct 28 16:37:04 2020
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package
org.apache.jackrabbit.oak.exercise.security.authorization.principalbased;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import
org.apache.jackrabbit.oak.security.authorization.AuthorizationConfigurationImpl;
+import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.EmptyPermissionProvider;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import
org.apache.jackrabbit.oak.spi.security.authorization.principalbased.Filter;
+import
org.apache.jackrabbit.oak.spi.security.authorization.principalbased.FilterProvider;
+import
org.apache.jackrabbit.oak.spi.security.authorization.principalbased.impl.PrincipalBasedAuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.junit.Test;
+
+import javax.jcr.security.AccessControlManager;
+import java.security.Principal;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * <pre>
+ * Module: Principal-Based Authorization
+ *
=============================================================================
+ *
+ * Title: Introduction to Principal-Based Authorization
+ *
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Recap extensions to JCR access control management defined by Jackrabbit API
and get a basic understanding of
+ * the additional authorization model 'oak-authorization-principalbased'.
+ *
+ * Exercises:
+ *
+ * - Recap extensions to JCR access control management API defined in
Jackrabbit API and compare getting/setting
+ * access control policies by path and by principal.
+ *
+ *
http://jackrabbit.apache.org/oak/docs/apidocs/org/apache/jackrabbit/api/security/JackrabbitAccessControlManager.html
+ *
http://jackrabbit.apache.org/oak/docs/security/accesscontrol.html#jackrabbit_api
+ *
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#jackrabbit_api
+ *
+ * Question: What does binding a policy to a node means in this context?
+ * Question: Where does a principal-based policy take effect? see also
+ *
https://docs.adobe.com/docs/en/spec/jcr/2.0/16_Access_Control_Management.html#16.3%20Access%20Control%20Policies
+ * Question: How does the PrincipalAccessControlList allow to specify where
a given entry takes effect and how
+ * restrictions could be used to achieve the same effect?
+ *
+ * - Repository setup with principal-based authorization:
+ * The subsequent exercises will use a default repository setup including
principal-based authorization. Get the basics
+ * of the security setup and the configuration options.
+ *
+ * - {@link #testAuthorizationConfiguration()}:
+ * Inspect the authorization configuration present with the exercise setup
and fix the test case.
+ * Discuss, why the order of the aggregated configurations matters. Can
you explain it?
+ *
+ * - Supported Principals
+ * The principal-based authorization module is designed to apply to a
limited set of supported principals:
+ *
+ *
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#api_extensions
+ *
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#details_filterprovider
+ *
+ * - {@link #testSupportedPrincipals()}
+ * Distribute the different principals to the 2 set of principals
(unsupported and supported) and verify that the test passes.
+ * Try out different combinations and explain, which principals are
supported and why.
+ *
+ * Question: what change in the setup would be needed, if you wished to
support other paths?
+ * Question: what change in the setup would be needed, if you wished to
support other types of principals?
+ *
+ * - Access Control Mangement and Permission Evaluation
+ * Before starting with the detailed tests let's take another look at the
impact of injecting the principal based
+ * authorization module into the Oak security setup:
+ *
+ * - {@link #testAccessControlManager()}: compare the access control manager
obtained from the principal-based
+ * authorization configuration with the manager obtained from the
complete security setup.
+ *
+ * Question: how are the different manager aggregated?
+ * Question: can you explain the order?
+ *
+ * Read
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#details_permission_eval
and
+ * complete the following 2 tests to get an idea how supported vs
unsupported principals impact the permission evaluation.
+ *
+ * - {@link #testPermissionProviderSupportedPrincipals()}: create a set of
supported principals to make sure
+ * the principal-based module contributes to the evaluation
+ * - {@link #testPermissionProviderUnsupportedPrincipals()}: create a
principal set that is not supported.
+ *
+ * Question: can you explain the usage of {@link EmptyPermissionProvider}
+ * Question: can you explain why the composite-PermissionProvider looks
different for supported vs unsupported principals?
+ *
+ * Related Exercises:
+ *
-----------------------------------------------------------------------------
+ *
+ * - {@link L2_AccessControlManagementTest}
+ * - {@link L3_PermissionEvaluationTest}
+ * - {@link L4_DisabledAggregationFilterTest}
+ *
+ * </pre>
+ */
+public class L1_IntroductionTest extends AbstractPrincipalBasedTest {
+
+ @Test
+ public void testAuthorizationConfiguration() {
+ AuthorizationConfiguration ac =
getConfig(AuthorizationConfiguration.class);
+ assertTrue(ac instanceof CompositeConfiguration);
+
+ CompositeConfiguration<AuthorizationConfiguration> composite =
(CompositeConfiguration<AuthorizationConfiguration>) ac;
+ assertEquals(2, composite.getConfigurations().size());
+
+ List<AuthorizationConfiguration> aggregates =
composite.getConfigurations();
+ // EXERCISE: retrieve the principal-based authorization from the
aggregated authorization configurations
+ AuthorizationConfiguration principalbased = aggregates.get(0);
+ assertTrue(principalbased instanceof
PrincipalBasedAuthorizationConfiguration);
+
+ // EXERCISE: retrieve the default authorization from the aggregated
authorization configurations
+ AuthorizationConfiguration defaultAc = aggregates.get(1);
+ assertTrue(defaultAc instanceof AuthorizationConfigurationImpl);
+ }
+
+ @Test
+ public void testSupportedPrincipals() throws Exception {
+ FilterProvider pf = getFilterProvider();
+ Filter filter = pf.getFilter(getSecurityProvider(), root,
getNamePathMapper());
+
+ // EXERCISE: use different combinations of the 6 principals to build 2
sets: one that is supported and one that is not supported by the filter
+ Principal regularUserPrincipal = getRegularUserPrincipal();
+ Principal groupPrincipal = getGroupPrincipal();
+ Principal systemUser1 = getSystemUserPrincipal("su1", null);
+ Principal systemUser2 = getSystemUserPrincipal("su2",
getSupportedIntermediatePath());
+ Principal systemUser3 = getSystemUserPrincipal("su3",
PathUtils.concatRelativePaths(UserConstants.DEFAULT_SYSTEM_RELATIVE_PATH,
"testpath"));
+ Principal systemUser4 = getSystemUserPrincipal("su4",
getSupportedIntermediatePath() + "/testpath");
+
+ Set<Principal> unsupported = ImmutableSet.of(/* EXERCISE*/);
+ Set<Principal> supported = ImmutableSet.of(/* EXERCISE*/);
+
+ assertFalse(filter.canHandle(unsupported));
+ assertTrue(filter.canHandle(supported));
+ }
+
+ @Test
+ public void testAccessControlManager() throws Exception {
+ AccessControlManager acMgr =
getPrincipalBasedAuthorizationConfiguration().getAccessControlManager(root,
getNamePathMapper());
+ assertTrue(acMgr instanceof JackrabbitAccessControlManager);
+ assertEquals("EXERCISE", acMgr.getClass().getName());
+
+ AccessControlManager compositeAcMgr =
getConfig(AuthorizationConfiguration.class).getAccessControlManager(root,
getNamePathMapper());
+ assertTrue(compositeAcMgr instanceof JackrabbitAccessControlManager);
+
+ // EXERCISE: inspect the 'compositeAcMgr'
+ }
+
+ @Test
+ public void testPermissionProviderSupportedPrincipals() throws Exception {
+ Set<Principal> principals = ImmutableSet.of(/* EXERCISE: fill set with
supported principal(s) */);
+
+ PermissionProvider pp =
getPrincipalBasedAuthorizationConfiguration().getPermissionProvider(root,
adminSession.getWorkspaceName(), principals);
+ assertFalse(pp instanceof EmptyPermissionProvider);
+
+ // EXERCISE: inspect the return value and explain it. add an assertion.
+ PermissionProvider compositePP =
getConfig(AuthorizationConfiguration.class).getPermissionProvider(root,
root.getContentSession().getWorkspaceName(), principals);
+ assertEquals("EXERCISE", compositePP.getClass().getName());
+ }
+
+ @Test
+ public void testPermissionProviderUnsupportedPrincipals() throws Exception
{
+ Set<Principal> principals = ImmutableSet.of(/* EXERCISE: fill set with
unsupported principal(s) */);
+
+ PermissionProvider pp =
getPrincipalBasedAuthorizationConfiguration().getPermissionProvider(root,
root.getContentSession().getWorkspaceName(), principals);
+ assertTrue(pp instanceof EmptyPermissionProvider);
+
+ // EXERCISE: inspect the return value and explain it. add an assertion.
+ PermissionProvider compositePP =
getConfig(AuthorizationConfiguration.class).getPermissionProvider(root,
root.getContentSession().getWorkspaceName(), principals);
+ assertEquals("EXERCISE", compositePP.getClass().getName());
+ }
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L1_IntroductionTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L2_AccessControlManagementTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L2_AccessControlManagementTest.java?rev=1882944&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L2_AccessControlManagementTest.java
(added)
+++
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L2_AccessControlManagementTest.java
Wed Oct 28 16:37:04 2020
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package
org.apache.jackrabbit.oak.exercise.security.authorization.principalbased;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import
org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
+import
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlPolicy;
+import java.security.Principal;
+import java.util.Iterator;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * <pre>
+ * Module: Principal-Based Authorization
+ *
=============================================================================
+ *
+ * Title: Access Control Management with Principal-Based Authorization
+ *
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Learn how to manage access control by principal and how to use it
combination with path-based access control
+ * management.
+ *
+ * Reading:
+ *
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#details_access_mgt
+ *
+ * Exercises:
+ *
+ * Applicable Access Control Policies
+ * Complete the following 3 tests to train your understanding of applicable
access control policies. Compare the
+ * policies obtained from the principal-based authorization module with the
actual repository setup.
+ *
+ * - {@link #testApplicablePoliciesSupportedPrincipal()}
+ * - {@link #testApplicablePoliciesUnsupportedPrincipal()}
+ * - {@link #testApplicablePoliciesByPath()}
+ *
+ * Questions: What are the main differences between the isolated
principal-based access control manager and the real-world composite setup?
+ * Can you explain the differences between accessing policies by
principal and by path?
+ *
+ * Editing Access Control
+ * The following tests focus on editing access control by principal. Complete
the tests such that they both pass.
+ * Notice, that the for the assertion of the effective permission setup, two
slightly different content sessions are
+ * created (one containing an unsupported principal).
+ *
+ * - {@link #testEditAccssControl()}
+ * - {@link #testEditAccssControl2()}
+ *
+ * Questions: Can you change the access control setup using alternative ways
to get the expected effective permissions (not changing the assertion)?
+ * Can you explain the main difference between
'testEditAccssControl' and 'testEditAccssControl2'?
+ * Could you use
AccessControlManager.getApplicablePolicies(testPath) in 'testEditAccssControl'
and/or 'testEditAccssControl2'? Explain why or why not.
+ *
+ * Effective Access Control Policies
+ * Walk through the tests to understand how effective policies are computed
when accessed by a set of principals or by path.
+ *
+ * - {@link #testEffectivePolicies()}: The same access control setup results
in different effective policies depending
+ * on the set of principals passed to the
method. Complete the assertions such that the
+ * test passes.
+ * - {@link #testEffectivePoliciesByPath()}: This time effective policies are
access by path. Complete the assertions and
+ * compare the results with the previous
test.
+ *
+ * Questions: What are the differences between effective policies by
principals and by path?
+ * Discuss how the notion of supported principal is reflected in
each case.
+ * </pre>
+ */
+public class L2_AccessControlManagementTest extends AbstractPrincipalBasedTest
{
+
+ private Principal supportedPrincipal;
+ private Principal unsupportedPrincipal;
+
+ private JackrabbitAccessControlManager principalBasedAcMgr;
+ private JackrabbitAccessControlManager compositeAcMgr;
+
+ private String testPath;
+
+ @Before
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ supportedPrincipal = getSystemUserPrincipal("systemUser",
getSupportedIntermediatePath());
+ unsupportedPrincipal = getGroupPrincipal();
+
+ principalBasedAcMgr = (JackrabbitAccessControlManager)
getPrincipalBasedAuthorizationConfiguration().getAccessControlManager(root,
getNamePathMapper());
+ compositeAcMgr = (JackrabbitAccessControlManager)
getConfig(AuthorizationConfiguration.class).getAccessControlManager(root,
getNamePathMapper());
+
+ Tree testTree = TreeUtil.addChild(root.getTree(PathUtils.ROOT_PATH),
"test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ testPath = getNamePathMapper().getJcrPath(testTree.getPath());
+ root.commit();
+ }
+
+ @After
+ @Override
+ public void after() throws Exception {
+ try {
+ root.getTree(testPath).remove();
+ root.commit();
+ } finally {
+ super.after();
+ }
+ }
+
+ @Test
+ public void testApplicablePoliciesSupportedPrincipal() throws Exception {
+ AccessControlPolicy[] applicable =
principalBasedAcMgr.getApplicablePolicies(supportedPrincipal);
+ assertEquals(-1 /*EXERCISE: fix assertion */, applicable.length);
+ assertTrue(applicable[0] instanceof PrincipalAccessControlList);
+
+ applicable = compositeAcMgr.getApplicablePolicies(supportedPrincipal);
+ assertEquals(-1 /*EXERCISE: fix assertion */, applicable.length);
+
+ // EXERCISE: inspect the applicable policies and write assertions
+ // EXERCISE: explain the difference between the composite setup and
the principal-based-only access control manager.
+ }
+
+ @Test
+ public void testApplicablePoliciesUnsupportedPrincipal() throws Exception {
+ AccessControlPolicy[] applicable =
principalBasedAcMgr.getApplicablePolicies(unsupportedPrincipal);
+ assertEquals(-1 /*EXERCISE: fix assertion */, applicable.length);
+
+ applicable =
compositeAcMgr.getApplicablePolicies(unsupportedPrincipal);
+ assertEquals(-1 /*EXERCISE: fix assertion */, applicable.length);
+
+ // EXERCISE: inspect the applicable policies and write test-assertions
+ // EXERCISE: explain the difference between the composite setup and
the principal-based-only access control manager.
+ }
+
+ @Test
+ public void testApplicablePoliciesByPath() throws Exception {
+ Iterator<AccessControlPolicy> applicable =
principalBasedAcMgr.getApplicablePolicies(testPath);
+ assertEquals(null /*EXERCISE: complete assertion */,
applicable.hasNext());
+
+ applicable = compositeAcMgr.getApplicablePolicies(testPath);
+ assertEquals(null /*EXERCISE: complete assertion */,
applicable.hasNext());
+
+ // EXERCISE: inspect the available applicable policies
+ // EXERCISE: explain the difference between the composite setup and
the principal-based-only access control manager.
+ }
+
+ @Test
+ public void testEditAccssControl() throws Exception {
+ PrincipalAccessControlList acl =
getApplicablePrincipalAccessControlList(compositeAcMgr, supportedPrincipal);
+ assertNotNull(acl);
+
+ // EXERCISE: modify the PrincipalAccessControlList such that the test
passes.
+ // EXERCISE: can you identify an alternative way to edit the access
control entries?
+ compositeAcMgr.setPolicy(acl.getPath(), acl);
+ root.commit();
+
+ try (ContentSession cs = getTestSession(supportedPrincipal)) {
+ Root testRoot = cs.getLatestRoot();
+ assertTrue(testRoot.getTree(testPath).exists());
+ }
+ }
+
+ @Test
+ public void testEditAccssControl2() throws Exception {
+ // EXERCISE: Obtain the applicable policy that results in effective
permissions for the Subject containing
+ // both the supportedPrincipal and unsupportedPrincipal
+ JackrabbitAccessControlList acl = null; // EXERCISE
+ acl.addEntry(supportedPrincipal,
privilegesFromNames(PrivilegeConstants.JCR_READ), true,
+ ImmutableMap.of(AccessControlConstants.REP_NODE_PATH,
getValueFactory(root).createValue(testPath)));
+ compositeAcMgr.setPolicy(acl.getPath(), acl);
+ root.commit();
+
+ // EXERCISE: Can you identify another way of obtaining _and_ modifying
the access control setup to achieve
+ // the same effective setup?
+
+ try (ContentSession cs = getTestSession(supportedPrincipal,
unsupportedPrincipal)) {
+ Root testRoot = cs.getLatestRoot();
+ assertTrue(testRoot.getTree(testPath).exists());
+ }
+ }
+
+ @Test
+ public void testEffectivePolicies() throws Exception {
+ JackrabbitAccessControlList acl =
checkNotNull(AccessControlUtils.getAccessControlList(compositeAcMgr, testPath));
+ acl.addAccessControlEntry(supportedPrincipal,
privilegesFromNames(PrivilegeConstants.JCR_REMOVE_CHILD_NODES));
+ acl.addAccessControlEntry(unsupportedPrincipal,
privilegesFromNames(PrivilegeConstants.JCR_MODIFY_PROPERTIES));
+ compositeAcMgr.setPolicy(acl.getPath(), acl);
+
+ PrincipalAccessControlList pacl =
checkNotNull(getApplicablePrincipalAccessControlList(compositeAcMgr,
supportedPrincipal));
+ pacl.addEntry(testPath,
privilegesFromNames(PrivilegeConstants.JCR_ADD_CHILD_NODES));
+ compositeAcMgr.setPolicy(pacl.getPath(), pacl);
+ root.commit();
+
+ // 1. get effective policies for just 'supportedPrincipal'
+
+ // EXERCISE: what is the expected result? verify by filling in the
missing assertions.
+ AccessControlPolicy[] effective =
compositeAcMgr.getEffectivePolicies(ImmutableSet.of(supportedPrincipal));
+ assertEquals(-1 /*EXERCISE*/, effective.length);
+ // EXERCISE: inspect the nature of the policies
+
+ assertTrue(effective[0] instanceof AccessControlList);
+ AccessControlEntry[] entries = ((AccessControlList)
effective[0]).getAccessControlEntries();
+ assertEquals(-1 /*EXERCISE*/, entries.length);
+ assertArrayEquals(null /*EXERCISE*/, entries[0].getPrivileges());
+ // EXERCISE: inspect the entries. where do they take effect?
+
+ // 2. get effective policies for the set containing both
'supportedPrincipal' and 'unsupportedPrincipal'
+
+ // EXERCISE: what is the expected result? verify it by filling in the
missing assertions.
+ effective =
compositeAcMgr.getEffectivePolicies(ImmutableSet.of(supportedPrincipal,
unsupportedPrincipal));
+ assertEquals(-1 /*EXERCISE*/, effective.length);
+ // EXERCISE: inspect the nature of the policies
+
+ assertTrue(effective[0] instanceof AccessControlList);
+ entries = ((AccessControlList) effective[0]).getAccessControlEntries();
+ assertEquals(-1 /*EXERCISE*/, entries.length);
+ assertArrayEquals(null /*EXERCISE*/, entries[0].getPrivileges());
+ // EXERCISE: inspect the entries. where do they take effect?
+ }
+
+ @Test
+ public void testEffectivePoliciesByPath() throws Exception {
+ JackrabbitAccessControlList acl =
checkNotNull(AccessControlUtils.getAccessControlList(compositeAcMgr, testPath));
+ acl.addAccessControlEntry(unsupportedPrincipal,
privilegesFromNames(PrivilegeConstants.REP_REMOVE_PROPERTIES));
+ compositeAcMgr.setPolicy(acl.getPath(), acl);
+
+ PrincipalAccessControlList pacl =
checkNotNull(getApplicablePrincipalAccessControlList(compositeAcMgr,
supportedPrincipal));
+ pacl.addEntry(testPath,
privilegesFromNames(PrivilegeConstants.REP_ADD_PROPERTIES));
+ compositeAcMgr.setPolicy(pacl.getPath(), pacl);
+ root.commit();
+
+ // notice, that effective policies are accessed by path!
+ AccessControlPolicy[] effective =
compositeAcMgr.getEffectivePolicies(testPath);
+ assertEquals(-1 /*EXERCISE*/, effective.length);
+ // EXERCISE: inspect the policies
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L2_AccessControlManagementTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L3_PermissionEvaluationTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L3_PermissionEvaluationTest.java?rev=1882944&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L3_PermissionEvaluationTest.java
(added)
+++
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L3_PermissionEvaluationTest.java
Wed Oct 28 16:37:04 2020
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package
org.apache.jackrabbit.oak.exercise.security.authorization.principalbased;
+
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import
org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
+import
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.jetbrains.annotations.NotNull;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.Principal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_MODIFY_PROPERTIES;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_READ;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_READ_ACCESS_CONTROL;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_WRITE;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_ADD_PROPERTIES;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_READ_NODES;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_READ_PROPERTIES;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_REMOVE_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * <pre>
+ * Module: Principal-Based Authorization
+ *
=============================================================================
+ *
+ * Title: Permission Evaluation with Principal-Based Authorization
+ *
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * Learn how effective permissions are being evaluation in a composite setup
that includes both principal-based and
+ * path based authorization.
+ *
+ * Reading:
+ *
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#details_permission_eval
+ *
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#details_aggregationfilter
+ *
+ * Exercises:
+ *
+ * - {@link #testPermissions()}: defined the list of principals whose
effective permission make the test pass
+ * Question: Are the other combinations of principals with the same effect?
+ * Can you explain the test and the permission evaluation for this
test case?
+ *
+ * - {@link #testPermissions2()}: fix the assertions for the given content
session and explain the result
+ *
+ * - {@link #testPermissions3()}: defined the list of principals whose
effective permission make the test pass
+ * - {@link #testPermissions4()}: defined the list of principals whose
effective permission make the test pass
+ * Question: Can you explain the main difference between the two tests?
+ *
+ * - {@link #testPermissions5()}:
+ *
+ * - {@link #testReadablePaths()}: fill in a path that with the current setup
is always readable.
+ * Question: How many alternative paths would make the test pass?
+ * Question: Discuss what changes to the authorization setup would be needed
to have a different set of paths marked as readable.
+ *
+ * </pre>
+ */
+public class L3_PermissionEvaluationTest extends AbstractPrincipalBasedTest {
+
+ private Principal systemUserPrincipal1;
+ private Principal systemUserPrincipal2;
+ private Principal userPrincipal;
+ private Principal groupPrincipal;
+
+ private String testPath;
+
+ @Before
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ systemUserPrincipal1 = getSystemUserPrincipal("systemUser1",
getSupportedIntermediatePath());
+ systemUserPrincipal2 = getSystemUserPrincipal("systemUser2",
getSupportedIntermediatePath());
+ userPrincipal = getRegularUserPrincipal();
+ groupPrincipal = getGroupPrincipal();
+
+ Tree testTree = TreeUtil.addChild(root.getTree(PathUtils.ROOT_PATH),
"test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ testTree.setProperty("prop", "value");
+
+ testPath = getNamePathMapper().getJcrPath(testTree.getPath());
+
+ setupAccessControl();
+ root.commit();
+ }
+
+ @After
+ @Override
+ public void after() throws Exception {
+ try {
+ root.getTree(testPath).remove();
+ root.commit();
+ } finally {
+ super.after();
+ }
+ }
+
+ private void setupAccessControl() throws Exception {
+ JackrabbitAccessControlManager compositeAcMgr =
(JackrabbitAccessControlManager)
getConfig(AuthorizationConfiguration.class).getAccessControlManager(root,
getNamePathMapper());
+
+ PrincipalAccessControlList pacl =
checkNotNull(getApplicablePrincipalAccessControlList(compositeAcMgr,
systemUserPrincipal1));
+ pacl.addEntry(testPath, privilegesFromNames(REP_READ_NODES));
+ compositeAcMgr.setPolicy(pacl.getPath(), pacl);
+
+ pacl =
checkNotNull(getApplicablePrincipalAccessControlList(compositeAcMgr,
systemUserPrincipal2));
+ pacl.addEntry(testPath, privilegesFromNames(REP_READ_PROPERTIES,
REP_ADD_PROPERTIES));
+ compositeAcMgr.setPolicy(pacl.getPath(), pacl);
+
+ JackrabbitAccessControlList acl =
AccessControlUtils.getAccessControlList(compositeAcMgr, testPath);
+ acl.addAccessControlEntry(groupPrincipal,
privilegesFromNames(JCR_READ));
+ acl.addAccessControlEntry(systemUserPrincipal1,
privilegesFromNames(JCR_WRITE));
+ acl.addAccessControlEntry(systemUserPrincipal2,
privilegesFromNames(JCR_READ_ACCESS_CONTROL));
+ acl.addEntry(userPrincipal,
privilegesFromNames(REP_REMOVE_PROPERTIES), false);
+ compositeAcMgr.setPolicy(acl.getPath(), acl);
+ }
+
+ @NotNull
+ private PermissionProvider getPermissionProvider(@NotNull ContentSession
cs) {
+ return
getConfig(AuthorizationConfiguration.class).getPermissionProvider(cs.getLatestRoot(),
cs.getWorkspaceName(), cs.getAuthInfo().getPrincipals());
+ }
+
+ @Test
+ public void testPermissions() throws Exception {
+ try (ContentSession cs = getTestSession(/*EXERCISE: add principals
such that the test passes */)) {
+ Root r = cs.getLatestRoot();
+ assertTrue(r.getTree(testPath).exists());
+ assertFalse(r.getTree(testPath).hasProperty("prop"));
+ }
+ }
+
+ @Test
+ public void testPermissions2() throws Exception {
+ try (ContentSession cs = getTestSession(systemUserPrincipal1,
systemUserPrincipal2)) {
+ PermissionProvider pp = getPermissionProvider(cs);
+
+ Tree t = cs.getLatestRoot().getTree(testPath);
+
+ // EXERCISE: fix the assertions and explain the result
+ assertEquals(null /*EXERCISE */, t.exists());
+ assertEquals(null /*EXERCISE */,
t.hasChild(AccessControlConstants.REP_POLICY));
+ assertEquals(null /*EXERCISE */, t.hasProperty("prop"));
+
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
JCR_READ_ACCESS_CONTROL));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t, JCR_WRITE));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
JCR_MODIFY_PROPERTIES));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
REP_ADD_PROPERTIES));
+ }
+ }
+
+ @Test
+ public void testPermissions3() throws Exception {
+ try (ContentSession cs = getTestSession(/*EXERCISE: add principals
such that the test passes */)) {
+ Tree t = cs.getLatestRoot().getTree(testPath);
+ assertTrue(t.exists());
+ assertTrue(t.hasProperty("prop"));
+ assertTrue(t.hasChild(AccessControlConstants.REP_POLICY));
+ assertFalse(getPermissionProvider(cs).hasPrivileges(t, JCR_WRITE));
+ }
+ }
+
+ @Test
+ public void testPermissions4() throws Exception {
+ try (ContentSession cs = getTestSession(/*EXERCISE: add principals
such that the test passes */)) {
+ Tree t = cs.getLatestRoot().getTree(testPath);
+ assertTrue(t.exists());
+ assertTrue(t.hasProperty("prop"));
+ assertFalse(t.hasChild(AccessControlConstants.REP_POLICY));
+
+ PermissionProvider pp = getPermissionProvider(cs);
+ assertTrue(pp.hasPrivileges(t, REP_ADD_PROPERTIES));
+ assertFalse(pp.hasPrivileges(t, REP_REMOVE_PROPERTIES));
+ }
+ }
+
+ @Test
+ public void testPermissions5() throws Exception {
+ try (ContentSession cs = getTestSession(systemUserPrincipal1,
groupPrincipal)) {
+ PermissionProvider pp = getPermissionProvider(cs);
+
+ Tree t = cs.getLatestRoot().getTree(testPath);
+
+ // EXERCISE: fix the assertions and explain the result
+ assertEquals(null /*EXERCISE */, t.exists());
+ assertEquals(null /*EXERCISE */,
t.hasChild(AccessControlConstants.REP_POLICY));
+ assertEquals(null /*EXERCISE */, t.hasProperty("prop"));
+
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
JCR_READ_ACCESS_CONTROL));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t, JCR_WRITE));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
REP_REMOVE_PROPERTIES));
+ }
+ }
+
+ @Test
+ public void testReadablePaths() throws Exception {
+ try (ContentSession cs = getTestSession(systemUserPrincipal1,
systemUserPrincipal2)) {
+ String readablePath = null; // EXERCISE: enter a path that is
always readable for the given 2 principals
+ assertTrue(cs.getLatestRoot().getTree(readablePath).exists());
+ }
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L3_PermissionEvaluationTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L4_DisabledAggregationFilterTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L4_DisabledAggregationFilterTest.java?rev=1882944&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L4_DisabledAggregationFilterTest.java
(added)
+++
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L4_DisabledAggregationFilterTest.java
Wed Oct 28 16:37:04 2020
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package
org.apache.jackrabbit.oak.exercise.security.authorization.principalbased;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
+import
org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
+import
org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
+import
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import
org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import
org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.jetbrains.annotations.NotNull;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.jcr.security.AccessControlPolicy;
+import java.security.Principal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_MODIFY_PROPERTIES;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_READ_ACCESS_CONTROL;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.JCR_WRITE;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_ADD_PROPERTIES;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_READ_NODES;
+import static
org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants.REP_READ_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * <pre>
+ * Module: Principal-Based Authorization
+ *
=============================================================================
+ *
+ * Title: Effect of AggregationFilter
+ *
-----------------------------------------------------------------------------
+ *
+ * Goal:
+ * All previous exercises had the AggregationFilter enabled. The following
test will illustrate the behavior of the
+ * composite permission provider, if the filter was disabled.
+ *
+ * Reading:
+ *
https://jackrabbit.apache.org/oak/docs/security/authorization/composite.html#AggregationFilter
+ *
http://jackrabbit.apache.org/oak/docs/security/authorization/principalbased.html#details_aggregationfilter
+ *
+ * Exercises:
+ *
+ * - {@link #testPermissions()}: complete the assertions to make the test case
pass and compare the results with the
+ * previous lession. Explain the difference and
discuss the benefits of enabling the filter.
+ *
+ * - {@link #testEffectivePolicies()}: fix the assertion and explain the
result (compared to previous exercises)
+ * Question: How do the effective policies explain the outcome of the
permission evaluation?
+ *
+ * Advanced Exercise:
+ *
-----------------------------------------------------------------------------
+ *
+ * - Change the {@link #getCompositionType()} to OR and observe how it changes
the effective permissions.
+ * Explain your findings.
+ *
+ * </pre>
+ */
+public class L4_DisabledAggregationFilterTest extends
AbstractPrincipalBasedTest {
+
+ private Principal supportedPrincipal1;
+ private Principal supportedPrincipal2;
+
+ private String testPath;
+
+ @Before
+ @Override
+ public void before() throws Exception {
+ super.before();
+
+ supportedPrincipal1 = getSystemUserPrincipal("systemUser1",
getSupportedIntermediatePath());
+ supportedPrincipal2 = getSystemUserPrincipal("systemUser2",
getSupportedIntermediatePath());
+
+ Tree testTree = TreeUtil.addChild(root.getTree(PathUtils.ROOT_PATH),
"test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+ testTree.setProperty("prop", "value");
+
+ testPath = getNamePathMapper().getJcrPath(testTree.getPath());
+
+ setupAccessControl();
+ root.commit();
+ }
+
+ @After
+ @Override
+ public void after() throws Exception {
+ try {
+ root.getTree(testPath).remove();
+ root.commit();
+ } finally {
+ super.after();
+ }
+ }
+
+ @Override
+ boolean enableAggregationFilter() {
+ return false;
+ }
+
+ private void setupAccessControl() throws Exception {
+ JackrabbitAccessControlManager compositeAcMgr =
(JackrabbitAccessControlManager)
getConfig(AuthorizationConfiguration.class).getAccessControlManager(root,
getNamePathMapper());
+
+ PrincipalAccessControlList pacl =
checkNotNull(getApplicablePrincipalAccessControlList(compositeAcMgr,
supportedPrincipal1));
+ pacl.addEntry(testPath, privilegesFromNames(REP_READ_NODES));
+ compositeAcMgr.setPolicy(pacl.getPath(), pacl);
+
+ pacl =
checkNotNull(getApplicablePrincipalAccessControlList(compositeAcMgr,
supportedPrincipal2));
+ pacl.addEntry(testPath, privilegesFromNames(REP_READ_PROPERTIES,
REP_ADD_PROPERTIES));
+ compositeAcMgr.setPolicy(pacl.getPath(), pacl);
+
+ JackrabbitAccessControlList acl =
AccessControlUtils.getAccessControlList(compositeAcMgr, testPath);
+ acl.addAccessControlEntry(supportedPrincipal1,
privilegesFromNames(JCR_WRITE));
+ acl.addAccessControlEntry(supportedPrincipal2,
privilegesFromNames(JCR_READ_ACCESS_CONTROL));
+ compositeAcMgr.setPolicy(acl.getPath(), acl);
+ }
+
+ @NotNull
+ private PermissionProvider getPermissionProvider(@NotNull ContentSession
cs) {
+ return
getConfig(AuthorizationConfiguration.class).getPermissionProvider(cs.getLatestRoot(),
cs.getWorkspaceName(), cs.getAuthInfo().getPrincipals());
+ }
+
+ @Test
+ public void testPermissions() throws Exception {
+ try (ContentSession cs = getTestSession(supportedPrincipal1,
supportedPrincipal2)) {
+ PermissionProvider pp = getPermissionProvider(cs);
+
+ Tree t = cs.getLatestRoot().getTree(testPath);
+
+ // EXERCISE: fix the assertions and explain the result
+ assertEquals(null /*EXERCISE */, t.exists());
+ assertEquals(null /*EXERCISE */,
t.hasChild(AccessControlConstants.REP_POLICY));
+ assertEquals(null /*EXERCISE */, t.hasProperty("prop"));
+
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
JCR_READ_ACCESS_CONTROL));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t, JCR_WRITE));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
JCR_MODIFY_PROPERTIES));
+ assertEquals(null /*EXERCISE */, pp.hasPrivileges(t,
REP_ADD_PROPERTIES));
+
+ assertEquals(ImmutableSet.of(/*EXERCISE */), pp.getPrivileges(t));
+ }
+ }
+
+ @Test
+ public void testEffectivePolicies() throws Exception {
+ JackrabbitAccessControlManager compositeAcMgr =
(JackrabbitAccessControlManager)
getConfig(AuthorizationConfiguration.class).getAccessControlManager(root,
getNamePathMapper());
+ AccessControlPolicy[] effectivePolicies =
compositeAcMgr.getEffectivePolicies(ImmutableSet.of(supportedPrincipal1,
supportedPrincipal2));
+
+ // EXERCISE: inspect the effective policies and explain the result
+ assertEquals(-1 /*EXERCISE*/, effectivePolicies.length);
+ }
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-exercise/src/test/java/org/apache/jackrabbit/oak/exercise/security/authorization/principalbased/L4_DisabledAggregationFilterTest.java
------------------------------------------------------------------------------
svn:eol-style = native