From 0922ea0aafd7334c15ecd1f412f903bd4f89f199 Mon Sep 17 00:00:00 2001 From: Xiao Chen Date: Sun, 28 Jan 2018 22:15:58 -0800 Subject: [PATCH] HDFS-12974. Exception message is not printed when creating an encryption zone fails with AuthorizationException. Contributed by fang zhenyi. (cherry picked from commit b63dcd583f0b98e785831004f41bd7c7de8b3c18) (cherry picked from commit 75be15cf021e31d167570b3038060ddce62e2120) Conflicts: hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionFaultInjector.java --- .../authorize/AuthorizationException.java | 6 ++-- .../namenode/EncryptionFaultInjector.java | 3 ++ .../namenode/FSDirEncryptionZoneOp.java | 1 + .../hadoop/hdfs/TestEncryptionZones.java | 31 ++++++++++++++++++- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java index 03f4d9971bb..79c7d1814da 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/AuthorizationException.java @@ -64,17 +64,19 @@ public class AuthorizationException extends AccessControlException { @Override public void printStackTrace() { - // Do not provide the stack-trace + printStackTrace(System.err); } @Override public void printStackTrace(PrintStream s) { // Do not provide the stack-trace + s.println(this); } @Override public void printStackTrace(PrintWriter s) { // Do not provide the stack-trace + s.println(this); } - + } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionFaultInjector.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionFaultInjector.java index 104d8c3dd37..7b51848c2ad 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionFaultInjector.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionFaultInjector.java @@ -42,4 +42,7 @@ public class EncryptionFaultInjector { @VisibleForTesting public void startFileAfterGenerateKey() throws IOException {} + + @VisibleForTesting + public void ensureKeyIsInitialized() throws IOException {} } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirEncryptionZoneOp.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirEncryptionZoneOp.java index 22039d15db3..f9c71a2ed25 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirEncryptionZoneOp.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirEncryptionZoneOp.java @@ -114,6 +114,7 @@ final class FSDirEncryptionZoneOp { throw new IOException("Must specify a key name when creating an " + "encryption zone"); } + EncryptionFaultInjector.getInstance().ensureKeyIsInitialized(); KeyProvider.Metadata metadata = provider.getMetadata(keyName); if (metadata == null) { /* diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java index b8615b44a76..1b8fe8f7b99 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestEncryptionZones.java @@ -82,9 +82,11 @@ import org.apache.hadoop.hdfs.web.WebHdfsConstants; import org.apache.hadoop.hdfs.web.WebHdfsFileSystem; import org.apache.hadoop.hdfs.web.WebHdfsTestUtil; import org.apache.hadoop.io.EnumSetWritable; +import org.apache.hadoop.ipc.RemoteException; import org.apache.hadoop.security.AccessControlException; import org.apache.hadoop.security.Credentials; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authorize.AuthorizationException; import org.apache.hadoop.security.token.Token; import org.apache.hadoop.util.DataChecksum; import org.apache.hadoop.util.ToolRunner; @@ -151,6 +153,9 @@ public class TestEncryptionZones { private File testRootDir; protected final String TEST_KEY = "test_key"; private static final String NS_METRICS = "FSNamesystem"; + private static final String AUTHORIZATION_EXCEPTION_MESSAGE = + "User [root] is not authorized to perform [READ] on key " + + "with ACL name [key2]!!"; protected FileSystemTestWrapper fsWrapper; protected FileContextTestWrapper fcWrapper; @@ -449,7 +454,6 @@ public class TestEncryptionZones { dfsAdmin.createEncryptionZone(zone2, myKeyName, NO_TRASH); assertNumZones(++numZones); assertZonePresent(myKeyName, zone2.toString()); - /* Test failure of create encryption zones as a non super user. */ final UserGroupInformation user = UserGroupInformation. createUserForTesting("user", new String[] { "mygroup" }); @@ -1070,6 +1074,31 @@ public class TestEncryptionZones { } } + private class AuthorizationExceptionInjector extends EncryptionFaultInjector { + @Override + public void ensureKeyIsInitialized() throws IOException { + throw new AuthorizationException(AUTHORIZATION_EXCEPTION_MESSAGE); + } + } + + @Test + public void testExceptionInformationReturn() { + /* Test exception information can be returned when + creating transparent encryption zone.*/ + final Path zone1 = new Path("/zone1"); + EncryptionFaultInjector.instance = new AuthorizationExceptionInjector(); + try { + dfsAdmin.createEncryptionZone(zone1, TEST_KEY, NO_TRASH); + fail("exception information can be returned when creating " + + "transparent encryption zone"); + } catch (IOException e) { + assertTrue(e instanceof RemoteException); + assertTrue(((RemoteException) e).unwrapRemoteException() + instanceof AuthorizationException); + assertExceptionContains(AUTHORIZATION_EXCEPTION_MESSAGE, e); + } + } + private class MyInjector extends EncryptionFaultInjector { volatile int generateCount; CountDownLatch ready;