14

I would like to create a user who can only do one thing: via ssh specify a script ( and commandline arguments to the script ) that resides in one particular folder ( for the purposes of this question let us call it /local/remote_only_scripts/foo ) and have that script execute and return it's output.

To be clear some examples of things I do not want the user to be able to do:

  • Locally log in to the account. The login application is /bin/login. It is not a script in the /local/remote_only_scripts/foo folder, so should not be called by the user.
  • Remotely log in to the account. Again login ( is that what is called by ssh? ) is not a script in the relevant folder.
  • List the contents of the directory. ls is in /bin/ls. It is not a script in the appropriate directory.
  • Edit a file in that directory. emacs, vi, gedit most other editors are not scripts in that directoy.
  • View the contents of a file in that directory.
  • Execute a file in that directory that he does not have permission to execute.

Note that these are examples there are many other actions which I do not want the user to be able to do. In considering an action, ask "is this being done by a script in /local/remote_only_scripts/foo?" if the answer is no the user should not be able to do it. If the answer is yes then the user should be able to do it.

PS: Let me clarify what I mean by "adding a user". I do not mean adding a user to some ssh subsystem. Rather I mean adding a user to the computer system. So, for example, I have a system running debian stable, call it by it's address, www.hg.bar.com. I want to add a user ( via kuser, users-admin or useradd or some similar way ) call him hg_guest. hg_guest cannot login locally or do any of the things in the above list. All hg_guest can do is execute scripts "remotely". I said he should be able to do so via ssh, but thinking about it now, maybe allowing him to use ssh may allow him to login in locally, so some other mechanism may be required.

HandyGandy
  • 2,209

3 Answers3

13

There's a command option in authorized_keys file. This options seems to do exactly what you want.

Note that it's not a chroot or a restricted shell. It's allowing to execute only those commands via ssh. With your example, it would be :

ssh somehost /local/remote_only_scripts/foo

For this authorized_keys file :

command="/local/remote_only_scripts/foo",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ...public key... 

There's plenty of way if you don't want your user to be able to log in locally. You can either :

  • simply set its shell to /bin/false (maybe you'll need /bin/true since ssh needs a valid log in)
  • lock its password, see passwd -l

EDIT : added more restriction options and clarify how you remove local access.

Coren
  • 5,010
  • I don't think you need to specify that command in ssh on client side, it is 'forced' command so it would be always executed ;) The user on remote site still needs valid shell defined in /etc/passwd. – jirib Mar 19 '12 at 08:14
  • 1
    Beside command=, the options no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty are needed to really restrict the account. – jofel Mar 19 '12 at 08:20
  • Ok. I woke up in the middle of the night and decided to check answers. Since I'm drowsy I will not assimilate the entire answer but ask something which leaves me confused. How does this prevent hg_quest from logging in from a tty? – HandyGandy Mar 19 '12 at 09:19
  • @HandyGandy This is the most simple part. I have added 2 ways of doing it, but I think there's more – Coren Mar 19 '12 at 10:07
0

Try this as the login shell for the user:

#!/bin/sh
basedir=/local/remote_only_scripts
while read -p '$ ' prog args; do
    if [ ! -x "$basedir/$prog" ]; then
        echo "Invalid program: $prog"
    else
        case "$prog $args" in
            *\**|*\?*|*\^*|*\&*|*\<*|*\>*|*\|*|*\;*|*\`*|*\[*|*\]*)
                echo "Invalid character in command";;
            *)
                eval "$prog $args"
                echo;; # force a trailing newline after the program
        esac
    fi
done

You will probably also want to have this in the authorized_keys file explicitly as in Coren's answer; but replace the '.../foo; with the program here. That will prevent commands from SSH like sftp, scp, and ssh hostname command.

Arcege
  • 22,536
  • If you only want the user to be able to execute the commands from your directory (and there aren't too many), you could take the "prog" out of the read above and use a select statement to offer a text menu of choices of those programs and then do the read for the arguments. I would also test this to make sure what happens if you type a bunch of Ctrl-Cs at various points in the script. You may want a trap command in there too. – Joe Mar 29 '12 at 06:05
0

In the off chance they only need to access one script this works really well for me. Add the user and change their default shell to the path of the script. When they connect via ssh it will execute the script and close their session.

server1:/ # useradd -s "/local/remote_only_scripts/foo/script.sh" hg_guest

server1:/ # grep hg_guest /etc/passwd

hg_guest:x:2002:100::/home/hg_guest:/local/remote_only_scripts/foo/script.sh

2bc
  • 3,978