HDFS-10324. Trash directory in an encryption zone should be pre-created with correct permissions. Contributed by Wei-Chiu Chuang.

This commit is contained in:
Xiaoyu Yao 2016-05-05 18:07:47 -07:00
parent 4e5e87ddd4
commit dacd1f50fe
13 changed files with 519 additions and 73 deletions

View File

@ -56,7 +56,6 @@ public class TrashPolicyDefault extends TrashPolicy {
LogFactory.getLog(TrashPolicyDefault.class);
private static final Path CURRENT = new Path("Current");
private static final Path TRASH = new Path(".Trash/");
private static final FsPermission PERMISSION =
new FsPermission(FsAction.ALL, FsAction.NONE, FsAction.NONE);

View File

@ -29,7 +29,6 @@
import java.util.EnumSet;
import org.apache.hadoop.crypto.key.JavaKeyStoreProvider;
import org.apache.hadoop.crypto.key.KeyProviderFactory;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystemTestHelper;
@ -38,6 +37,7 @@
import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.nfs.conf.NfsConfigKeys;
import org.apache.hadoop.hdfs.nfs.conf.NfsConfiguration;
@ -118,6 +118,8 @@ public class TestRpcProgramNfs3 {
private static final String TEST_KEY = "test_key";
private static FileSystemTestHelper fsHelper;
private static File testRootDir;
private static final EnumSet<CreateEncryptionZoneFlag> NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
@BeforeClass
public static void setup() throws Exception {
@ -340,7 +342,7 @@ public void testEncryptedReadWrite() throws Exception {
final Path zone = new Path("/zone");
hdfs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY);
dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final byte[] buffer = new byte[len];
for (int i = 0; i < len; i++) {

View File

@ -0,0 +1,71 @@
/**
* 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.hadoop.hdfs.client;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
/**
* CreateEncryptionZoneFlag is used in
* {@link HdfsAdmin#createEncryptionZone(Path, String, EnumSet)} to indicate
* what should be done when creating an encryption zone.
*
* Use CreateEncryptionZoneFlag as follows:
* <ol>
* <li>PROVISION_TRASH - provision a trash directory for the encryption zone
* to support soft delete.</li>
* </ol>
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public enum CreateEncryptionZoneFlag {
/**
* Do not provision a trash directory in the encryption zone.
*
* @see CreateEncryptionZoneFlag#NO_TRASH
*/
NO_TRASH((short) 0x00),
/**
* Provision a trash directory .Trash/ in the
* encryption zone.
*
* @see CreateEncryptionZoneFlag#PROVISION_TRASH
*/
PROVISION_TRASH((short) 0x01);
private final short mode;
CreateEncryptionZoneFlag(short mode) {
this.mode = mode;
}
public static CreateEncryptionZoneFlag valueOf(short mode) {
for (CreateEncryptionZoneFlag flag : CreateEncryptionZoneFlag.values()) {
if (flag.getMode() == mode) {
return flag;
}
}
return null;
}
public short getMode() {
return mode;
}
}

View File

@ -22,14 +22,18 @@
import java.net.URI;
import java.util.EnumSet;
import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CacheFlag;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.StorageType;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DFSInotifyEventInputStream;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry;
@ -56,6 +60,8 @@
public class HdfsAdmin {
private DistributedFileSystem dfs;
private static final FsPermission TRASH_PERMISSION = new FsPermission(
FsAction.ALL, FsAction.ALL, FsAction.ALL, true);
/**
* Create a new HdfsAdmin client.
@ -270,11 +276,53 @@ public RemoteIterator<CachePoolEntry> listCachePools() throws IOException {
* @throws AccessControlException if the caller does not have access to path
* @throws FileNotFoundException if the path does not exist
*/
@Deprecated
public void createEncryptionZone(Path path, String keyName)
throws IOException, AccessControlException, FileNotFoundException {
throws IOException, AccessControlException, FileNotFoundException {
dfs.createEncryptionZone(path, keyName);
}
/**
* Create an encryption zone rooted at an empty existing directory, using the
* specified encryption key. An encryption zone has an associated encryption
* key used when reading and writing files within the zone.
*
* Additional options, such as provisioning the trash directory, can be
* specified using {@link CreateEncryptionZoneFlag} flags.
*
* @param path The path of the root of the encryption zone. Must refer to
* an empty, existing directory.
* @param keyName Name of key available at the KeyProvider.
* @param flags flags for this operation.
* @throws IOException if there was a general IO exception
* @throws AccessControlException if the caller does not have access to path
* @throws FileNotFoundException if the path does not exist
* @throws HadoopIllegalArgumentException if the flags are invalid
*/
public void createEncryptionZone(Path path, String keyName,
EnumSet<CreateEncryptionZoneFlag> flags)
throws IOException, AccessControlException, FileNotFoundException,
HadoopIllegalArgumentException{
dfs.createEncryptionZone(path, keyName);
if (flags.contains(CreateEncryptionZoneFlag.PROVISION_TRASH)) {
if (flags.contains(CreateEncryptionZoneFlag.NO_TRASH)) {
throw new HadoopIllegalArgumentException(
"can not have both PROVISION_TRASH and NO_TRASH flags");
}
this.provisionEZTrash(path);
}
}
/**
* Provision a trash directory for a given encryption zone.
* @param path the root of the encryption zone
* @throws IOException if the trash directory can not be created.
*/
public void provisionEncryptionZoneTrash(Path path) throws IOException {
this.provisionEZTrash(path);
}
/**
* Get the path of the encryption zone for a given file or directory.
*
@ -399,4 +447,43 @@ public ErasureCodingPolicy getErasureCodingPolicy(final Path path)
public ErasureCodingPolicy[] getErasureCodingPolicies() throws IOException {
return dfs.getClient().getErasureCodingPolicies();
}
private void provisionEZTrash(Path path) throws IOException {
// make sure the path is an EZ
EncryptionZone ez = dfs.getEZForPath(path);
if (ez == null) {
throw new IllegalArgumentException(path + " is not an encryption zone.");
}
String ezPath = ez.getPath();
if (!path.toString().equals(ezPath)) {
throw new IllegalArgumentException(path + " is not the root of an " +
"encryption zone. Do you mean " + ez.getPath() + "?");
}
// check if the trash directory exists
Path trashPath = new Path(ez.getPath(), FileSystem.TRASH_PREFIX);
if (dfs.exists(trashPath)) {
String errMessage = "Will not provision new trash directory for " +
"encryption zone " + ez.getPath() + ". Path already exists.";
FileStatus trashFileStatus = dfs.getFileStatus(trashPath);
if (!trashFileStatus.isDirectory()) {
errMessage += "\r\n" +
"Warning: " + trashPath.toString() + " is not a directory";
}
if (!trashFileStatus.getPermission().equals(TRASH_PERMISSION)) {
errMessage += "\r\n" +
"Warning: the permission of " +
trashPath.toString() + " is not " + TRASH_PERMISSION;
}
throw new IOException(errMessage);
}
// Update the permission bits
dfs.mkdir(trashPath, TRASH_PERMISSION);
dfs.setPermission(trashPath, TRASH_PERMISSION);
}
}

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
/**
* This package provides the administrative APIs for HDFS.
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
package org.apache.hadoop.hdfs.client;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;

View File

@ -18,15 +18,18 @@
package org.apache.hadoop.hdfs.tools;
import java.io.IOException;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.protocol.EncryptionZone;
import org.apache.hadoop.tools.TableListing;
import org.apache.hadoop.util.StringUtils;
@ -103,12 +106,13 @@ public String getShortUsage() {
public String getLongUsage() {
final TableListing listing = AdminHelper.getOptionDescriptionListing();
listing.addRow("<path>", "The path of the encryption zone to create. " +
"It must be an empty directory.");
"It must be an empty directory. A trash directory is provisioned " +
"under this path.");
listing.addRow("<keyName>", "Name of the key to use for the " +
"encryption zone.");
return getShortUsage() + "\n" +
"Create a new encryption zone.\n\n" +
listing.toString();
"Create a new encryption zone.\n\n" +
listing.toString();
}
@Override
@ -131,15 +135,16 @@ public int run(Configuration conf, List<String> args) throws IOException {
return 1;
}
final DistributedFileSystem dfs = AdminHelper.getDFS(conf);
HdfsAdmin admin = new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
EnumSet<CreateEncryptionZoneFlag> flags =
EnumSet.of(CreateEncryptionZoneFlag.PROVISION_TRASH);
try {
dfs.createEncryptionZone(new Path(path), keyName);
admin.createEncryptionZone(new Path(path), keyName, flags);
System.out.println("Added encryption zone " + path);
} catch (IOException e) {
System.err.println(prettifyException(e));
return 2;
}
return 0;
}
}
@ -168,12 +173,12 @@ public int run(Configuration conf, List<String> args) throws IOException {
return 1;
}
final DistributedFileSystem dfs = AdminHelper.getDFS(conf);
HdfsAdmin admin = new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
try {
final TableListing listing = new TableListing.Builder()
.addField("").addField("", true)
.wrapWidth(AdminHelper.MAX_LINE_WIDTH).hideHeaders().build();
final RemoteIterator<EncryptionZone> it = dfs.listEncryptionZones();
final RemoteIterator<EncryptionZone> it = admin.listEncryptionZones();
while (it.hasNext()) {
EncryptionZone ez = it.next();
listing.addRow(ez.getPath(), ez.getKeyName());
@ -188,8 +193,50 @@ public int run(Configuration conf, List<String> args) throws IOException {
}
}
private static class ProvisionTrashCommand implements AdminHelper.Command {
@Override
public String getName() {
return "-provisionTrash";
}
@Override
public String getShortUsage() {
return "[" + getName() + " -path <path>]\n";
}
@Override
public String getLongUsage() {
final TableListing listing = AdminHelper.getOptionDescriptionListing();
listing.addRow("<path>", "The path to the root of the encryption zone. ");
return getShortUsage() + "\n" +
"Provision a trash directory for an encryption zone.\n\n" +
listing.toString();
}
@Override
public int run(Configuration conf, List<String> args) throws IOException {
final String path = StringUtils.popOptionWithArgument("-path", args);
if (!args.isEmpty()) {
System.err.println("Can't understand argument: " + args.get(0));
return 1;
}
HdfsAdmin admin = new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
try {
admin.provisionEncryptionZoneTrash(new Path(path));
System.out.println("Created a trash directory for " + path);
} catch (IOException ioe) {
System.err.println(prettifyException(ioe));
return 2;
}
return 0;
}
}
private static final AdminHelper.Command[] COMMANDS = {
new CreateZoneCommand(),
new ListZonesCommand()
new CreateZoneCommand(),
new ListZonesCommand(),
new ProvisionTrashCommand()
};
}

View File

@ -338,6 +338,7 @@ Usage:
hdfs crypto -createZone -keyName <keyName> -path <path>
hdfs crypto -listZones
hdfs crypto -provisionTrash -path <path>
hdfs crypto -help <command-name>
See the [HDFS Transparent Encryption Documentation](./TransparentEncryption.html#crypto_command-line_interface) for more information.

View File

@ -170,7 +170,7 @@ Create a new encryption zone.
| | |
|:---- |:---- |
| *path* | The path of the encryption zone to create. It must be an empty directory. |
| *path* | The path of the encryption zone to create. It must be an empty directory. A trash directory is provisioned under this path.|
| *keyName* | Name of the key to use for the encryption zone. |
### <a name="listZones"></a>listZones
@ -179,6 +179,16 @@ Usage: `[-listZones]`
List all encryption zones. Requires superuser permissions.
### <a name="provisionTrash"></a>provisionTrash
Usage: `[-provisionTrash -path <path>]`
Provision a trash directory for an encryption zone.
| | |
|:---- |:---- |
| *path* | The path to the root of the encryption zone. |
<a name="Example_usage"></a>Example usage
-------------
@ -222,6 +232,7 @@ This restriction enhances security and eases system management significantly. Al
To comply with the above rule, each encryption zone has its own `.Trash` directory under the "zone directory". E.g., after `hdfs dfs rm /zone/encryptedFile`, `encryptedFile` will be moved to `/zone/.Trash`, instead of the `.Trash` directory under the user's home directory. When the entire encryption zone is deleted, the "zone directory" will be moved to the `.Trash` directory under the user's home directory.
The `crypto` command before Hadoop 2.8.0 does not provision the `.Trash` directory automatically. If an encryption zone is created before Hadoop 2.8.0, and then the cluster is upgraded to Hadoop 2.8.0 or above, the trash directory can be provisioned using `-provisionTrash` option (e.g., `hdfs crypto -provisionTrash -path /zone`).
<a name="Attack_vectors"></a>Attack vectors
--------------

View File

@ -29,6 +29,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@ -59,7 +60,9 @@
import org.apache.hadoop.fs.FsShell;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
import org.apache.hadoop.hdfs.protocol.EncryptionZone;
@ -70,6 +73,7 @@
import org.apache.hadoop.hdfs.server.namenode.EncryptionZoneManager;
import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil;
import org.apache.hadoop.hdfs.server.namenode.NamenodeFsck;
import org.apache.hadoop.hdfs.tools.CryptoAdmin;
import org.apache.hadoop.hdfs.tools.DFSck;
import org.apache.hadoop.hdfs.tools.offlineImageViewer.PBImageXmlWriter;
import org.apache.hadoop.hdfs.web.WebHdfsConstants;
@ -131,6 +135,9 @@ public class TestEncryptionZones {
protected FileSystemTestWrapper fsWrapper;
protected FileContextTestWrapper fcWrapper;
protected static final EnumSet< CreateEncryptionZoneFlag > NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
protected String getKeyProviderURI() {
return JavaKeyStoreProvider.SCHEME_NAME + "://file" +
new Path(testRootDir.toString(), "test.jks").toUri();
@ -215,6 +222,106 @@ public void assertZonePresent(String keyName, String path) throws IOException {
);
}
/**
* Make sure hdfs crypto -createZone command creates a trash directory
* with sticky bits.
* @throws Exception
*/
@Test(timeout = 60000)
public void testTrashStickyBit() throws Exception {
// create an EZ /zones/zone1, make it world writable.
final Path zoneParent = new Path("/zones");
final Path zone1 = new Path(zoneParent, "zone1");
CryptoAdmin cryptoAdmin = new CryptoAdmin(conf);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
fsWrapper.setPermission(zone1,
new FsPermission(FsAction.ALL, FsAction.ALL, FsAction.ALL));
String[] cryptoArgv = new String[]{"-createZone", "-keyName", TEST_KEY,
"-path", zone1.toUri().getPath()};
cryptoAdmin.run(cryptoArgv);
// create a file in EZ
final Path ezfile1 = new Path(zone1, "file1");
// Create the encrypted file in zone1
final int len = 8192;
DFSTestUtil.createFile(fs, ezfile1, len, (short) 1, 0xFEED);
// enable trash, delete /zones/zone1/file1,
// which moves the file to
// /zones/zone1/.Trash/$SUPERUSER/Current/zones/zone1/file1
Configuration clientConf = new Configuration(conf);
clientConf.setLong(FS_TRASH_INTERVAL_KEY, 1);
final FsShell shell = new FsShell(clientConf);
String[] argv = new String[]{"-rm", ezfile1.toString()};
int res = ToolRunner.run(shell, argv);
assertEquals("Can't remove a file in EZ as superuser", 0, res);
final Path trashDir = new Path(zone1, FileSystem.TRASH_PREFIX);
assertTrue(fsWrapper.exists(trashDir));
FileStatus trashFileStatus = fsWrapper.getFileStatus(trashDir);
assertTrue(trashFileStatus.getPermission().getStickyBit());
// create a non-privileged user
final UserGroupInformation user = UserGroupInformation.
createUserForTesting("user", new String[] { "mygroup" });
user.doAs(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
final Path ezfile2 = new Path(zone1, "file2");
final int len = 8192;
// create a file /zones/zone1/file2 in EZ
// this file is owned by user:mygroup
FileSystem fs2 = FileSystem.get(cluster.getConfiguration(0));
DFSTestUtil.createFile(fs2, ezfile2, len, (short) 1, 0xFEED);
// delete /zones/zone1/file2,
// which moves the file to
// /zones/zone1/.Trash/user/Current/zones/zone1/file2
String[] argv = new String[]{"-rm", ezfile2.toString()};
int res = ToolRunner.run(shell, argv);
assertEquals("Can't remove a file in EZ as user:mygroup", 0, res);
return null;
}
});
}
/**
* Make sure hdfs crypto -provisionTrash command creates a trash directory
* with sticky bits.
* @throws Exception
*/
@Test(timeout = 60000)
public void testProvisionTrash() throws Exception {
// create an EZ /zones/zone1
final Path zoneParent = new Path("/zones");
final Path zone1 = new Path(zoneParent, "zone1");
CryptoAdmin cryptoAdmin = new CryptoAdmin(conf);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
String[] cryptoArgv = new String[]{"-createZone", "-keyName", TEST_KEY,
"-path", zone1.toUri().getPath()};
cryptoAdmin.run(cryptoArgv);
// remove the trash directory
Configuration clientConf = new Configuration(conf);
clientConf.setLong(FS_TRASH_INTERVAL_KEY, 1);
final FsShell shell = new FsShell(clientConf);
final Path trashDir = new Path(zone1, FileSystem.TRASH_PREFIX);
String[] argv = new String[]{"-rmdir", trashDir.toUri().getPath()};
int res = ToolRunner.run(shell, argv);
assertEquals("Unable to delete trash directory.", 0, res);
assertFalse(fsWrapper.exists(trashDir));
// execute -provisionTrash command option and make sure the trash
// directory has sticky bit.
String[] provisionTrashArgv = new String[]{"-provisionTrash", "-path",
zone1.toUri().getPath()};
cryptoAdmin.run(provisionTrashArgv);
assertTrue(fsWrapper.exists(trashDir));
FileStatus trashFileStatus = fsWrapper.getFileStatus(trashDir);
assertTrue(trashFileStatus.getPermission().getStickyBit());
}
@Test(timeout = 60000)
public void testBasicOperations() throws Exception {
@ -223,8 +330,9 @@ public void testBasicOperations() throws Exception {
/* Test failure of create EZ on a directory that doesn't exist. */
final Path zoneParent = new Path("/zones");
final Path zone1 = new Path(zoneParent, "zone1");
try {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
fail("expected /test doesn't exist");
} catch (IOException e) {
assertExceptionContains("cannot find", e);
@ -232,20 +340,20 @@ public void testBasicOperations() throws Exception {
/* Normal creation of an EZ */
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
assertNumZones(++numZones);
assertZonePresent(null, zone1.toString());
/* Test failure of create EZ on a directory which is already an EZ. */
try {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
} catch (IOException e) {
assertExceptionContains("is already an encryption zone", e);
}
/* create EZ on parent of an EZ should fail */
try {
dfsAdmin.createEncryptionZone(zoneParent, TEST_KEY);
dfsAdmin.createEncryptionZone(zoneParent, TEST_KEY, NO_TRASH);
fail("EZ over an EZ");
} catch (IOException e) {
assertExceptionContains("encryption zone for a non-empty directory", e);
@ -256,7 +364,7 @@ public void testBasicOperations() throws Exception {
final Path notEmptyChild = new Path(notEmpty, "child");
fsWrapper.mkdir(notEmptyChild, FsPermission.getDirDefault(), true);
try {
dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY);
dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY, NO_TRASH);
fail("Created EZ on an non-empty directory with folder");
} catch (IOException e) {
assertExceptionContains("create an encryption zone", e);
@ -266,7 +374,7 @@ public void testBasicOperations() throws Exception {
/* create EZ on a folder with a file fails */
fsWrapper.createFile(notEmptyChild);
try {
dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY);
dfsAdmin.createEncryptionZone(notEmpty, TEST_KEY, NO_TRASH);
fail("Created EZ on an non-empty directory with file");
} catch (IOException e) {
assertExceptionContains("create an encryption zone", e);
@ -274,7 +382,7 @@ public void testBasicOperations() throws Exception {
/* Test failure of create EZ on a file. */
try {
dfsAdmin.createEncryptionZone(notEmptyChild, TEST_KEY);
dfsAdmin.createEncryptionZone(notEmptyChild, TEST_KEY, NO_TRASH);
fail("Created EZ on a file");
} catch (IOException e) {
assertExceptionContains("create an encryption zone for a file.", e);
@ -285,7 +393,7 @@ public void testBasicOperations() throws Exception {
fsWrapper.mkdir(zone2, FsPermission.getDirDefault(), false);
final String myKeyName = "mykeyname";
try {
dfsAdmin.createEncryptionZone(zone2, myKeyName);
dfsAdmin.createEncryptionZone(zone2, myKeyName, NO_TRASH);
fail("expected key doesn't exist");
} catch (IOException e) {
assertExceptionContains("doesn't exist.", e);
@ -293,13 +401,13 @@ public void testBasicOperations() throws Exception {
/* Test failure of empty and null key name */
try {
dfsAdmin.createEncryptionZone(zone2, "");
dfsAdmin.createEncryptionZone(zone2, "", NO_TRASH);
fail("created a zone with empty key name");
} catch (IOException e) {
assertExceptionContains("Must specify a key name when creating", e);
}
try {
dfsAdmin.createEncryptionZone(zone2, null);
dfsAdmin.createEncryptionZone(zone2, null, NO_TRASH);
fail("created a zone with null key name");
} catch (IOException e) {
assertExceptionContains("Must specify a key name when creating", e);
@ -309,7 +417,7 @@ public void testBasicOperations() throws Exception {
/* Test success of creating an EZ when they key exists. */
DFSTestUtil.createKey(myKeyName, cluster, conf);
dfsAdmin.createEncryptionZone(zone2, myKeyName);
dfsAdmin.createEncryptionZone(zone2, myKeyName, NO_TRASH);
assertNumZones(++numZones);
assertZonePresent(myKeyName, zone2.toString());
@ -325,7 +433,7 @@ public Object run() throws Exception {
final HdfsAdmin userAdmin =
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
try {
userAdmin.createEncryptionZone(nonSuper, TEST_KEY);
userAdmin.createEncryptionZone(nonSuper, TEST_KEY, NO_TRASH);
fail("createEncryptionZone is superuser-only operation");
} catch (AccessControlException e) {
assertExceptionContains("Superuser privilege is required", e);
@ -337,7 +445,7 @@ public Object run() throws Exception {
// Test success of creating an encryption zone a few levels down.
Path deepZone = new Path("/d/e/e/p/zone");
fsWrapper.mkdir(deepZone, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(deepZone, TEST_KEY);
dfsAdmin.createEncryptionZone(deepZone, TEST_KEY, NO_TRASH);
assertNumZones(++numZones);
assertZonePresent(null, deepZone.toString());
@ -345,7 +453,7 @@ public Object run() throws Exception {
for (int i=1; i<6; i++) {
final Path zonePath = new Path("/listZone" + i);
fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY, NO_TRASH);
numZones++;
assertNumZones(numZones);
assertZonePresent(null, zonePath.toString());
@ -365,7 +473,7 @@ public Object run() throws Exception {
// without persisting the namespace.
Path nonpersistZone = new Path("/nonpersistZone");
fsWrapper.mkdir(nonpersistZone, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(nonpersistZone, TEST_KEY);
dfsAdmin.createEncryptionZone(nonpersistZone, TEST_KEY, NO_TRASH);
numZones++;
cluster.restartNameNode(true);
assertNumZones(numZones);
@ -379,7 +487,7 @@ public void testBasicOperationsRootDir() throws Exception {
final Path zone1 = new Path(rootDir, "zone1");
/* Normal creation of an EZ on rootDir */
dfsAdmin.createEncryptionZone(rootDir, TEST_KEY);
dfsAdmin.createEncryptionZone(rootDir, TEST_KEY, NO_TRASH);
assertNumZones(++numZones);
assertZonePresent(null, rootDir.toString());
@ -407,10 +515,10 @@ public void testListEncryptionZonesAsNonSuperUser() throws Exception {
final Path allPath = new Path(testRoot, "accessall");
fsWrapper.mkdir(superPath, new FsPermission((short) 0700), true);
dfsAdmin.createEncryptionZone(superPath, TEST_KEY);
dfsAdmin.createEncryptionZone(superPath, TEST_KEY, NO_TRASH);
fsWrapper.mkdir(allPath, new FsPermission((short) 0707), true);
dfsAdmin.createEncryptionZone(allPath, TEST_KEY);
dfsAdmin.createEncryptionZone(allPath, TEST_KEY, NO_TRASH);
user.doAs(new PrivilegedExceptionAction<Object>() {
@Override
@ -450,8 +558,8 @@ public void testGetEZAsNonSuperUser() throws Exception {
fsWrapper.mkdir(superPath, new FsPermission((short) 0700), false);
fsWrapper.mkdir(allPath, new FsPermission((short) 0777), false);
fsWrapper.mkdir(nonEZDir, new FsPermission((short) 0777), false);
dfsAdmin.createEncryptionZone(superPath, TEST_KEY);
dfsAdmin.createEncryptionZone(allPath, TEST_KEY);
dfsAdmin.createEncryptionZone(superPath, TEST_KEY, NO_TRASH);
dfsAdmin.createEncryptionZone(allPath, TEST_KEY, NO_TRASH);
dfsAdmin.allowSnapshot(new Path("/"));
final Path newSnap = fs.createSnapshot(new Path("/"));
DFSTestUtil.createFile(fs, superPathFile, len, (short) 1, 0xFEED);
@ -556,7 +664,7 @@ private void doRenameEncryptionZone(FSTestWrapper wrapper) throws Exception {
final Path pathFooBarFile = new Path(pathFooBar, "file");
final int len = 8192;
wrapper.mkdir(pathFoo, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(pathFoo, TEST_KEY);
dfsAdmin.createEncryptionZone(pathFoo, TEST_KEY, NO_TRASH);
wrapper.mkdir(pathFooBaz, FsPermission.getDirDefault(), true);
DFSTestUtil.createFile(fs, pathFooBazFile, len, (short) 1, 0xFEED);
String contents = DFSTestUtil.readFile(fs, pathFooBazFile);
@ -615,7 +723,7 @@ public void testReadWrite() throws Exception {
// Create the first enc file
final Path zone = new Path("/zone");
fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY);
dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final Path encFile1 = new Path(zone, "myfile");
DFSTestUtil.createFile(fs, encFile1, len, (short) 1, 0xFEED);
// Read them back in and compare byte-by-byte
@ -650,7 +758,7 @@ public void testReadWriteUsingWebHdfs() throws Exception {
final Path zone = new Path("/zone");
fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY);
dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
/* Create an unencrypted file for comparison purposes. */
final Path unencFile = new Path("/unenc");
@ -696,7 +804,7 @@ public void testVersionAndSuiteNegotiation() throws Exception {
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
final Path zone = new Path("/zone");
fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY);
dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
// Create a file in an EZ, which should succeed
DFSTestUtil
.createFile(fs, new Path(zone, "success1"), 0, (short) 1, 0xFEED);
@ -827,7 +935,7 @@ public void testCreateEZWithNoProvider() throws Exception {
final Path zone1 = new Path("/zone1");
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
try {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
fail("expected exception");
} catch (IOException e) {
assertExceptionContains("since no key provider is available", e);
@ -869,7 +977,7 @@ private void dTIEM(Path prefix) throws Exception {
// Create an encrypted file to check isEncrypted returns true
final Path zone = new Path(prefix, "zone");
fsWrapper.mkdir(zone, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone, TEST_KEY);
dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final Path encFile = new Path(zone, "encfile");
fsWrapper.createFile(encFile);
stat = fsWrapper.getFileStatus(encFile);
@ -1010,7 +1118,7 @@ public void testStartFileRetry() throws Exception {
executor.submit(new InjectFaultTask() {
@Override
public void doFault() throws Exception {
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
}
@Override
public void doCleanup() throws Exception {
@ -1036,14 +1144,14 @@ public void doCleanup() throws Exception {
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
final String otherKey = "other_key";
DFSTestUtil.createKey(otherKey, cluster, conf);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
executor.submit(new InjectFaultTask() {
@Override
public void doFault() throws Exception {
fsWrapper.delete(zone1, true);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, otherKey);
dfsAdmin.createEncryptionZone(zone1, otherKey, NO_TRASH);
}
@Override
public void doCleanup() throws Exception {
@ -1056,7 +1164,7 @@ public void doCleanup() throws Exception {
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
final String anotherKey = "another_key";
DFSTestUtil.createKey(anotherKey, cluster, conf);
dfsAdmin.createEncryptionZone(zone1, anotherKey);
dfsAdmin.createEncryptionZone(zone1, anotherKey, NO_TRASH);
String keyToUse = otherKey;
MyInjector injector = new MyInjector();
@ -1068,7 +1176,7 @@ public void doCleanup() throws Exception {
injector.ready.await();
fsWrapper.delete(zone1, true);
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, keyToUse);
dfsAdmin.createEncryptionZone(zone1, keyToUse, NO_TRASH);
if (keyToUse == otherKey) {
keyToUse = anotherKey;
} else {
@ -1129,7 +1237,7 @@ public void testFsckOnEncryptionZones() throws Exception {
final Path zone1 = new Path(zoneParent, "zone1");
final Path zone1File = new Path(zone1, "file");
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zone1File, len, (short) 1, 0xFEED);
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bStream, true);
@ -1164,7 +1272,7 @@ public void testSnapshotsOnEncryptionZones() throws Exception {
final Path zoneFile = new Path(zone, "zoneFile");
fsWrapper.mkdir(zone, FsPermission.getDirDefault(), true);
dfsAdmin.allowSnapshot(zoneParent);
dfsAdmin.createEncryptionZone(zone, TEST_KEY);
dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED);
String contents = DFSTestUtil.readFile(fs, zoneFile);
final Path snap1 = fs.createSnapshot(zoneParent, "snap1");
@ -1182,7 +1290,7 @@ public void testSnapshotsOnEncryptionZones() throws Exception {
dfsAdmin.getEncryptionZoneForPath(snap2Zone));
// Create the encryption zone again
dfsAdmin.createEncryptionZone(zone, TEST_KEY2);
dfsAdmin.createEncryptionZone(zone, TEST_KEY2, NO_TRASH);
final Path snap3 = fs.createSnapshot(zoneParent, "snap3");
final Path snap3Zone = new Path(snap3, zone.getName());
// Check that snap3's EZ has the correct settings
@ -1245,7 +1353,7 @@ public void testEncryptionZonesWithSymlinks() throws Exception {
final Path link = new Path(linkParent, "link");
final Path target = new Path(targetParent, "target");
fs.mkdirs(parent);
dfsAdmin.createEncryptionZone(parent, TEST_KEY);
dfsAdmin.createEncryptionZone(parent, TEST_KEY, NO_TRASH);
fs.mkdirs(linkParent);
fs.mkdirs(targetParent);
DFSTestUtil.createFile(fs, target, len, (short)1, 0xFEED);
@ -1259,8 +1367,8 @@ public void testEncryptionZonesWithSymlinks() throws Exception {
// encryption zones
fs.mkdirs(linkParent);
fs.mkdirs(targetParent);
dfsAdmin.createEncryptionZone(linkParent, TEST_KEY);
dfsAdmin.createEncryptionZone(targetParent, TEST_KEY);
dfsAdmin.createEncryptionZone(linkParent, TEST_KEY, NO_TRASH);
dfsAdmin.createEncryptionZone(targetParent, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, target, len, (short)1, 0xFEED);
content = DFSTestUtil.readFile(fs, target);
fs.createSymlink(target, link, false);
@ -1275,7 +1383,7 @@ public void testConcatFailsInEncryptionZones() throws Exception {
final int len = 8192;
final Path ez = new Path("/ez");
fs.mkdirs(ez);
dfsAdmin.createEncryptionZone(ez, TEST_KEY);
dfsAdmin.createEncryptionZone(ez, TEST_KEY, NO_TRASH);
final Path src1 = new Path(ez, "src1");
final Path src2 = new Path(ez, "src2");
final Path target = new Path(ez, "target");
@ -1302,7 +1410,7 @@ public void testOfflineImageViewerOnEncryptionZones() throws Exception {
final Path zone1 = new Path(zoneParent, "zone1");
final Path zone1File = new Path(zone1, "file");
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zone1File, len, (short) 1, 0xFEED);
fs.setSafeMode(SafeModeAction.SAFEMODE_ENTER, false);
fs.saveNamespace();
@ -1332,7 +1440,7 @@ public void testEncryptionZonesOnRootPath() throws Exception {
final Path rootDir = new Path("/");
final Path zoneFile = new Path(rootDir, "file");
final Path rawFile = new Path("/.reserved/raw/file");
dfsAdmin.createEncryptionZone(rootDir, TEST_KEY);
dfsAdmin.createEncryptionZone(rootDir, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED);
assertEquals("File can be created on the root encryption zone " +
@ -1353,7 +1461,7 @@ public void testEncryptionZonesOnRelativePath() throws Exception {
final Path zoneFile = new Path("file");
fs.setWorkingDirectory(baseDir);
fs.mkdirs(zoneDir);
dfsAdmin.createEncryptionZone(zoneDir, TEST_KEY);
dfsAdmin.createEncryptionZone(zoneDir, TEST_KEY, NO_TRASH);
DFSTestUtil.createFile(fs, zoneFile, len, (short) 1, 0xFEED);
assertNumZones(1);
@ -1367,7 +1475,7 @@ public void testEncryptionZonesOnRelativePath() throws Exception {
public void testGetEncryptionZoneOnANonExistentZoneFile() throws Exception {
final Path ez = new Path("/ez");
fs.mkdirs(ez);
dfsAdmin.createEncryptionZone(ez, TEST_KEY);
dfsAdmin.createEncryptionZone(ez, TEST_KEY, NO_TRASH);
Path zoneFile = new Path(ez, "file");
try {
fs.getEZForPath(zoneFile);
@ -1392,7 +1500,7 @@ public void testEncryptionZoneWithTrash() throws Exception {
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
final Path zone1 = new Path("/zone1");
fs.mkdirs(zone1);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY);
dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH);
// Create the encrypted file in zone1
final Path encFile1 = new Path(zone1, "encFile1");
@ -1413,12 +1521,12 @@ public void testEncryptionZoneWithTrash() throws Exception {
final Path topEZ = new Path("/topEZ");
fs.mkdirs(topEZ);
dfsAdmin.createEncryptionZone(topEZ, TEST_KEY);
dfsAdmin.createEncryptionZone(topEZ, TEST_KEY, NO_TRASH);
final String NESTED_EZ_TEST_KEY = "nested_ez_test_key";
DFSTestUtil.createKey(NESTED_EZ_TEST_KEY, cluster, conf);
final Path nestedEZ = new Path(topEZ, "nestedEZ");
fs.mkdirs(nestedEZ);
dfsAdmin.createEncryptionZone(nestedEZ, NESTED_EZ_TEST_KEY);
dfsAdmin.createEncryptionZone(nestedEZ, NESTED_EZ_TEST_KEY, NO_TRASH);
final Path topEZFile = new Path(topEZ, "file");
final Path nestedEZFile = new Path(nestedEZ, "file");
DFSTestUtil.createFile(fs, topEZFile, len, (short) 1, 0xFEED);
@ -1433,7 +1541,7 @@ public void testEncryptionZoneWithTrash() throws Exception {
public void testRootDirEZTrash() throws Exception {
final HdfsAdmin dfsAdmin =
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
dfsAdmin.createEncryptionZone(new Path("/"), TEST_KEY);
dfsAdmin.createEncryptionZone(new Path("/"), TEST_KEY, NO_TRASH);
final Path encFile = new Path("/encFile");
final int len = 8192;
DFSTestUtil.createFile(fs, encFile, len, (short) 1, 0xFEED);
@ -1449,13 +1557,13 @@ public void testGetTrashRoots() throws Exception {
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
Path ezRoot1 = new Path("/ez1");
fs.mkdirs(ezRoot1);
dfsAdmin.createEncryptionZone(ezRoot1, TEST_KEY);
dfsAdmin.createEncryptionZone(ezRoot1, TEST_KEY, NO_TRASH);
Path ezRoot2 = new Path("/ez2");
fs.mkdirs(ezRoot2);
dfsAdmin.createEncryptionZone(ezRoot2, TEST_KEY);
dfsAdmin.createEncryptionZone(ezRoot2, TEST_KEY, NO_TRASH);
Path ezRoot3 = new Path("/ez3");
fs.mkdirs(ezRoot3);
dfsAdmin.createEncryptionZone(ezRoot3, TEST_KEY);
dfsAdmin.createEncryptionZone(ezRoot3, TEST_KEY, NO_TRASH);
Collection<FileStatus> trashRootsBegin = fs.getTrashRoots(true);
assertEquals("Unexpected getTrashRoots result", 0, trashRootsBegin.size());

View File

@ -23,6 +23,7 @@
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.FileSystemTestHelper;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.server.namenode.ha.HATestUtil;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
@ -33,6 +34,7 @@
import java.io.File;
import java.io.IOException;
import java.util.EnumSet;
/**
* Tests interaction of encryption zones with HA failover.
@ -49,7 +51,8 @@ public class TestEncryptionZonesWithHA {
private File testRootDir;
private final String TEST_KEY = "test_key";
protected static final EnumSet< CreateEncryptionZoneFlag > NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
@Before
public void setupCluster() throws Exception {
@ -101,7 +104,7 @@ public void testEncryptionZonesTrackedOnStandby() throws Exception {
final Path dirChild = new Path(dir, "child");
final Path dirFile = new Path(dir, "file");
fs.mkdir(dir, FsPermission.getDirDefault());
dfsAdmin0.createEncryptionZone(dir, TEST_KEY);
dfsAdmin0.createEncryptionZone(dir, TEST_KEY, NO_TRASH);
fs.mkdir(dirChild, FsPermission.getDirDefault());
DFSTestUtil.createFile(fs, dirFile, len, (short) 1, 0xFEED);
String contents = DFSTestUtil.readFile(fs, dirFile);

View File

@ -73,7 +73,7 @@ protected void setProvider() {
public void testCreateEZPopulatesEDEKCache() throws Exception {
final Path zonePath = new Path("/TestEncryptionZone");
fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY, NO_TRASH);
@SuppressWarnings("unchecked")
KMSClientProvider kcp = (KMSClientProvider) Whitebox
.getInternalState(cluster.getNamesystem().getProvider(), "extension");
@ -102,7 +102,7 @@ public void testDelegationToken() throws Exception {
public void testWarmupEDEKCacheOnStartup() throws Exception {
final Path zonePath = new Path("/TestEncryptionZone");
fsWrapper.mkdir(zonePath, FsPermission.getDirDefault(), false);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY);
dfsAdmin.createEncryptionZone(zonePath, TEST_KEY, NO_TRASH);
@SuppressWarnings("unchecked")
KMSClientProvider spy = (KMSClientProvider) Whitebox

View File

@ -21,6 +21,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.PrivilegedExceptionAction;
import java.util.EnumSet;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.crypto.key.JavaKeyStoreProvider;
@ -31,6 +32,7 @@
import org.apache.hadoop.fs.FileSystemTestWrapper;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.client.CreateEncryptionZoneFlag;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.hdfs.server.namenode.EncryptionZoneManager;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
@ -61,6 +63,8 @@ public class TestReservedRawPaths {
protected FileSystemTestWrapper fsWrapper;
protected FileContextTestWrapper fcWrapper;
protected static final EnumSet< CreateEncryptionZoneFlag > NO_TRASH =
EnumSet.of(CreateEncryptionZoneFlag.NO_TRASH);
@Before
public void setup() throws Exception {
@ -114,7 +118,7 @@ public void testReadWriteRaw() throws Exception {
// Create the first enc file
final Path zone = new Path("/zone");
fs.mkdirs(zone);
dfsAdmin.createEncryptionZone(zone, TEST_KEY);
dfsAdmin.createEncryptionZone(zone, TEST_KEY, NO_TRASH);
final Path encFile1 = new Path(zone, "myfile");
DFSTestUtil.createFile(fs, encFile1, len, (short) 1, 0xFEED);
// Read them back in and compare byte-by-byte
@ -154,7 +158,7 @@ public void testGetFileStatus() throws Exception {
final Path zone = new Path("zone");
final Path slashZone = new Path("/", zone);
fs.mkdirs(slashZone);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY, NO_TRASH);
final Path base = new Path("base");
final Path reservedRaw = new Path("/.reserved/raw");
@ -186,7 +190,7 @@ public void testReservedRawMkdir() throws Exception {
final Path zone = new Path("zone");
final Path slashZone = new Path("/", zone);
fs.mkdirs(slashZone);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY, NO_TRASH);
final Path rawRoot = new Path("/.reserved/raw");
final Path dir1 = new Path("dir1");
final Path rawDir1 = new Path(rawRoot, dir1);
@ -224,7 +228,7 @@ public void testAdminAccessOnly() throws Exception {
final Path zone = new Path("zone");
final Path slashZone = new Path("/", zone);
fs.mkdirs(slashZone);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY);
dfsAdmin.createEncryptionZone(slashZone, TEST_KEY, NO_TRASH);
final Path base = new Path("base");
final Path reservedRaw = new Path("/.reserved/raw");
final int len = 8192;

View File

@ -68,6 +68,7 @@
<command>-fs NAMENODE -mkdir /foo</command>
<command>-fs NAMENODE -ls /</command>-
<crypto-admin-command>-createZone -path /foo -keyName myKey</crypto-admin-command>
<command>-fs NAMENODE -rmdir /foo/.Trash</command>
<crypto-admin-command>-createZone -path /foo -keyName myKey</crypto-admin-command>
</test-commands>
<cleanup-commands>
@ -91,7 +92,9 @@
<crypto-admin-command>-createZone -keyName myKey -path /foo/bar</crypto-admin-command>
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /foo/bar/.Trash</command>
<command>-fs NAMENODE -rmdir /foo/bar</command>
<command>-fs NAMENODE -rmdir /foo/.Trash</command>
<command>-fs NAMENODE -rmdir /foo</command>
</cleanup-commands>
<comparators>
@ -180,6 +183,7 @@
<crypto-admin-command>-createZone -path /foo/bar/baz -keyName myKey</crypto-admin-command>
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /foo/bar/baz/.Trash</command>
<command>-fs NAMENODE -rmdir /foo/bar/baz</command>
<command>-fs NAMENODE -rmdir /foo/bar</command>
<command>-fs NAMENODE -rmdir /foo/</command>
@ -205,7 +209,9 @@
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src/subdir</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst/.Trash</command>
<command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands>
<comparators>
@ -227,6 +233,7 @@
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst/.Trash</command>
<command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands>
<comparators>
@ -249,6 +256,7 @@
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rm /src/foo</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands>
@ -269,6 +277,7 @@
<command>-fs NAMENODE -ls /</command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
<command>-fs NAMENODE -rmdir /dst</command>
</cleanup-commands>
@ -292,6 +301,7 @@
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src/subdir2/subdir1</command>
<command>-fs NAMENODE -rmdir /src/subdir2</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
@ -302,5 +312,81 @@
</comparators>
</test>
<test>
<description>Test failure of provisioning a trash dir if the EZ does not exist</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-provisionTrash -path /src</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>/src is not an encryption zone.</expected-output>
</comparator>
</comparators>
</test>
<test>
<description>Test failure of provisioning a trash dir if .Trash exists</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
<crypto-admin-command>-provisionTrash -path /src</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rm /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>Will not provision new trash directory for encryption zone /src. Path already exists.</expected-output>
</comparator>
</comparators>
</test>
<test>
<description>Test success of provisioning a trash dir</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<crypto-admin-command>-provisionTrash -path /src</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>Created a trash directory for /src</expected-output>
</comparator>
</comparators>
</test>
<test>
<description>Test failure of provisioning a trash dir for incorrect EZ directory</description>
<test-commands>
<command>-fs NAMENODE -mkdir /src</command>
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
<command>-fs NAMENODE -mkdir /src/dir1</command>
<crypto-admin-command>-provisionTrash -path /src/dir1</crypto-admin-command>-
</test-commands>
<cleanup-commands>
<command>-fs NAMENODE -rmdir /src/dir1</command>
<command>-fs NAMENODE -rmdir /src/.Trash</command>
<command>-fs NAMENODE -rmdir /src</command>
</cleanup-commands>
<comparators>
<comparator>
<type>SubstringComparator</type>
<expected-output>/src/dir1 is not the root of an encryption zone.</expected-output>
</comparator>
</comparators>
</test>
</tests>
</configuration>