You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by st...@apache.org on 2017/06/28 06:56:01 UTC

svn commit: r1800129 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/ oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/ oak-core/src/main/java/org/apache/jackrabbit/oa...

Author: stillalex
Date: Wed Jun 28 06:56:00 2017
New Revision: 1800129

URL: http://svn.apache.org/viewvc?rev=1800129&view=rev
Log:
OAK-3777 Multiplexing support in default PermissionStore implementation


Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingPermissionProvider.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingProviderTest.java   (with props)
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MutiplexingProviderRandomTestIT.java   (with props)
    jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/multiplexing.md   (with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHook.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/AccessControlConstants.java
    jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission.md
    jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/default.md

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java?rev=1800129&r1=1800128&r2=1800129&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationConfigurationImpl.java Wed Jun 28 06:56:00 2017
@@ -17,19 +17,20 @@
 package org.apache.jackrabbit.oak.security.authorization;
 
 import java.security.Principal;
-import java.util.Collections;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import javax.annotation.Nonnull;
 import javax.jcr.security.AccessControlManager;
 
-import com.google.common.collect.ImmutableList;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.PropertyOption;
+import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
@@ -39,6 +40,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.security.authorization.accesscontrol.AccessControlImporter;
 import org.apache.jackrabbit.oak.security.authorization.accesscontrol.AccessControlManagerImpl;
 import org.apache.jackrabbit.oak.security.authorization.accesscontrol.AccessControlValidatorProvider;
+import org.apache.jackrabbit.oak.security.authorization.composite.MultiplexingPermissionProvider;
 import org.apache.jackrabbit.oak.security.authorization.permission.PermissionHook;
 import org.apache.jackrabbit.oak.security.authorization.permission.PermissionProviderImpl;
 import org.apache.jackrabbit.oak.security.authorization.permission.PermissionStoreValidatorProvider;
@@ -48,6 +50,9 @@ import org.apache.jackrabbit.oak.spi.com
 import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
 import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
 import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
 import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
@@ -56,6 +61,7 @@ import org.apache.jackrabbit.oak.spi.sec
 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.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
@@ -63,6 +69,8 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
 import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
 
+import com.google.common.collect.ImmutableList;
+
 /**
  * Default implementation of the {@code AccessControlConfiguration}.
  */
@@ -104,6 +112,9 @@ import org.apache.jackrabbit.oak.spi.xml
 })
 public class AuthorizationConfigurationImpl extends ConfigurationBase implements AuthorizationConfiguration {
 
+    @Reference
+    private MountInfoProvider mountInfoProvider;
+
     public AuthorizationConfigurationImpl() {
         super();
     }
@@ -116,6 +127,8 @@ public class AuthorizationConfigurationI
 
     public AuthorizationConfigurationImpl(SecurityProvider securityProvider) {
         super(securityProvider, securityProvider.getParameters(NAME));
+        mountInfoProvider = getParameters().getConfigValue(AccessControlConstants.PARAM_MOUNT_PROVIDER,
+                Mounts.defaultMountInfoProvider(), MountInfoProvider.class);
     }
 
     //----------------------------------------------< SecurityConfiguration >---
@@ -134,7 +147,7 @@ public class AuthorizationConfigurationI
     @Nonnull
     @Override
     public WorkspaceInitializer getWorkspaceInitializer() {
-        return new AuthorizationInitializer();
+        return new AuthorizationInitializer(mountInfoProvider);
     }
 
     @Nonnull
@@ -142,7 +155,7 @@ public class AuthorizationConfigurationI
     public List<? extends CommitHook> getCommitHooks(@Nonnull String workspaceName) {
         return ImmutableList.of(
                 new VersionablePathHook(workspaceName),
-                new PermissionHook(workspaceName, getRestrictionProvider()));
+                new PermissionHook(workspaceName, getRestrictionProvider(), mountInfoProvider));
     }
 
     @Nonnull
@@ -157,7 +170,7 @@ public class AuthorizationConfigurationI
     @Nonnull
     @Override
     public List<ProtectedItemImporter> getProtectedItemImporters() {
-        return Collections.<ProtectedItemImporter>singletonList(new AccessControlImporter());
+        return ImmutableList.of(new AccessControlImporter());
     }
 
     //-----------------------------------------< AccessControlConfiguration >---
@@ -180,8 +193,22 @@ public class AuthorizationConfigurationI
 
     @Nonnull
     @Override
-    public PermissionProvider getPermissionProvider(@Nonnull Root root, @Nonnull String workspaceName, @Nonnull Set<Principal> principals) {
+    public PermissionProvider getPermissionProvider(@Nonnull Root root, @Nonnull String workspaceName,
+            @Nonnull Set<Principal> principals) {
         Context ctx = getSecurityProvider().getConfiguration(AuthorizationConfiguration.class).getContext();
-        return new PermissionProviderImpl(root, workspaceName, principals, getRestrictionProvider(), getParameters(), ctx);
+
+        if (mountInfoProvider.hasNonDefaultMounts()) {
+            List<AggregatedPermissionProvider> agg = new ArrayList<>();
+            agg.add(new PermissionProviderImpl(root, workspaceName, principals, getRestrictionProvider(),
+                    getParameters(), ctx));
+            for (Mount m : mountInfoProvider.getNonDefaultMounts()) {
+                String ws = MultiplexingPermissionProvider.getWorkspaceName(m, workspaceName);
+                agg.add(new PermissionProviderImpl(root, ws, principals, getRestrictionProvider(), getParameters(),
+                        ctx));
+            }
+            return new MultiplexingPermissionProvider(root, agg, ctx);
+        }
+        return new PermissionProviderImpl(root, workspaceName, principals, getRestrictionProvider(), getParameters(),
+                ctx);
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java?rev=1800129&r1=1800128&r2=1800129&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java Wed Jun 28 06:56:00 2017
@@ -20,9 +20,12 @@ import com.google.common.collect.Immutab
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexUtils;
-import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
+import org.apache.jackrabbit.oak.security.authorization.composite.MultiplexingPermissionProvider;
 import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
@@ -40,6 +43,12 @@ import static org.apache.jackrabbit.JcrC
  */
 class AuthorizationInitializer implements WorkspaceInitializer, AccessControlConstants, PermissionConstants {
 
+    private final MountInfoProvider mountInfoProvider;
+
+    public AuthorizationInitializer(MountInfoProvider mountInfoProvider) {
+            this.mountInfoProvider = mountInfoProvider;
+    }
+
     @Override
     public void initialize(NodeBuilder builder, String workspaceName) {
         // property index for rep:principalName stored in ACEs
@@ -62,6 +71,12 @@ class AuthorizationInitializer implement
         if (!permissionStore.hasChildNode(workspaceName)) {
             permissionStore.child(workspaceName).setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_REP_PERMISSION_STORE, Type.NAME);
         }
+        for (Mount m : mountInfoProvider.getNonDefaultMounts()) {
+            String ws =  MultiplexingPermissionProvider.getWorkspaceName(m, workspaceName);
+            if (!permissionStore.hasChildNode(ws)) {
+                permissionStore.child(ws).setProperty(JcrConstants.JCR_PRIMARYTYPE, NT_REP_PERMISSION_STORE, Type.NAME);
+            }
+        }
     }
 
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingPermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingPermissionProvider.java?rev=1800129&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingPermissionProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingPermissionProvider.java Wed Jun 28 06:56:00 2017
@@ -0,0 +1,37 @@
+/*
+ * 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.security.authorization.composite;
+
+import java.util.List;
+
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration.CompositionType;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.security.Context;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
+
+public class MultiplexingPermissionProvider extends CompositePermissionProvider {
+
+    public MultiplexingPermissionProvider(Root root, List<AggregatedPermissionProvider> pps, Context acContext) {
+        super(root, pps, acContext, CompositionType.OR);
+    }
+
+    public static String getWorkspaceName(Mount m, String workspace) {
+        return m.getPathFragmentName() + "-" + workspace;
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingPermissionProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHook.java?rev=1800129&r1=1800128&r2=1800129&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionHook.java Wed Jun 28 06:56:00 2017
@@ -23,8 +23,11 @@ import javax.annotation.Nonnull;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
 import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
+import org.apache.jackrabbit.oak.security.authorization.composite.MultiplexingPermissionProvider;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.PostValidationHook;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
 import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
 import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionConstants;
 import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
@@ -64,6 +67,7 @@ public class PermissionHook implements P
 
     private final RestrictionProvider restrictionProvider;
     private final String workspaceName;
+    private final MountInfoProvider mountInfoProvider;
 
     private NodeBuilder permissionRoot;
     private PrivilegeBitsProvider bitsProvider;
@@ -75,9 +79,10 @@ public class PermissionHook implements P
     private Map<String, PermissionStoreEditor> modified = new HashMap<String, PermissionStoreEditor>();
     private Map<String, PermissionStoreEditor> deleted = new HashMap<String, PermissionStoreEditor>();
 
-    public PermissionHook(String workspaceName, RestrictionProvider restrictionProvider) {
+    public PermissionHook(String workspaceName, RestrictionProvider restrictionProvider, MountInfoProvider mountInfoProvider) {
         this.workspaceName = workspaceName;
         this.restrictionProvider = restrictionProvider;
+        this.mountInfoProvider = mountInfoProvider;
     }
 
     //---------------------------------------------------------< CommitHook >---
@@ -121,9 +126,19 @@ public class PermissionHook implements P
     }
 
     @Nonnull
-    private NodeBuilder getPermissionRoot(NodeBuilder rootBuilder) {
+    private static NodeBuilder getPermissionRoot(NodeBuilder rootBuilder) {
         // permission root has been created during workspace initialization
-        return rootBuilder.getChildNode(JCR_SYSTEM).getChildNode(REP_PERMISSION_STORE).getChildNode(workspaceName);
+        return rootBuilder.getChildNode(JCR_SYSTEM).getChildNode(REP_PERMISSION_STORE);
+    }
+
+    @Nonnull
+    private NodeBuilder getPermissionRoot(String path) {
+        Mount m = mountInfoProvider.getMountByPath(path);
+        String ws = workspaceName;
+        if (!m.isDefault()) {
+            ws = MultiplexingPermissionProvider.getWorkspaceName(m, ws);
+        }
+        return permissionRoot.getChildNode(ws);
     }
 
     private final class Diff extends DefaultNodeStateDiff {
@@ -199,7 +214,7 @@ public class PermissionHook implements P
         }
 
         private PermissionStoreEditor createPermissionStoreEditor(@Nonnull String nodeName, @Nonnull NodeState nodeState) {
-            return new PermissionStoreEditor(parentPath, nodeName, nodeState, permissionRoot, isACE, isGrantACE, bitsProvider, restrictionProvider);
+            return new PermissionStoreEditor(parentPath, nodeName, nodeState, getPermissionRoot(parentPath), isACE, isGrantACE, bitsProvider, restrictionProvider);
         }
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/AccessControlConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/AccessControlConstants.java?rev=1800129&r1=1800128&r2=1800129&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/AccessControlConstants.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/accesscontrol/AccessControlConstants.java Wed Jun 28 06:56:00 2017
@@ -82,4 +82,6 @@ public interface AccessControlConstants
     Collection<String> AC_NODETYPE_NAMES = ImmutableSet.of(NT_REP_POLICY, NT_REP_ACL, NT_REP_ACE, NT_REP_DENY_ACE, NT_REP_GRANT_ACE, NT_REP_RESTRICTIONS);
 
     String PARAM_RESTRICTION_PROVIDER = "restrictionProvider";
+
+    String PARAM_MOUNT_PROVIDER = "mountInfoProvider";
 }

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingProviderTest.java?rev=1800129&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingProviderTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingProviderTest.java Wed Jun 28 06:56:00 2017
@@ -0,0 +1,132 @@
+/*
+ * 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.security.authorization.composite;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.security.Principal;
+import java.util.Collections;
+
+import javax.jcr.security.AccessControlManager;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
+import org.apache.jackrabbit.oak.AbstractSecurityTest;
+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.plugins.tree.TreeUtil;
+import org.apache.jackrabbit.oak.spi.mount.Mount;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+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.PermissionConstants;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+
+public class MultiplexingProviderTest extends AbstractSecurityTest
+        implements AccessControlConstants, PrivilegeConstants, PermissionConstants {
+
+    private MountInfoProvider mountInfoProvider;
+    private String testNode = "MultiplexingProviderTest";
+    private String testPath = "/" + testNode;
+
+    @Override
+    @Before
+    public void before() throws Exception {
+        mountInfoProvider = Mounts.newBuilder().mount("testMount", testPath).build();
+        super.before();
+    }
+
+    @Override
+    @After
+    public void after() throws Exception {
+        try {
+            root.refresh();
+            Tree test = root.getTree(testPath);
+            if (test.exists()) {
+                test.remove();
+            }
+            root.commit();
+        } finally {
+            super.after();
+        }
+    }
+
+    @Override
+    protected ConfigurationParameters getSecurityConfigParameters() {
+        ConfigurationParameters authConfig = ConfigurationParameters.of(Collections.singletonMap(
+                AccessControlConstants.PARAM_MOUNT_PROVIDER, Preconditions.checkNotNull(mountInfoProvider)));
+        return ConfigurationParameters.of(ImmutableMap.of(AuthorizationConfiguration.NAME, authConfig));
+    }
+
+    @Test
+    public void multiplexingProvider() throws Exception {
+
+        // check init
+        Tree permStore = root.getTree(PERMISSIONS_STORE_PATH);
+        String wsName = adminSession.getWorkspaceName();
+        assertTrue(permStore.hasChild(wsName));
+        for (Mount m : mountInfoProvider.getNonDefaultMounts()) {
+            assertTrue(permStore.hasChild(MultiplexingPermissionProvider.getWorkspaceName(m, wsName)));
+        }
+
+        Tree rootNode = root.getTree("/");
+        Tree test = TreeUtil.addChild(rootNode, testNode, JcrConstants.NT_UNSTRUCTURED);
+        Tree content = TreeUtil.addChild(test, "content", JcrConstants.NT_UNSTRUCTURED);
+        root.commit();
+
+        Principal p = getTestUser().getPrincipal();
+        setPrivileges(p, test.getPath(), true, JCR_READ);
+        setPrivileges(p, content.getPath(), false, JCR_READ);
+
+        permStore = root.getTree(PERMISSIONS_STORE_PATH);
+        // no entries in the default store
+        assertFalse(permStore.getChild(wsName).hasChild(p.getName()));
+        for (Mount m : mountInfoProvider.getNonDefaultMounts()) {
+            Tree mps = permStore.getChild(MultiplexingPermissionProvider.getWorkspaceName(m, wsName));
+            assertTrue(mps.hasChild(p.getName()));
+        }
+
+        ContentSession testSession = createTestSession();
+        try {
+            Root r = testSession.getLatestRoot();
+            assertFalse(r.getTree("/").exists());
+            assertTrue(r.getTree(test.getPath()).exists());
+            assertFalse(r.getTree(content.getPath()).exists());
+        } finally {
+            testSession.close();
+        }
+    }
+
+    private void setPrivileges(Principal principal, String path, boolean allow, String... privileges) throws Exception {
+        AccessControlManager acm = getAccessControlManager(root);
+        JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acm, path);
+        acl.addEntry(principal, privilegesFromNames(privileges), allow);
+        acm.setPolicy(path, acl);
+        root.commit();
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MultiplexingProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MutiplexingProviderRandomTestIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MutiplexingProviderRandomTestIT.java?rev=1800129&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MutiplexingProviderRandomTestIT.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MutiplexingProviderRandomTestIT.java Wed Jun 28 06:56:00 2017
@@ -0,0 +1,66 @@
+/*
+ * 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.security.authorization.composite;
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
+import org.apache.jackrabbit.oak.security.authorization.permission.AbstractPermissionRandomTestIT;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.mount.Mounts;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+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 com.google.common.base.Preconditions;
+import com.google.common.collect.Iterators;
+
+public class MutiplexingProviderRandomTestIT extends AbstractPermissionRandomTestIT {
+
+    private MountInfoProvider mountInfoProvider;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        String[] mpxs = new String[] { Iterators.get(allowU.iterator(), allowU.size() / 2) };
+        Mounts.Builder builder = Mounts.newBuilder();
+        int i = 0;
+        for (String p : mpxs) {
+            builder.mount("m" + i, p);
+            i++;
+        }
+        mountInfoProvider = builder.build();
+    }
+
+    @Override
+    protected PermissionProvider candidatePermissionProvider(@Nonnull Root root, @Nonnull String workspaceName,
+            @Nonnull Set<Principal> principals) {
+        ConfigurationParameters authConfig = ConfigurationParameters.of(Collections.singletonMap(
+                AccessControlConstants.PARAM_MOUNT_PROVIDER, Preconditions.checkNotNull(mountInfoProvider)));
+        SecurityProviderImpl sp = new SecurityProviderImpl(authConfig);
+        AuthorizationConfiguration acConfig = sp.getConfiguration(AuthorizationConfiguration.class);
+        return acConfig.getPermissionProvider(root, workspaceName, principals);
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/MutiplexingProviderRandomTestIT.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission.md?rev=1800129&r1=1800128&r2=1800129&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission.md (original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission.md Wed Jun 28 06:56:00 2017
@@ -371,6 +371,7 @@ The supported configuration options of t
 - [Differences wrt Jackrabbit 2.x](permission/differences.html)
 - [Permissions : The Default Implementation](permission/default.html)
 - [Permission Evaluation in Detail](permission/evaluation.html)
+- [Multiplexed PermissionStore](permission/multiplexing.html)
 - [Restriction Management](authorization/restriction.html)
 
 <!-- references -->

Modified: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/default.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/default.md?rev=1800129&r1=1800128&r2=1800129&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/default.md (original)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/default.md Wed Jun 28 06:56:00 2017
@@ -61,6 +61,10 @@ on the Oak API) irrespective of the acce
 evaluation and is currently not reflected in other security models nor methods
 that deal with the administrator (i.e. `User#isAdmin`).
 
+#### Permission Evaluation in Multiplexed Stores
+
+See section [Multiplexing support in the PermissionStore](multiplexing.html).
+
 <a name="representation"/>
 ### Representation in the Repository
 

Added: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/multiplexing.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/multiplexing.md?rev=1800129&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/multiplexing.md (added)
+++ jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/multiplexing.md Wed Jun 28 06:56:00 2017
@@ -0,0 +1,59 @@
+<!--
+   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.
+-->
+
+Multiplexing support in the PermissionStore
+--------------------------------------------------------------------------------
+
+### General Notes
+
+Multiplexing support is implemented as a composite `PermissionProvider` made of
+the default workspace provider and the existing mounts.
+This is available since Oak 1.7.3 [OAK-3777](https://issues.apache.org/jira/browse/OAK-3777).
+
+### PermissionStore Evaluation (reading)
+
+Given the following mount setup
+
+    private
+        - /libs
+        - /apps
+    default
+        - /
+
+In above setup nodes under /apps and /libs (include apps and libs) are part of "private" mount (mount name is "private") and all other paths are part of default mount.
+A dedicated PermissionStore will be created under `oak:mount-private-default` that contains information relevant to this specific mount.
+
+    /jcr:system/rep:permissionStore
+        + oak:mount-private-default
+            + editor //principal name
+                + 1345610890 (rep:PermissionStore) //path hash
+                    - rep:accessControlledPath = /libs
+                        + 0
+                          - rep:isAllow = false
+                          - rep:privileges = [1279]
+        + default  //workspace name
+            + editor //principal name
+                + 1227964008 (rep:PermissionStore) //path hash
+                    - rep:accessControlledPath = /content
+                        + 0
+                          - rep:isAllow = true
+                          - rep:privileges = [1279]
+
+### PermissionStore updates (writing)
+
+The `PermissionHook` is now mount-aware and will delegate changes to specific path to their designated components based on path.
+

Propchange: jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/permission/multiplexing.md
------------------------------------------------------------------------------
    svn:eol-style = native