Shell – restrict private apt repository with rssh – why does apt-get try /bin/sh

aptrepositoryshellssh

I am trying to set up a private repository via ssh. My sources.list.d/ contains the entry

deb ssh://user@host:/repo ./ 

user is a certificate only account on host. apt-get update works fine.

However, I would like to restrict the access to downloading the repository, i.e. disable shell access. If I set the user shell to rssh, allowing only scp and sftp, the update breaks.

From /var/log/syslog:

user user attempted to execute forbidden commands
command: /bin/sh

Why does apt need shell access on the repository machine, and is there a way to avoid this?

I noticed there is an github repository for apt-transport-sftp which I might have a look at, but I'd rather stick to more common packages for user convenience.

Best Answer

What is APT doing remotely

I have set up a test account, and logged every command apt executed on the remote server by using a simple script as a replacement for the repo owner's shell. Apparently, apt is spawning a remote shell in order to find the full path to well-known files::

2015-09-14: Executing 'sh -c /bin/sh'; input and output follows:
find /tmp/repo/./InRelease -follow -printf '%s\n' 2> /dev/null || echo

find /tmp/repo/./Release.gpg -follow -printf '%s\n' 2> /dev/null || echo

find /tmp/repo/./Release -follow -printf '%s\n' 2> /dev/null || echo

find /tmp/repo/./Packages.bz2 -follow -printf '%s\n' 2> /dev/null || echo

find /tmp/repo/./it_CH.bz2 -follow -printf '%s\n' 2> /dev/null || echo

find /tmp/repo/./it.bz2 -follow -printf '%s\n' 2> /dev/null || echo

find /tmp/repo/./en.bz2 -follow -printf '%s\n' 2> /dev/null || echo

find /tmp/repo/./Packages.xz -follow -printf '%s\n' 2> /dev/null || echo

...

Therefore, I think you cannot restrict actions of the repo user via rssh, as: (1) the commands to be executed are being passed to the remote shell via STDIN (as opposed to SSH's remote exec feature), and (2) commands are shell pipelines.

Workarounds?

If you still want to restrict actions performed by the repo user remotely, I see two ways forward:

  • Set the repo user's shell to rbash instead, and provide a customized $PATH setting with only the commands that need to be run. (Be sure to set $PATH and unset other shell variables from a startup file that cannot be written from the repo user.) This still leaves the possibility to anyone having the access credentials to read any file in the system.

  • Create a chroot jail with just the repo files and any command needed by APT, and set the repo user's shell to a script or program that performs chroot /jail "$@" instead.

Logging apt-get update actions

Here's the script I used to log actions executed remotely::

#!/bin/sh

echo "$(date -I): executing 'sh $@'; input and output follows" >> /tmp/sh.log
tee -a /tmp/sh.log | /bin/sh "$@" | tee -a /tmp/sh.log
Related Question