blob: d78945614ece3c0e32fe8e3b987872f41d31fe62 [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.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 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));
// This is the expected ACL for the above aclView.
private final Acl expectedAcl = expectedBuilder().build();
@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 testGetAcl() throws Exception {
assertEquals(expectedAcl, newBuilder(aclView).getAcl().build());
}
@Test
public void testGetInheritableByAllDescendentFoldersAcl() throws Exception {
assertEquals(expectedAcl,
newBuilder(aclView).getInheritableByAllDescendentFoldersAcl().build());
}
@Test
public void testGetInheritableByAllDescendentFilesAcl() throws Exception {
assertEquals(expectedAcl,
newBuilder(aclView).getInheritableByAllDescendentFilesAcl().build());
}
@Test
public void testGetInheritableByChildFoldersOnlyAcl() throws Exception {
assertEquals(expectedAcl,
newBuilder(aclView).getInheritableByChildFoldersOnlyAcl().build());
}
@Test
public void testGetInheritableByChildFilesOnlyAcl() throws Exception {
assertEquals(expectedAcl,
newBuilder(aclView).getInheritableByChildFilesOnlyAcl().build());
}
@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);
// The file inherit ACLs should have all the users and groups.
assertEquals(expectedAcl,
aclBuilder.getInheritableByAllDescendentFilesAcl().build());
assertEquals(expectedAcl,
aclBuilder.getInheritableByChildFilesOnlyAcl().build());
// The folder inherit ACLs should not include "mary" or "sales".
Acl expected = expectedBuilder()
.setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build();
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFoldersAcl().build());
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFoldersAcl().build());
}
@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);
// The folder inherit ACLs should have all the users and groups.
assertEquals(expectedAcl,
aclBuilder.getInheritableByAllDescendentFoldersAcl().build());
assertEquals(expectedAcl,
aclBuilder.getInheritableByChildFoldersOnlyAcl().build());
// The file inherit ACLs should not include "mary" or "sales".
Acl expected = expectedBuilder()
.setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build();
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFilesAcl().build());
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFilesAcl().build());
}
@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().build();
Acl expected = emptyExpectedBuilder()
.setPermitUsers(users("joe", "mary")).build();
assertEquals(expected, acl);
acl = aclBuilder.getInheritableByChildFoldersOnlyAcl().build();
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().build();
Acl expected = emptyExpectedBuilder()
.setPermitUsers(users("joe", "mary")).build();
assertEquals(expected, acl);
acl = aclBuilder.getInheritableByChildFilesOnlyAcl().build();
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 expected = emptyExpectedBuilder()
.setPermitUsers(users("joe", "mary")).build();
assertEquals(expected, aclBuilder.getAcl().build());
// However, all of its children should include mike.
expected = emptyExpectedBuilder()
.setPermitUsers(users("joe", "mike", "mary")).build();
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFoldersAcl().build());
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFilesAcl().build());
}
@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();
assertEquals(expected, aclBuilder.getAcl().build());
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFoldersAcl().build());
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFilesAcl().build());
}
@Test
public void testReadAttributesPermNotNeeded() 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, READ_ACL, READ_NAMED_ATTRS)
.flags(FILE_INHERIT, DIRECTORY_INHERIT));
AclBuilder aclBuilder = newBuilder(aclView);
// This node's ACLs should include both joe and mike.
Acl expected = emptyExpectedBuilder()
.setPermitUsers(users("joe", "mike")).build();
assertEquals(expected, aclBuilder.getAcl().build());
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFoldersAcl().build());
assertEquals(expected,
aclBuilder.getInheritableByAllDescendentFilesAcl().build());
}
@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();
assertEquals(expected, aclBuilder.getAcl().build());
}
/** 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 emptyExpectedBuilder()
.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 new Acl.Builder().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;
}
}