blob: 1fb34146d6c3c2629a61a58a39154f131b687c63 [file] [log] [blame]
// 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;
}
}