keys: Allow for pushing of Paramiko PEM format keys

End users don't really have a good way of using MDT if they can't push
additional MDT public keys. This adds functionality to generate a public key
line in a generic way and push Paramiko keys to the boards in the same way
OpenSSH public keys are pushed.

Change-Id: Ifdec1f4cea1d2934c07afa00e0b19c25962d368b
diff --git a/mdt/keys.py b/mdt/keys.py
index 964ee78..7864266 100644
--- a/mdt/keys.py
+++ b/mdt/keys.py
@@ -38,6 +38,12 @@
 KEYFILE_PATH = os.path.join(config.CONFIG_BASEDIR, "keys", "mdt.key")
 
 
+def GenerateAuthorizedKeysLine(paramiko_key):
+    public_key = paramiko_key.get_base64()
+    authorized_keys_line = 'ssh-rsa {0} mdt'.format(public_key)
+    return authorized_keys_line
+
+
 class Keystore:
     def __init__(self):
         if not os.path.exists(config.CONFIG_BASEDIR):
diff --git a/mdt/shell.py b/mdt/shell.py
index cef6128..313c79a 100644
--- a/mdt/shell.py
+++ b/mdt/shell.py
@@ -126,8 +126,9 @@
     '''Usage: mdt pushkey [<path-to-ssh-public-key>]
 
 Copies an SSH public key provided to the device's ~/.ssh/authorized_keys
-file. If no public key is provided, attempts to push MDTs previously generated
-public key from ~/.config/mdt/keys/mdt.key.
+file. If an MDT private key is provided, will push the public half of that key
+to the device's authorized_keys file. If no public key is provided, attempts to
+push MDTs previously generated public key from ~/.config/mdt/keys/mdt.key.
 '''
 
     def _pushMdtKey(self, client):
@@ -153,6 +154,12 @@
             sftp.mkdir('/home/mendel/.ssh', mode=0o700)
 
         with sftp.open('/home/mendel/.ssh/authorized_keys', 'a+b') as fp:
+            # Paramiko RSA private key -- get the public part by converting
+            if source_key.startswith('-----BEGIN RSA PRIVATE KEY-----'):
+                keyfp = io.StringIO(source_key)
+                pkey = RSAKey.from_private_key_file(keyfp)
+                source_key = keys.GenerateAuthorizedKeysLine(pkey)
+
             fp.write('\r\n')
             fp.write(source_key)
 
diff --git a/mdt/sshclient.py b/mdt/sshclient.py
index 270f758..9f4455d 100644
--- a/mdt/sshclient.py
+++ b/mdt/sshclient.py
@@ -79,11 +79,6 @@
         finally:
             self.client.close()
 
-    def _generateAuthorizedKeysLine(self):
-        public_key = self.keystore.key().get_base64()
-        authorized_keys_line = 'ssh-rsa {0} mdt'.format(public_key)
-        return authorized_keys_line
-
     def _pushKeyViaKeymaster(self):
         if not self.address:
             raise discoverer.DeviceNotFoundError()
@@ -93,7 +88,7 @@
 
         connection = http.client.HTTPConnection(self.address, KEYMASTER_PORT)
         try:
-            key_line = self._generateAuthorizedKeysLine()
+            key_line = keys.GenerateAuthorizedKeysLine(self.keystore.key())
             connection.request('PUT', '/', key_line + '\r\n')
             response = connection.getresponse()
         except ConnectionRefusedError as e:
@@ -102,10 +97,15 @@
             print()
             print("Did you previously connect from a different machine? If so,\n"
                   "mdt-keymaster will not be running as it only accepts a single key.\n")
-            print("You will need to either remove the key from ~/.ssh/authorized_keys\n"
-                  "via some other method (serial console, etc), or you will need to\n"
-                  "connect from the other machine to push an SSH public key to the\n"
-                  "authorized_keys file.")
+            print("You will need to either:\n"
+                  "   1) Remove the key from /home/mendel/.ssh/authorized_keys on the\n"
+                  "      device via the serial console and then restart mdt-keymaster\n"
+                  "      by running 'sudo systemctl restart mdt-keymaster'\n"
+                  "\n- or -\n\n"
+                  "   2) Copy the mdt private key from your home directory on this host\n"
+                  "      in ~/.config/mdt/keys/mdt.key to the first machine and use\n"
+                  "      'mdt pushkey mdt.key' to add that key to the device's\n"
+                  "      authorized_keys file.")
             print()
             raise KeyPushError(e)
         except ConnectionError as e: