HDDS-5. Enable OzoneManager kerberos auth. Contributed by Ajay Kumar.

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

Branch: refs/heads/HDDS-4
Commit: 1e95b5def78d6b61ad2b1e7053a27bb99ee5822c
Parents: 998df5a
Author: Xiaoyu Yao <x...@apache.org>
Authored: Mon May 14 09:36:57 2018 -0700
Committer: Xiaoyu Yao <x...@apache.org>
Committed: Tue May 15 16:55:52 2018 -0700

----------------------------------------------------------------------
 .../org/apache/hadoop/hdds/HddsConfigKeys.java  |   4 +
 .../common/src/main/resources/ozone-default.xml |  33 +++-
 .../apache/hadoop/ozone/ksm/KSMConfigKeys.java  |   5 +
 .../ksm/protocol/KeySpaceManagerProtocol.java   |   4 +
 .../protocolPB/KeySpaceManagerProtocolPB.java   |   5 +
 .../hadoop/ozone/MiniOzoneClusterImpl.java      |   3 +-
 .../ozone/TestOzoneConfigurationFields.java     |   3 +-
 .../hadoop/ozone/TestSecureOzoneCluster.java    | 169 +++++++++++++++----
 .../hadoop/ozone/ksm/KeySpaceManager.java       |  53 +++++-
 .../ozone/ksm/KeySpaceManagerHttpServer.java    |   5 +-
 10 files changed, 238 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java
----------------------------------------------------------------------
diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java
index dec2c1c..a12d6ac 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/HddsConfigKeys.java
@@ -20,4 +20,8 @@ package org.apache.hadoop.hdds;
 public final class HddsConfigKeys {
   private HddsConfigKeys() {
   }
+  public static final String HDDS_KSM_KERBEROS_KEYTAB_FILE_KEY = "hdds.ksm."
+      + "kerberos.keytab.file";
+  public static final String HDDS_KSM_KERBEROS_PRINCIPAL_KEY = "hdds.ksm"
+      + ".kerberos.principal";
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-hdds/common/src/main/resources/ozone-default.xml
----------------------------------------------------------------------
diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml 
b/hadoop-hdds/common/src/main/resources/ozone-default.xml
index 46c67fd..deb286d 100644
--- a/hadoop-hdds/common/src/main/resources/ozone-default.xml
+++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml
@@ -1071,7 +1071,23 @@
     <name>ozone.scm.kerberos.principal</name>
     <value></value>
     <tag> OZONE, SECURITY</tag>
-    <description>The SCM service principal. Ex 
scm/_h...@realm.tld.</description>
+    <description>The SCM service principal. Ex 
scm/_h...@realm.com</description>
+  </property>
+
+  <property>
+    <name>hdds.ksm.kerberos.keytab.file</name>
+    <value></value>
+    <tag> HDDS, SECURITY</tag>
+    <description> The keytab file used by KSM daemon to login as its
+      service principal. The principal name is configured with
+      hdds.ksm.kerberos.principal.
+    </description>
+  </property>
+  <property>
+    <name>hdds.ksm.kerberos.principal</name>
+    <value></value>
+    <tag> HDDS, SECURITY</tag>
+    <description>The KSM service principal. Ex 
ksm/_h...@realm.com</description>
   </property>
 
   <property>
@@ -1083,4 +1099,19 @@
     <value>/etc/security/keytabs/HTTP.keytab</value>
   </property>
 
+  <property>
+    <name>hdds.ksm.web.authentication.kerberos.principal</name>
+    <value>HTTP/_h...@example.com</value>
+    <description>
+      KSM http server kerberos principal.
+    </description>
+  </property>
+  <property>
+    <name>hdds.ksm.web.authentication.kerberos.keytab</name>
+    <value>/etc/security/keytabs/HTTP.keytab</value>
+    <description>
+      KSM http server kerberos keytab.
+    </description>
+  </property>
+
 </configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/KSMConfigKeys.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/KSMConfigKeys.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/KSMConfigKeys.java
index 75cf613..d911bcb 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/KSMConfigKeys.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/KSMConfigKeys.java
@@ -78,4 +78,9 @@ public final class KSMConfigKeys {
   public static final String OZONE_KEY_DELETING_LIMIT_PER_TASK =
       "ozone.key.deleting.limit.per.task";
   public static final int OZONE_KEY_DELETING_LIMIT_PER_TASK_DEFAULT = 1000;
+
+  public static final String KSM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL =
+      "hdds.ksm.web.authentication.kerberos.principal";
+  public static final String KSM_WEB_AUTHENTICATION_KERBEROS_KEYTAB_FILE =
+      "hdds.ksm.web.authentication.kerberos.keytab";
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocol/KeySpaceManagerProtocol.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocol/KeySpaceManagerProtocol.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocol/KeySpaceManagerProtocol.java
index 54862d3..de27108 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocol/KeySpaceManagerProtocol.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocol/KeySpaceManagerProtocol.java
@@ -17,6 +17,7 @@
  */
 package org.apache.hadoop.ozone.ksm.protocol;
 
+import org.apache.hadoop.hdds.HddsConfigKeys;
 import org.apache.hadoop.ozone.ksm.helpers.KsmBucketArgs;
 import org.apache.hadoop.ozone.ksm.helpers.KsmBucketInfo;
 import org.apache.hadoop.ozone.ksm.helpers.KsmKeyArgs;
@@ -29,10 +30,13 @@ import org.apache.hadoop.ozone.protocol.proto
     .KeySpaceManagerProtocolProtos.OzoneAclInfo;
 import java.io.IOException;
 import java.util.List;
+import org.apache.hadoop.security.KerberosInfo;
 
 /**
  * Protocol to talk to KSM.
  */
+@KerberosInfo(
+    serverPrincipal = HddsConfigKeys.HDDS_KSM_KERBEROS_PRINCIPAL_KEY)
 public interface KeySpaceManagerProtocol {
 
   /**

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocolPB/KeySpaceManagerProtocolPB.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocolPB/KeySpaceManagerProtocolPB.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocolPB/KeySpaceManagerProtocolPB.java
index 8acca8a..71b9da0 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocolPB/KeySpaceManagerProtocolPB.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/ksm/protocolPB/KeySpaceManagerProtocolPB.java
@@ -18,9 +18,12 @@
 package org.apache.hadoop.ozone.ksm.protocolPB;
 
 import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.hdds.HddsConfigKeys;
 import org.apache.hadoop.ipc.ProtocolInfo;
+import org.apache.hadoop.ozone.OzoneConfigKeys;
 import org.apache.hadoop.ozone.protocol.proto
     .KeySpaceManagerProtocolProtos.KeySpaceManagerService;
+import org.apache.hadoop.security.KerberosInfo;
 
 /**
  * Protocol used to communicate with KSM.
@@ -28,6 +31,8 @@ import org.apache.hadoop.ozone.protocol.proto
 @ProtocolInfo(protocolName =
     "org.apache.hadoop.ozone.protocol.KeySpaceManagerProtocol",
     protocolVersion = 1)
+@KerberosInfo(
+    serverPrincipal = HddsConfigKeys.HDDS_KSM_KERBEROS_PRINCIPAL_KEY)
 @InterfaceAudience.Private
 public interface KeySpaceManagerProtocolPB
     extends KeySpaceManagerService.BlockingInterface {

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java
index e4f8e62..b837100 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java
@@ -344,7 +344,8 @@ public final class MiniOzoneClusterImpl implements 
MiniOzoneCluster {
      *
      * @throws IOException
      */
-    private KeySpaceManager createKSM() throws IOException {
+    private KeySpaceManager createKSM()
+        throws IOException, AuthenticationException {
       configureKSM();
       KSMStorage ksmStore = new KSMStorage(conf);
       ksmStore.setClusterId(clusterId);

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestOzoneConfigurationFields.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestOzoneConfigurationFields.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestOzoneConfigurationFields.java
index 533a3b4..a1d3fd0 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestOzoneConfigurationFields.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestOzoneConfigurationFields.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.ozone;
 
 import org.apache.hadoop.conf.TestConfigurationFieldsBase;
+import org.apache.hadoop.hdds.HddsConfigKeys;
 import org.apache.hadoop.ozone.ksm.KSMConfigKeys;
 import org.apache.hadoop.hdds.scm.ScmConfigKeys;
 
@@ -31,7 +32,7 @@ public class TestOzoneConfigurationFields extends 
TestConfigurationFieldsBase {
     xmlFilename = new String("ozone-default.xml");
     configurationClasses =
         new Class[] {OzoneConfigKeys.class, ScmConfigKeys.class,
-            KSMConfigKeys.class};
+            KSMConfigKeys.class, HddsConfigKeys.class};
     errorIfMissingConfigProps = true;
     errorIfMissingXmlProps = true;
   }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
index 9c430ad..b917dfe 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestSecureOzoneCluster.java
@@ -26,24 +26,34 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Properties;
 import java.util.UUID;
+import java.util.concurrent.Callable;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeys;
 import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
+import org.apache.hadoop.hdds.HddsConfigKeys;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.scm.ScmConfigKeys;
 import org.apache.hadoop.hdds.scm.ScmInfo;
 import org.apache.hadoop.hdds.scm.server.SCMStorage;
 import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
 import org.apache.hadoop.minikdc.MiniKdc;
+import org.apache.hadoop.ozone.ksm.KSMConfigKeys;
+import org.apache.hadoop.ozone.ksm.KSMStorage;
+import org.apache.hadoop.ozone.ksm.KeySpaceManager;
 import org.apache.hadoop.security.KerberosAuthException;
 import org.apache.hadoop.security.UserGroupInformation;
 import 
org.apache.hadoop.security.authentication.client.AuthenticationException;
 import org.apache.hadoop.security.authentication.util.KerberosUtil;
 import org.apache.hadoop.test.GenericTestUtils;
+import org.apache.hadoop.test.GenericTestUtils.LogCapturer;
 import org.apache.hadoop.test.LambdaTestUtils;
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.Timeout;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,13 +66,23 @@ public final class TestSecureOzoneCluster {
   private Logger LOGGER = LoggerFactory
       .getLogger(TestSecureOzoneCluster.class);
 
+  @Rule
+  public Timeout timeout = new Timeout(80000);
+
   private MiniKdc miniKdc;
   private OzoneConfiguration conf;
   private File workDir;
   private static Properties securityProperties;
   private File scmKeytab;
   private File spnegoKeytab;
+  private File ksmKeyTab;
   private String curUser;
+  private StorageContainerManager scm;
+  private KeySpaceManager ksm;
+
+  private static String clusterId;
+  private static String scmId;
+  private static String ksmId;
 
   @Before
   public void init() {
@@ -71,6 +91,10 @@ public final class TestSecureOzoneCluster {
       startMiniKdc();
       setSecureConfig(conf);
       createCredentialsInKDC(conf, miniKdc);
+
+      clusterId = UUID.randomUUID().toString();
+      scmId = UUID.randomUUID().toString();
+      ksmId = UUID.randomUUID().toString();
     } catch (IOException e) {
       LOGGER.error("Failed to initialize TestSecureOzoneCluster", e);
     } catch (Exception e) {
@@ -78,12 +102,30 @@ public final class TestSecureOzoneCluster {
     }
   }
 
+  @After
+  public void stop() {
+    try {
+      stopMiniKdc();
+      if (scm != null) {
+        scm.stop();
+      }
+      if (ksm != null) {
+        ksm.stop();
+      }
+    } catch (Exception e) {
+      LOGGER.error("Failed to stop TestSecureOzoneCluster", e);
+    }
+  }
+
   private void createCredentialsInKDC(Configuration conf, MiniKdc miniKdc)
       throws Exception {
     createPrincipal(scmKeytab,
         conf.get(ScmConfigKeys.OZONE_SCM_KERBEROS_PRINCIPAL_KEY));
     createPrincipal(spnegoKeytab,
-        conf.get(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY));
+        conf.get(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY),
+        conf.get(KSMConfigKeys.KSM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL));
+    createPrincipal(ksmKeyTab,
+        conf.get(HddsConfigKeys.HDDS_KSM_KERBEROS_PRINCIPAL_KEY));
   }
 
   private void createPrincipal(File keytab, String... principal)
@@ -99,6 +141,10 @@ public final class TestSecureOzoneCluster {
     miniKdc.start();
   }
 
+  private void stopMiniKdc() throws Exception {
+    miniKdc.stop();
+  }
+
   private void setSecureConfig(Configuration conf) throws IOException {
     conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
     String host = KerberosUtil.getLocalHostName();
@@ -114,59 +160,56 @@ public final class TestSecureOzoneCluster {
     conf.set(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL_KEY,
         "HTTP_SCM/" + host + "@" + realm);
 
+    conf.set(HddsConfigKeys.HDDS_KSM_KERBEROS_PRINCIPAL_KEY,
+        "ksm/" + host + "@" + realm);
+    conf.set(KSMConfigKeys.KSM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL,
+        "HTTP_KSM/" + host + "@" + realm);
+
     scmKeytab = new File(workDir, "scm.keytab");
     spnegoKeytab = new File(workDir, "http.keytab");
+    ksmKeyTab = new File(workDir, "ksm.keytab");
 
     conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY,
         scmKeytab.getAbsolutePath());
     conf.set(ScmConfigKeys.SCM_WEB_AUTHENTICATION_KERBEROS_KEYTAB_FILE_KEY,
         spnegoKeytab.getAbsolutePath());
+    conf.set(HddsConfigKeys.HDDS_KSM_KERBEROS_KEYTAB_FILE_KEY,
+        ksmKeyTab.getAbsolutePath());
 
   }
 
   @Test
   public void testSecureScmStartupSuccess() throws Exception {
+
+    initSCM();
+    scm = StorageContainerManager.createSCM(null, conf);
+    //Reads the SCM Info from SCM instance
+    ScmInfo scmInfo = scm.getClientProtocolServer().getScmInfo();
+    Assert.assertEquals(clusterId, scmInfo.getClusterId());
+    Assert.assertEquals(scmId, scmInfo.getScmId());
+  }
+
+  private void initSCM()
+      throws IOException, AuthenticationException {
     final String path = GenericTestUtils
         .getTempPath(UUID.randomUUID().toString());
     Path scmPath = Paths.get(path, "scm-meta");
     conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, scmPath.toString());
     conf.setBoolean(OzoneConfigKeys.OZONE_ENABLED, true);
     SCMStorage scmStore = new SCMStorage(conf);
-    String clusterId = UUID.randomUUID().toString();
-    String scmId = UUID.randomUUID().toString();
     scmStore.setClusterId(clusterId);
     scmStore.setScmId(scmId);
     // writes the version file properties
     scmStore.initialize();
-    StorageContainerManager scm = StorageContainerManager.createSCM(null, 
conf);
-    //Reads the SCM Info from SCM instance
-    ScmInfo scmInfo = scm.getClientProtocolServer().getScmInfo();
-    Assert.assertEquals(clusterId, scmInfo.getClusterId());
-    Assert.assertEquals(scmId, scmInfo.getScmId());
   }
 
   @Test
   public void testSecureScmStartupFailure() throws Exception {
-    final String path = GenericTestUtils
-        .getTempPath(UUID.randomUUID().toString());
-    Path scmPath = Paths.get(path, "scm-meta");
-
-    OzoneConfiguration conf = new OzoneConfiguration();
-    conf.setBoolean(OZONE_SECURITY_ENABLED_KEY, true);
-    conf.set(OzoneConfigKeys.OZONE_METADATA_DIRS, scmPath.toString());
-    conf.setBoolean(OzoneConfigKeys.OZONE_ENABLED, true);
-    conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_PRINCIPAL_KEY,
-        "scm@" + miniKdc.getRealm());
+    initSCM();
+    conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY, "");
     conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
         "kerberos");
 
-    SCMStorage scmStore = new SCMStorage(conf);
-    String clusterId = UUID.randomUUID().toString();
-    String scmId = UUID.randomUUID().toString();
-    scmStore.setClusterId(clusterId);
-    scmStore.setScmId(scmId);
-    // writes the version file properties
-    scmStore.initialize();
     LambdaTestUtils.intercept(IOException.class,
         "Running in secure mode, but config doesn't have a keytab",
         () -> {
@@ -178,28 +221,82 @@ public final class TestSecureOzoneCluster {
     conf.set(ScmConfigKeys.OZONE_SCM_KERBEROS_KEYTAB_FILE_KEY,
         "/etc/security/keytabs/scm.keytab");
 
+    testCommonKerberosFailures(
+        () -> StorageContainerManager.createSCM(null, conf));
+
+  }
+
+  private void testCommonKerberosFailures(Callable callable) throws Exception {
     LambdaTestUtils.intercept(KerberosAuthException.class, "failure "
-            + "to login: for principal:",
-        () -> {
-          StorageContainerManager.createSCM(null, conf);
-        });
+        + "to login: for principal:", callable);
     conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
         "OAuth2");
 
     LambdaTestUtils.intercept(IllegalArgumentException.class, "Invalid"
             + " attribute value for hadoop.security.authentication of OAuth2",
-        () -> {
-          StorageContainerManager.createSCM(null, conf);
-        });
+        callable);
 
     conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION,
         "KERBEROS_SSL");
     LambdaTestUtils.intercept(AuthenticationException.class,
-        "KERBEROS_SSL authentication method not support.",
-        () -> {
-          StorageContainerManager.createSCM(null, conf);
-        });
+        "KERBEROS_SSL authentication method not",
+        callable);
+  }
 
+  /**
+   * Tests the secure KSM Initialization Failure.
+   *
+   * @throws IOException
+   */
+  @Test
+  public void testSecureKsmInitializationFailure() throws Exception {
+    initSCM();
+    // Create a secure SCM instance as ksm client will connect to it
+    scm = StorageContainerManager.createSCM(null, conf);
+
+    final String path = GenericTestUtils
+        .getTempPath(UUID.randomUUID().toString());
+    KSMStorage ksmStore = new KSMStorage(conf);
+    ksmStore.setClusterId("testClusterId");
+    ksmStore.setScmId("testScmId");
+    // writes the version file properties
+    ksmStore.initialize();
+    conf.set(HddsConfigKeys.HDDS_KSM_KERBEROS_PRINCIPAL_KEY,
+        "non-existent-u...@example.com");
+    testCommonKerberosFailures(() -> KeySpaceManager.createKSM(null, conf));
+  }
+
+  /**
+   * Tests the secure KSM Initialization success.
+   *
+   * @throws IOException
+   */
+  @Test
+  public void testSecureKsmInitializationSuccess() throws Exception {
+    initSCM();
+    // Create a secure SCM instance as ksm client will connect to it
+    scm = StorageContainerManager.createSCM(null, conf);
+    LogCapturer logs = LogCapturer.captureLogs(KeySpaceManager.LOG);
+    GenericTestUtils
+        .setLogLevel(LoggerFactory.getLogger(KeySpaceManager.class.getName()),
+            org.slf4j.event.Level.INFO);
+
+    final String path = GenericTestUtils
+        .getTempPath(UUID.randomUUID().toString());
+    Path metaDirPath = Paths.get(path, "ksm-meta");
+
+    KSMStorage ksmStore = new KSMStorage(conf);
+    ksmStore.setClusterId("testClusterId");
+    ksmStore.setScmId("testScmId");
+    // writes the version file properties
+    ksmStore.initialize();
+    try {
+      ksm = KeySpaceManager.createKSM(null, conf);
+    } catch (Exception ex) {
+      // Expects timeout failure from scmClient in KSM but KSM user login via
+      // kerberos should succeed
+      Assert.assertTrue(logs.getOutput().contains("KSM login successful"));
+    }
   }
 
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java
index d0f0c9b..700260d 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManager.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.ipc.Client;
 import org.apache.hadoop.ipc.ProtobufRpcEngine;
 import org.apache.hadoop.ipc.RPC;
 import org.apache.hadoop.hdds.server.ServiceRuntimeInfoImpl;
+import org.apache.hadoop.ozone.OzoneConfigKeys;
 import org.apache.hadoop.ozone.common.Storage.StorageState;
 import org.apache.hadoop.ozone.ksm.exceptions.KSMException;
 import org.apache.hadoop.ozone.ksm.helpers.KsmBucketArgs;
@@ -59,7 +60,10 @@ import 
org.apache.hadoop.hdds.scm.protocolPB.ScmBlockLocationProtocolPB;
 import org.apache.hadoop.hdds.scm.protocolPB
     .StorageContainerLocationProtocolClientSideTranslatorPB;
 import 
org.apache.hadoop.hdds.scm.protocolPB.StorageContainerLocationProtocolPB;
+import org.apache.hadoop.security.SecurityUtil;
 import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
+import 
org.apache.hadoop.security.authentication.client.AuthenticationException;
 import org.apache.hadoop.util.GenericOptionsParser;
 import org.apache.hadoop.util.StringUtils;
 
@@ -83,6 +87,8 @@ import java.util.List;
 import java.util.Map;
 
 import static org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_ENABLED;
+import static 
org.apache.hadoop.hdds.HddsConfigKeys.HDDS_KSM_KERBEROS_PRINCIPAL_KEY;
+import static 
org.apache.hadoop.hdds.HddsConfigKeys.HDDS_KSM_KERBEROS_KEYTAB_FILE_KEY;
 import static org.apache.hadoop.ozone.ksm.KSMConfigKeys
     .OZONE_KSM_ADDRESS_KEY;
 import static org.apache.hadoop.ozone.ksm.KSMConfigKeys
@@ -102,7 +108,7 @@ import static org.apache.hadoop.util.ExitUtil.terminate;
 @InterfaceAudience.LimitedPrivate({"HDFS", "CBLOCK", "OZONE", "HBASE"})
 public final class KeySpaceManager extends ServiceRuntimeInfoImpl
     implements KeySpaceManagerProtocol, KSMMXBean {
-  private static final Logger LOG =
+  public static final Logger LOG =
       LoggerFactory.getLogger(KeySpaceManager.class);
 
   private static final String USAGE =
@@ -153,8 +159,8 @@ public final class KeySpaceManager extends 
ServiceRuntimeInfoImpl
   private KeySpaceManager(OzoneConfiguration conf) throws IOException {
     Preconditions.checkNotNull(conf);
     configuration = conf;
+
     ksmStorage = new KSMStorage(conf);
-    scmBlockClient = getScmBlockClient(configuration);
     scmContainerClient = getScmContainerClient(configuration);
     if (ksmStorage.getState() != StorageState.INITIALIZED) {
       throw new KSMException("KSM not initialized.",
@@ -162,6 +168,7 @@ public final class KeySpaceManager extends 
ServiceRuntimeInfoImpl
     }
 
     // verifies that the SCM info in the KSM Version file is correct.
+    scmBlockClient = getScmBlockClient(configuration);
     ScmInfo scmInfo = scmBlockClient.getScmInfo();
     if (!(scmInfo.getClusterId().equals(ksmStorage.getClusterID()) && scmInfo
         .getScmId().equals(ksmStorage.getScmId()))) {
@@ -194,6 +201,34 @@ public final class KeySpaceManager extends 
ServiceRuntimeInfoImpl
   }
 
   /**
+   * Login KSM service user if security and Kerberos are enabled.
+   *
+   * @param  conf
+   * @throws IOException, AuthenticationException
+   */
+  private static void loginKSMUser(OzoneConfiguration conf)
+      throws IOException, AuthenticationException {
+
+    if (SecurityUtil.getAuthenticationMethod(conf).equals
+        (AuthenticationMethod.KERBEROS)) {
+      LOG.debug("Ozone security is enabled. Attempting login for KSM user. "
+              + "Principal: {},keytab: {}", 
conf.get(HDDS_KSM_KERBEROS_PRINCIPAL_KEY),
+          conf.get(HDDS_KSM_KERBEROS_KEYTAB_FILE_KEY));
+
+      UserGroupInformation.setConfiguration(conf);
+
+      InetSocketAddress socAddr = getKsmAddress(conf);
+      SecurityUtil.login(conf, HDDS_KSM_KERBEROS_KEYTAB_FILE_KEY,
+          HDDS_KSM_KERBEROS_PRINCIPAL_KEY, socAddr.getHostName());
+    } else {
+      throw new AuthenticationException(SecurityUtil.getAuthenticationMethod
+          (conf) + " authentication method not supported. KSM user login "
+          + "failed.");
+    }
+    LOG.info("KSM login successful.");
+  }
+
+  /**
    * Create a scm block client, used by putKey() and getKey().
    *
    * @return {@link ScmBlockLocationProtocol}
@@ -337,7 +372,7 @@ public final class KeySpaceManager extends 
ServiceRuntimeInfoImpl
    */
 
   public static KeySpaceManager createKSM(String[] argv,
-      OzoneConfiguration conf) throws IOException {
+      OzoneConfiguration conf) throws IOException, AuthenticationException {
     if (!isHddsEnabled(conf)) {
       System.err.println("KSM cannot be started in secure mode or when " +
           OZONE_ENABLED + " is set to false");
@@ -349,6 +384,10 @@ public final class KeySpaceManager extends 
ServiceRuntimeInfoImpl
       terminate(1);
       return null;
     }
+    // Authenticate KSM if security is enabled
+    if (conf.getBoolean(OzoneConfigKeys.OZONE_SECURITY_ENABLED_KEY, true)) {
+      loginKSMUser(conf);
+    }
     switch (startOpt) {
     case CREATEOBJECTSTORE:
       terminate(ksmInit(conf) ? 0 : 1);
@@ -443,7 +482,13 @@ public final class KeySpaceManager extends 
ServiceRuntimeInfoImpl
     metadataManager.start();
     keyManager.start();
     ksmRpcServer.start();
-    httpServer.start();
+    try {
+      httpServer.start();
+    } catch (Exception ex) {
+      // Allow KSM to start as Http Server failure is not fatal.
+      LOG.error("KSM HttpServer failed to start.", ex);
+    }
+
     registerMXBean();
     setStartTime();
   }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/1e95b5de/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManagerHttpServer.java
----------------------------------------------------------------------
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManagerHttpServer.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManagerHttpServer.java
index 478804b..a0d15b3 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManagerHttpServer.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/ksm/KeySpaceManagerHttpServer.java
@@ -18,7 +18,6 @@
 package org.apache.hadoop.ozone.ksm;
 
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.ozone.OzoneConfigKeys;
 import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.hdds.server.BaseHttpServer;
 
@@ -65,11 +64,11 @@ public class KeySpaceManagerHttpServer extends 
BaseHttpServer {
   }
 
   @Override protected String getKeytabFile() {
-    return KSMConfigKeys.OZONE_KSM_KEYTAB_FILE;
+    return KSMConfigKeys.KSM_WEB_AUTHENTICATION_KERBEROS_KEYTAB_FILE;
   }
 
   @Override protected String getSpnegoPrincipal() {
-    return OzoneConfigKeys.OZONE_SCM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL;
+    return KSMConfigKeys.KSM_WEB_AUTHENTICATION_KERBEROS_PRINCIPAL;
   }
 
   @Override protected String getEnabledKey() {


---------------------------------------------------------------------
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