You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2023/04/18 06:59:02 UTC

[jackrabbit-filevault] 01/03: JCRVLT-683 expect import of principal-based Authz to obey acHandling rules

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch bugfix/JCRVLT-683
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git

commit 4b540232e655ec2ccf2d8013442eacae3d4af5bc
Author: Mark Adamcin <ad...@adobe.com>
AuthorDate: Tue Feb 7 10:23:27 2023 -0800

    JCRVLT-683 expect import of principal-based Authz to obey acHandling rules
---
 .../apache/jackrabbit/vault/fs/io/Importer.java    |   2 +-
 .../packaging/integration/PrincipalBasedIT.java    | 214 ++++++++++++++++++++-
 .../META-INF/MANIFEST.MF                           |   5 +
 .../META-INF/vault/config.xml                      |  93 +++++++++
 .../META-INF/vault/definition/.content.xml         |  32 +++
 .../META-INF/vault/filter.xml                      |   4 +
 .../META-INF/vault/nodetypes.cnd                   |  10 +
 .../META-INF/vault/properties.xml                  |  22 +++
 .../jcr_root/.content.xml                          |   6 +
 .../jcr_root/home/.content.xml                     |   4 +
 .../jcr_root/home/users/.content.xml               |   4 +
 .../jcr_root/home/users/system/.content.xml        |   4 +
 .../home/users/system/intermediate/.content.xml    |   3 +
 .../intermediate/tBUjdNwIM-i9bTqCYP5D/.content.xml |   7 +
 14 files changed, 404 insertions(+), 6 deletions(-)

diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
index 88316a0c..81a0b3d8 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/Importer.java
@@ -328,7 +328,7 @@ public class Importer {
         this.isStrict = opts.isStrict(isStrictByDefault);
         this.isStrictByDefault = isStrictByDefault;
         this.overwritePrimaryTypesOfFoldersByDefault = overwritePrimaryTypesOfFoldersByDefault;
-        if (!this.opts.hasIdConflictPolicyBeenSet()) {
+        if (!this.opts.hasIdConflictPolicyBeenSet() && defaultIdConflictPolicy != null) {
             this.opts.setIdConflictPolicy(defaultIdConflictPolicy);
         }
     }
diff --git a/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/PrincipalBasedIT.java b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/PrincipalBasedIT.java
index 50d56380..2431e5f8 100644
--- a/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/PrincipalBasedIT.java
+++ b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/PrincipalBasedIT.java
@@ -24,6 +24,8 @@ import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
 import org.apache.jackrabbit.api.security.authorization.PrincipalAccessControlList;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeCollection;
+import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
@@ -46,6 +48,7 @@ import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
 import org.apache.jackrabbit.vault.fs.io.ImportOptions;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -57,12 +60,14 @@ import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
 import javax.jcr.security.AccessControlEntry;
 import javax.jcr.security.AccessControlPolicy;
 import javax.jcr.security.Privilege;
 import java.security.Principal;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Stream;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -224,18 +229,49 @@ public class PrincipalBasedIT extends IntegrationTestBase {
     }
 
     @Test
-    public void testHandlingIgnoreModeReplace() throws Exception {
+    public void testNewUserHandlingIgnoreModeReplace() throws Exception {
         assumeTrue(isOak());
         ImportOptions opts = getDefaultOptions();
         opts.setAccessControlHandling(AccessControlHandling.IGNORE);
         opts.setImportMode(ImportMode.REPLACE);
 
+        admin.getNode(testUser.getPath()).remove();
+        admin.save();
         extractVaultPackage("/test-packages/principalbased.zip", opts);
-        // user may have been moved due to 'replace' mode -> need to retrieve again
         Principal p = userManager.getAuthorizable(SYSTEM_USER_ID).getPrincipal();
         assertEquals(0, acMgr.getPolicies(p).length);
     }
 
+    @Test
+    public void testHandlingIgnoreModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.IGNORE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        final String oldPath = testUser.getPath();
+        extractVaultPackage("/test-packages/principalbased.zip", opts);
+        // user may have been moved due to 'replace' mode -> need to retrieve again
+        Authorizable newUser = userManager.getAuthorizable(SYSTEM_USER_ID);
+        assertPolicy(newUser.getPrincipal(),
+                filterEffectivePathForMovedSelf(existingEntries, oldPath, newUser.getPath()));
+    }
+
+    @Test
+    public void testNoPolicyHandlingIgnoreModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.IGNORE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        final String oldPath = testUser.getPath();
+        extractVaultPackage("/test-packages/principalbased_nopolicy.zip", opts);
+        // user may have been moved due to 'replace' mode -> need to retrieve again
+        Authorizable newUser = userManager.getAuthorizable(SYSTEM_USER_ID);
+        assertPolicy(newUser.getPrincipal(),
+                filterEffectivePathForMovedSelf(existingEntries, oldPath, newUser.getPath()));
+    }
+
     @Test
     public void testHandlingOverwriteModeUpdate() throws Exception {
         assumeTrue(isOak());
@@ -258,6 +294,20 @@ public class PrincipalBasedIT extends IntegrationTestBase {
         assertPolicy(testUser.getPrincipal(), packageEntries);
     }
 
+    @Test
+    public void testNewUserHandlingOverwriteModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.OVERWRITE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        admin.getNode(testUser.getPath()).remove();
+        admin.save();
+
+        extractVaultPackage("/test-packages/principalbased.zip");
+        assertPolicy(testUser.getPrincipal(), packageEntries);
+    }
+
     @Test
     public void testHandlingOverwriteModeReplace() throws Exception {
         assumeTrue(isOak());
@@ -269,6 +319,18 @@ public class PrincipalBasedIT extends IntegrationTestBase {
         assertPolicy(testUser.getPrincipal(), packageEntries);
     }
 
+    @Test
+    public void testNoPolicyHandlingOverwriteModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.OVERWRITE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        extractVaultPackage("/test-packages/principalbased_nopolicy.zip");
+        Principal p = userManager.getAuthorizable(SYSTEM_USER_ID).getPrincipal();
+        assertEquals(0, acMgr.getPolicies(p).length);
+    }
+
     @Test
     public void testHandlingMergeModeUpdate() throws Exception {
         assumeTrue(isOak());
@@ -298,18 +360,56 @@ public class PrincipalBasedIT extends IntegrationTestBase {
     }
 
     @Test
-    public void testHandlingMergeModeReplace() throws Exception {
+    public void testNewUserHandlingMergeModeReplace() throws Exception {
         assumeTrue(isOak());
         ImportOptions opts = getDefaultOptions();
         opts.setAccessControlHandling(AccessControlHandling.MERGE);
         opts.setImportMode(ImportMode.REPLACE);
 
+        admin.getNode(testUser.getPath()).remove();
+        admin.save();
         extractVaultPackage("/test-packages/principalbased.zip", opts);
 
         // user may have been moved due to 'replace' mode -> need to retrieve again
         assertPolicy(userManager.getAuthorizable(SYSTEM_USER_ID).getPrincipal(), packageEntries);
     }
 
+    @Test
+    public void testHandlingMergeModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.MERGE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        final String oldPath = testUser.getPath();
+        extractVaultPackage("/test-packages/principalbased.zip", opts);
+
+        // user may have been moved due to 'replace' mode -> need to retrieve again
+        Authorizable newUser = userManager.getAuthorizable(SYSTEM_USER_ID);
+
+        List<AccessControlEntry> expected = Lists.newArrayList(
+                filterEffectivePathForMovedSelf(existingEntries, oldPath, newUser.getPath()));
+        expected.addAll(ImmutableList.copyOf(packageEntries));
+
+        assertPolicy(newUser.getPrincipal(), expected.toArray(new AccessControlEntry[0]));
+    }
+
+    @Test
+    public void testNoPolicyHandlingMergeModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.MERGE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        final String oldPath = testUser.getPath();
+        extractVaultPackage("/test-packages/principalbased_nopolicy.zip", opts);
+
+        // user may have been moved due to 'replace' mode -> need to retrieve again
+        Authorizable newUser = userManager.getAuthorizable(SYSTEM_USER_ID);
+        assertPolicy(newUser.getPrincipal(),
+                filterEffectivePathForMovedSelf(existingEntries, oldPath, newUser.getPath()));
+    }
+
     @Test
     public void testHandlingMergePreserveModeUpdate() throws Exception {
         assumeTrue(isOak());
@@ -332,6 +432,21 @@ public class PrincipalBasedIT extends IntegrationTestBase {
         assertPolicy(testUser.getPrincipal(), existingEntries);
     }
 
+    @Test
+    public void testNewUserHandlingMergePreserveModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.MERGE_PRESERVE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        admin.getNode(testUser.getPath()).remove();
+        admin.save();
+
+        extractVaultPackage("/test-packages/principalbased.zip", opts);
+        Principal p = userManager.getAuthorizable(SYSTEM_USER_ID).getPrincipal();
+        assertPolicy(p, packageEntries);
+    }
+
     @Test
     public void testHandlingMergePreserveModeReplace() throws Exception {
         assumeTrue(isOak());
@@ -339,9 +454,98 @@ public class PrincipalBasedIT extends IntegrationTestBase {
         opts.setAccessControlHandling(AccessControlHandling.MERGE_PRESERVE);
         opts.setImportMode(ImportMode.REPLACE);
 
+        final String oldPath = testUser.getPath();
         extractVaultPackage("/test-packages/principalbased.zip", opts);
         // user may have been moved due to 'replace' mode -> need to retrieve again
-        Principal p = userManager.getAuthorizable(SYSTEM_USER_ID).getPrincipal();
-        assertEquals(0, acMgr.getPolicies(p).length);
+        Authorizable newUser = userManager.getAuthorizable(SYSTEM_USER_ID);
+        assertPolicy(newUser.getPrincipal(),
+                filterEffectivePathForMovedSelf(existingEntries, oldPath, newUser.getPath()));
+    }
+
+    @Test
+    public void testNoPolicyHandlingMergePreserveModeReplace() throws Exception {
+        assumeTrue(isOak());
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.MERGE_PRESERVE);
+        opts.setImportMode(ImportMode.REPLACE);
+
+        final String oldPath = testUser.getPath();
+        extractVaultPackage("/test-packages/principalbased_nopolicy.zip", opts);
+        // user may have been moved due to 'replace' mode -> need to retrieve again
+        Authorizable newUser = userManager.getAuthorizable(SYSTEM_USER_ID);
+        assertPolicy(newUser.getPrincipal(),
+                filterEffectivePathForMovedSelf(existingEntries, oldPath, newUser.getPath()));
+    }
+
+    static AccessControlEntry[] filterEffectivePathForMovedSelf(final AccessControlEntry[] entries,
+                                                                      final String oldPath,
+                                                                      final String newPath) {
+        return Stream.of(entries).map(ace -> {
+            if (ace instanceof PrincipalAccessControlList.Entry) {
+                PrincipalAccessControlList.Entry pace = (PrincipalAccessControlList.Entry) ace;
+                final String effectivePath = pace.getEffectivePath();
+                if (effectivePath != null
+                        && (oldPath.equals(effectivePath) || effectivePath.startsWith(oldPath + "/"))) {
+                    return new EffectivePathEntryWrapper(pace, newPath +
+                            pace.getEffectivePath().substring(oldPath.length()));
+                } else {
+                    return ace;
+                }
+            } else {
+                return ace;
+            }
+        }).toArray(AccessControlEntry[]::new);
+    }
+
+    static class EffectivePathEntryWrapper implements PrincipalAccessControlList.Entry {
+
+        private final PrincipalAccessControlList.Entry pace;
+        @Nullable
+        private final String effectivePath;
+
+        public EffectivePathEntryWrapper(PrincipalAccessControlList.Entry pace, @Nullable String effectivePath) {
+            this.pace = pace;
+            this.effectivePath = effectivePath;
+        }
+
+        @Override
+        public @Nullable String getEffectivePath() {
+            return effectivePath;
+        }
+
+        @Override
+        public boolean isAllow() {
+            return pace.isAllow();
+        }
+
+        @Override
+        public @NotNull String[] getRestrictionNames() throws RepositoryException {
+            return pace.getRestrictionNames();
+        }
+
+        @Override
+        public @Nullable Value getRestriction(@NotNull String s) throws ValueFormatException, RepositoryException {
+            return pace.getRestriction(s);
+        }
+
+        @Override
+        public @Nullable Value[] getRestrictions(@NotNull String s) throws RepositoryException {
+            return pace.getRestrictions(s);
+        }
+
+        @Override
+        public @NotNull PrivilegeCollection getPrivilegeCollection() throws RepositoryException {
+            return pace.getPrivilegeCollection();
+        }
+
+        @Override
+        public Principal getPrincipal() {
+            return pace.getPrincipal();
+        }
+
+        @Override
+        public Privilege[] getPrivileges() {
+            return pace.getPrivileges();
+        }
     }
 }
\ No newline at end of file
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/MANIFEST.MF b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..b0a5f97f
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Content-Package-Roots: /home/users/system/intermediate
+Content-Package-Type: content
+Content-Package-Id: my_packages:testsystemuser
+
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/config.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/config.xml
new file mode 100644
index 00000000..b525f1c5
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/config.xml
@@ -0,0 +1,93 @@
+<!--
+  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.
+  -->
+<vaultfs version="1.1">
+    <!--
+        Defines the content aggregation. The order of the defined aggregates
+        is important for finding the correct aggregator.
+    -->
+    <aggregates>
+        <!--
+            Defines an aggregate that handles nt:file and nt:resource nodes.
+        -->
+        <aggregate type="file" title="File Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles file/folder like nodes. It matches
+            all nt:hierarchyNode nodes that have or define a jcr:content
+            child node and excludes child nodes that are nt:hierarchyNodes.
+        -->
+        <aggregate type="filefolder" title="File/Folder Aggregate"/>
+
+        <!--
+            Defines an aggregate that handles nt:nodeType nodes and serializes
+            them into .cnd notation.
+        -->
+        <aggregate type="nodetype" title="Node Type Aggregate" />
+
+        <!--
+            Defines an aggregate that defines full coverage for certain node
+            types that cannot be covered by the default aggregator.
+        -->
+        <aggregate type="full" title="Full Coverage Aggregate">
+            <matches>
+                <include nodeType="rep:AccessControl" respectSupertype="true" />
+                <include nodeType="rep:Policy" respectSupertype="true" />
+                <include nodeType="cq:Widget" respectSupertype="true" />
+                <include nodeType="cq:EditConfig" respectSupertype="true" />
+                <include nodeType="cq:WorkflowModel" respectSupertype="true" />
+                <include nodeType="vlt:FullCoverage" respectSupertype="true" />
+                <include nodeType="mix:language" respectSupertype="true" />
+                <include nodeType="sling:OsgiConfig" respectSupertype="true" />
+            </matches>
+        </aggregate>
+
+        <!--
+            Defines an aggregate that handles nt:folder like nodes.
+        -->
+        <aggregate type="generic" title="Folder Aggregate">
+            <matches>
+                <include nodeType="nt:folder" respectSupertype="true" />
+            </matches>
+            <contains>
+                <exclude isNode="true" />
+            </contains>
+        </aggregate>
+
+        <!--
+            Defines the default aggregate
+        -->
+        <aggregate type="generic" title="Default Aggregator" isDefault="true">
+            <matches>
+                <!-- all -->
+            </matches>
+            <contains>
+                <exclude nodeType="nt:hierarchyNode" respectSupertype="true" />
+            </contains>
+        </aggregate>
+
+    </aggregates>
+
+    <!--
+      defines the input handlers
+    -->
+    <handlers>
+        <handler type="folder"/>
+        <handler type="file"/>
+        <handler type="nodetype"/>
+        <handler type="generic"/>
+    </handlers>
+</vaultfs>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/definition/.content.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/definition/.content.xml
new file mode 100644
index 00000000..27822589
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/definition/.content.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:vlt="http://www.day.com/jcr/vault/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
+    jcr:created="{Date}2019-07-23T10:20:20.089+02:00"
+    jcr:createdBy="admin"
+    jcr:description=""
+    jcr:lastModified="{Date}2019-07-23T10:20:20.089+02:00"
+    jcr:lastModifiedBy="admin"
+    jcr:primaryType="vlt:PackageDefinition"
+    buildCount="1"
+    builtWith=""
+    fixedBugs=""
+    group="integrationtesting"
+    lastUnwrapped="{Date}2019-07-23T10:20:20.089+02:00"
+    lastUnwrappedBy="admin"
+    lastWrapped="{Date}2019-07-23T10:20:20.089+02:00"
+    lastWrappedBy="admin"
+    name="principalbased_overwrite"
+    acHandling="OVERWRITE"
+    providerLink=""
+    providerName=""
+    providerUrl=""
+    testedWith=""
+    version="">
+    <filter jcr:primaryType="nt:unstructured">
+        <f0
+            jcr:primaryType="nt:unstructured"
+            mode="replace"
+            root="/home/users/system/intermediate"
+            rules="[]"/>
+    </filter>
+    <screenshots jcr:primaryType="nt:unstructured"/>
+</jcr:root>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/filter.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/filter.xml
new file mode 100644
index 00000000..44bdf212
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/filter.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<workspaceFilter version="1.0">
+    <filter root="/home/users/system/intermediate" mode="update"/>
+</workspaceFilter>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/nodetypes.cnd b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/nodetypes.cnd
new file mode 100644
index 00000000..915f6991
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/nodetypes.cnd
@@ -0,0 +1,10 @@
+<'rep'='internal'>
+
+[rep:Password]
+  - * (undefined) protected
+  - * (undefined) protected multiple
+
+[rep:RepoAccessControllable]
+  mixin
+  + rep:repoPolicy (rep:Policy) protected ignore
+
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/properties.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/properties.xml
new file mode 100644
index 00000000..d7aaea86
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/META-INF/vault/properties.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+<comment>FileVault Package Properties</comment>
+<entry key="createdBy">admin</entry>
+<entry key="name">principalbased_overwrite</entry>
+<entry key="lastModified">2019-07-23T10:20:20.089Z</entry>
+<entry key="lastModifiedBy">admin</entry>
+<entry key="created">2019-07-23T10:20:20.170+02:00</entry>
+<entry key="buildCount">1</entry>
+<entry key="version">2</entry>
+<entry key="packageType">content</entry>
+<entry key="dependencies">depgroup:dep1:1,depgroup:dep2:2</entry>
+<entry key="packageFormatVersion">2</entry>
+<entry key="description"/>
+<entry key="lastWrapped">2019-07-23T10:20:20.089+02:00</entry>
+<entry key="group">integrationtesting</entry>
+<entry key="lastWrappedBy">admin</entry>
+<entry key="acHandling">OVERWRITE</entry>
+<entry key="requiresRoot">true</entry>
+<entry key="foo">bar</entry>
+</properties>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/.content.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/.content.xml
new file mode 100644
index 00000000..8ea9f2ae
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/.content.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable,rep:RepoAccessControllable]"
+    jcr:primaryType="rep:root"
+    sling:resourceType="sling:redirect"
+    sling:target="/index.html"/>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/.content.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/.content.xml
new file mode 100644
index 00000000..4af0ea84
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/.content.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="rep:AuthorizableFolder"/>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/.content.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/.content.xml
new file mode 100644
index 00000000..4af0ea84
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/.content.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="rep:AuthorizableFolder"/>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/.content.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/.content.xml
new file mode 100644
index 00000000..4af0ea84
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/.content.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:mixinTypes="[rep:AccessControllable]"
+    jcr:primaryType="rep:AuthorizableFolder"/>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/intermediate/.content.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/intermediate/.content.xml
new file mode 100644
index 00000000..90e51b0c
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/intermediate/.content.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:primaryType="rep:AuthorizableFolder"/>
diff --git a/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/intermediate/tBUjdNwIM-i9bTqCYP5D/.content.xml b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/intermediate/tBUjdNwIM-i9bTqCYP5D/.content.xml
new file mode 100644
index 00000000..4ab01579
--- /dev/null
+++ b/vault-core/src/test/resources/test-packages/principalbased_nopolicy.zip/jcr_root/home/users/system/intermediate/tBUjdNwIM-i9bTqCYP5D/.content.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+    jcr:primaryType="rep:SystemUser"
+    jcr:mixinTypes="[rep:PrincipalBasedMixin]"
+    jcr:uuid="22a2d7fa-b8c4-3523-be63-1b5789e5694f"
+    rep:authorizableId="testSystemUser"
+    rep:principalName="testSystemUser"/>