keys: Add in pushkey and setkey to help with key management
pushkey allows someone to push their OpenSSH public key into a device's
~/.ssh/authorized_keys file, and setkey allows one to import their PEM-format
OpenSSH private key into MDT's keyfile.
Change-Id: I5301c6d8fb6365e6ac60d396aba2225e861cee66
diff --git a/mdt/keys.py b/mdt/keys.py
index 309862a..964ee78 100644
--- a/mdt/keys.py
+++ b/mdt/keys.py
@@ -19,6 +19,7 @@
import platform
import shutil
import subprocess
+import sys
import paramiko
from paramiko.ssh_exception import SSHException, PasswordRequiredException
@@ -66,6 +67,28 @@
else:
return True
+ def importKey(self, keyfile):
+ try:
+ self.pkey = RSAKey.from_private_key_file(keyfile)
+ except IOError as e:
+ print("Unable to read private key from file: {0}".format(e))
+ return False
+ except PasswordRequiredException as e:
+ print("Unable to load in private key: {0}".format(e))
+ return False
+ except SSHException as e:
+ print("Unable to import private key: {0}".format(e))
+ print("Note: Only OpenSSH keys generated using ssh-keygen in PEM format are supported.")
+ return False
+
+ try:
+ self.pkey.write_private_key_file(KEYFILE_PATH)
+ except IOError as e:
+ print("Unable to write private key to disk: {0}".format(e))
+ return False
+ else:
+ return True
+
def key(self):
return self.pkey
@@ -107,6 +130,9 @@
print("Can't copy {0}: no such file or directory.".format(source_keyfile))
return 1
- shutil.copy(source_keyfile, KEYFILE_PATH)
+ keystore = Keystore()
+ if not keystore.importKey(source_keyfile):
+ return 1
+
print("Key {0} imported.".format(source_keyfile))
return 0
diff --git a/mdt/main.py b/mdt/main.py
index d31f32d..e0b7862 100755
--- a/mdt/main.py
+++ b/mdt/main.py
@@ -96,6 +96,7 @@
'install': files.InstallCommand(),
'pull': files.PullCommand(),
'push': files.PushCommand(),
+ 'pushkey': shell.PushKeyCommand(),
'reboot': shell.RebootCommand(),
'reboot-bootloader': shell.RebootBootloaderCommand(),
'set': config.SetCommand(),
diff --git a/mdt/shell.py b/mdt/shell.py
index df4061a..4ef1441 100644
--- a/mdt/shell.py
+++ b/mdt/shell.py
@@ -15,6 +15,7 @@
'''
+import os
import sys
from mdt import command
@@ -104,3 +105,47 @@
channel = client.shellExec("sudo reboot-bootloader")
cons = console.Console(channel, sys.stdin)
return cons.run()
+
+
+class PushKeyCommand(command.NetworkCommand):
+ '''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.
+'''
+
+ def runWithClient(self, client, args):
+ key_to_push = None
+
+ if len(args) == 1:
+ # The key was most likely pushed by the NetworkCommand substrate. We
+ # can simply return here.
+ print("MDT Key pushed.")
+ return 0
+
+ if len(args) != 2:
+ print("Usage: mdt pushkey [<path-to-public-key>]")
+ return 1
+
+ source_keyfile = args[1]
+ if not os.path.exists(source_keyfile):
+ print("Can't copy {0}: no such file or directory.".format(source_keyfile))
+ return 1
+
+ source_key = ''
+ with open(args[1], 'rb') as fp:
+ source_key = fp.read()
+
+ sftp = client.openSftp()
+ try:
+ sftp.chdir('/home/mendel/.ssh')
+ except FileNotFoundError as e:
+ sftp.mkdir('/home/mendel/.ssh', mode=0o700)
+
+ with sftp.open('/home/mendel/.ssh/authorized_keys', 'a+b') as fp:
+ fp.write('\r\n')
+ fp.write(source_key)
+
+ print("Key {0} pushed.".format(source_keyfile))
+ return 0