SSH in Python using Paramiko

SivaraamTK
featurepreneur
Published in
3 min readAug 19, 2022

When working with remote servers, there will be times when we will need to directly interact with them and when we will need to use SSH, the method typically used to access a remote machine and run commands, retrieve files or upload files, or transfer files from the remote machine to the local or vice versa using SFTP (Secure File Transfer Protocol) and SCP(Secure Copy Protocol).

But these can generally be used only through terminals and are difficult to automate. That’s where Paramiko comes in.

Paramiko:

Paramiko is a pure-Python implementation of the SSHv2 protocol, providing both client and server functionality. It provides the foundation for the high-level SSH library Fabric, which is recommended to use for common client use-cases such as running remote shell commands or transferring files. Direct use of Paramiko itself is only intended for users who need advanced/low-level primitives or want to run an in-Python sshd.

The primary client of Paramiko as documented in the API is Paramiko.SSHClient. An instance of the Paramiko.SSHClient can be used to make connections to the remote server and transfer files.

As a client, you can authenticate yourself using a password or key and as a server, you can decide which users are allowed access and the channels you allow.

Install Paramiko:

Run the following command in the terminal to install the paramiko library:

pip install paramiko

Making a Connection:

import paramikossh_client =paramiko.SSHClient()ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh_client.connect(hostname=’hostname’,port=’PORT’,username=’dummy’,password=’mypassword’)

we use “set_missing_host_key_policy()” to let know Paramiko that you validate your trust with the machine for the first time you try to connect to the server. Parsing an instance of the AutoAddPolicy to set_missing_host_key_policy() changes it to allow any host.

Alternatively for Password and Private key-based auth:

transport = paramiko.Transport()transport.start_client()transport.auth_password(USER_NAME, PASSWORD)pkey = paramiko.RSAKey.from_private_key_file(PRIVATE_KEY_FILE) transport.auth_publickey(USER_NAME, pkey)

For Password and OTP-based auth:

transport = paramiko.Transport()transport.start_client()transport.auth_interactive(username, handler)def handler(self, title, instructions, prompt_list):  answers = []  for prompt_, _ in prompt_list:    prompt = prompt_.strip().lower()    if prompt.startswith(‘password’):      answers.append(PASSWORD)    elif prompt.startswith(‘verification’):      answers.append(OTP)    else:      raise ValueError(‘Unknown prompt: {}’.format(prompt_))  return answers

we use the auth_interactive method which accepts a handler for passing the values to the prompt. The custom handler that we write has the logic to pass the OTP or Password etc.. based on the output in the prompt. If we want to get the input to the handler from stdin instead then we can use the auth_interactive_dumb method.

**NOTE: Storing your credentials in your scripts is not secure and, you should never do this, we can set them as environment variables or use `.env` file and load it into the Python script but, even storing sensitive information in a plain text file is not very secure. The better and more secure way is to store these data in an encrypted store, like Hashicorp Vault, Keywhiz, etc…

Running Commands Remotely:

To run a command “exec_command()” is called on the SSHClient with the command passed. The response is returned as a tuple of (stdin, stdout, stderr)

To list all the files in a directory:

stdin,stdout,stderr=ssh_client.exec_command(“ls”)print(stdout.readlines())# → [u’Desktop\n’,u’Documents\n’,u’Downloads\n’,u’Videos\n’]print(stderr.readlines())# → []

type(stdin) and type(stdout) is ‘paramiko.channel.ChannelFile’

type(stderr) is class ‘paramiko.channel.ChannelStderrFile’

According to paramiko.org, they are all python file-like objects.

The stdin is a write-only file that can be used for commands requiring input.

The stdout file gives the output of the command.

The stderr gives the errors returned on executing the command. It will be empty if there is no error

To list all the files in a directory with sudo:

stdin, stdout, stderr = ssh.exec_command(“sudo ls”)stdin.write(‘mypassword\n’)print (stdout.readlines())# → [u’Desktop\n’,u’Documents\n’,u’Downloads\n’,u’Videos\n’]

File Transfers:

File transfers are handled by the paramiko.SFTPClient which you get from calling open_sftp() on an instance of Paramiko.SSHClient.

Downloading a file from a remote machine:

ftp_client=ssh_client.open_sftp()ftp_client.get(‘remotefileth’,’localfilepath’)ftp_client.close()

Uploading file from local to a remote machine:

ftp_client=ssh.open_sftp()ftp_client.put(‘localfilepath’,remotefilepath’)ftp_client.close()

Conclusion:

I came across Paramiko when I was looking into if we can directly SSH into an EC2 instance from Python using Boto3 and found it interesting and tested it out with DB-Tunneling in PostgreSQL. Give it a go and let me know what you think. You check out its repository here.

!HAPPY-CODING!

--

--

SivaraamTK
featurepreneur

An aspiring developer from Chennai who’s passionate to learn new technologies and overcome all challenges to become better than the me from yesterday