One of OpenSSH coolest features is the ability to force a command for a given SSH access. You can use this to create limited access for demos, monitoring tools, administration tasks and backup process.
Command without arguments
This is the simplest case, you want to restrict the user to a single command without any arguments. This can be achieved with the command=
option into the authorized_keys
file like this:
command="/usr/bin/command",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key
Note that in addition to enforcing the command, i also disabled terminal and a number of advanced SSH features, such as TCP and X11 forwarding.
Command with fixed arguments
Same as before, just add the complete chain into the command=
block. For example with rsync
:
command="rsync --server --delete -logDtpre.iLsf . ~/foobar",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key
Or if you use rsync
in daemon mode:
command="rsync --server --daemon .",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key
Command with arbitrary arguments
Authorize arbitrary arguments is a little more complicated. This is where the environment variable $SSH_ORIGINAL_COMMAND
comes in. When forcing the user command, OpenSSH store the original user command into this variable. By forcing the user to a custom script shell parsing the content of the $SSH_ORIGINAL_COMMAND
, you can authorize a specific command with arbitrary arguments:
#!/bin/sh
# /usr/local/bin/limitssh.sh
set -- $SSH_ORIGINAL_COMMAND
case "$1" in
/usr/bin/command *)
;;
*)
exit 1
;;
esac
exec "/usr/bin/command" "$@"
Then modify your authorized_keys
file like this:
command="/usr/local/bin/limitssh.sh $SSH_ORIGINAL_COMMAND",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key
It is important to be aware of potential security issues here, such as user escaping to a shell prompted from the listed command. Therefore i recommend you to always disable user terminal (no-pty
option) and never use this technique with complex ‘command’ like rsync
.
Multiple commands
You can modify your bash script to authorize multiple commands instead of one. Keep in mind this solution is kind of a patch-up job and you should really consider using a more robust restricted shell solution instead:
#!/bin/sh
# /usr/local/bin/limitssh.sh
set -- $SSH_ORIGINAL_COMMAND
case "$1" in
"ps")
ps -ef
;;
"vmstat")
vmstat 1 100
;;
"apache stop")
/etc/init.d/apache2 stop
;;
"apache start")
/etc/init.d/apache2 start
;;
*)
exit 1
;;
esac