def __prepare_key_pair(self, key_name, private_key_path, public_key_path, password): if not key_name: log.warn('user_key_name has not been defined, assuming password-based authentication') return if key_name in [k.name for k in self.driver.list_key_pairs()]: log.info('Key pair `%s` already exists, skipping import.', key_name) return if public_key_path: log.debug("importing public key from file %s ...", public_key_path) if not self.driver.import_key_pair_from_file( name=key_name, key_file_path=os.path.expandvars(os.path.expanduser(public_key_path))): raise KeypairError( 'Could not upload public key {p}' .format(p=public_key_path)) elif private_key_path: if not private_key_path.endswith('.pem'): raise KeypairError( 'can only work with .pem private keys,' ' derive public key and set user_key_public') log.debug("deriving and importing public key from private key") self.__import_pem(key_name, private_key_path, password) else: pem_file_path = os.path.join(self.storage_path, key_name + '.pem') if not os.path.exists(pem_file_path): with open(pem_file_path, 'w') as new_key_file: new_key_file.write( self.driver.create_key_pair(name=key_name)) self.__import_pem(key_name, pem_file_path, password)
def __import_pem(self, key_name, pem_file_path, password): """ Import PEM certificate with provider :param key_name: name of the key to import :param pem_file_path: path to the pem file :param password: optional password for the pem file """ key_import = self.__get_function_or_ex_function( 'import_key_pair_from_file') pem_file = os.path.expandvars(os.path.expanduser(pem_file_path)) try: pem = paramiko.RSAKey.from_private_key_file(pem_file, password) except SSHException: try: pem = paramiko.DSSKey.from_private_key_file(pem_file, password) except SSHException as e: raise KeypairError( 'could not import {f}, neither as RSA key nor as DSA key: {e}' .format(f=pem_file_path, e=e)) if not pem: raise KeypairError('could not import {f}'.format(f=pem_file_path)) else: with NamedTemporaryFile('w+t') as f: f.write('{n} {p}'.format(n=pem.get_name(), p=pem.get_base64())) key_import(name=key_name, key_file_path=f.name)
def _check_keypair(self, name, public_key_path, private_key_path): connection = self._connect() keypairs = connection.get_all_key_pairs() keypairs = dict((k.name, k) for k in keypairs) # decide if dsa or rsa key is provided pkey = None is_dsa_key = False try: pkey = DSSKey.from_private_key_file(private_key_path) is_dsa_key = True except PasswordRequiredException: log.warning( "Unable to check key file `%s` because it is encrypted with a " "password. Please, ensure that you added it to the SSH agent " "with `ssh-add %s`", private_key_path, private_key_path) except SSHException: try: pkey = RSAKey.from_private_key_file(private_key_path) except PasswordRequiredException: log.warning( "Unable to check key file `%s` because it is encrypted with a " "password. Please, ensure that you added it to the SSH agent " "with `ssh-add %s`", private_key_path, private_key_path) except SSHException: raise KeypairError('File `%s` is neither a valid DSA key ' 'or RSA key.' % private_key_path) # create keys that don't exist yet if name not in keypairs: log.warning( "Keypair `%s` not found on resource `%s`, Creating a new one", name, self._url) with open(os.path.expanduser(public_key_path)) as f: key_material = f.read() try: # check for DSA on amazon if "amazon" in self._ec2host and is_dsa_key: log.error( "Apparently, amazon does not support DSA keys. " "Please specify a valid RSA key.") raise KeypairError( "Apparently, amazon does not support DSA keys." "Please specify a valid RSA key.") connection.import_key_pair(name, key_material) except Exception, ex: log.error( "Could not import key `%s` with name `%s` to `%s`", name, public_key_path, self._url) raise KeypairError( "could not create keypair `%s`: %s" % (name, ex))
def __prepare_key_pair(self, key_name, private_key_path, public_key_path, password): if not key_name: log.warn('user_key_name has not been defined, assuming password based authentication') return try: list_key_pairs = self.__get_function_by_pattern('list_key_pairs') except AttributeError: raise UnsupportedError('key management not supported by provider') try: self.__get_function_or_ex_function('import_key_pair_from_file') except AttributeError: raise UnsupportedError('key import not supported by provider') try: self.__get_function_or_ex_function('create_key_pair') except AttributeError: raise UnsupportedError('key creation not supported by provider') if key_name in [k.name for k in list_key_pairs()]: log.info('Key pair (%s) already exists, skipping import.', key_name) return if public_key_path: log.debug("importing public key from path %s", public_key_path) key_import = self.__get_function_or_ex_function('import_key_pair_from_file') if not key_import(name=key_name, key_file_path=os.path.expandvars(os.path.expanduser(public_key_path))): raise KeypairError('failure during import of public key {p}'.format(p=public_key_path)) elif private_key_path: if not private_key_path.endswith('.pem'): raise KeypairError('can only work with .pem private keys, derive public key and set user_key_public') log.debug("deriving and importing public key from private key") self.__import_pem(key_name, private_key_path, password) elif os.path.exists(os.path.join(self.storage_path, '{p}.pem'.format(p=key_name))): self.__import_pem(key_name, os.path.join(self.storage_path, '{}.pem'.format(key_name)), password) else: with open(os.path.join(self.storage_path, '{p}.pem'.format(p=key_name)), 'w') as new_key_file: new_key_file.write(self.__get_function_or_ex_function('create_key_pair')(name=key_name)) self.__import_pem(key_name, os.path.join(self.storage_path, '{p}.pem'.format(p=key_name)), password)
def _check_keypair(self, name, public_key_path, private_key_path): """First checks if the keypair is valid, then checks if the keypair is registered with on the cloud. If not the keypair is added to the users ssh keys. :param str name: name of the ssh key :param str public_key_path: path to the ssh public key file :param str private_key_path: path to the ssh private key file :raises: `KeypairError` if key is not a valid RSA or DSA key, the key could not be uploaded or the fingerprint does not match to the one uploaded to the cloud. """ self._init_os_api() # Read key. We do it as first thing because we need it either # way, to check the fingerprint of the remote keypair if it # exists already, or to create a new keypair. pkey = None try: pkey = DSSKey.from_private_key_file(private_key_path) except PasswordRequiredException: warn( "Unable to check key file `{0}` because it is encrypted with a " "password. Please, ensure that you added it to the SSH agent " "with `ssh-add {1}`".format(private_key_path, private_key_path)) except SSHException: try: pkey = RSAKey.from_private_key_file(private_key_path) except PasswordRequiredException: warn( "Unable to check key file `{0}` because it is encrypted with a " "password. Please, ensure that you added it to the SSH agent " "with `ssh-add {1}`".format(private_key_path, private_key_path)) except SSHException: raise KeypairError('File `%s` is neither a valid DSA key ' 'or RSA key.' % private_key_path) try: # Check if a keypair `name` exists on the cloud. keypair = self.nova_client.keypairs.get(name) # Check if it has the correct keypair, but only if we can read the local key if pkey: fingerprint = str.join(':', (i.encode('hex') for i in pkey.get_fingerprint())) if fingerprint != keypair.fingerprint: raise KeypairError("Keypair `%s` is present but has " "different fingerprint. Aborting!" % name) else: warn( "Unable to check if the keypair is using the correct key.") except NotFound: log.warning( "Keypair `%s` not found on resource `%s`, Creating a new one", name, self._os_auth_url) # Create a new keypair with open(os.path.expanduser(public_key_path)) as f: key_material = f.read() try: self.nova_client.keypairs.create(name, key_material) except Exception as ex: log.error( "Could not import key `%s` with name `%s` to `%s`", name, public_key_path, self._os_auth_url) raise KeypairError("could not create keypair `%s`: %s" % (name, ex))
def _check_keypair(self, name, public_key_path, private_key_path): """First checks if the keypair is valid, then checks if the keypair is registered with on the cloud. If not the keypair is added to the users ssh keys. :param str name: name of the ssh key :param str public_key_path: path to the ssh public key file :param str private_key_path: path to the ssh private key file :raises: `KeypairError` if key is not a valid RSA or DSA key, the key could not be uploaded or the fingerprint does not match to the one uploaded to the cloud. """ connection = self._connect() keypairs = connection.get_all_key_pairs() keypairs = dict((k.name, k) for k in keypairs) # decide if dsa or rsa key is provided pkey = None is_dsa_key = False try: pkey = DSSKey.from_private_key_file(private_key_path) is_dsa_key = True except PasswordRequiredException: warn( "Unable to check key file `{0}` because it is encrypted with a " "password. Please, ensure that you added it to the SSH agent " "with `ssh-add {1}`".format(private_key_path, private_key_path)) except SSHException: try: pkey = RSAKey.from_private_key_file(private_key_path) except PasswordRequiredException: warn( "Unable to check key file `{0}` because it is encrypted with a " "password. Please, ensure that you added it to the SSH agent " "with `ssh-add {1}`".format(private_key_path, private_key_path)) except SSHException: raise KeypairError('File `%s` is neither a valid DSA key ' 'or RSA key.' % private_key_path) # create keys that don't exist yet if name not in keypairs: log.warning( "Keypair `%s` not found on resource `%s`, Creating a new one", name, self._url) with open(os.path.expanduser(public_key_path)) as f: key_material = f.read() try: # check for DSA on amazon if "amazon" in self._ec2host and is_dsa_key: log.error( "Apparently, amazon does not support DSA keys. " "Please specify a valid RSA key.") raise KeypairError( "Apparently, amazon does not support DSA keys." "Please specify a valid RSA key.") connection.import_key_pair(name, key_material) except Exception as ex: log.error( "Could not import key `%s` with name `%s` to `%s`", name, public_key_path, self._url) raise KeypairError("could not create keypair `%s`: %s" % (name, ex)) else: # check fingerprint cloud_keypair = keypairs[name] if pkey: fingerprint = str.join(':', (i.encode('hex') for i in pkey.get_fingerprint())) if fingerprint != cloud_keypair.fingerprint: if "amazon" in self._ec2host: log.error( "Apparently, Amazon does not compute the RSA key " "fingerprint as we do! We cannot check if the " "uploaded keypair is correct!") else: raise KeypairError("Keypair `%s` is present but has " "different fingerprint. Aborting!" % name)
# check fingerprint cloud_keypair = keypairs[name] if pkey: fingerprint = str.join(':', (i.encode('hex') for i in pkey.get_fingerprint())) if fingerprint != cloud_keypair.fingerprint: if "amazon" in self._ec2host: log.error( "Apparently, Amazon does not compute the RSA key " "fingerprint as we do! We cannot check if the " "uploaded keypair is correct!") else: raise KeypairError("Keypair `%s` is present but has " "different fingerprint. Aborting!" % name) def _check_security_group(self, name): """Checks if the security group exists. :param str name: name of the security group :return: str - security group id of the security group :raises: `SecurityGroupError` if group does not exist """ connection = self._connect() filters = {} if self._vpc: filters = {'vpc-id': self._vpc_id}