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("}");
|
builder.append("}");
|
||||||
return builder.toString();
|
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.FSDataOutputStream;
|
||||||
import org.apache.hadoop.fs.FSLinkResolver;
|
import org.apache.hadoop.fs.FSLinkResolver;
|
||||||
import org.apache.hadoop.fs.FileChecksum;
|
import org.apache.hadoop.fs.FileChecksum;
|
||||||
|
import org.apache.hadoop.fs.FileEncryptionInfo;
|
||||||
import org.apache.hadoop.fs.FileStatus;
|
import org.apache.hadoop.fs.FileStatus;
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.FileSystemLinkResolver;
|
import org.apache.hadoop.fs.FileSystemLinkResolver;
|
||||||
@ -2204,6 +2205,35 @@ public RemoteIterator<EncryptionZone> listEncryptionZones()
|
|||||||
return dfs.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
|
@Override
|
||||||
public void setXAttr(Path path, final String name, final byte[] value,
|
public void setXAttr(Path path, final String name, final byte[] value,
|
||||||
final EnumSet<XAttrSetFlag> flag) throws IOException {
|
final EnumSet<XAttrSetFlag> flag) throws IOException {
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.BlockStoragePolicySpi;
|
import org.apache.hadoop.fs.BlockStoragePolicySpi;
|
||||||
import org.apache.hadoop.fs.CacheFlag;
|
import org.apache.hadoop.fs.CacheFlag;
|
||||||
|
import org.apache.hadoop.fs.FileEncryptionInfo;
|
||||||
import org.apache.hadoop.fs.FileStatus;
|
import org.apache.hadoop.fs.FileStatus;
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
@ -353,6 +354,19 @@ public RemoteIterator<EncryptionZone> listEncryptionZones()
|
|||||||
return dfs.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
|
* Exposes a stream of namesystem events. Only events occurring after the
|
||||||
* stream is created are available.
|
* stream is created are available.
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
import org.apache.hadoop.classification.InterfaceAudience;
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.conf.Configured;
|
import org.apache.hadoop.conf.Configured;
|
||||||
|
import org.apache.hadoop.fs.FileEncryptionInfo;
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
import org.apache.hadoop.fs.FileSystem;
|
||||||
import org.apache.hadoop.fs.Path;
|
import org.apache.hadoop.fs.Path;
|
||||||
import org.apache.hadoop.fs.RemoteIterator;
|
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 {
|
private static class ProvisionTrashCommand implements AdminHelper.Command {
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -237,6 +285,7 @@ public int run(Configuration conf, List<String> args) throws IOException {
|
|||||||
private static final AdminHelper.Command[] COMMANDS = {
|
private static final AdminHelper.Command[] COMMANDS = {
|
||||||
new CreateZoneCommand(),
|
new CreateZoneCommand(),
|
||||||
new ListZonesCommand(),
|
new ListZonesCommand(),
|
||||||
new ProvisionTrashCommand()
|
new ProvisionTrashCommand(),
|
||||||
|
new GetFileEncryptionInfoCommand()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ Transparent Encryption in HDFS
|
|||||||
* [crypto command-line interface](#crypto_command-line_interface)
|
* [crypto command-line interface](#crypto_command-line_interface)
|
||||||
* [createZone](#createZone)
|
* [createZone](#createZone)
|
||||||
* [listZones](#listZones)
|
* [listZones](#listZones)
|
||||||
|
* [provisionTrash](#provisionTrash)
|
||||||
|
* [getFileEncryptionInfo](#getFileEncryptionInfo)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#Example_usage)
|
||||||
* [Distcp considerations](#Distcp_considerations)
|
* [Distcp considerations](#Distcp_considerations)
|
||||||
* [Running as the superuser](#Running_as_the_superuser)
|
* [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. |
|
| *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
|
<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 -put helloWorld /zone
|
||||||
hadoop fs -cat /zone/helloWorld
|
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
|
<a name="Distcp_considerations"></a>Distcp considerations
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
@ -388,5 +388,95 @@
|
|||||||
</comparator>
|
</comparator>
|
||||||
</comparators>
|
</comparators>
|
||||||
</test>
|
</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>
|
</tests>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
Loading…
Reference in New Issue
Block a user