28

The authorized_keys has a command="..." option that restricts a key to a single command. Is there a way to restrict a key to multiple commands? E.g. by having a regex there, or by editing some other configuration file?

dkaeae
  • 407
  • 1
  • 5
  • 9

4 Answers4

48

You can have only one command per key, because the command is “forced”.

But you can use a wrapper script. The called command gets the original command line as environment variable $SSH_ORIGINAL_COMMAND, which it can evaluate.

E.g. put this in ~/.ssh/allowed-commands.sh:

#!/bin/sh
#
# You can have only one forced command in ~/.ssh/authorized_keys. Use this
# wrapper to allow several commands.

case "$SSH_ORIGINAL_COMMAND" in
    "systemctl restart cups")
        systemctl restart cups
        ;;
    "shutdown -r now")
        shutdown -r now
        ;;
    *)
        echo "Access denied"
        exit 1
        ;;
esac

Then reference it in ~/.ssh/authorized_keys with

command="/home/user/.ssh/allowed-commands.sh",…
hfs
  • 755
  • 9
  • 10
  • 5
    Useful. May be worth making it clearer that it is sshd itself that adds `SSH_ORIGINAL_COMMAND` (per `man sshd`) so that it's available in scripts. Also to give an example for automated scripts that allow certain patterns of `SSH_ORIGINAL_COMMAND` to run. See also https://unixwars.blogspot.com/2014/12/getting-sshoriginalcommand.html – Cedric Knight Nov 27 '19 at 18:42
13

In the great SSH, The Secure Shell: The Definitive Guide book by O'Reilly, in chapter eight, there is a nice example given using a script like the following:

#!/bin/sh

/bin/echo "Welcome!
Your choices are:
1       See today's date
2       See who's logged in
3       See current processes
q       Quit"

/bin/echo "Your choice:"

read ans

while [ "$ans" != "q" ]
do
   case "$ans" in
      1)
         /bin/date
         ;;
      2)
         /usr/bin/who
         ;;
      3)
         /usr/bin/top
         ;;
      q)
         /bin/echo "Goodbye"
         exit 0
         ;;
      *)
         /bin/echo "Invalid choice '$ans': please try again"
         ;;
   esac
   /bin/echo "Your choice:"
   read ans
done
exit 0

Using this in your .authorized_keys file like:

command="/path/to/your/script.sh" <ssh-key>

...gives you this when doing ssh:

Welcome!
Your choices are:
1       See today's date
2       See who's logged in
3       See current processes
q       Quit
Your choice:
gxx
  • 5,483
  • 2
  • 21
  • 42
10

No. It is not "allowed" command, but "forced" command (as ForceCommand option).

The only possibility is to use different keys for different commands or read parameters from stdin.

leeand00
  • 4,807
  • 13
  • 64
  • 106
Jakuje
  • 9,145
  • 2
  • 40
  • 44
2

Other approaches use e.g. a restricted shell for the given user or use a wrapper which restrains commands to al files/scripts found in a specific directory, thus allowing to augment the list of commands without changing the wrapper.

Another article describes a generic script, which also permits command line arguments to the allowed commands, but allows to lock them down with rules expressed as regular expressions.

This example would be expressed the following way:

command="only systemctl shutdown"

And an .onlyrules files would be crafted with this content:

\:^systemctl restart cups$:{p;q}
\:^shutdown -r now$:{p;q}

The advantage of this 'only' approach is that there is no need to write individual scripts for each user and situation.

  • The problem with changing the shell is that it will apply to all logins, even those with a key that is not intended to be restricted. Moreover if you only shell login and no administrator access you cannot just change your configured shell to whatever you want. But you can still edit your authorized_keys file. – kasperd Mar 12 '17 at 22:28
  • You can use a "restricted shell" as a `ForcedCommand` – Georg Lehner Mar 14 '17 at 02:06
  • It occurs to me, for the situation where the account being used is a normal user account, and the actions required are privileged, that one could rely on sudo to do the checking, and set the authorized_keys command option to "sudo $SSH_ORIGINAL_COMMAND"? – Steve Dee Aug 15 '18 at 18:35