scp between two remote servers in Python - python

I am trying to connect a remote server using Paramiko and send some files to other remote server. I tried the code below, but it didn't work. I checked all connections, username and password parameters, they don't have any problem. Also the file which I want to transfer exist in first remote server in proper path.
The reason why I don't download files to my local computer and upload to second server is, connection speed between two remote servers is a lot faster.
Things that I tried:
I set paramiko log level to debug, but couldn't find any useful information.
I tried same scp command from first server to second server from command line, worked fine.
I tried to log by data = stdout.readlines() after stdin.flush() line but that didn't log anything.
import paramiko
s = paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
s.connect("10.10.10.10", 22, username='oracle', password='oracle', timeout=4)
stdin, stdout, stderr = s.exec_command(
"scp /home/oracle/myFile.txt oracle#10.10.10.20:/home/oracle/myFile.txt")
stdin.write('password\n')
stdin.flush()
s.close()

You cannot write a password to the standard input of OpenSSH scp.
Try it in a shell, it won't work either:
echo password | scp /home/oracle/myFile.txt oracle#10.10.10.20:/home/oracle/myFile.txt
OpenSSH tools (including scp) read the password from a terminal only.
You can emulate the terminal by setting get_pty parameter of SSHClient.exec_command:
stdin, stdout, stderr = s.exec_command("scp ...", get_pty=True)
stdin.write('password\n')
stdin.flush()
Though enabling terminal emulation can bring you unwanted side effects.
A way better solution is to use a public key authentication. There also other workarounds. See How to pass password to scp? (though they internally have to do something similar to get_pty=True anyway).
Other issues:
You have to wait for the command to complete. Calling s.close() will likely terminate the transfer. Using stdout.readlines() will do in most cases. But it may hang, see Paramiko ssh die/hang with big output.
Do not use AutoAddPolicy – You are losing a protection against MITM attacks by doing so. For a correct solution, see Paramiko "Unknown Server".

Related

Paramiko session scope

I have some doubts about Paramiko. If I do the standard code found in internet:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='remote_host', username='...', password='...')
// TODO
ssh.close()
Let's say I have some kind of JDBC connector and I try to connect to a database placing the code below within the TODO section
ssh.connect(hostname='remote_host', username='...', password='...')
connector.connect(database_params...)
ssh.close()
My question is. In that case the client of the database server would be remote_host or my local machine where the Python script is being executed?
Or the right way would be using sshtunnel? like so:
with open_tunnel(
('remote_host', '22'),
ssh_username=...,
ssh_password=...,
remote_bind_address=('DB_ADDRESS', 'DB_PORT')
local_bind_address=('SOME_IP', 'SOME_PORT')
) as server:
connector.connect(db_host='SOME_IP', db_port='SOME_PORT', ...)
Is there any difference between those two approaches?
Thanks in advance.
Opening SSH connection using Paramiko or any other way, has no effect whatsoever on your database connection, nor any other connections, nor a file access, nor command execution. So your first code has no chance of doing, what you want.
Everything you want to do via the SSH connection, you need to do via the Paramiko API.
And that's what open_tunnel does, internally.
For an equivalent standalone code, see forward_tunnel function in Paramiko forward.py demo.

SSH using Python via private keys

In my script, I need to do an SSH to a remote system using a private key and dump the file into its directory.
The command I am using to SSH into the system is this:
ssh -i private_key localhost
Followed by the standard input:
Enter passphrase for key 'private_key'
I am trying to do this in a Python script, but am not sure about the way of writing a command and passing a passphrase as a parameter so that the whole sequence can be automated.
Please suggest me a way to achieve this via a library (Paramiko SSHClient) or a code snippet would be highly really appreciated.
SSHClient.connect can handle public key authentication with a simple call:
import paramiko
ssh = paramiko.SSHClient()
ssh.connect(hostname, username=username, key_filename=key_path, password=passphrase)
The password argument is used as a passphrase, when key_filename is provided.
Additionally, you will also have to verify the server's host key (as you must have done with ssh before). See Paramiko "Unknown Server".

Using ssh_config file with Paramiko

I need to connect to a server with SSH to download files. I have Ubuntu and I've set up SSH in the standard way: I have a ssh_config file in .ssh which defines a host entry (say host_key) for the server address (Hostname.com) and username, and I've set up an RSA key. So when I try to log into SSH from the command line or bash, I just need to use ssh host_key
I would like to do this in Python. The standard solutions seems to be to use Paramiko to set up the connection. I tried this:
from paramiko import SSHClient
from scp import SCPClient
ssh = SSHClient()
ssh.load_system_host_keys()
ssh.connect('host_key')
scp = SCPClient(ssh.get_transport())
# etc...
However, it always seems to hang and time out on ssh.connect('host_key'). Even when I try to include the username and password: ssh.connect('host_key', username='usrnm', password='pswd').
Are my host keys not loading properly? And would this take care of the RSA keys as well?
It only works if I use the whole Hostname.com with username and typed-out password. Which is maybe a bit insecure.
Since paramiko has a SSHConfig class, you can use it for your ~/.ssh/config.
However, it is slightly messy, I recommend you to use fabric instead of that.
Here is the code example:
from fabric.api import put
put('local path', 'remote path')
I do not think that it is common to use ssh_config file with Paramiko (or any other code/language). ssh_config is a configuration file for OpenSSH tools, not for SSH in general.
Usually, you specify your private key directly in your code as an argument of SSHClient.connect method:
How to access to a remote server using Paramiko with a public key-file
If you want to keep using ssh_config, Paramiko can parse it. Check parse_ssh_config and lookup_ssh_host_config functions. But I believe, you still have to look up the key file from the config and pass it explicitly to SSHClient.connect method.

How to move multiple files from local machine to a sever using Python

We have a framework used to validate few test cases and results will be stored in local machine containing multiple text and images.
Need to move these files from our local host to server.
I have the sever IP address, username and password.
So using Python I need to move these files or copy it to server
If you are going for ssh, you'll have to use scp and there is a dedicated Python package for that: Paramiko. See this post on stackoverflow.
import paramiko
def createSSHClient(server, port, user, password):
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(server, port, user, password)
return client
ssh = createSSHClient(server, port, user, password)
scp = SCPClient(ssh.get_transport())
scp.put([file1,file2],remotePath)
Of course, you have to specify the various variables according to their name. The scp.put function takes a list of local files and a destination path on the remote system as arguments.
used SCP to do the transfer
ssh -i ~/.ssh/id_rsa intel#10.223.98.165 "mkdir < Folder created >"
scp -i ~/.ssh/id_rsa < source >*.txt < destination >
using os.system()
Thanks for helping
This is not really a Python problem: You say you have a username and a password to the server, but that doesn't tell us the least in which way you can access that server. Do you have SSH access? Then use scp as a command-line program or one of the numerous Python modules that make that possible.
The same goes for protocols like FTP, WebDAV, cifs/smb, NFS, ... It all depends on what ways you have to access/modify/create files on the server. Hence, this answer is all I can give you to your extremely inaccurate question.

Paramiko connect without asking ssh key

This is my python script to connect to server. But when I run the script, it is asking me to keying my ssh passphrase. How could I avoid to asking my ssh passphrase key?
host = '192.168.43.3'
user = 'root'
passwd = 'ppawd'
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=user, password=passwd)
transport = ssh.get_transport()
channel = transport.open_session()
channel.setblocking(1)
channel.settimeout(30)
command = "ls -a"
ssh.exec_command(command)
I ran into the same issue. I don't think the other answers here realized what the question was actually for. This is an old question but I wanted to help anyone else like me who ended up here after googling.
You need to disable the ssh agent feature allow_agent=False and then it will no longer prompt you for a passphrase. Paramiko is trying to connect to the ssh agent and I assume trying to read the key. I also added look_for_keys=False, as it will disable checking for private keys to use.
Example:
client.connect(server, port=port, username=username, password=password, look_for_keys=False, allow_agent=False)
My advice would be generating a key without a passphrase - just press enter when asked for a password while creating the key.
This key should be used specifically for your script - avoid re-using keys you use for other purposes (such as your user's interactive login), since it makes key revocation and access control harder.
A passphrase-less key has some advantages compared to hardcoding the password in your script:
The presence of a passphrase-less key makes it clear to anyone that the key is compromised as soon as anyone has access to it. Separating the password from the key hides this fact without providing any additional security.
It avoids you publishing your password to source-control accidentally (separation of source code and access control credentials)
Possibly, it'll make it less tempting to re-use any existing user's ssh key with a proper passphrase.
A few security considerations:
Remember that anyone with access to that key will get access to the remote system. You may consider putting restrictive permissions on the key file, and create a separate user for your script to login into in the remote system, if it's possible at all.
If your script is single purpose, you may also consider limiting the list of shell commands available to the user on the remote system
If you have no physical security on the system that stores the key (i.e.: a laptop or desktop in a untrusted location), you may also want to use full disk encryption, block device encryption (LUKS) or file-level encryption (encfs).
I solved the problem as
ssh-copy-id root#192.168.43.133
Credit to http://sshmenu.sourceforge.net/articles/key-setup.html
You can add the fingerprint to each server's known_hosts. For a single user:
cat ~/.ssh/known_hosts
echo "$SERVER,$PORT ssh-rsa $SERVER_KEY_FINGERPRINT" >> ~/.ssh/known_hosts
add your connection host ip to known_hosts then it will not ask for any questions like
Are you sure you want to continue connecting (yes/no)?
or if u want to disable the password asking too, then check this links
http://www.linuxproblem.org/art_9.html
https://www.debian.org/devel/passwordlessssh

Categories