Differentiate between SSH connection and authentication in Bash / Python - python

This isn't tied to a specific code sample that I have, but many of them. I'm using Python Fabric to make connections to various servers over SSH from a single host that I'm running my script on. Sometimes it connects just fine and that is the end of it. However, sometimes it can make a connection but gives me a "[serverName] Login password for 'userUser'" error. I don't have access to this server, so even though the connection is being made, I can't authenticate to it. Is there any way to make Bash / Fab / Python realize that I can't connect?

I would investigate the following ssh_config options:
KbdInteractiveAuthentication no
PasswordAuthentication no
See man ssh_config for more info on these options.
You can set these options in your ~/.ssh/config file or on the ssh command line using -o. I imagine using the ~/.ssh/config file would be transparent to Fabric.

Related

How to stub out and test ssh commands

I am a developer on a system that sends out ssh commands, roughly in the format 'ssh -o 'BatchMode yes' hostname command'. I am working on our end to end testing and am tasked with mocking out the remote servers during testing. I need to prevent the ssh command running on the remote server, and instead capture the ssh command in some way, check it matches what I expect for that test and return a response specified specifically for that test to control the test flow. My system is in python and runs in RHEL7 docker containers, a solution that can be created within those technologies would be preferable. Does anyone have any suggestions of the best way to do this?
I have considered alias'ing ssh but i don't think that's ideal as i'm restricting the scope of the test more than if the ssh command is carried out. My best idea is creating a mock ssh server that captures the command but i have yet to find the technology to easily capture a non-interactive ssh command and respond.

How to connect to ssh server from another server

I've been trying to connect to first an out-of-band management server (in my case, since I'm connecting to DELL-servers, an iDRAC) and through that connect to the main server itself. I've got it to work when I do it manually, using, in the (windows) terminal:
putty.exe -ssh 'username'#'iDRAC-IP'
followed by PuTTY window opening where I type in the password, followed by
connect
which connects to the server itself, and then I type in the username and password for the server, completing the process.
When I've been writing my script in python, I'm using paramiko, http://www.paramiko.org/, suggested here on stackoverflow, and following this example: https://www.ivankrizsan.se/2016/04/24/execute-shell-commands-over-ssh-using-python-and-paramiko/, and it works just splendid for the iDRAC (the first server I connect to). It also works when I type in
stdin, stdout, stderr = ssh_client.exec_command('connect')
because I am still in my first server (ssh_client) (I can tell this is working because when I try to connect to the server manually afterwards, it is occupied). But after that it stops working, since when doing 'connect' I am no longer in ssh_client, but in a different server.
So my question is - how do I connect to a server from another server (in this case being the out-of-band management server) and log in to this one?
You can use ssh tunnel to do so.
this post may resolve your problem:
PyCharm: Configuring multi-hop remote Interpreters via SSH

How to remote debug in PyCharm

The issue I'm facing right now:
I deploy Python code on a remote host via SSH
the scripts are passed some arguments and must be ran by a specific user
the PyCharm run/debug configuration that I create connects through SSH via a different user (can't connect with the user that actually runs the scripts)
I want to remote debug this code via PyCharm...I managed to do all configuration, I just get permission errors.
Are there any ways on how I can run/debug the scripts as a specific user (like sudo su - user)?
I've read about specifying some Python Interpeter options in PyCharm's remote/debug configuration, but didn't manage to get a working solution.
If you want an easy and more flexible way to get into the PyCharm debugger, rather than necessarily having a one-click "play" button in PyCharm, you can use the debug server functionality. I've used this in situations where running some Python code isn't as simple as running python ....
See the Remote debug with a Python Debug Server docs for more details, but here's a rough summary of how it works:
Upload & install remote debugging helper egg on your server (On OSX, these are found under /Applications/PyCharm.app/Contents/debug-eggs)
Setup remote debug server run configuration: click on the drop-down run configuration menu, select Edit configurations..., hit the + button, choose Python remote debug.
The details entered here (somewhat confusingly) tell the remote server running the Python script how to connect to your laptop's PyCharm instance.
set Local host name to your laptop's IP address
set port to any free port that you can use on your laptop (e.g. 8888)
Now follow the remaining instructions in that dialog box: copy-paste the import and pydevd.settrace(...) statements into your code, specifically where you want your code to "hit a breakpoint". This is basically the PyCharm equivalent of import pdb; pdb.set_trace(). Make sure the changed code is sync'ed to your server.
Hit the bug button (next to play; this starts the PyCharm debug server), and run your Python script just like you'd normally do, under whatever user, environment etc. When the breakpoint is hit, PyCharm should drop into debug mode.
I have this (finally) working with ssh RemoteForward open, like so:
ssh -R 5678:localhost:5678 user#<remotehost>
Then start the script in this ssh session. The python script host must connect to localhost:5678 and of course your local pycharm debugger must listen to 5678
(or whatever port you choose)

Paramiko Script for SSH and VNC

I am trying to write a script to use when connecting remotely to various computers in my office. We also use VNC to allow us to see the user desktops. I have been trying to find a script that would allow me to do this, but I have had no luck. Right now, we use the SSH command in Terminal (we all use Macs), which looks like the following:
ssh "hostname" -L 5901:127.0.0.1:5900
This then requires RSA fingerprint and user password. Username is never requested as it is the same as the user profile on the computer. 5901 can also be 5902, 5903, etc, depending on which display port is specified in our VNC client.
I would ultimately like to created a script that would prompt for hostname and display port, assuming username and password can be stored permanently in the script. If not, we would need prompts for those as well. Is this even possible?
I while ago had a similar use case so I put together this script:
http://code.activestate.com/recipes/576810-copy-files-over-ssh-using-paramiko/
To tunnel VNC over SSH you would need to forward port 5900 for connecting to the real xorg instance, e.g. via x11vnc, or port 5901 to connect to the first virtual xorg (e.g. via vncserver), 5902 to connect to the second xorg, etc.
I am not aware of paramiko being able to forward ports but there seems to be a pure Python module that does just that https://gist.github.com/1399529

Implement a remote command line interface using Ruby/Python

Are there any existing library for implementing a remote command line interface?
e.g.
Consider the case of gitolite, when you do a git push origin, it will ssh into the remote server and execute some code (namely hooks, no server is needed for the whole transaction.
What I want to archive is something like that, e.g.
./remote get_up_time
It will invoke ssh into the remote machine and do execute the script get_up_time already deployed
the ruby standard distribution provides DRb aka Distributed Ruby:
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html
Implementing your own script would be easy enough.
#!/bin/bash
ssh root#example.com "$1"
Then you could just call like:
./remote.sh get_up_time
Assuming that ssh is installed and that your public key is on the remote server (and thus, you do not need to provide a password), this would be a crude implementation:
#!/usr/bin/env ruby
host = ARGV.shift
command = ARGV.join(' ')
IO.popen("ssh #{host} \"#{command}\"") do |io|
io.sync = true
io.readlines.each { |line| puts line }
end
Usable like:
$ ./remote.rb www.example.com ls -l
You can expand this as needed to provide extra features, such as reading from stdin to provide ssh a password or something.
Although it appears there is "no server", there is certainly an sshd (a remote server) running on the remote system that allows this to work.
If you don't want to use ssh, you will need to use another server running on the remote machine or write your own.

Categories