Implement a remote command line interface using Ruby/Python - 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.

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.

Execute command on remote windows machine and get output in python

I want to write a script that executes command on remote windows machine, and get output from that command. The problem is, I want to use built-in software in windows, so I can't unfortunately use for example SSH for that. I found "wmi" library, and I can log in to the machine and execute command, but i don't know how to recieve output from that command.
import wmi
c = wmi.WMI("10.0.0.2", user="administrator", password="admin")
process_startup = c.Win32_ProcessStartup.new()
process_id, result = c.Win32_Process.Create (r'cmd /c ping 10.0.0.1 -n 1 > c:\temp\temp.txt')
if result == 0:
print("Process started successfully: %d" % process_id)
print(result)
I tried to redirect output to file, but I can't find any way to get text file content either.
Is there any possible way to get output or text file content using wmi, or other python libraries?
For the application you're describing you may find RPyC is a good fit. It's a python remoting server you can connect to and issue commands; it will do anything that Python can do on the target machine. So you could, for example, use the subprocess module to run a windows command and capture the output then return the result.
The safe thing to do is to expose your remote functionality as a service -- basically, it's just a python script that RPyC can run for you. However you can also use RPyC classic mode, which is pretty much like running a python session directly on the remote machine. You should use it only when you are not worried about security, since classic mode can do anything on the remote machine -- but it's useful for prototyping.

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.

run ssh command remotely without redirecting output

I want to run a python script on my server (that python script has GUI). But I want to start it from ssh. Something like this:
ssh me#server -i my_key "nohup python script.py"
... > let the script run forever
BUT it complains "unable to access video driver" since it is trying to use my ssh terminal as output.
Can I somehow make my commands output run on server machine and not to my terminal... Basically something like "wake-on-lan functionality" -> tell the server you want something and he will do everything using its own system (not sending any output back)
What about
ssh me#server -i my_key "nohup python script.py >/dev/null 2>&1"
You can use redirection to some remote logfile instead of /dev/null of course.
? :)
EDIT: GUI applications on X usually use $DISPLAY variable to know where they should be displayed. Moreover, X11 display servers use authorization to permit or disallow applications connecting to its display. Commands
export DISPLAY=:0 && xhost +
may be helpful for you.
Isn't it possible for you to rather use python ssh extension instead of calling external application?
It would:
run as one process
guarantee that invocation will be the same among all possible system
lose the overhead from "execution"
send everything trough ssh (you won't have to worry about input like "; possibly local executed command)
If not, go with what Piotr Wades suggested.

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