HDFS-6389. Rename restrictions for encryption zones. (clamb)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/fs-encryption@1606253 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2efea95213
commit
31617733ac
@ -26,6 +26,8 @@ fs-encryption (Unreleased)
|
|||||||
HDFS-6391. Get the Key/IV from the NameNode for encrypted files in
|
HDFS-6391. Get the Key/IV from the NameNode for encrypted files in
|
||||||
DFSClient. (Charles Lamb and wang)
|
DFSClient. (Charles Lamb and wang)
|
||||||
|
|
||||||
|
HDFS-6389. Rename restrictions for encryption zones. (clamb)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
import org.apache.hadoop.hdfs.protocol.Block;
|
import org.apache.hadoop.hdfs.protocol.Block;
|
||||||
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
|
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
|
||||||
import org.apache.hadoop.hdfs.protocol.DirectoryListing;
|
import org.apache.hadoop.hdfs.protocol.DirectoryListing;
|
||||||
|
import org.apache.hadoop.hdfs.protocol.EncryptionZone;
|
||||||
import org.apache.hadoop.hdfs.protocol.FSLimitException.MaxDirectoryItemsExceededException;
|
import org.apache.hadoop.hdfs.protocol.FSLimitException.MaxDirectoryItemsExceededException;
|
||||||
import org.apache.hadoop.hdfs.protocol.FSLimitException.PathComponentTooLongException;
|
import org.apache.hadoop.hdfs.protocol.FSLimitException.PathComponentTooLongException;
|
||||||
import org.apache.hadoop.hdfs.protocol.FsAclPermission;
|
import org.apache.hadoop.hdfs.protocol.FsAclPermission;
|
||||||
@ -544,6 +545,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEncryptionZoneMoveValidity(src, dst);
|
||||||
// Ensure dst has quota to accommodate rename
|
// Ensure dst has quota to accommodate rename
|
||||||
verifyFsLimitsForRename(srcIIP, dstIIP);
|
verifyFsLimitsForRename(srcIIP, dstIIP);
|
||||||
verifyQuotaForRename(srcIIP.getINodes(), dstIIP.getINodes());
|
verifyQuotaForRename(srcIIP.getINodes(), dstIIP.getINodes());
|
||||||
@ -748,6 +750,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
throw new IOException(error);
|
throw new IOException(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEncryptionZoneMoveValidity(src, dst);
|
||||||
final INode dstInode = dstIIP.getLastINode();
|
final INode dstInode = dstIIP.getLastINode();
|
||||||
List<INodeDirectorySnapshottable> snapshottableDirs =
|
List<INodeDirectorySnapshottable> snapshottableDirs =
|
||||||
new ArrayList<INodeDirectorySnapshottable>();
|
new ArrayList<INodeDirectorySnapshottable>();
|
||||||
@ -971,6 +974,37 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
throw new IOException("rename from " + src + " to " + dst + " failed.");
|
throw new IOException("rename from " + src + " to " + dst + " failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkEncryptionZoneMoveValidity(String src, String dst)
|
||||||
|
throws IOException {
|
||||||
|
final EncryptionZone srcEZ =
|
||||||
|
getFSNamesystem().getEncryptionZoneForPath(src);
|
||||||
|
final EncryptionZone dstEZ =
|
||||||
|
getFSNamesystem().getEncryptionZoneForPath(dst);
|
||||||
|
final boolean srcInEZ = srcEZ != null;
|
||||||
|
final boolean dstInEZ = dstEZ != null;
|
||||||
|
if (srcInEZ) {
|
||||||
|
if (!dstInEZ) {
|
||||||
|
throw new IOException(src + " can't be moved from an encryption zone.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dstInEZ) {
|
||||||
|
throw new IOException(src + " can't be moved into an encryption zone.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcInEZ || dstInEZ) {
|
||||||
|
if (!srcEZ.getPath().equals(dstEZ.getPath())) {
|
||||||
|
final StringBuilder sb = new StringBuilder(src);
|
||||||
|
sb.append(" can't be moved from encryption zone ");
|
||||||
|
sb.append(srcEZ.getPath());
|
||||||
|
sb.append(" to encryption zone ");
|
||||||
|
sb.append(dstEZ.getPath());
|
||||||
|
sb.append(".");
|
||||||
|
throw new IOException(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set file replication
|
* Set file replication
|
||||||
*
|
*
|
||||||
|
@ -8395,7 +8395,7 @@ List<EncryptionZone> listEncryptionZones() throws IOException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Lookup the encryption zone of a path. */
|
/** Lookup the encryption zone of a path. */
|
||||||
private EncryptionZone getEncryptionZoneForPath(String src) {
|
EncryptionZone getEncryptionZoneForPath(String src) {
|
||||||
final String[] components = INode.getPathNames(src);
|
final String[] components = INode.getPathNames(src);
|
||||||
for (int i = components.length; i > 0; i--) {
|
for (int i = components.length; i > 0; i--) {
|
||||||
final List<String> l = Arrays.asList(Arrays.copyOfRange(components, 0, i));
|
final List<String> l = Arrays.asList(Arrays.copyOfRange(components, 0, i));
|
||||||
|
@ -65,7 +65,11 @@ public void setUpCluster() throws IOException {
|
|||||||
conf.set(KeyProviderFactory.KEY_PROVIDER_PATH,
|
conf.set(KeyProviderFactory.KEY_PROVIDER_PATH,
|
||||||
JavaKeyStoreProvider.SCHEME_NAME + "://file" + tmpDir + "/test.jks");
|
JavaKeyStoreProvider.SCHEME_NAME + "://file" + tmpDir + "/test.jks");
|
||||||
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
|
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
|
||||||
fs = cluster.getFileSystem();
|
fs = createFileSystem(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FileSystem createFileSystem(Configuration conf) throws IOException {
|
||||||
|
return cluster.getFileSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -401,4 +405,23 @@ public Object run() throws Exception {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Test success of Rename EZ on a directory which is already an EZ. */
|
||||||
|
@Test(timeout = 30000)
|
||||||
|
public void testRenameEncryptionZone()
|
||||||
|
throws Exception {
|
||||||
|
final HdfsAdmin dfsAdmin =
|
||||||
|
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
|
||||||
|
FileSystem.mkdirs(fs, TEST_PATH_WITH_CHILD,
|
||||||
|
new FsPermission((short) 0777));
|
||||||
|
dfsAdmin.createEncryptionZone(TEST_PATH_WITH_CHILD, null);
|
||||||
|
FileSystem.mkdirs(fs, TEST_PATH_WITH_MULTIPLE_CHILDREN,
|
||||||
|
new FsPermission((short) 0777));
|
||||||
|
try {
|
||||||
|
fs.rename(TEST_PATH_WITH_MULTIPLE_CHILDREN, TEST_PATH);
|
||||||
|
} catch (IOException e) {
|
||||||
|
GenericTestUtils.assertExceptionContains(
|
||||||
|
"/test/foo/baz can't be moved from an encryption zone.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* 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.server.namenode;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.fs.FileContext;
|
||||||
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.fs.XAttrSetFlag;
|
||||||
|
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
||||||
|
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
||||||
|
import org.apache.hadoop.hdfs.TestEncryptionZonesAPI;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests of encryption zone operations using FileContext APIs.
|
||||||
|
*/
|
||||||
|
public class TestFileContextEncryptionZones extends TestEncryptionZonesAPI {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FileSystem createFileSystem(Configuration conf) throws IOException {
|
||||||
|
FileContextFS fcFs = new FileContextFS();
|
||||||
|
fcFs.initialize(FileSystem.getDefaultUri(conf), conf);
|
||||||
|
return fcFs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This reuses FSXAttrBaseTest's testcases by creating a filesystem
|
||||||
|
* implementation which uses FileContext by only overriding the xattr related
|
||||||
|
* methods. Other operations will use the normal filesystem.
|
||||||
|
*/
|
||||||
|
public static class FileContextFS extends DistributedFileSystem {
|
||||||
|
|
||||||
|
private FileContext fc;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URI uri, Configuration conf) throws IOException {
|
||||||
|
super.initialize(uri, conf);
|
||||||
|
fc = FileContext.getFileContext(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean rename(Path src, Path dst) throws IOException {
|
||||||
|
fc.rename(src, dst);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -262,5 +262,99 @@
|
|||||||
</comparator>
|
</comparator>
|
||||||
</comparators>
|
</comparators>
|
||||||
</test>
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<description>Test failure of renaming file cross EZ's</description>
|
||||||
|
<test-commands>
|
||||||
|
<command>-fs NAMENODE -mkdir /src</command>
|
||||||
|
<command>-fs NAMENODE -mkdir /dst</command>
|
||||||
|
<command>-fs NAMENODE -ls /</command>-
|
||||||
|
<crypto-admin-command>-createZone -path /src</crypto-admin-command>
|
||||||
|
<crypto-admin-command>-createZone -path /dst</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -mkdir /src/subdir</command>
|
||||||
|
<command>-fs NAMENODE -mv /src/subdir /dst</command>-
|
||||||
|
</test-commands>
|
||||||
|
<cleanup-commands>
|
||||||
|
<command>-fs NAMENODE -rmdir /src/subdir</command>
|
||||||
|
<crypto-admin-command>-deleteZone -path /src</crypto-admin-command>
|
||||||
|
<crypto-admin-command>-deleteZone -path /dst</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -rmdir /src</command>
|
||||||
|
<command>-fs NAMENODE -rmdir /dst</command>
|
||||||
|
</cleanup-commands>
|
||||||
|
<comparators>
|
||||||
|
<comparator>
|
||||||
|
<type>SubstringComparator</type>
|
||||||
|
<expected-output>/src/subdir can't be moved from encryption zone /src to encryption zone /dst.</expected-output>
|
||||||
|
</comparator>
|
||||||
|
</comparators>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<description>Test failure of renaming a non-EZ file into an EZ</description>
|
||||||
|
<test-commands>
|
||||||
|
<command>-fs NAMENODE -mkdir /src</command>
|
||||||
|
<command>-fs NAMENODE -mkdir /dst</command>
|
||||||
|
<command>-fs NAMENODE -ls /</command>-
|
||||||
|
<crypto-admin-command>-createZone -path /dst</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -mv /src /dst</command>-
|
||||||
|
</test-commands>
|
||||||
|
<cleanup-commands>
|
||||||
|
<crypto-admin-command>-deleteZone -path /dst</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -rmdir /src</command>
|
||||||
|
<command>-fs NAMENODE -rmdir /dst</command>
|
||||||
|
</cleanup-commands>
|
||||||
|
<comparators>
|
||||||
|
<comparator>
|
||||||
|
<type>SubstringComparator</type>
|
||||||
|
<expected-output>/src can't be moved into an encryption zone</expected-output>
|
||||||
|
</comparator>
|
||||||
|
</comparators>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<description>Test failure of renaming a non-EZ file from an EZ</description>
|
||||||
|
<test-commands>
|
||||||
|
<command>-fs NAMENODE -mkdir /src</command>
|
||||||
|
<command>-fs NAMENODE -mkdir /dst</command>
|
||||||
|
<command>-fs NAMENODE -ls /</command>-
|
||||||
|
<crypto-admin-command>-createZone -path /src</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -mv /src /dst</command>-
|
||||||
|
</test-commands>
|
||||||
|
<cleanup-commands>
|
||||||
|
<crypto-admin-command>-deleteZone -path /src</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -rmdir /src</command>
|
||||||
|
<command>-fs NAMENODE -rmdir /dst</command>
|
||||||
|
</cleanup-commands>
|
||||||
|
<comparators>
|
||||||
|
<comparator>
|
||||||
|
<type>SubstringComparator</type>
|
||||||
|
<expected-output>/src can't be moved from an encryption zone</expected-output>
|
||||||
|
</comparator>
|
||||||
|
</comparators>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
<test>
|
||||||
|
<description>Test success of renaming file intra-EZ</description>
|
||||||
|
<test-commands>
|
||||||
|
<command>-fs NAMENODE -mkdir /src</command>
|
||||||
|
<crypto-admin-command>-createZone -path /src</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -mkdir /src/subdir1</command>
|
||||||
|
<command>-fs NAMENODE -mkdir /src/subdir2</command>
|
||||||
|
<command>-fs NAMENODE -mv /src/subdir1 /src/subdir2</command>-
|
||||||
|
</test-commands>
|
||||||
|
<cleanup-commands>
|
||||||
|
<command>-fs NAMENODE -rmdir /src/subdir2/subdir1</command>
|
||||||
|
<command>-fs NAMENODE -rmdir /src/subdir2</command>
|
||||||
|
<crypto-admin-command>-deleteZone -path /src</crypto-admin-command>
|
||||||
|
<command>-fs NAMENODE -rmdir /src</command>
|
||||||
|
</cleanup-commands>
|
||||||
|
<comparators>
|
||||||
|
<comparator>
|
||||||
|
<type>SubstringComparator</type>
|
||||||
|
<expected-output></expected-output>
|
||||||
|
</comparator>
|
||||||
|
</comparators>
|
||||||
|
</test>
|
||||||
|
|
||||||
</tests>
|
</tests>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
Loading…
Reference in New Issue
Block a user