What is this?
This is an integration between the Mina SSH server and the Groovy Shell. Using this integration, you can quickly add an SSH server to your app and be able to remotely access a Groovy shell that lets you interactively run code inside your running JVM. In other words, it's a remotely accessible REPL that's inside your JVM, thereby allowing you to inspect what's happening inside your app without having to write JMX or other ways of externally exposing management functionality.
There's a demo app included. In your clone of the repo, run:
If you want to run the demo, you'll need Java 8 since it uses the shiny new JSR-310 classes. (The rest of the library doesn't require Java 8.)
This will start up a simple HTTP service on
localhost:8080 that exposes a
/nowUtc endpoint that spits out a timestamp in ISO-8601. Here it is in action along with the
date command to show that it's doing what it should:
% TZ=UTC date --iso-8601=seconds && curl http://localhost:8080/nowUtc 2014-02-09T22:47:43+0000 2014-02-09T22:47:43.059Z
To show what you might do with the Groovy shell, the time is generated by the
TimeSource class that has a
setSecondsOffset(int seconds) method. Unsurprisingly, this shoves the timestamps forwards or backwards relative to the correct time. Let's make time be wrong by 30 seconds (using Groovy property syntax, because we can). The demo app's groovy shell is preconfigured to have a
timeSource binding to the relevant
% ssh -p 10222 localhost groovy:000> timeSource ===> com.palominolabs.ssh.groovy.demo.TimeSource@6013754e groovy:000> timeSource.secondsOffset = 30 ===> 30
(If you try this yourself, you'll see the line wraps aren't working right yet -- it's a known issue.)
You should see a log line:
2014-02-09 14:50:55,712 [pool-1-thread-1] INFO MDC c.p.ssh.groovy.demo.TimeSource - Setting offset to 30
And now, to check that it worked:
% TZ=UTC date --iso-8601=seconds && curl http://localhost:8080/nowUtc 2014-02-09T22:51:14+0000 2014-02-09T22:51:44.300Z
Sure enough, the second timestamp is 30 seconds fast.
Obviously this is a contrived example, but it should be clear how useful it is to be able to interactively execute arbitrary code inside a running JVM.
In the demo above, you didn't have to provide a password because the demo app defaults to allowing all connections. However, that's not realistic for real-world use, so there's also a
PublickeyAuthenticator implementation provided (
AuthorizedKeysPublickeyAuthenticator) that uses ssh's
authorized_keys format to define the public keys to allow. Currently, it supports RSA and DSA keys.
The demo app supports public key authentication; you simply need to tell it what authorized_keys file to use. If you already have ssh keys set up, you can point the demo app at your current public key to quickly test it.
./gradlew -DDEMO_SSH_AUTHORIZED_KEYS=$HOME/.ssh/id_rsa.pub :demo-app:run
In a real deployment, you'd probably use a file containing many such public keys, like the
authorized_keys file you might already have on your servers. For now ,
using your own public key will of course allow your corresponding private key to work.
Check the source of
DemoMain to see how to hook up this style of authentication.