Today I created limited access for a buildbot user via SSH. The build machines need SSH access to upload built software to our file server. This works using rsync over SSH.

Whereas real users are using a Yubikey and not SSH key files anymore, the build machines still require SSH key files, but to limit the risk of lost key files it is important to limit the access on the file server.

Therefor two important steps are necessary:

  1. Configure correct file permissions, so that the buildbot user can only access its own folders and files, nothing else.
  2. Restrict what the user can do via SSH. In this case only allow the rsync command and disable every other SSH feature like port-forwarding.

The first step should be clear. The second step can be configured in the ~/.ssh/authorized_keys file using the command directive.

Example:

command="/usr/bin/rsync" ssh-rsa ....

The problem with this is it allows no arguments. For backup scripts which use always the same arguments you can simply add them to the command, but in this case arbitrary arguments are used, depending on what products and versions get built.

The $SSH_ORIGINAL_COMMAND variable contains the orignal command, but when using this inside command it again would allow everything, which is not what we want.

So I created a wrapper bash script based on the example from Thomas Krenn (Ausführbare SSH-Kommandos per authorized_keys einschränken).

But in my script a verify that the $SSH_ORIGINAL_COMMAND starts with the rsync command, and only executes this. This way I can allow all arguments (which could be further restricted). And in addition I log all executed commands and mark the denied ones with a special keyword.

checkssh.sh:

#!/bin/bash
if [ -n "$SSH_ORIGINAL_COMMAND" ]; then
    if [[ "$SSH_ORIGINAL_COMMAND" =~ ^rsync\  ]]; then
        echo "`/bin/date`: $SSH_ORIGINAL_COMMAND" >> $HOME/ssh-command-log
        exec $SSH_ORIGINAL_COMMAND
    else
        echo "`/bin/date`: DENIED $SSH_ORIGINAL_COMMAND" >> $HOME/ssh-command-log
    fi
fi

Then all you need to do is making this script executable by the user and change the authorized_keys files to use the new wrapper script.

authorized_keys:

command="/home/buildbot/checkssh.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa ...

Important note: Make the checkssh.sh script executable by the buildbot user, but not writable. Otherwise an attacker could use rsync to replace the checkssh script with his own version which contains no restrictions at all.

Then try to use rsync and watch the ssg-command-log file:

~$ tail -f ssh-command-log
Wed Jul  5 15:04:32 CEST 2017: DENIED cat /etc/passwd
Wed Jul  5 15:05:08 CEST 2017: DENIED rsyncx -abc -def
Wed Jul  5 15:37:03 CEST 2017: rsync --server -vtre.iLsfx . /raid/projekte/Unified_Automation_Produkte/kmtarget_ci/embeddedstack/ci-debian

Comments

comments powered by Disqus