Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AuthenticationError: Can't use key authentication to older Junos devices due to change in Paramiko #526

Open
daemonkeeper opened this issue Mar 17, 2022 · 8 comments
Labels
Enhancement Waiting Waiting for a response from issue or PR author or for someone to volunteer to pick up an enhancement

Comments

@daemonkeeper
Copy link

daemonkeeper commented Mar 17, 2022

Hi,

ncclient can no longer authenticate using keys to older Junos devices as per paramiko 2.9. This issue might be the same as reported in #518 but that one lacks substantial information.

The issue is found in the changelog of paramiko:

Warning This change is slightly backwards incompatible, insofar as action is required if your target systems do not support either RSA2 or the server-sig-algs protocol extension.
cf. https://www.paramiko.org/changelog.html

This results in key based authentication attempts to fail:

  File "/usr/local/lib/python3.9/site-packages/ncclient/manager.py", line 135, in connect_ssh
    session.connect(*args, **kwds)
  File "/usr/local/lib/python3.9/site-packages/ncclient/transport/ssh.py", line 362, in connect
    self._auth(username, password, key_filenames, allow_agent, look_for_keys)
  File "/usr/local/lib/python3.9/site-packages/ncclient/transport/ssh.py", line 464, in _auth
    raise AuthenticationError(repr(saved_exception))
ncclient.transport.errors.AuthenticationError: AuthenticationException('Authentication failed.')

On the router's end, the log prints

Mar 17 10:17:22  my.router sshd[4630]: userauth_pubkey: unsupported public key algorithm: rsa-sha2-256 [preauth]
Mar 17 10:17:23  my.router sshd[4630]: userauth_pubkey: unsupported public key algorithm: ssh-ed25519 [preauth]

This appears to be the case with oldish/older Junos versions (e.g. here we use 14.1X53-D40.8) which has a quite old SSH daemon. The workaround is to disable "new" algorithms in Paramiko's Transport class. However, in your code you instantiate paramiko.Transport in the SSHSession class without ability for the ncclient user to override the arguments.

line 299 of transport/ssh.py:

        self._transport = paramiko.Transport(sock)

A workaround would be

        self._transport = paramiko.Transport(sock, disabled_algorithms={'pubkeys': ["ssh-ed25519", "rsa-sha2-512", "rsa-sha2-256"],  'keys': ["ssh-ed25519", "rsa-sha2-512", "rsa-sha2-256"])

Arguably you don't want to hardcode this as a crypto upgrade is probably wanted for newer systems, but you may wish to let the ncclient user override this.

@einarnn
Copy link
Contributor

einarnn commented Apr 11, 2022

@daemonkeeper, just now ncclient only requires Paramiko >= 1.15.0. In the short term is it practical to select an older version of Paramiko for use with older JunOS devices?

For a longer-term solution, maybe a solution around device handlers and the JunOS-specific device handler may be appropriate? For example, we could extend the default device handler callbacks to include one to retrieve parameters to pass to SSH transport creation?

@daemonkeeper
Copy link
Author

For now I did opt to monkeypatch paramiko.Transport to fall-back to the older behavior instead of downgrading paramiko, i.e. I did something like

class MonkeyPatchedTransport(paramiko.Transport):
    def __init__(self, *args, **kwargs):
        kwargs['disabled_algorithms'] = {'pubkeys': ["ssh-ed25519", "rsa-sha2-512", "rsa-sha2-256"],
                                         'keys': ["ssh-ed25519", "rsa-sha2-512", "rsa-sha2-256"]}
        super().__init__(*args, **kwargs)

paramiko.Transport = MonkeyPatchedTransport

before instantiating ncclient (I do actually use ncclient through a dependency of py-eznc, I need to file a bug report with them as soon you agreed on a proper fix, they can adapt to). A callback with the ability to set custom Transport arguments, as you propose, would be fine with me, but making it a SSHSession.connect() argument, maybe by providing two or three meaningful pre-sets sounds the easiest and in-line with existing session customization (e.g. user name, password or keys).

Thinking of something like

session = SSHSession(..)
session.connect(..., crypto_pool=SSHSession.CRYPTO_LEGACY_ALGORITHMS)
session.connect(..., crypto_pool=SSHSession.CRYPTO_DEFAULT_ALGORITHMS)
session.connect(..., crypto_pool=SSHSession.CRYPTO_STRONG_ALGORITHMS)
...

where the constants would default to some meaningful presets in your session class to pass to paramiko. That also gives you the ability to change the pre-sets as time goes by, as the actual candidate ciphers in those pools are likely to change over the years. My monkepatched selection would then for example be the "LEGACY" variant, DEFAULT would leave "disabled_algorithms" blank and STRONG reverse it to only use the modern choices.

@ghost
Copy link

ghost commented Jun 27, 2022

I have the same problem using ansible with Junos modules which rely on ncclient. Would be really appreciated to have a solution for this problem without monkeypatching ncclient. As I am just a user, I have no idea/suggestion of how best to implement it.

Thanks a lot for your work!

@mirceaulinic
Copy link
Contributor

Same here... I think @daemonkeeper's solution makes sense, as I don't think it's reasonable to have to pin to Paramiko 2.8.1 (or older) which is already 8 months old and many security fixes have been applied in the meantime. On some systems it's practically impossible to upgrade them in order to have modern SSH, or this fix is pretty straight forward.

@daemonkeeper would you mind opening a PR? I can do it otherwise, no worries.

@amartin3225
Copy link

I'm also running into this; any updates on a possible PR with the proposed fix above? Thanks!

@einarnn
Copy link
Contributor

einarnn commented Apr 7, 2023

@mirceaulinic, @daemonkeeper -- have either of you been looking at a PR for this? I don't want to duplicate effort...

@einarnn einarnn added Waiting Waiting for a response from issue or PR author or for someone to volunteer to pick up an enhancement Enhancement labels Apr 7, 2023
@fischa
Copy link

fischa commented Jul 4, 2023

@einarnn I guess it's safe to assume that no effort is duplicated after waiting almost three months.

@jillesca
Copy link

I got this issue too using the XR DevNet always On, running7.3.2

In my case downgraded paramiko to 2.8.1. I tried to pass disabled_algorithms to paramiko but I didn't find how to from ncclient.

Then I got issues with the authentication using the publickey (this is specific to XR on 7.3.2), so I used the connect method with the allow_agent and look_for_keys as False.

After this, I was able to connect to XR via Netconf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Waiting Waiting for a response from issue or PR author or for someone to volunteer to pick up an enhancement
Projects
None yet
Development

No branches or pull requests

6 participants