| // Copyright 2013 Google Inc. All Rights Reserved. |
| // |
| // Licensed 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 com.google.enterprise.adaptor.fs; |
| |
| import static com.google.enterprise.adaptor.fs.AclView.user; |
| import static com.google.enterprise.adaptor.fs.AclView.group; |
| import static com.google.enterprise.adaptor.fs.AclView.GenericPermission.*; |
| |
| import static org.junit.Assert.*; |
| |
| import static java.nio.file.attribute.AclEntryFlag.*; |
| import static java.nio.file.attribute.AclEntryPermission.*; |
| import static java.nio.file.attribute.AclEntryType.*; |
| |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Iterables; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Sets; |
| import com.google.enterprise.adaptor.Acl; |
| import com.google.enterprise.adaptor.Acl.InheritanceType; |
| import com.google.enterprise.adaptor.DocId; |
| import com.google.enterprise.adaptor.GroupPrincipal; |
| import com.google.enterprise.adaptor.Principal; |
| import com.google.enterprise.adaptor.UserPrincipal; |
| |
| import org.junit.*; |
| import org.junit.rules.ExpectedException; |
| |
| import java.io.IOException; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.nio.file.attribute.AclEntry; |
| import java.nio.file.attribute.AclFileAttributeView; |
| import java.util.ArrayList; |
| import java.util.Set; |
| |
| /** |
| * Test cases for {@link AclBuilder}. |
| */ |
| public class AclBuilderTest { |
| @Rule |
| public ExpectedException thrown = ExpectedException.none(); |
| |
| private final Path doc = Paths.get("foo", "bar"); |
| private final DocId inheritId = new DocId("foo"); |
| private final Set<String> windowsAccounts = ImmutableSet.of( |
| "BUILTIN\\Administrators", "Everyone", "BUILTIN\\Users", |
| "BUILTIN\\Guest", "NT AUTHORITY\\INTERACTIVE", |
| "NT AUTHORITY\\Authenticated Users"); |
| private final String builtinPrefix = "BUILTIN\\"; |
| private final String namespace = "namespace"; |
| private final Set<GroupPrincipal> emptyGroups = ImmutableSet.of(); |
| private final AclFileAttributeView aclView = new AclView( |
| user("joe").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mary").type(ALLOW).perms(GENERIC_READ, GENERIC_WRITE) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mike").type(DENY).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| group("EVERYONE").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| group("sales").type(DENY).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT)); |
| |
| @Test |
| public void testConstructorNullPath() throws Exception { |
| thrown.expect(NullPointerException.class); |
| new AclBuilder(null, aclView, windowsAccounts, builtinPrefix, namespace); |
| } |
| |
| @Test |
| public void testConstructorNullAclView() throws Exception { |
| thrown.expect(NullPointerException.class); |
| new AclBuilder(doc, null, windowsAccounts, builtinPrefix, namespace); |
| } |
| |
| @Test |
| public void testConstructorNullAccounts() throws Exception { |
| thrown.expect(NullPointerException.class); |
| new AclBuilder(doc, aclView, null, builtinPrefix, namespace); |
| } |
| |
| @Test |
| public void testConstructorNullPrefix() throws Exception { |
| thrown.expect(NullPointerException.class); |
| new AclBuilder(doc, aclView, windowsAccounts, null, namespace); |
| } |
| |
| @Test |
| public void testConstructorNullNamespace() throws Exception { |
| thrown.expect(NullPointerException.class); |
| new AclBuilder(doc, aclView, windowsAccounts, builtinPrefix, null); |
| } |
| |
| @Test |
| public void testGetAclForDirectory() throws Exception { |
| Acl acl = newBuilder(aclView).getAcl(inheritId, true, null); |
| Acl expected = expectedBuilder().build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testGetAclForFile() throws Exception { |
| Acl acl = newBuilder(aclView).getAcl(inheritId, false, null); |
| Acl expected = expectedBuilder() |
| .setInheritanceType(InheritanceType.LEAF_NODE) |
| .build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testGetShareAcl() throws Exception { |
| Acl acl = newBuilder(aclView).getShareAcl(inheritId); |
| Acl expected = expectedBuilder() |
| .setInheritanceType(InheritanceType.AND_BOTH_PERMIT) |
| .build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testGetInheritableByAllDescendentFoldersAcl() throws Exception { |
| String fragment = "allFoldersAcl"; |
| Acl acl = newBuilder(aclView).getInheritableByAllDescendentFoldersAcl( |
| inheritId, fragment); |
| Acl expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testGetInheritableByAllDescendentFilesAcl() throws Exception { |
| String fragment = "allFilesAcl"; |
| Acl acl = newBuilder(aclView).getInheritableByAllDescendentFilesAcl( |
| inheritId, fragment); |
| Acl expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testGetInheritableByChildFoldersOnlyAcl() throws Exception { |
| String fragment = "childFoldersAcl"; |
| Acl acl = newBuilder(aclView).getInheritableByChildFoldersOnlyAcl( |
| inheritId, fragment); |
| Acl expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testGetInheritableByChildFilesOnlyAcl() throws Exception { |
| String fragment = "childFilesAcl"; |
| Acl acl = newBuilder(aclView).getInheritableByChildFilesOnlyAcl( |
| inheritId, fragment); |
| Acl expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testFileInheritAcl() throws Exception { |
| // "mary" and "sales" are only inheritable by files, not directories. |
| AclFileAttributeView aclView = new AclView( |
| user("joe").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mary").type(ALLOW).perms(GENERIC_READ, GENERIC_WRITE) |
| .flags(FILE_INHERIT), |
| user("mike").type(DENY).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| group("EVERYONE").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| group("sales").type(DENY).perms(GENERIC_READ) |
| .flags(FILE_INHERIT)); |
| AclBuilder aclBuilder = newBuilder(aclView); |
| |
| String fragment = "allFilesAcl"; |
| Acl acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, |
| fragment); |
| Acl expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| |
| fragment = "childFilesAcl"; |
| acl = aclBuilder.getInheritableByChildFilesOnlyAcl(inheritId, fragment); |
| expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| |
| // The folder inherit ACLs should not include "mary" or "sales". |
| fragment = "allFoldersAcl"; |
| acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, |
| fragment); |
| expected = expectedBuilder(fragment) |
| .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build(); |
| assertEquals(expected, acl); |
| |
| fragment = "childFoldersAcl"; |
| acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, |
| fragment); |
| expected = expectedBuilder(fragment) |
| .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testFolderInheritAcl() throws Exception { |
| // "mary" and "sales" are only inheritable by directories, not files. |
| AclFileAttributeView aclView = new AclView( |
| user("joe").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mary").type(ALLOW).perms(GENERIC_READ, GENERIC_WRITE) |
| .flags(DIRECTORY_INHERIT), |
| user("mike").type(DENY).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| group("EVERYONE").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| group("sales").type(DENY).perms(GENERIC_READ) |
| .flags(DIRECTORY_INHERIT)); |
| AclBuilder aclBuilder = newBuilder(aclView); |
| |
| String fragment = "allFoldersAcl"; |
| Acl acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, |
| fragment); |
| Acl expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| |
| fragment = "childFoldersAcl"; |
| acl = aclBuilder.getInheritableByChildFoldersOnlyAcl(inheritId, fragment); |
| expected = expectedBuilder(fragment).build(); |
| assertEquals(expected, acl); |
| |
| // The file inherit ACLs should not include "mary" or "sales". |
| fragment = "allFilesAcl"; |
| acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, |
| fragment); |
| expected = expectedBuilder(fragment) |
| .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build(); |
| assertEquals(expected, acl); |
| |
| fragment = "childFilesAcl"; |
| acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, |
| fragment); |
| expected = expectedBuilder(fragment) |
| .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testNoPropagateFolderInheritAcl() throws Exception { |
| AclFileAttributeView aclView = new AclView( |
| user("joe").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mike").type(ALLOW).perms(GENERIC_READ) |
| .flags(DIRECTORY_INHERIT, NO_PROPAGATE_INHERIT), |
| user("mary").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT)); |
| AclBuilder aclBuilder = newBuilder(aclView); |
| |
| Acl acl = |
| aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, null); |
| Acl expected = emptyExpectedBuilder() |
| .setPermitUsers(users("joe", "mary")).build(); |
| assertEquals(expected, acl); |
| |
| acl = aclBuilder.getInheritableByChildFoldersOnlyAcl(inheritId, null); |
| expected = emptyExpectedBuilder() |
| .setPermitUsers(users("joe", "mike", "mary")).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testNoPropagateFileInheritAcl() throws Exception { |
| AclFileAttributeView aclView = new AclView( |
| user("joe").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mike").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, NO_PROPAGATE_INHERIT), |
| user("mary").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT)); |
| AclBuilder aclBuilder = newBuilder(aclView); |
| |
| Acl acl = |
| aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, null); |
| Acl expected = emptyExpectedBuilder() |
| .setPermitUsers(users("joe", "mary")).build(); |
| assertEquals(expected, acl); |
| |
| acl = aclBuilder.getInheritableByChildFilesOnlyAcl(inheritId, null); |
| expected = emptyExpectedBuilder() |
| .setPermitUsers(users("joe", "mike", "mary")).build(); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testInheritOnlyAcl() throws Exception { |
| AclFileAttributeView aclView = new AclView( |
| user("joe").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mike").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT, INHERIT_ONLY), |
| user("mary").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT)); |
| AclBuilder aclBuilder = newBuilder(aclView); |
| |
| // This node's ACL should not include mike. |
| Acl acl = aclBuilder.getAcl(inheritId, true, null); |
| Acl expected = emptyExpectedBuilder() |
| .setPermitUsers(users("joe", "mary")).build(); |
| assertEquals(expected, acl); |
| |
| // However, all of its children should include mike. |
| expected = emptyExpectedBuilder() |
| .setPermitUsers(users("joe", "mike", "mary")).build(); |
| acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, null); |
| assertEquals(expected, acl); |
| acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, null); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testInsufficientReadPerms() throws Exception { |
| AclFileAttributeView aclView = new AclView( |
| user("joe").type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT), |
| user("mike").type(ALLOW).perms(READ_DATA) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT)); |
| AclBuilder aclBuilder = newBuilder(aclView); |
| |
| // This node's ACLs should not include mike. |
| Acl expected = emptyExpectedBuilder() |
| .setPermitUsers(users("joe")).build(); |
| Acl acl = aclBuilder.getAcl(inheritId, true, null); |
| assertEquals(expected, acl); |
| acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, null); |
| assertEquals(expected, acl); |
| acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, null); |
| assertEquals(expected, acl); |
| } |
| |
| @Test |
| public void testWindowsBuiltinUsers() throws Exception { |
| ArrayList<AclEntry> entries = Lists.newArrayList(); |
| // Add all the permitted builtin users. |
| for (String builtin : windowsAccounts) { |
| entries.add(user(builtin).type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT).build()); |
| } |
| String badBuiltin = builtinPrefix + "BACKUP"; |
| // Now add a builtin user that should be excluded. |
| entries.add(user(badBuiltin).type(ALLOW).perms(GENERIC_READ) |
| .flags(FILE_INHERIT, DIRECTORY_INHERIT).build()); |
| |
| AclFileAttributeView aclView = |
| new AclView(entries.toArray(new AclEntry[0])); |
| AclBuilder aclBuilder = newBuilder(aclView); |
| |
| // The permitted users should contain all of the acceptable builtins. |
| // But should not contain the bad builtin. |
| Acl expected = emptyExpectedBuilder() |
| .setPermitUsers(users(Iterables.toArray(windowsAccounts, String.class))) |
| .build(); |
| Acl acl = aclBuilder.getAcl(inheritId, true, null); |
| assertEquals(expected, acl); |
| } |
| |
| /** Returns an AclBuilder for the AclFileAttributeView. */ |
| private AclBuilder newBuilder(AclFileAttributeView aclView) { |
| return new AclBuilder(doc, aclView, windowsAccounts, builtinPrefix, |
| namespace); |
| } |
| |
| /** |
| * Returns an Acl.Builder representing the aclView field. |
| * The caller is expected to overwrite any of thes presets, |
| * then call build(). |
| */ |
| private Acl.Builder expectedBuilder() { |
| return expectedBuilder(null); |
| } |
| |
| /** |
| * Returns an Acl.Builder representing the aclView field. |
| * The caller is expected to overwrite any of thes presets, |
| * then call build(). |
| */ |
| private Acl.Builder expectedBuilder(String fragment) { |
| return emptyExpectedBuilder(fragment) |
| .setPermitUsers(users("joe", "mary")).setDenyUsers(users("mike")) |
| .setPermitGroups(groups("EVERYONE")).setDenyGroups(groups("sales")); |
| } |
| |
| /** |
| * Returns an Acl.Builder with no users or groups. |
| */ |
| private Acl.Builder emptyExpectedBuilder() { |
| return emptyExpectedBuilder(null); |
| } |
| |
| /** |
| * Returns an Acl.Builder with no users or groups. |
| */ |
| private Acl.Builder emptyExpectedBuilder(String fragment) { |
| return new Acl.Builder().setInheritFrom(inheritId, fragment) |
| .setInheritanceType(InheritanceType.CHILD_OVERRIDES) |
| .setEverythingCaseInsensitive(); |
| } |
| |
| /** |
| * Returns a Set of UserPrincipals of the named users. |
| */ |
| private Set<UserPrincipal> users(String... users) { |
| Set<UserPrincipal> principals = Sets.newHashSet(); |
| for (String user : users) { |
| principals.add(new UserPrincipal(user, namespace)); |
| } |
| return principals; |
| } |
| |
| /** |
| * Returns a Set of GroupPrincipals of the named groups. |
| */ |
| private Set<GroupPrincipal> groups(String... groups) { |
| Set<GroupPrincipal> principals = Sets.newHashSet(); |
| for (String group : groups) { |
| principals.add(new GroupPrincipal(group, namespace)); |
| } |
| return principals; |
| } |
| } |