pyinfra icon indicating copy to clipboard operation
pyinfra copied to clipboard

SSH Key of type ED25519-SK work with pyinfra==3.1 & paramiko==3.1 but not with newer versions of paramiko (3.2+)

Open julienfr112 opened this issue 1 year ago • 4 comments

Describe the bug

PyInfra cannot connect to host with ED25519-SK key and paramiko on 3.2+ version (works with 3.1) ED25519-SK is the ssh key type use with a yubikey FA

To Reproduce

  • setup a host with ED25519-SK (https://developers.yubico.com/SSH/Securing_SSH_with_FIDO2.html)
  • put the host in inventory.py (test= "XX.XX.XX.XX" ...)
  • pyinfra inventory.py exec --limit test -- hostname

Expected behavior

pyinfra should connect to host but give this error:

` File "/home/julien/.local/lib/python3.11/site-packages/paramiko/auth_handler.py", line 394, in _parse_service_accept key_type, bits = self._get_key_type_and_bits(self.private_key) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/julien/.local/lib/python3.11/site-packages/paramiko/auth_handler.py", line 218, in _get_key_type_and_bits if key.public_blob: ^^^^^^^^^^^^^^^ File "/home/julien/.local/lib/python3.11/site-packages/paramiko/agent.py", line 476, in getattr raise AttributeError(name) AttributeError: public_blob 2024-11-20T09:21:46Z <Greenlet at 0x7362bfc313a0: <bound method Host.connect of Host(X.X.X.X)>> failed with AttributeError

--> Disconnecting from hosts... --> An internal exception occurred: `

julienfr112 avatar Nov 20 '24 09:11 julienfr112

This seems to be a bug in Paramiko itself: https://github.com/paramiko/paramiko/issues/2462

There are PRs for this issue: https://github.com/paramiko/paramiko/pull/2465 / https://github.com/paramiko/paramiko/pull/2475

simonhammes avatar Nov 26 '24 13:11 simonhammes

I have my own little wrapper script around pyinfra, so I was able to use this approach and it actually helped:


def apply_monkey_pathes():
    import paramiko
    # https://github.com/paramiko/paramiko/pull/2475
    def _get_key_type_and_bits_patched(self, key):
        if hasattr(key, "public_blob") and key.public_blob:
            return key.public_blob.key_type, key.public_blob.key_blob
        else:
            return key.get_name(), key
    paramiko.AuthHandler._get_key_type_and_bits = _get_key_type_and_bits_patched
apply_monkey_pathes()

I've verified it works on Linux, on Windows it throws "Invalid key", but it's better than nothing. I'll see if anything can be done to make it works on Windows too, but hopes are low, given how finicky yubikey based SSH auth on Windows already is

Renerick avatar Aug 26 '25 20:08 Renerick

Other workarounds:

  1. Specifying a bespoke ssh config with ssh_config_file to use a different key for Pyinfra
    • Doesn't help, probably because Paramiko just consumes the entire ssh-agent and dies anyway if any scary keys are present
  2. Pass a ssh_paramiko_connect_kwargs = {'key_filename': 'non-complicated-key'}
    • Would work, but only works if you have a simple private key available locally, no agent for you.
  3. Could construct a monkeypatched paramiko.pkey.PKey and pass that via ssh_paramiko_connect_kwargs
    • This actually has a chance to work as it's used before Paramiko hurts itself in confusion
    • A lot of work, but if someone does it we can all crib off of that.
  4. Move the hell away from Paramiko, it seems dangerously abandoned.

jinnatar avatar Sep 01 '25 07:09 jinnatar

Move the hell away from Paramiko, it seems dangerously abandoned.

Very much agree with this sentiment

Renerick avatar Sep 01 '25 12:09 Renerick