HDFS-10918. Add a tool to get FileEncryptionInfo from CLI. Contributed by Xiao 
Chen.


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/853d65a1
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/853d65a1
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/853d65a1

Branch: refs/heads/HADOOP-12756
Commit: 853d65a157362661ccab10379c2d82e780382f83
Parents: 736d33c
Author: Xiao Chen <x...@apache.org>
Authored: Mon Oct 3 16:01:54 2016 -0700
Committer: Xiao Chen <x...@apache.org>
Committed: Mon Oct 3 16:01:54 2016 -0700

----------------------------------------------------------------------
 .../apache/hadoop/fs/FileEncryptionInfo.java    | 21 +++++
 .../hadoop/hdfs/DistributedFileSystem.java      | 30 +++++++
 .../apache/hadoop/hdfs/client/HdfsAdmin.java    | 14 +++
 .../apache/hadoop/hdfs/tools/CryptoAdmin.java   | 51 ++++++++++-
 .../src/site/markdown/TransparentEncryption.md  | 16 ++++
 .../src/test/resources/testCryptoConf.xml       | 90 ++++++++++++++++++++
 6 files changed, 221 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/853d65a1/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileEncryptionInfo.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileEncryptionInfo.java
 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileEncryptionInfo.java
index 00ddfe8..1129e07 100644
--- 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileEncryptionInfo.java
+++ 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileEncryptionInfo.java
@@ -121,4 +121,25 @@ public class FileEncryptionInfo {
     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();
+  }
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/853d65a1/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java
----------------------------------------------------------------------
diff --git 
a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java
 
b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java
index 24ffb40..548815f 100644
--- 
a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java
+++ 
b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java
@@ -41,6 +41,7 @@ import org.apache.hadoop.fs.FSDataInputStream;
 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 class DistributedFileSystem extends FileSystem {
     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 {

http://git-wip-us.apache.org/repos/asf/hadoop/blob/853d65a1/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/client/HdfsAdmin.java
----------------------------------------------------------------------
diff --git 
a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/client/HdfsAdmin.java
 
b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/client/HdfsAdmin.java
index bac2809..b12fe01 100644
--- 
a/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/client/HdfsAdmin.java
+++ 
b/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/client/HdfsAdmin.java
@@ -29,6 +29,7 @@ import org.apache.hadoop.classification.InterfaceStability;
 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;
@@ -354,6 +355,19 @@ public class HdfsAdmin {
   }
 
   /**
+   * 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.
    * See {@link org.apache.hadoop.hdfs.DFSInotifyEventInputStream}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/853d65a1/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/CryptoAdmin.java
----------------------------------------------------------------------
diff --git 
a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/CryptoAdmin.java
 
b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/CryptoAdmin.java
index 06389a1..b78da31 100644
--- 
a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/CryptoAdmin.java
+++ 
b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/CryptoAdmin.java
@@ -25,6 +25,7 @@ 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.FileEncryptionInfo;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.RemoteIterator;
@@ -193,6 +194,53 @@ public class CryptoAdmin extends Configured implements 
Tool {
     }
   }
 
+  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 class CryptoAdmin extends Configured implements Tool 
{
   private static final AdminHelper.Command[] COMMANDS = {
       new CreateZoneCommand(),
       new ListZonesCommand(),
-      new ProvisionTrashCommand()
+      new ProvisionTrashCommand(),
+      new GetFileEncryptionInfoCommand()
   };
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/853d65a1/hadoop-hdfs-project/hadoop-hdfs/src/site/markdown/TransparentEncryption.md
----------------------------------------------------------------------
diff --git 
a/hadoop-hdfs-project/hadoop-hdfs/src/site/markdown/TransparentEncryption.md 
b/hadoop-hdfs-project/hadoop-hdfs/src/site/markdown/TransparentEncryption.md
index ee98df8..e7d9f1d 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/site/markdown/TransparentEncryption.md
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/site/markdown/TransparentEncryption.md
@@ -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
 ---------------------
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/853d65a1/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testCryptoConf.xml
----------------------------------------------------------------------
diff --git 
a/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testCryptoConf.xml 
b/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testCryptoConf.xml
index ddd4adc..0294368 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testCryptoConf.xml
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/resources/testCryptoConf.xml
@@ -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>


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to