HDFS-10918. Add a tool to get FileEncryptionInfo from CLI. Contributed by Xiao Chen.
This commit is contained in:
parent
736d33cddd
commit
853d65a157
@ -121,4 +121,25 @@ public String toString() {
|
||||
builder.append("}");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A frozen version of {@link #toString()} to be backward compatible.
|
||||
* When backward compatibility is not needed, use {@link #toString()}, which
|
||||
* provides more info and is supposed to evolve.
|
||||
* Don't change this method except for major revisions.
|
||||
*
|
||||
* NOTE:
|
||||
* Currently this method is used by CLI for backward compatibility.
|
||||
*/
|
||||
public String toStringStable() {
|
||||
StringBuilder builder = new StringBuilder("{");
|
||||
builder.append("cipherSuite: " + cipherSuite);
|
||||
builder.append(", cryptoProtocolVersion: " + version);
|
||||
builder.append(", edek: " + Hex.encodeHexString(edek));
|
||||
builder.append(", iv: " + Hex.encodeHexString(iv));
|
||||
builder.append(", keyName: " + keyName);
|
||||
builder.append(", ezKeyVersionName: " + ezKeyVersionName);
|
||||
builder.append("}");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
import org.apache.hadoop.fs.FSDataOutputStream;
|
||||
import org.apache.hadoop.fs.FSLinkResolver;
|
||||
import org.apache.hadoop.fs.FileChecksum;
|
||||
import org.apache.hadoop.fs.FileEncryptionInfo;
|
||||
import org.apache.hadoop.fs.FileStatus;
|
||||
import org.apache.hadoop.fs.FileSystem;
|
||||
import org.apache.hadoop.fs.FileSystemLinkResolver;
|
||||
@ -2204,6 +2205,35 @@ public RemoteIterator<EncryptionZone> listEncryptionZones()
|
||||
return dfs.listEncryptionZones();
|
||||
}
|
||||
|
||||
/* HDFS only */
|
||||
public FileEncryptionInfo getFileEncryptionInfo(final Path path)
|
||||
throws IOException {
|
||||
Path absF = fixRelativePart(path);
|
||||
return new FileSystemLinkResolver<FileEncryptionInfo>() {
|
||||
@Override
|
||||
public FileEncryptionInfo doCall(final Path p) throws IOException {
|
||||
final HdfsFileStatus fi = dfs.getFileInfo(getPathName(p));
|
||||
if (fi == null) {
|
||||
throw new FileNotFoundException("File does not exist: " + p);
|
||||
}
|
||||
return fi.getFileEncryptionInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileEncryptionInfo next(final FileSystem fs, final Path p)
|
||||
throws IOException {
|
||||
if (fs instanceof DistributedFileSystem) {
|
||||
DistributedFileSystem myDfs = (DistributedFileSystem)fs;
|
||||
return myDfs.getFileEncryptionInfo(p);
|
||||
}
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot call getFileEncryptionInfo"
|
||||
+ " on a symlink to a non-DistributedFileSystem: " + path
|
||||
+ " -> " + p);
|
||||
}
|
||||
}.resolve(this, absF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXAttr(Path path, final String name, final byte[] value,
|
||||
final EnumSet<XAttrSetFlag> flag) throws IOException {
|
||||
|
@ -29,6 +29,7 @@
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.fs.BlockStoragePolicySpi;
|
||||
import org.apache.hadoop.fs.CacheFlag;
|
||||
import org.apache.hadoop.fs.FileEncryptionInfo;
|
||||
import org.apache.hadoop.fs.FileStatus;
|
||||
import org.apache.hadoop.fs.FileSystem;
|
||||
import org.apache.hadoop.fs.Path;
|
||||
@ -353,6 +354,19 @@ public RemoteIterator<EncryptionZone> listEncryptionZones()
|
||||
return dfs.listEncryptionZones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FileEncryptionInfo on the HdfsFileStatus for the given path.
|
||||
* The return value can be null if the path points to a directory, or a file
|
||||
* that is not in an encryption zone.
|
||||
*
|
||||
* @throws FileNotFoundException if the path does not exist.
|
||||
* @throws AccessControlException if no execute permission on parent path.
|
||||
*/
|
||||
public FileEncryptionInfo getFileEncryptionInfo(final Path path)
|
||||
throws IOException {
|
||||
return dfs.getFileEncryptionInfo(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes a stream of namesystem events. Only events occurring after the
|
||||
* stream is created are available.
|
||||
|
@ -25,6 +25,7 @@
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.conf.Configured;
|
||||
import org.apache.hadoop.fs.FileEncryptionInfo;
|
||||
import org.apache.hadoop.fs.FileSystem;
|
||||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.fs.RemoteIterator;
|
||||
@ -193,6 +194,53 @@ public int run(Configuration conf, List<String> args) throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
private static class GetFileEncryptionInfoCommand
|
||||
implements AdminHelper.Command {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "-getFileEncryptionInfo";
|
||||
}
|
||||
|
||||
@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 file to show encryption info.");
|
||||
return getShortUsage() + "\n" + "Get encryption info of a file.\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;
|
||||
}
|
||||
|
||||
final HdfsAdmin admin =
|
||||
new HdfsAdmin(FileSystem.getDefaultUri(conf), conf);
|
||||
try {
|
||||
final FileEncryptionInfo fei =
|
||||
admin.getFileEncryptionInfo(new Path(path));
|
||||
if (fei == null) {
|
||||
System.out.println("No FileEncryptionInfo found for path " + path);
|
||||
return 2;
|
||||
}
|
||||
System.out.println(fei.toStringStable());
|
||||
} catch (IOException e) {
|
||||
System.err.println(prettifyException(e));
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProvisionTrashCommand implements AdminHelper.Command {
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -237,6 +285,7 @@ public int run(Configuration conf, List<String> args) throws IOException {
|
||||
private static final AdminHelper.Command[] COMMANDS = {
|
||||
new CreateZoneCommand(),
|
||||
new ListZonesCommand(),
|
||||
new ProvisionTrashCommand()
|
||||
new ProvisionTrashCommand(),
|
||||
new GetFileEncryptionInfoCommand()
|
||||
};
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ Transparent Encryption in HDFS
|
||||
* [crypto command-line interface](#crypto_command-line_interface)
|
||||
* [createZone](#createZone)
|
||||
* [listZones](#listZones)
|
||||
* [provisionTrash](#provisionTrash)
|
||||
* [getFileEncryptionInfo](#getFileEncryptionInfo)
|
||||
* [Example usage](#Example_usage)
|
||||
* [Distcp considerations](#Distcp_considerations)
|
||||
* [Running as the superuser](#Running_as_the_superuser)
|
||||
@ -189,6 +191,16 @@ Provision a trash directory for an encryption zone.
|
||||
|:---- |:---- |
|
||||
| *path* | The path to the root of the encryption zone. |
|
||||
|
||||
### <a name="getFileEncryptionInfo"></a>getFileEncryptionInfo
|
||||
|
||||
Usage: `[-getFileEncryptionInfo -path <path>]`
|
||||
|
||||
Get encryption information from a file. This can be used to find out whether a file is being encrypted, and the key name / key version used to encrypt it.
|
||||
|
||||
| | |
|
||||
|:---- |:---- |
|
||||
| *path* | The path of the file to get encryption information. |
|
||||
|
||||
<a name="Example_usage"></a>Example usage
|
||||
-------------
|
||||
|
||||
@ -208,6 +220,10 @@ These instructions assume that you are running as the normal user or HDFS superu
|
||||
hadoop fs -put helloWorld /zone
|
||||
hadoop fs -cat /zone/helloWorld
|
||||
|
||||
# As the normal user, get encryption information from the file
|
||||
hdfs crypto -getFileEncryptionInfo -path /zone/helloWorld
|
||||
# console output: {cipherSuite: {name: AES/CTR/NoPadding, algorithmBlockSize: 16}, cryptoProtocolVersion: CryptoProtocolVersion{description='Encryption zones', version=1, unknownValue=null}, edek: 2010d301afbd43b58f10737ce4e93b39, iv: ade2293db2bab1a2e337f91361304cb3, keyName: mykey, ezKeyVersionName: mykey@0}
|
||||
|
||||
<a name="Distcp_considerations"></a>Distcp considerations
|
||||
---------------------
|
||||
|
||||
|
@ -388,5 +388,95 @@
|
||||
</comparator>
|
||||
</comparators>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<description>Test success of getFileEncryptionInfo on a EZ file</description>
|
||||
<test-commands>
|
||||
<command>-fs NAMENODE -mkdir /src</command>
|
||||
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
|
||||
<command>-fs NAMENODE -touchz /src/file</command>
|
||||
<crypto-admin-command>-getFileEncryptionInfo -path /src/file</crypto-admin-command>
|
||||
</test-commands>
|
||||
<cleanup-commands>
|
||||
<command>-fs NAMENODE -rm -r /src</command>
|
||||
</cleanup-commands>
|
||||
<comparators>
|
||||
<comparator>
|
||||
<type>SubstringComparator</type>
|
||||
<expected-output>keyName: myKey, ezKeyVersionName: myKey@0</expected-output>
|
||||
</comparator>
|
||||
</comparators>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<description>Test failure of getFileEncryptionInfo on a non-EZ file</description>
|
||||
<test-commands>
|
||||
<command>-fs NAMENODE -mkdir /src</command>
|
||||
<command>-fs NAMENODE -touchz /src/cleartext</command>
|
||||
<crypto-admin-command>-getFileEncryptionInfo -path /src/cleartext</crypto-admin-command>
|
||||
</test-commands>
|
||||
<cleanup-commands>
|
||||
<command>-fs NAMENODE -rm -r /src</command>
|
||||
</cleanup-commands>
|
||||
<comparators>
|
||||
<comparator>
|
||||
<type>SubstringComparator</type>
|
||||
<expected-output>No FileEncryptionInfo found for path</expected-output>
|
||||
</comparator>
|
||||
</comparators>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<description>Test failure of getFileEncryptionInfo on a non-exist file</description>
|
||||
<test-commands>
|
||||
<crypto-admin-command>-getFileEncryptionInfo -path /src/file</crypto-admin-command>
|
||||
</test-commands>
|
||||
<cleanup-commands>
|
||||
<command>-fs NAMENODE -rm -r /src</command>
|
||||
</cleanup-commands>
|
||||
<comparators>
|
||||
<comparator>
|
||||
<type>SubstringComparator</type>
|
||||
<expected-output>FileNotFoundException:</expected-output>
|
||||
</comparator>
|
||||
</comparators>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<description>Test failure of getFileEncryptionInfo on a EZ dir</description>
|
||||
<test-commands>
|
||||
<command>-fs NAMENODE -mkdir /src</command>
|
||||
<crypto-admin-command>-createZone -path /src -keyName myKey</crypto-admin-command>
|
||||
<crypto-admin-command>-getFileEncryptionInfo -path /src</crypto-admin-command>
|
||||
</test-commands>
|
||||
<cleanup-commands>
|
||||
<command>-fs NAMENODE -rm -r /src</command>
|
||||
</cleanup-commands>
|
||||
<comparators>
|
||||
<comparator>
|
||||
<type>SubstringComparator</type>
|
||||
<expected-output>No FileEncryptionInfo found for path </expected-output>
|
||||
</comparator>
|
||||
</comparators>
|
||||
</test>
|
||||
|
||||
<test>
|
||||
<description>Test failure of getFileEncryptionInfo on a EZ subdir</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/dir</command>
|
||||
<crypto-admin-command>-getFileEncryptionInfo -path /src/dir</crypto-admin-command>
|
||||
</test-commands>
|
||||
<cleanup-commands>
|
||||
<command>-fs NAMENODE -rm -r /src</command>
|
||||
</cleanup-commands>
|
||||
<comparators>
|
||||
<comparator>
|
||||
<type>SubstringComparator</type>
|
||||
<expected-output>No FileEncryptionInfo found for path </expected-output>
|
||||
</comparator>
|
||||
</comparators>
|
||||
</test>
|
||||
</tests>
|
||||
</configuration>
|
||||
|
Loading…
Reference in New Issue
Block a user