How to stub out and test ssh commands - python

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.

Related

How to provide run time input in ssh while execution using python?

I am executing an application over ssh using python.
ssh connection is properly established and application is also successfully launched.
But the application which I am running, will take input during a run time like below:
1.Register
2.Unregister
3.Subscribe
Here, I need to send 1,2,3 accordingly. But I could not do it as I don't have the option to send such inputs over ssh unlike ssh commands.
Could anyone help me with this?

Create terminal for ssh on socket with Python

I need to create a terminal/console program on my server compute and I want to connect to it with ssh from client. And I want to do it from a python script. So, I figured that I need to somehow have this script run the program (subprocess maybe?) and put it out on the socket.
How can I put out a certain program on a specified socket for ssh connection?
Can I even ssh to a certain program run in a console, not to a whole PC? I need client to have only acces to what I set up.
How can I put out a certain program on a specified socket for ssh connection?
I think that what you actually want to do is changing what is run when logging in with ssh.
You can do this in /etc/passwd by changing /bin/bash to the program you want to run when you log in. Do this for the user that you want to log in to via ssh.
I didn't understand if you wanted to log in from a python script or log in to a python program in an interactive shell, so:
You can use the paramiko library to log into a machine with ssh. (if that is what you want)
I need to create a terminal/console program on my server compute and I want to connect to it with ssh from client.
You can look at this project https://github.com/python-cmd2/cmd2 to build interactive console programs in python.

Differentiate between SSH connection and authentication in Bash / 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.

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.

Emulate SSH server for testing purposes

I have to write test for deployment script which uploads files through SSH, but I'd like to have it not depending on external servers configuration. This is how i see it:
Create 2 SSH daemons without authentication on different ports of loopback interface.
Run the deployment script on these two ports
The only question is how to run these dummy SSH daemons.
I use Python and Fabric.
If you want full control over the server's actions (e.g. in order to simulate various problem conditions and thereby do a really thorough testing) I recommend twisted: as this article shows, it makes it really easy to set up your own custom SSH server.
If you'd rather use an existing ssh server, pick one from the list here (or use the one that comes with your system, if any; or maybe sshwindows if you're on windows) and run it with subprocess from Python as a part of starting up your tests.
Another option is to spin up a dockerized container with sshd service running. You can use a docker image like these:
https://github.com/kabirbaidhya/fakeserver
https://github.com/panubo/docker-sshd.
I've used this for testing out a deployment script (made on top of fabric ).
Here's how you use it.
Pull the image.
➜ docker pull kabirbaidhya/fakeserver
Set authorized keys for the server.
➜ cat ~/.ssh/id_rsa.pub > /path/to/authorized_keys
Run the fakeserver.
➜ docker run -d -p 2222:22 \
-v "/path/to/authorized_keys:/etc/authorized_keys/tester" \
-e SSH_USERS="tester:1001:1001" \
--name=fakeserver kabirbaidhya/fakeserver
You can now use the fakeserver from any ssh client. For instance:
➜ ssh tester#localhost -p 2222
➜ ssh tester#localhost -p 2222 "echo 'Hello World'"
If this works, you can then use any ssh clients or scripts on top of paramiko or fabric to test against this mock server.
Hope this helps.
Reimplementing an SSH daemon is not trivial.
If your only problem is you don't want them depending on existing configurations, you can start up new sshd with -f to specify a specific configuration and -p to run on a given port.
You can use os.system to make calls to the shell:
os.system('sshd -f myconfig -p 22022')

Categories