def test_bad_account_password_ssh_key(alice, tmpdir): """ Can't login with unknown username, any password, or wrong SSH pub key. """ # Any password, wrong username: for u, p in [("alice-key", "wrong"), ("someuser", "password")]: with pytest.raises(AuthenticationException): connect_sftp(connect_args={ "username": u, "password": p, }) another_key = os.path.join(str(tmpdir), "ssh_key") generate_ssh_key(another_key) good_key = RSAKey( filename=os.path.join(alice.node_dir, "private", "ssh_client_rsa_key")) bad_key = RSAKey(filename=another_key) # Wrong key: with pytest.raises(AuthenticationException): connect_sftp(connect_args={ "username": "******", "pkey": bad_key, }) # Wrong username: with pytest.raises(AuthenticationException): connect_sftp(connect_args={ "username": "******", "pkey": good_key, })
def init_key(self): if self.ssh_custom_key: return for filename in os.listdir(self.config.get('local', 'data_dir')): if not filename.startswith('yakey') or not os.path.isfile( os.path.join(self.config.get('local', 'data_dir'), filename)): continue key_path = os.path.join(self.config.get('local', 'data_dir'), filename) self.key_name = key_path.split(os.sep)[-1] pmk_key = RSAKey.from_private_key_file(key_path) logging.info('LOADED KEY %s' % key_path) break else: self.key_name = self.get_rnd_name('yakey') key = rsa.generate_private_key(backend=crypto_default_backend(), public_exponent=65537, key_size=2048) pmk_key = RSAKey(key=key) key_path = os.path.join(self.config.get('local', 'data_dir'), self.key_name) pmk_key.write_private_key_file(key_path) logging.info('WRITTEN KEY %s' % key_path) self.public_key = "%s %s" % (pmk_key.get_name(), pmk_key.get_base64()) self.ssh_custom_key = {'pkey': pmk_key} if self.yascheduler: self.yascheduler.ssh_custom_key = self.ssh_custom_key
def _authenticate_public_key(self) -> None: """ Attempt to authenticate with public key authentication Args: N/A Returns: N/A # noqa: DAR202 Raises: exc: (really the paramiko auth exception) if auth exception occurs exc: (really the paramiko base exception) if unknown exception occurs """ try: # paramiko wants to see its key in a PKey object when crafting the paramiko connection # from Transport and Channel objects from paramiko.rsakey import RSAKey # pylint: disable=C0415 paramiko_key = RSAKey(filename=self.auth_private_key) self.session.auth_publickey(self.auth_username, paramiko_key) except self.lib_auth_exception as exc: LOG.critical( f"Public key authentication with host {self.host} failed. Exception: {exc}." ) except Exception as exc: # pylint: disable=W0703 LOG.critical( "Unknown error occurred during public key authentication with host " f"{self.host}; Exception: {exc}" )
def load_ssh_key_from_file(filename): """ Load an ssh key from a file into a paramiko RSAKey object """ with open(filename, 'r') as fd: key = RSAKey(file_obj=fd) return key
def _authenticate_public_key(self) -> None: """ Attempt to authenticate with public key authentication Args: N/A Returns: None Raises: ScrapliConnectionNotOpened: if session is unopened/None """ if not self.session: raise ScrapliConnectionNotOpened if self._base_transport_args.transport_options.get( "enable_rsa2", False) is False: self.session.disabled_algorithms = { "keys": ["rsa-sha2-256", "rsa-sha2-512"] } try: paramiko_key = RSAKey( filename=self.plugin_transport_args.auth_private_key) self.session.auth_publickey( username=self.plugin_transport_args.auth_username, key=paramiko_key) except AuthenticationException: pass except Exception: # pylint: disable=W0703 pass
def from_line(cls, line): """ Parses the given line of text to find the names for the host, the type of key, and the key data. The line is expected to be in the format used by the openssh known_hosts file. Lines are expected to not have leading or trailing whitespace. We don't bother to check for comments or empty lines. All of that should be taken care of before sending the line to us. @param line: a line from an OpenSSH known_hosts file @type line: str """ fields = line.split(' ') if len(fields) < 3: # Bad number of fields return None fields = fields[:3] names, keytype, key = fields names = names.split(',') # Decide what kind of key we're looking at and create an object # to hold it accordingly. if keytype == 'ssh-rsa': key = RSAKey(data=base64.decodestring(key)) elif keytype == 'ssh-dss': key = DSSKey(data=base64.decodestring(key)) else: return None return cls(names, key)
def _authenticate_public_key(self) -> None: """ Attempt to authenticate with public key authentication Args: N/A Returns: None Raises: ScrapliConnectionNotOpened: if session is unopened/None """ if not self.session: raise ScrapliConnectionNotOpened try: paramiko_key = RSAKey( filename=self.plugin_transport_args.auth_private_key) self.session.auth_publickey( username=self.plugin_transport_args.auth_username, key=paramiko_key) except AuthenticationException: pass except Exception: # pylint: disable=W0703 pass
def _authenticate_public_key(self) -> None: """ Attempt to authenticate with public key authentication Args: N/A Returns: N/A # noqa: DAR202 Raises: N/A """ try: paramiko_key = RSAKey(filename=self.auth_private_key) self.session.auth_publickey(self.auth_username, paramiko_key) except AuthenticationException as exc: LOG.critical( f"Public key authentication with host {self.host} failed. Exception: {exc}." ) except Exception as exc: # pylint: disable=W0703 LOG.critical( "Unknown error occurred during public key authentication with host " f"{self.host}; Exception: {exc}" )
def create_rsa_key(private_key): """ Creates the RSAKey for paramiko. :param private_key: String version of the private key :return: The RSAKey object to be used in paramiko """ fobj = cStringIO.StringIO(private_key) key = RSAKey(file_obj=fobj) return key
def __init__(self, data, username=None, sudo=False, passphrase=None): self._data = data self.username = username self.sudo = sudo self.passphrase = passphrase self.pkey = None if data is not None: self.pkey = RSAKey(file_obj=io.StringIO(data), password=passphrase)
def load_ssh_key_from_keypair(kp): """ Load a nova keypair object into a paramiko RSAKey """ keyfileobject = StringIO() keyfileobject.write(kp.material) keyfileobject.seek(0) key = RSAKey(file_obj=keyfileobject) return key
def loadRsaPrivKey(name="id_rsa"): """ :rtype : paramiko.rsakey.RSAKey :type name: str """ import os.path as ospath from paramiko.rsakey import RSAKey filename = ospath.expanduser("~/.ssh/%s" % name) LOG("Loading SSH private key from %s" % filename) rsaKey = RSAKey(filename=filename) return rsaKey
def list_keys(self, identity: Identity) -> collections.abc.Set: logger = logging.getLogger(__name__ + '.GitHubKeyStore.list_keys') keys = request(identity, self.LIST_URL) result = set() for key in keys: try: pubkey = RSAKey(data=base64.b64decode(key['key'].split()[1])) except Exception as e: logger.exception(e) continue result.add(pubkey) return result
def _parse_rsa_key(msg): # This method avoids having to keep track of how paramiko handles keys # or having to go into the cryptography.hazmat modules. It takes the # parts of the key from the certificate then puts them in a Message that # resembles a normally encoded keyh. That Message is then handed to the # key constructor which should be able to handle the parsing. key_msg = Message() key_msg.add_string('ssh-rsa') key_msg.add_mpint(msg.get_mpint()) key_msg.add_mpint(msg.get_mpint()) key_msg.rewind() return RSAKey(msg=key_msg)
def from_line(cls, line, lineno=None): """ Parses the given line of text to find the names for the host, the type of key, and the key data. The line is expected to be in the format used by the OpenSSH known_hosts file. Lines are expected to not have leading or trailing whitespace. We don't bother to check for comments or empty lines. All of that should be taken care of before sending the line to us. :param str line: a line from an OpenSSH known_hosts file """ log = get_logger("paramiko.hostkeys") fields = line.split(" ") if len(fields) < 3: # Bad number of fields msg = "Not enough fields found in known_hosts in line {} ({!r})" log.info(msg.format(lineno, line)) return None fields = fields[:3] names, keytype, key = fields names = names.split(",") # Decide what kind of key we're looking at and create an object # to hold it accordingly. try: key = b(key) if keytype == "ssh-rsa": key = RSAKey(data=decodebytes(key)) elif keytype == "ssh-dss": key = DSSKey(data=decodebytes(key)) elif keytype in ECDSAKey.supported_key_format_identifiers(): key = ECDSAKey(data=decodebytes(key), validate_point=False) elif keytype == "ssh-ed25519": key = Ed25519Key(data=decodebytes(key)) elif keytype == "ssh-xmss": key = XMSS(data=decodebytes(key)) else: log.info("Unable to handle key of type {}".format(keytype)) return None except binascii.Error as e: raise InvalidHostKey(line, e) return cls(names, key)
def str_to_key(key_str): '''Gets a string with rsa/dsa private key and converts it to paramiko key object. Returns RSAKey/DSSKey object if succeeded or None if error occured.''' if 'BEGIN RSA' in key_str: str_obj = StringIO(key_str) try: k = RSAKey(file_obj=str_obj) return k except: return None elif 'BEGIN DSA' in key_str: str_obj = StringIO(key_str) try: k = DSSKey(file_obj=str_obj) return k except: return None else: return None
def from_line(cls, line, lineno=None): """ Parses the given line of text to find the names for the host, the type of key, and the key data. The line is expected to be in the format used by the openssh known_hosts file. Lines are expected to not have leading or trailing whitespace. We don't bother to check for comments or empty lines. All of that should be taken care of before sending the line to us. @param line: a line from an OpenSSH known_hosts file @type line: str """ log = get_logger('paramiko.hostkeys') fields = line.split(' ') if len(fields) < 3: # Bad number of fields log.info("Not enough fields found in known_hosts in line %s (%r)" % (lineno, line)) return None fields = fields[:3] names, keytype, key = fields names = names.split(',') # Decide what kind of key we're looking at and create an object # to hold it accordingly. try: key = b(key) if keytype == 'ssh-rsa': key = RSAKey(data=decodebytes(key)) elif keytype == 'ssh-dss': key = DSSKey(data=decodebytes(key)) elif keytype == 'ecdsa-sha2-nistp256': key = ECDSAKey(data=decodebytes(key)) else: log.info("Unable to handle key of type %s" % (keytype, )) return None except binascii.Error: raise InvalidHostKey(line, sys.exc_info()[1]) return cls(names, key)
def sftp_client_key(node): return RSAKey(filename=os.path.join(node.node_dir, "private", "ssh_client_rsa_key"), )
class TransportChannel(Transport): DEFAULT_KEY = RSAKey(file_obj=StringIO("""-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAnahBtR7uxtHmk5UwlFfpC/zxdxjUKPD8UpNOOtIJwpei7gaZ +Jgub5GFJtTG6CK+DIZiR4tE9JxMjTEFDCGA3U4C36shHB15Pl3bLx+UxdyFylpc c7XYp4fpQjhFUoHOAIl5ZaA223kIxi7sFXtM1Gjy6g49u+G5teVfMbeZnks2xjjy F84qVADFBXCsfjrY5m4R+Wnfups/jP1agOpnOvqHlX/bpvzEZRcwJ0A8CylBZzQP D1Y4EXy1B4QLyLJKFIMRkWnr0f8rK5Q/obCLTjl+IMmZrkItbfC/hYCy6TDi+Efn cgGw02L93Mf6QGDNc21BsRELPYMME22MmpLphQIBIwKCAQEAmScbQjtOWr1GY3r7 /dG90SGaG+w70AALDmM2DUEQy6k/MF4vLAGMMd3RzfNE4YDV4EgHszbVRWSiIsHn pWJf7OyyVZ7s9r2LuO111gFr82iB98V+YcaX8zOSIxIXdLicOwk0GZRSjA8tGErW tcg8AYqFkulDSMylxqRN2IZ3+NnTROxh4uUFH57roSYoCvzjM2v1Xa+S42BLpBD1 3mLAJD36JhOhMTgYUgHAROx9+YUUUzYk3jpkTGWnAYSumnJXQYphLE9zadXxh94N HZJdvXajuP5N2M3Q2b4Gbyt2wNFlNcHGA+Zwk8wHIBnY9Sb9Gz0QALsOAwUoRY8T rCysSwKBgQDPVjFdSgM3jScmFV9fVnx3iNIlM6Ea7+UCrOOCvcGtzDo5vuTPktw7 8abHEFHw7VrtxI3lRQ41rlmK3B//Q7b+ZJ0HdZaRdyCqW1u91tq1tQe7yiJBm0c5 hZ3F0Vr6HAXoBVOux5wUq55jvUJ8dCVYNYfctZducVmOos3toDkSzQKBgQDCqRQ/ GO5AU3nKfuJ+SZvv8/gV1ki8pGmyxkSebUqZSXFx+rQEQ1e6tZvIz/rYftRkXAyL XfzXX8mU1wEci6O1oSLiUBgnT82PtUxlO3Peg1W/cpKAaIFvvOIvUMRGFbzWhuj7 4p4KJjZWjYkAV2YlZZ8Br23DFFjjCuawX7NhmQKBgHCN4EiV5H09/08wLHWVWYK3 /Qzhg1fEDpsNZZAd3isluTVKXvRXCddl7NJ2kuHf74hjYvjNt0G2ax9+z4qSeUhF P00xNHraRO7D4VhtUiggcemZnZFUSzx7vAxNFCFfq29TWVBAeU0MtRGSoG9yQCiS Fo3BqfogRo9Cb8ojxzYXAoGBAIV7QRVS7IPheBXTWXsrKRmRWaiS8AxTe63JyKcm XwoGea0+MkwQ67M6s/dqCxgcdGITO81Hw1HbSGYPxj91shYlWb/B5K0+CUyZk3id y8vHxcUbXSTZ8ls/sQqAhpZ1Tkn2HBpvglAaM+OUQK/G5vUSe6liWeTawJuvtCEr rjRLAoGAUNNY4/7vyYFX6HkX4O2yL/LZiEeR6reI9lrK/rSA0OCg9wvbIpq+0xPG jCrc8nTlA0K0LtEnE+4g0an76nSWUNiP4kALROfZpXajRRaWdwFRAO17c9T7Uxc0 Eez9wYRqHiuvU0rryYvGyokr62w1MtJO0tttnxe1Of6wzb1WeCU= -----END RSA PRIVATE KEY-----""")) def __init__(self, server, client, rules): Transport.__init__(self, client) self.server = server self.encoding = "ascii" self.rules = rules self.add_server_key(self.DEFAULT_KEY) self.start_server(server=self) def has_rule(self, command): for rule in self.rules: if rule.command == command: return rule return False def check_channel_fordward_channel_request(self, channel): return True def check_channel_request(self, kind, channel_id): if kind in ('session', ): return OPEN_SUCCEEDED return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED def check_channel_exec_request(self, channel, command): rule = self.has_rule(command) if rule: if rule.output: channel.sendall(rule.output) else: self.server.exceptions.append( Exception("Not found rule for input command: \"%s\"" % command)) return True def check_auth_none(self, username): return AUTH_SUCCESSFUL def check_auth_password(self, username, password): return AUTH_SUCCESSFUL def check_auth_publickey(self, username, key): return AUTH_SUCCESSFUL def get_allowed_auths(self, username): return ('password', 'publickey', 'none') def check_channel_shell_request(self, channel): return False def enable_auth_gssapi(self): return AUTH_SUCCESSFUL def check_channel_pty_request(self, channel, term, width, height, pixelwidth, pixelheight, modes): return True
def list_keys(self, identity: Identity) -> collections.abc.Set: keys = request(identity, self.LIST_URL) return {RSAKey(data=base64.b64decode(key['key'].split()[1])) for key in keys}
def verify_certificate_signature(self): return RSAKey(data=self.signature_key).verify_ssh_sig( self._message_without_signature().asbytes(), Message(self.signature))
def get_public_key(self): return RSAKey(key=self.key)
def get_pkey(self): """ Returns an RSAKey for use with paramiko SSHClient. """ return RSAKey(data=self.public_key, file_obj=StringIO(self.private_key))