You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by sm...@apache.org on 2015/03/16 17:48:47 UTC

[14/19] incubator-slider git commit: SLIDER-811 added provider/alias options to client getcertstore command

SLIDER-811 added provider/alias options to client getcertstore command


Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/dd2a70bd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/dd2a70bd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/dd2a70bd

Branch: refs/heads/feature/package_simplification_II
Commit: dd2a70bd63a60178de8a5d67e5ab2a43ac281420
Parents: 148a435
Author: Billie Rinaldi <bi...@gmail.com>
Authored: Fri Mar 13 06:47:24 2015 -0700
Committer: Billie Rinaldi <bi...@gmail.com>
Committed: Fri Mar 13 10:36:46 2015 -0700

----------------------------------------------------------------------
 .../org/apache/slider/client/SliderClient.java  |  50 +++++--
 .../slider/common/params/ActionClientArgs.java  |  11 +-
 .../apache/slider/common/params/Arguments.java  |   1 +
 .../AMClientCertStoreRetrievalIT.groovy         | 131 ++++++++++++++-----
 4 files changed, 148 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/dd2a70bd/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
index 8c1a9b2..df3ba95 100644
--- a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
+++ b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java
@@ -697,7 +697,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
     return startCluster(clustername, createArgs);
   }
 
-  private void checkForCredentials(Configuration conf,
+  private static void checkForCredentials(Configuration conf,
       ConfTree tree) throws IOException {
     if (tree.credentials == null || tree.credentials.size()==0) {
       log.info("No credentials requested");
@@ -726,9 +726,6 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
               br = new BufferedReader(new InputStreamReader(System.in));
             }
             char[] pass = readPassword(alias, br);
-            if (pass == null)
-              throw new IOException("Could not read credentials for " + alias +
-                  " from stdin");
             credentialProvider.createCredentialEntry(alias, pass);
             credentialProvider.flush();
             Arrays.fill(pass, ' ');
@@ -742,9 +739,21 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
     }
   }
 
+  private static char[] readOnePassword(String alias) throws IOException {
+    BufferedReader br = null;
+    try {
+      br = new BufferedReader(new InputStreamReader(System.in));
+      return readPassword(alias, br);
+    } finally {
+      if (br != null) {
+        br.close();
+      }
+    }
+  }
+
   // using a normal reader instead of a secure one,
   // because stdin is not hooked up to the command line
-  private char[] readPassword(String alias, BufferedReader br)
+  private static char[] readPassword(String alias, BufferedReader br)
       throws IOException {
     char[] cred = null;
 
@@ -763,6 +772,9 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
       }
       if (newPassword2 != null) Arrays.fill(newPassword2, ' ');
     } while (noMatch);
+    if (cred == null)
+      throw new IOException("Could not read credentials for " + alias +
+          " from stdin");
     return cred;
   }
 
@@ -944,7 +956,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
     }
 
     if (clientInfo.name == null) {
-      throw new BadCommandArgumentsException("No applicaiton name specified\n"
+      throw new BadCommandArgumentsException("No application name specified\n"
                                              + CommonArgs.usage(serviceArgs,
                                                                 ACTION_CLIENT));
     }
@@ -975,14 +987,26 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
 
     String password = clientInfo.password;
     if (password == null) {
-      // get a password
-      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-      try {
-        password = String.valueOf(readPassword(type.name(), br));
-      } finally {
-        if (br != null) {
-          br.close();
+      String provider = clientInfo.provider;
+      String alias = clientInfo.alias;
+      if (provider != null && alias != null) {
+        Configuration conf = new Configuration(getConfig());
+        conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, provider);
+        char[] chars = conf.getPassword(alias);
+        if (chars == null) {
+          CredentialProvider credentialProvider =
+              CredentialProviderFactory.getProviders(conf).get(0);
+          chars = readOnePassword(alias);
+          credentialProvider.createCredentialEntry(alias, chars);
+          credentialProvider.flush();
         }
+        password = String.valueOf(chars);
+        Arrays.fill(chars, ' ');
+      } else {
+        log.info("No password and no provider/alias pair were provided, " +
+            "prompting for password");
+        // get a password
+        password = String.valueOf(readOnePassword(type.name()));
       }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/dd2a70bd/slider-core/src/main/java/org/apache/slider/common/params/ActionClientArgs.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/params/ActionClientArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/ActionClientArgs.java
index c7f8c2e..85d39ea 100644
--- a/slider-core/src/main/java/org/apache/slider/common/params/ActionClientArgs.java
+++ b/slider-core/src/main/java/org/apache/slider/common/params/ActionClientArgs.java
@@ -57,8 +57,17 @@ public class ActionClientArgs extends AbstractActionArgs {
       description = "The name of the application")
   public String name;
 
+  @Parameter(names = {ARG_PROVIDER},
+      description = "The credential provider in which the password is stored")
+  public String provider;
+
+  @Parameter(names = {ARG_ALIAS},
+      description = "The credential provider alias associated with the password")
+  public String alias;
+
   @Parameter(names = {ARG_PASSWORD},
-      description = "The certificate store password")
+      description = "The certificate store password (alternative to " +
+          "provider/alias; if password is specified, those will be ignored)")
   public String password;
 
   @Parameter(names = {ARG_PACKAGE},

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/dd2a70bd/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java b/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
index 14be81e..9164edc 100644
--- a/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
+++ b/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
@@ -27,6 +27,7 @@ package org.apache.slider.common.params;
  */
 public interface Arguments {
   String ARG_ALL = "--all";
+  String ARG_ALIAS = "--alias";
   String ARG_APPLICATION = "--application";
   String ARG_APP_HOME = "--apphome";
   String ARG_BASE_PATH = "--basepath";

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/dd2a70bd/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AMClientCertStoreRetrievalIT.groovy
----------------------------------------------------------------------
diff --git a/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AMClientCertStoreRetrievalIT.groovy b/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AMClientCertStoreRetrievalIT.groovy
index ab632d2..3163387 100644
--- a/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AMClientCertStoreRetrievalIT.groovy
+++ b/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AMClientCertStoreRetrievalIT.groovy
@@ -18,15 +18,14 @@
 
 package org.apache.slider.funtest.lifecycle
 
-import com.jcraft.jsch.Session
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
-import org.apache.bigtop.itest.shell.Shell
-import org.apache.chaos.remote.RemoteServer
-import org.apache.chaos.remote.SshCommands
+import org.apache.hadoop.conf.Configuration
+import org.apache.hadoop.fs.Path
+import org.apache.hadoop.security.ProviderUtils
 import org.apache.hadoop.security.UserGroupInformation
-import org.apache.hadoop.yarn.api.records.YarnApplicationState
-import org.apache.hadoop.yarn.conf.YarnConfiguration
+import org.apache.hadoop.security.alias.CredentialProvider
+import org.apache.hadoop.security.alias.CredentialProviderFactory
 import org.apache.slider.common.SliderExitCodes
 import org.apache.slider.common.params.Arguments
 import org.apache.slider.common.params.SliderActions
@@ -35,7 +34,6 @@ import org.apache.slider.funtest.framework.FuntestProperties
 import org.apache.slider.funtest.framework.SliderShell
 import org.junit.After
 import org.junit.Assert
-import org.junit.BeforeClass
 import org.junit.Test
 
 import javax.net.ssl.TrustManager
@@ -63,6 +61,21 @@ implements FuntestProperties, Arguments, SliderExitCodes, SliderActions {
     cleanup(APPLICATION_NAME)
   }
 
+  private static KeyStore loadKeystoreFromFile(String filename,
+                                               char[] password) {
+    FileInputStream is = null
+    try {
+      is = new FileInputStream(filename)
+      KeyStore keystore = KeyStore.getInstance("pkcs12")
+      keystore.load(is, password)
+      return keystore
+    } finally {
+      if (is != null) {
+        is.close()
+      }
+    }
+  }
+
   @Test
   public void testRetrieveCertificateStores() throws Throwable {
     cleanup(APPLICATION_NAME)
@@ -105,27 +118,9 @@ implements FuntestProperties, Arguments, SliderExitCodes, SliderActions {
 
     assert new File(filename).exists()
 
-    FileInputStream is = new FileInputStream(filename);
-    KeyStore keystore = KeyStore.getInstance("pkcs12");
-    keystore.load(is, password.toCharArray());
-
-    Certificate certificate = keystore.getCertificate(
-        keystore.aliases().nextElement());
-    Assert.assertNotNull(certificate);
-
-    String hostname = InetAddress.localHost.canonicalHostName;
-
-    if (certificate instanceof X509Certificate) {
-      X509Certificate x509cert = (X509Certificate) certificate;
-
-      // Get subject
-      Principal principal = x509cert.getSubjectDN();
-      String subjectDn = principal.getName();
-      Assert.assertEquals("wrong DN",
-                          "CN=" + hostname + ", OU=" + APPLICATION_NAME + ", OU=client",
-                          subjectDn);
+    KeyStore keystore = loadKeystoreFromFile(filename, password.toCharArray())
 
-    }
+    validateKeystore(keystore)
 
     filename = "/tmp/test.truststore"
     // ensure file doesn't exist
@@ -142,15 +137,89 @@ implements FuntestProperties, Arguments, SliderExitCodes, SliderActions {
 
     assert new File(filename).exists()
 
-    is = new FileInputStream(filename);
-    KeyStore truststore = KeyStore.getInstance("pkcs12");
-    truststore.load(is, password.toCharArray());
+    KeyStore truststore = loadKeystoreFromFile(filename, password.toCharArray())
+
+    validateTruststore(keystore, truststore);
+
+    // test retrieving using credential provider to provide password
+    filename = "/tmp/test.keystore"
+    String alias = "alias.for.password"
+    String providerString = "jceks://hdfs/user/" +
+      UserGroupInformation.getCurrentUser().getShortUserName() + "/test-" +
+      APPLICATION_NAME + ".jceks"
+    Path providerPath = ProviderUtils.unnestUri(new URI(providerString))
+
+    Configuration conf = loadSliderConf()
+    conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, providerString)
+    CredentialProvider provider =
+      CredentialProviderFactory.getProviders(conf).get(0)
+    provider.createCredentialEntry(alias, password.toCharArray())
+    provider.flush()
+    assert clusterFS.exists(providerPath), "jks $providerString not created"
+    log.info("Created credential provider $providerString for test")
+
+    // ensure file doesn't exist
+    new File(filename).delete();
+
+    shell = slider(EXIT_SUCCESS,
+      [
+        ACTION_CLIENT,
+        ARG_GETCERTSTORE,
+        ARG_KEYSTORE, filename,
+        ARG_NAME, APPLICATION_NAME,
+        ARG_ALIAS, alias,
+        ARG_PROVIDER, providerString
+      ])
+
+    assert new File(filename).exists()
+
+    keystore = loadKeystoreFromFile(filename, password.toCharArray())
+
+    validateKeystore(keystore)
+
+    filename = "/tmp/test.truststore"
+    // ensure file doesn't exist
+    new File(filename).delete();
+
+    shell = slider(EXIT_SUCCESS,
+      [
+        ACTION_CLIENT,
+        ARG_GETCERTSTORE,
+        ARG_TRUSTSTORE, filename,
+        ARG_NAME, APPLICATION_NAME,
+        ARG_ALIAS, alias,
+        ARG_PROVIDER, providerString
+      ])
+
+    assert new File(filename).exists()
+
+    truststore = loadKeystoreFromFile(filename, password.toCharArray())
 
     validateTruststore(keystore, truststore);
 
   }
 
-  private void validateTruststore(KeyStore keystore, KeyStore truststore)
+  private static void validateKeystore(KeyStore keystore) {
+    Certificate certificate = keystore.getCertificate(
+      keystore.aliases().nextElement());
+    Assert.assertNotNull(certificate);
+
+    String hostname = InetAddress.localHost.canonicalHostName;
+
+    if (certificate instanceof X509Certificate) {
+      X509Certificate x509cert = (X509Certificate) certificate;
+
+      // Get subject
+      Principal principal = x509cert.getSubjectDN();
+      String subjectDn = principal.getName();
+      Assert.assertEquals("wrong DN",
+        "CN=" + hostname + ", OU=" + APPLICATION_NAME + ", OU=client",
+        subjectDn);
+
+    }
+  }
+
+  private static void validateTruststore(KeyStore keystore, KeyStore truststore)
       throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
     // obtain server cert
     Certificate certificate = keystore.getCertificate(