Daniel's Blog

Testing ssh connection in Python

The problem

We have an old fabric based python script used to deploy our application to a particular on premise server.

However, it stopped running after a while and I needed to find out why.

The end reason was that the version of paramiko wasn't pegged to a specific older version and eventually the functionality changed which resulted in the ssh connection no longer working.

However, while trying to debug this I was facing the mildly infuriating case where I could use openssh to connect fine, but using python, it didn't work at all.

This is a small code snippet that I used to ssh to the machine just in case it comes up again.

import paramiko, os

paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG)

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("<remote domain>", username='<remote username>')

Looking at the code, it will ssh as the user who is running the script. As I have a different use in the CICD pipeline than on the machine, I manually specified the correct user name. As for the key, it was in ~/.ssh/id_rsa and automatically picked up.

The issue was, that the algorithm it was choosing was not supported on the server. In more recent versions of the library, a specific algorithm can be disabled using this:

import paramiko, os

paramiko.common.logging.basicConfig(level=paramiko.common.DEBUG)

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("<remote domain>", username='<remote username>', disabled_algorithms=dict(pubkeys=["rsa-sha2-512", "rsa-sha2-256"]))

Discovering this worked helped identify the problem, but how to fix it?

The script is not actually connecting using paramiko, but rather fabric. This doesn't work with the old version of fabric that was used, but does work with the more recent versions of fabric.

It wasn't cost effective to upgrade the fabric script as the server will be retired in two months and after which the fabric script will also be retired, so by downgrading the library, the original code worked.