(answering out of order)
On Wed, Aug 12, 2009 at 12:28 AM, Ludovic Dubost wrote:
I've been trying to do something similar to just
relaunch the JVM
itself from the Wiki itself.
I could not however find a solution to the JVM killing
the /etc/init.d/tomcat restart script just after
"stop" when the JVM
itself is killed..
This made the "start" not happen..
I believe a restart from a separate shell like the ssh-slave-shell from my
example should not have this problem if you use the "restart" command that
actually consists of two sequential subcommands: stop and start. That is the
whole point of the "restart" command -- that the "start" is going to
happen
after the "stop" independent of whether the invoking process that invoked
the command is still around.
Running it from another XWiki is another solution which though requires
more credentials settings..
The credentials settings are trivial with the ssh-slave-shell approach. The
technique works just as well with remote machines as it does for localhost.
You could, for example, have a single administrative host/wiki dedicated to
running processes via the ssh-slave-shell. In order to access the
SSH-server, each host that wanted to use the ssh-slave-shell needs its
specific ~tomcat6/.ssh/id_dsa.pub installed into the ssh-host's
/home/tomcat-ssh-slave/.ssh/authorized_keys . I'm sure there's an old
version of this "idea" helping run things quietly behind the scenes at
places like
java.net,
openoffice.org netbeans.org and
ipssources.com :-).
Useful for little things like adding x509 certificates to servers, or
setting up secure network tunnels via SSH without requiring a system login
account.
Nice,
Thanks! It's a very powerful bit of code. One of the things it's been making
me think about, is the use of this feature vs. JSR-223 languages in
computing custom web pages. Lets say that I setup one SSH connections per
machine that I want to subdivide the task of rendering a bunch of user's
"portal" pages, each containing tools and information that they've chosen
to
have presented on each login. Places like Yahoo and Google have spent
considerable effort in decomposing the computations needed for each
"portlet" to be farmed out to a separate processor. They employ a massive
amount of parallelism in order to render numerous custom and dynamic pages
with adequate performance:
http://research.yahoo.com/files/pnuts.pdf . Of
course with an adequate "cloud" backing up a java implementation, the same
could be considered true for launching a groovy-based set of "portlets" that
each render as their own separate thread, and then dynamically come back and
-- through AJAX -- update the part of the web page that just got
farmed off to a separate processor which finally completed it's
computation/thread.
Is the overhead of the aforementioned way of employing parallelism in a
high-volume web-app high enough that a solution where my much lighter-weight
groovy-based "portlets" would use this passwordless, pub/priv SSH key
exchange method of invoking computation on a remote machine?
If there was a way of persisting the actual SSH connection across the
web-session, then the overhead of authentication and connection occurs only
once, after a user logs in to the "portal." Thereafter, one can simply
invoke
sshHelper.runCommand("compute-portal-info-as-wikitext") which would return
it's results as wikitext to be rendered along with the rest of the current
document. At application close or logout, the sshHelper.close() gets called
and the remote "restricted shell" dies.
Is this a bad idea, and if so, why?
.......................
As for the restricted shell, on which the security of such a setup depends I
had some errors in the previous script (i see some syntax there from it's
other former life controlling a cable/satellite set-top-box running Linux
:-) ). now it's working, so if you give it parameters or a command it
doesn't expect, it gives an error. E.g.
println "==== Output from '/bin/rm -rf /' ===="
println "##" + sshHelper.runCommand("/bin/rm -rf /") + "##"
Renders as:
*Output from '/bin/rm -rf /'*
You are not authorized to do that.
A recognized command:
println "==== Output from 'top' ===="
println "##" + sshHelper.runCommand("top") + "##"
Always ends up running a shell script "wrapper" associated with the
restricted command, which ensures no command-injection is possible. In the
case of "top" the wrapper script ends up calling "/usr/bin/top -b -n
1" and
outputting the result.
To get this working on FireFox (see instructions in prev mails for rest of
setup)
(1) Add a user to /etc/passwd that looks like this:
tomcat-ssh-slave:x:592:592:User for SSH Subprocesses From
Tomcat:/home/tomcat-ssh-slave:/home/tomcat-ssh-slave/bin/ssh-slave-shell
(2) add a group to /etc/group that looks like this:
tomcat-ssh-slave:x:592:
(3) setup /home/tomcat-ssh-slave/.ssh as mentioned previously
(4) add /home/tomcat-ssh-slave/bin, populate with shell scripts you call
from:
(5) /home/tomcat-ssh-slave/bin/ssh-slave-shell is an executable script
implementing
the restricted shell used by tomcat-ssh-slave:
#!/bin/sh -noprofile
###############################################################################
#
# File: sshslave-shell
# RCS: $Header: $
# Description: Shell to allow execution of remote commands from a tomcat
server.
# For security purposes, this "login" is limited in commands it can
# perform, and runs as a separate user from the tomcat server, separating
# the ability to directly modify tomcat state from the functionality
provided
# by user tomcat-ssh-slave. This shell is run as the "login shell" (via
# /etc/passwd) for account tomcat-ssh-slave, which is accessed via SSH.
# The account is preferably a nonprivileged user account with pid>500, Home
# directory /home/tomcat-ssh-slave must exist, with correct permisssions.
# /home/tomcat-ssh-slave contains scripts referred to via
fully qualified
# filenames in this script. The directory would also store the accounts'
# .ssh settings, keys, etc. Secure, password-less access to the
tomcat-ssh-slave
# account can be achieved by having tomcat's SSH public identity
/usr/share/tomcat6/.ssh/id_dsa.pub
# installed as /home/tomcat-ssh-slave/.ssh/authorized_keys (and
keeping id_dsa secret)
# This would prevent use of tomcat-ssh-slave "account" from being used by
anything
# other than preauthorized accounts.
#
# Here's some example commands:
#
# ssh -x tomcat-ssh-slave(a)127.0.0.1 cleanlog
# ssh -x tomcat-ssh-slave(a)127.0.0.1 getlog
# ssh -x tomcat-ssh-slave(a)127.0.0.1 setdbglvl 'INFO'
# ssh -x tomcat-ssh-slave(a)127.0.0.1 getdbglvl
# ssh -x tomcat-ssh-slave(a)127.0.0.1 tomcat-restart
# ssh -x tomcat-ssh-slave(a)127.0.0.1 apache-restart
# ssh -x tomcat-ssh-slave(a)127.0.0.1 tomcat-start
# ssh -x tomcat-ssh-slave(a)127.0.0.1 apache-start
# ssh -x tomcat-ssh-slave(a)127.0.0.1 top
# ssh -x tomcat-ssh-slave(a)127.0.0.1 ps
# ssh -x tomcat-ssh-slave(a)127.0.0.1 df
# ssh -x tomcat-ssh-slave(a)127.0.0.1 free
# ssh -x tomcat-ssh-slave(a)127.0.0.1 reboot
# Author: Niels P. Mayer
# Created: Monday 8/10/2009
# Modified:
# Language: Shell-script
# Package: N/A
# Status: Production
#
# (C) Copyright 2009, Niels Mayer, all rights reserved.
#
###############################################################################
# make sure nothing funny goes on
PATH="/bin:/usr/bin"
# make sure they rsh or ssh in with a single command
if [ -z "$1" ] || [ "$1" != "-c" ]
then
echo You must use ssh -c to access this account
exit 1
else
shift
SSHSLAVE_COMMAND="$@"
fi
# only let them run specific commands, eg.
# ssh -x tomcat-ssh-slave(a)127.0.0.1 cleanlog
# ssh -x tomcat-ssh-slave(a)127.0.0.1 getlog
# ssh -x tomcat-ssh-slave(a)127.0.0.1 setdbglvl 'INFO'
# ssh -x tomcat-ssh-slave(a)127.0.0.1 getdbglvl
# ssh -x tomcat-ssh-slave(a)127.0.0.1 tomcat-restart
# ssh -x tomcat-ssh-slave(a)127.0.0.1 apache-restart
# ssh -x tomcat-ssh-slave(a)127.0.0.1 tomcat-start
# ssh -x tomcat-ssh-slave(a)127.0.0.1 apache-start
# ssh -x tomcat-ssh-slave(a)127.0.0.1 top
# ssh -x tomcat-ssh-slave(a)127.0.0.1 ps
# ssh -x tomcat-ssh-slave(a)127.0.0.1 df
# ssh -x tomcat-ssh-slave(a)127.0.0.1 free
# ssh -x tomcat-ssh-slave(a)127.0.0.1 reboot
case ${SSHSLAVE_COMMAND} in
cleanlog | \
getlog | \
getdbglvl | \
tomcat-restart | \
apache-restart | \
tomcat-start | \
apache-start | \
top | \
ps | \
df | \
free | \
reboot \
) #single argument commands -- exact match to SSHSLAVE_COMMAND
exec "/home/tomcat-ssh-slave/bin/${SSHSLAVE_COMMAND}"
;;
setdbglvl* ) #e.g., setdbglvl 'INFO' ... multiple argument command.
Beware command injection.
exec `echo "/home/tomcat-ssh-slave/bin/${SSHSLAVE_COMMAND}" | cut -f1 -d"
"`
`echo "${SSHSLAVE_COMMAND}" | cut -f2- -d" "`
;;
* ) #disallow anything else
exec echo You are not authorized to do that.
;;
esac