You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whirr.apache.org by to...@apache.org on 2011/01/04 01:02:22 UTC

svn commit: r1054836 - in /incubator/whirr/trunk: ./ core/ core/src/main/java/org/apache/whirr/service/ core/src/main/java/org/apache/whirr/ssh/ core/src/test/java/org/apache/whirr/service/ core/src/test/java/org/apache/whirr/ssh/ src/site/confluence/

Author: tomwhite
Date: Tue Jan  4 00:02:22 2011
New Revision: 1054836

URL: http://svn.apache.org/viewvc?rev=1054836&view=rev
Log:
WHIRR-161. Check that both SSH keys belong to the same pair. Contributed by Andrei Savu.

Modified:
    incubator/whirr/trunk/CHANGES.txt
    incubator/whirr/trunk/core/pom.xml
    incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java
    incubator/whirr/trunk/core/src/main/java/org/apache/whirr/ssh/KeyPair.java
    incubator/whirr/trunk/core/src/test/java/org/apache/whirr/service/ClusterSpecTest.java
    incubator/whirr/trunk/core/src/test/java/org/apache/whirr/ssh/KeyPairTest.java
    incubator/whirr/trunk/pom.xml
    incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence
    incubator/whirr/trunk/src/site/confluence/quick-start-guide.confluence

Modified: incubator/whirr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/CHANGES.txt?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/CHANGES.txt (original)
+++ incubator/whirr/trunk/CHANGES.txt Tue Jan  4 00:02:22 2011
@@ -52,6 +52,9 @@ Trunk (unreleased changes)
     WHIRR-181. Add descriptions for CLI command options.
     (Andrei Savu via tomwhite)
 
+    WHIRR-161. Check that both SSH keys belong to the same pair.
+    (Andrei Savu via tomwhite)
+
   BUG FIXES
 
     WHIRR-128. Fix DNS resolution for clients running within EC2.

Modified: incubator/whirr/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/pom.xml?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/core/pom.xml (original)
+++ incubator/whirr/trunk/core/pom.xml Tue Jan  4 00:02:22 2011
@@ -30,6 +30,10 @@
   <name>Apache Whirr Core</name>
   <dependencies>
     <dependency>
+      <groupId>ca.juliusdavies</groupId>
+      <artifactId>not-yet-commons-ssl</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.jclouds</groupId>
       <artifactId>jclouds-allcompute</artifactId>
     </dependency>
@@ -78,6 +82,10 @@
       <artifactId>commons-io</artifactId>
     </dependency>
     <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>

Modified: incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java (original)
+++ incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java Tue Jan  4 00:02:22 2011
@@ -23,6 +23,7 @@ import static com.google.common.base.Pre
 import static org.jclouds.io.Payloads.newFilePayload;
 import static org.jclouds.io.Payloads.newStringPayload;
 import static org.jclouds.util.Utils.toStringAndClose;
+import static org.apache.whirr.ssh.KeyPair.sameKeyPair;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.Lists;
@@ -253,6 +254,10 @@ public class ClusterSpec {
       if (pair.isEncrypted()) {
         throw new ConfigurationException("Key pair is encrypted");
       }
+      if (!sameKeyPair(new File(privateKeyPath), new File(publicKeyPath))) {
+        throw new ConfigurationException("Both keys should belong " +
+           "to the same key pair");
+      }
 
       setPrivateKey(new File(privateKeyPath));
       setPublicKey(new File(publicKeyPath));

Modified: incubator/whirr/trunk/core/src/main/java/org/apache/whirr/ssh/KeyPair.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/main/java/org/apache/whirr/ssh/KeyPair.java?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/core/src/main/java/org/apache/whirr/ssh/KeyPair.java (original)
+++ incubator/whirr/trunk/core/src/main/java/org/apache/whirr/ssh/KeyPair.java Tue Jan  4 00:02:22 2011
@@ -21,18 +21,34 @@ package org.apache.whirr.ssh;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.GeneralSecurityException;
 import java.util.Map;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.io.Files;
 import com.jcraft.jsch.JSch;
 import com.jcraft.jsch.JSchException;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.ssl.PKCS8Key;
+import org.apache.commons.codec.binary.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 
 /**
  * A convenience class for generating an RSA key pair.
  */
 public class KeyPair {
 
+  private static final Logger LOG =
+    LoggerFactory.getLogger(KeyPair.class);
+
   public static Map<String, String> generate() throws JSchException {
       return generate(null);
   }
@@ -82,4 +98,47 @@ public class KeyPair {
     return ImmutableMap.<String, File> of("public", publicKeyFile,
               "private", privateKeyFile);
   }
+
+  public static boolean sameKeyPair(File privateKeyFile, File publicKeyFile) throws IOException {
+    try {
+      PKCS8Key decodedKey = new PKCS8Key(
+          new FileInputStream(privateKeyFile), null);
+      PrivateKey privateKey = decodedKey.getPrivateKey();
+      PublicKey publicKey = decodedKey.getPublicKey();
+
+      byte[] actual = encodePublicKey((RSAPublicKey) publicKey);
+      byte[] expected = IOUtils.toByteArray(new FileReader(publicKeyFile));
+
+      for(int i=0; i<actual.length; i += 1) {
+        if (actual[i] != expected[i]) {
+          return false;
+        }
+      }
+      return true;
+    } catch (GeneralSecurityException e) {
+      LOG.error("Key pair validation failed", e);
+      return false;
+    }
+  }
+
+  private static byte[] encodePublicKey(RSAPublicKey key) throws IOException {
+    ByteArrayOutputStream keyBlob = new ByteArrayOutputStream();
+    write("ssh-rsa".getBytes(), keyBlob);
+    write(key.getPublicExponent().toByteArray(), keyBlob);
+    write(key.getModulus().toByteArray(), keyBlob);
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    out.write("ssh-rsa ".getBytes());
+    out.write(Base64.encodeBase64(keyBlob.toByteArray()));
+
+    return out.toByteArray();
+  }
+
+  private static void write(byte[] str, OutputStream os)
+  throws IOException {
+    for (int shift = 24; shift >= 0; shift -= 8)
+      os.write((str.length >>> shift) & 0xFF);
+    os.write(str);
+  }
+
 }

Modified: incubator/whirr/trunk/core/src/test/java/org/apache/whirr/service/ClusterSpecTest.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/test/java/org/apache/whirr/service/ClusterSpecTest.java?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/core/src/test/java/org/apache/whirr/service/ClusterSpecTest.java (original)
+++ incubator/whirr/trunk/core/src/test/java/org/apache/whirr/service/ClusterSpecTest.java Tue Jan  4 00:02:22 2011
@@ -179,4 +179,15 @@ public class ClusterSpecTest {
     ClusterSpec spec = new ClusterSpec(conf);
   }
 
+  @Test(expected = ConfigurationException.class)
+  public void testNotSameKeyPair() throws JSchException, IOException, ConfigurationException {
+    Map<String, File> first = KeyPair.generateTemporaryFiles();
+    Map<String, File> second = KeyPair.generateTemporaryFiles();
+
+    Configuration conf = new PropertiesConfiguration();
+    conf.setProperty("whirr.private-key-file", first.get("private").getAbsolutePath());
+    conf.setProperty("whirr.public-key-file", second.get("public").getAbsolutePath());
+
+    ClusterSpec spec = new ClusterSpec(conf);      
+  }
 }

Modified: incubator/whirr/trunk/core/src/test/java/org/apache/whirr/ssh/KeyPairTest.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/test/java/org/apache/whirr/ssh/KeyPairTest.java?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/core/src/test/java/org/apache/whirr/ssh/KeyPairTest.java (original)
+++ incubator/whirr/trunk/core/src/test/java/org/apache/whirr/ssh/KeyPairTest.java Tue Jan  4 00:02:22 2011
@@ -18,9 +18,16 @@
 
 package org.apache.whirr.ssh;
 
+import static org.apache.whirr.ssh.KeyPair.sameKeyPair;
+import static org.apache.whirr.ssh.KeyPair.generate;
+import static org.apache.whirr.ssh.KeyPair.generateTemporaryFiles;
+
 import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.Map;
 
 import org.junit.Test;
@@ -30,8 +37,20 @@ import com.jcraft.jsch.JSchException;
 public class KeyPairTest {
 
   @Test
+  public void testNotFromSamePair() throws JSchException, IOException {
+    Map<String, File> keys = generateTemporaryFiles();
+    assertThat(sameKeyPair(keys.get("private"), keys.get("public")), is(true));
+
+    Map<String, File> other = generateTemporaryFiles();
+    assertThat(sameKeyPair(other.get("private"), other.get("public")), is(true));
+
+    assertThat(sameKeyPair(keys.get("private"), other.get("public")), is(false));
+    assertThat(sameKeyPair(other.get("private"), keys.get("public")), is(false));
+  }
+
+  @Test
   public void testGenerate() throws JSchException {
-    Map<String, String> pair = KeyPair.generate();
+    Map<String, String> pair = generate();
     assertThat(pair.get("public"),
         containsString("ssh-rsa "));
     assertThat(pair.get("private"),

Modified: incubator/whirr/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/pom.xml?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/pom.xml (original)
+++ incubator/whirr/trunk/pom.xml Tue Jan  4 00:02:22 2011
@@ -53,6 +53,11 @@
   <dependencyManagement>
     <dependencies>
       <dependency>
+        <groupId>ca.juliusdavies</groupId>
+        <artifactId>not-yet-commons-ssl</artifactId>
+        <version>0.3.11</version>
+      </dependency>
+      <dependency>
         <groupId>org.jclouds</groupId>
         <artifactId>jclouds-allcompute</artifactId>
         <version>${jclouds.version}</version>
@@ -116,6 +121,11 @@
         <version>1.4</version>
       </dependency>
       <dependency>
+        <groupId>commons-codec</groupId>
+        <artifactId>commons-codec</artifactId>
+        <version>1.4</version>
+      </dependency>
+      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>1.6.0</version>

Modified: incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence (original)
+++ incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence Tue Jan  4 00:02:22 2011
@@ -10,8 +10,8 @@ Whirr is configured using a properties f
 | {{whirr.provider}} | {{\--provider}} | {{ec2}} | The name of the cloud provider. See the [table below|#cloud-provider-config] for possible provider names.|
 | {{whirr.identity}} | {{\--identity}} | none | The cloud identity. See the [table below|#cloud-provider-config] for how this maps to the credentials for your provider. |
 | {{whirr.credential}} | {{\--credential}} | none | The cloud credential. See the [table below|#cloud-provider-config] for how this maps to the credentials for your provider. |
-| {{whirr.private-key-file}} | {{\--private-key-file}} | _\~/.ssh/id\_rsa_ | The filename of the private key used to connect to instances. Note: the public/private key must be set together, and must be passwordless. |
-| {{whirr.public-key-file}} | {{\--public-key-file}} | _\~/.ssh/id\_rsa_.pub | The filename of the public key used to connect to instances. Note: the public/private key must be set together, and must be passwordless.|
+| {{whirr.private-key-file}} | {{\--private-key-file}} | _\~/.ssh/id\_rsa_ | The filename of the private RSA key used to connect to instances. Note: the public/private key must be set together, and must be passwordless. |
+| {{whirr.public-key-file}} | {{\--public-key-file}} | _\~/.ssh/id\_rsa_.pub | The filename of the public RSA key used to connect to instances. Note: the public/private key must be set together, and must be passwordless.|
 | {{whirr.image-id}} | {{\--image-id}} | none | The ID of the image to use for instances. If not specified then a vanilla Linux image is chosen. |
 | {{whirr.hardware-id}} | {{\--hardware-id}} | none | The type of hardware to use for the instance. This must be compatible with the image ID. |
 | {{whirr.location-id}} | {{\--location-id}} | none | The location to launch instances in. If not specified then an arbitrary location will be chosen. |

Modified: incubator/whirr/trunk/src/site/confluence/quick-start-guide.confluence
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/src/site/confluence/quick-start-guide.confluence?rev=1054836&r1=1054835&r2=1054836&view=diff
==============================================================================
--- incubator/whirr/trunk/src/site/confluence/quick-start-guide.confluence (original)
+++ incubator/whirr/trunk/src/site/confluence/quick-start-guide.confluence Tue Jan  4 00:02:22 2011
@@ -48,6 +48,8 @@ Note that you do not need to choose a pa
 choose a particular image if you want to; see the [Configuration Guide|configuration-guide]
 for details. 
 
+Also note that you should use only RSA SSH keys, DSA keys are not accepted yet. 
+
 Run the following command to launch a cluster:
 
 {code}