Source code for cloudmesh_client.shell.plugins.KeyCommand

from __future__ import print_function
import json

import yaml

from cloudmesh_client.shell.command import command
from cloudmesh_client.shell.console import Console
from cloudmesh_client.common.ConfigDict import Config
from cloudmesh_client.common.Printer import Printer
from cloudmesh_client.common.ConfigDict import ConfigDict
from cloudmesh_client.default import Default
from cloudmesh_client.shell.command import PluginCommand, CloudPluginCommand
from cloudmesh_client.common.Error import Error
from cloudmesh_client.cloud.key import Key

from cloudmesh_client.common.dotdict import dotdict
from pprint import pprint


[docs]class KeyCommand(PluginCommand, CloudPluginCommand): topics = {"key": "security"} def __init__(self, context): self.context = context if self.context.debug: print("init command key") # noinspection PyUnusedLocal @command def do_key(self, args, arguments): """ :: Usage: key -h | --help key list --cloud=CLOUD key list --source=db [--format=FORMAT] key list --source=yaml [--format=FORMAT] key list --source=ssh [--dir=DIR] [--format=FORMAT] key list --source=git [--format=FORMAT] [--username=USERNAME] key list key load [--format=FORMAT] key add [NAME] [--source=FILENAME] key add [NAME] [--git] key add [NAME] [--ssh] key get NAME key default --select key delete (NAME | --select | --all) key delete NAME --cloud=CLOUD key upload [NAME] [--cloud=CLOUD] key upload [NAME] --active Manages the keys Arguments: CLOUD The cloud NAME The name of the key. SOURCE db, ssh, all KEYNAME The name of a key. For key upload it defaults to the default key name. FORMAT The format of the output (table, json, yaml) FILENAME The filename with full path in which the key is located NAME_ON_CLOUD Typically the name of the keypair on the cloud. Options: --dir=DIR the directory with keys [default: ~/.ssh] --format=FORMAT the format of the output [default: table] --source=SOURCE the source for the keys [default: db] --username=USERNAME the source for the keys [default: none] --name=KEYNAME The name of a key --all delete all keys --force delete the key form the cloud --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud. Description: key list --source=git [--username=USERNAME] lists all keys in git for the specified user. If the name is not specified it is read from cloudmesh.yaml key list --source=ssh [--dir=DIR] [--format=FORMAT] lists all keys in the directory. If the directory is not specified the default will be ~/.ssh key list --source=yaml [--dir=DIR] [--format=FORMAT] lists all keys in cloudmesh.yaml file in the specified directory. dir is by default ~/.cloudmesh key list [--format=FORMAT] list the keys in the giiven format: json, yaml, table. table is default key list Prints list of keys. NAME of the key can be specified key add ssh adds the default key with the name id_rsa.pub key add NAME --source=FILENAME adds the key specifid by the filename to the key database key get NAME Retrieves the key indicated by the NAME parameter from database and prints its fingerprint. key default --select Select the default key interactively key delete NAME deletes a key. In yaml mode it can delete only key that are not saved in the database key rename NAME NEW renames the key from NAME to NEW. """ # pprint(arguments) invalid_names = ['tbd', 'none', "", 'id_rsa'] def _print_dict(d, header=None, format='table'): msg = Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=format, sort_keys=True) if msg is None: Console.error("No keys found.", traceflag=False) return None else: return msg directory = Config.path_expand(arguments["--dir"]) cloud = arguments["--cloud"] or Default.cloud if arguments['list']: _format = arguments['--format'] _source = arguments['--source'] _dir = arguments['--dir'] if "--source" not in arguments and "--cloud" not in arguments: arguments["--source"] = 'db' if arguments['--cloud']: # # get key list from openstack cloud # #keys = Key.list(cloud, output=_format) #keys = Key.list_on_cloud(cloud, live=True, format=_format) keys = Key.get_from_cloud(cloud, live=True, format=_format) if keys is None: Console.ok("The Key list is empty") else: print(Printer.write(keys, order=["name", "fingerprint"], output=_format or "table")) return "" elif arguments['--source'] == 'ssh': try: #sshm = SSHKeyManager() d = Key.get_from_dir(directory, store=False) #print("SSS", type(Key.__keys__)) #d = dict(Key.all()) #print(d) print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output="table")) # d = dict(sshm.__keys__) # print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) return "" except Exception as e: Error.traceback(e) Console.error("Problem listing keys from ssh") elif arguments['--source'] in ['cm', 'cloudmesh', 'yaml']: try: #sshm = SSHKeyManager() d = Key.get_from_yaml(load_order=directory, store=False) print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=_format)) return "" except Exception as e: Error.traceback(e) Console.error("Problem listing keys from `{:}`".format(arguments['--source'])) elif arguments['--source'] in ['git']: username = arguments["--username"] # print(username) if username == 'none': conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh.github.username"] #sshm = SSHKeyManager() try: d = Key.get_from_git(username, store=False) print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing git keys from database") return "" elif arguments['--source'] == 'db': try: #sshdb = SSHKeyDBManager() d = Key.all(output='dict') if d is not None or d != []: print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=_format)) # print(_print_dict(d, output=arguments['--format'])) msg = "info. OK." Console.ok(msg) else: Console.error("No keys in the database") except Exception as e: Error.traceback(e) Console.error("Problem listing keys from database") elif arguments['get']: try: name = arguments['NAME'] #sshdb = SSHKeyDBManager() d = Key.all(output="dict") for key in d: if key["name"] == name: print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("The key is not in the database") # key add [NAME] [--source=FILENAME] # key add [NAME] [--git] elif arguments['add'] and arguments["--git"]: # Console.error("This feature is not yet implemented", traceflag=False) # return "" print('git add') #sshdb = SSHKeyDBManager() data = dotdict(arguments) keyname = data.NAME # # get name # conf = ConfigDict("cloudmesh.yaml") data.username = conf["cloudmesh.github.username"] data.name = arguments['NAME'] or data.username # # get git username # data.username = ConfigDict("cloudmesh.yaml")["cloudmesh.github.username"] if str(data.name).lower() in invalid_names: Console.error("The github user name is not set in the yaml file", traceflag=False) return "" try: Console.msg("Retrieving github ssh keys for user {username}".format(**data)) #sshm = SSHKeyManager() Key.get_from_git(data.username) d = Key.all() # pprint(d) except Exception as e: Console.error("Problem adding keys to git for user: {username}".format(**data)) return "" for key in d: if key is not None: key["name"] = key["name"].replace("-", "_") key["source"] = "git" key["user"] = data.name try: o = dict(key) o['value'] = key["string"] Key.add_from_dict(key) except Exception as e: Console.error("The key {name} with that finger print already exists".format(**key), traceflag=False) elif arguments['add'] and not arguments["--git"]: # key add [NAME] [--source=FILENAME] # key add [NAME] [--git] #sshdb = SSHKeyDBManager() data = dotdict() # # get name # conf = ConfigDict("cloudmesh.yaml") data.username = conf["cloudmesh.profile.user"] data.name = arguments['NAME'] or data.username data.filename = arguments['--source'] if data.filename == "db" or data.filename is None: data.filename = Config.path_expand("~/.ssh/id_rsa.pub") if str(data.name).lower() in invalid_names: msg = ("Your choice of keyname {name} is insufficient. \n" "You must be chosing a keyname that is distingct on all clouds. \n" "Possible choices are your gmail name, your XSEDE name, or \n" "some name that is uniqe. " "Best is also to set this name in \n" "cloudmesh.profile.user as " "part of your \n~/cloudmesh/cloudmesh.yaml file.") Console.error(msg.format(**data), traceflag=False) return "" try: Key.add_from_path(data.filename, data.name, source="ssh", uri="file://" + data.filename) print("Key {name} successfully added to the database".format(**data)) msg = "info. OK." Console.ok(msg) except ValueError as e: Console.error("A key with this fingerprint already exists".format(**data), traceflag=False) Console.msg("Please use check with: key list") return "" elif arguments['default']: # print("default") if arguments['--select']: keyname = None try: #sshdb = SSHKeyDBManager() select = Key.select() if select != 'q': keyname = select.split(':')[0] print("Setting key: {:} as default.".format(keyname)) Default.key = keyname msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Setting default for selected key {:} failed.".format(keyname)) else: try: #sshdb = SSHKeyDBManager() d = Key.table_dict() for i in d: if d[i]["is_default"] == "True": key = d[i] print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("Problem retrieving default key.") elif arguments['delete'] and arguments["--cloud"]: key = dotdict({ 'cloud': arguments["--cloud"], 'name': arguments["NAME"] }) try: Key.delete(key.name, key.cloud) msg = "info. OK." Console.ok(msg) except: Console.error("Problem deleting the key {name} on the cloud {cloud}".format(**key)) elif arguments['delete']: # key delete (NAME | --select| --all) data = dotdict({ 'all': arguments['--all'] or False, 'select': arguments['--select'] or False, 'name': arguments['NAME'] or False, }) pprint(data) # BUG delete all is not properly implemented if data.all: Console.TODO("Delete --all is not yet implemented.") # Key.delete() elif data.select: key = Key.select() print (key) else: # name Key.delete(data.name) msg = "info. OK." Console.ok(msg) elif arguments['upload']: # pprint(arguments) try: # # get username # conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh"]["profile"]["user"] if username in ['None', 'TBD']: username = None # # get cloudnames # clouds = [] if arguments["--active"]: cloud = 'active' else: cloud = arguments["--cloud"] or Default.cloud if cloud == "all": config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["clouds"] elif cloud == 'active': config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["active"] else: clouds.append(cloud) # # get keyname # for cloud in clouds: status = 0 #sshdb = SSHKeyDBManager() #sshm = SSHKeyManager() keys = Key.all() for key in keys: print("upload key {} -> {}".format(key["name"], cloud)) try: status = Key.add_key_to_cloud( username, key["name"], cloud) except Exception as e: Console.error("problem") if "already exists" in str(e): print("key already exists. Skipping upload. OK.") if status == 1: print("Problem uploading key {} to {}. failed.".format(key["name"], cloud)) except Exception as e: Console.error("Problem adding key to cloud")