Last active
March 9, 2022 00:36
-
-
Save Fusl/cd0c00d7b6e5f79cc07a7f43268e2365 to your computer and use it in GitHub Desktop.
spawn a docker container when a specific unix user connects via SSH
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -e | |
### CONFIG START ### | |
homebasedir="/data/homes" | |
defaultimage="alpine" | |
### CONFIG END ### | |
# sudo up to root | |
test "root" "!=" "${USER}" && exec sudo -n "${0}" "${HOME}" "${@}" | |
homedir="${1}"; shift | |
# allow user to specify a docker image to use by placing a .dockerimage into their homedir | |
docker_image=$(test -f "${homedir}/.dockerimage" && cat "${homedir}/.dockerimage" || echo "${defaultimage}") | |
cap_drops=" | |
SETPCAP Modify process capabilities. | |
MKNOD Create special files using mknod(2). | |
AUDIT_WRITE Write records to kernel auditing log. | |
#CHOWN Make arbitrary changes to file UIDs and GIDs (see chown(2)). | |
NET_RAW Use RAW and PACKET sockets. | |
#DAC_OVERRIDE Bypass file read, write, and execute permission checks. | |
#FOWNER Bypass permission checks on operations that normally require the file system UID of the process to match the UID of the file. | |
#FSETID Don’t clear set-user-ID and set-group-ID permission bits when a file is modified. | |
KILL Bypass permission checks for sending signals. | |
#SETGID Make arbitrary manipulations of process GIDs and supplementary GID list. | |
#SETUID Make arbitrary manipulations of process UIDs. | |
#NET_BIND_SERVICE Bind a socket to internet domain privileged ports (port numbers less than 1024). | |
#SYS_CHROOT Use chroot(2), change root directory. | |
#SETFCAP Set file capabilities. | |
" | |
cap_drop="" | |
for cap in $(echo "${cap_drops}" | grep -vE '^(#|$)' | cut -d$'\t' -f1); do | |
cap_drop="${cap_drop} --cap-drop=${cap}" | |
done | |
# check if a docker container for this user is running already | |
if ! docker container inspect "dockroot_${SUDO_USER}" </dev/fd/1 1>/dev/null 2>/dev/null; then | |
# if no docker container is running, try to spawn a container using the customers specified docker image | |
if ! docker container run --log-driver none ${cap_drop} --memory 512M --rm -d -v "${homedir}:/data:rw" --name "dockroot_${SUDO_USER}" "${docker_image}" sh -c 'while ! test -f /exit; do sleep 1; done' </dev/fd/1 1>&2; then | |
# if spawning a docker container using the customers specified docker image failed, try to spawn one using our image | |
if ! docker container run --log-driver none ${cap_drop} --memory 512M --rm -d -v "${homedir}:/data:rw" --name "dockroot_${SUDO_USER}" "${defaultimage}" sh -c 'while ! test -f /exit; do sleep 1; done' </dev/fd/1 1>&2; then | |
# if everything fails, bail out | |
echo "Failed to start Docker container" 1>&2 | |
exit 1 | |
fi | |
fi | |
if test -t 1; then | |
( | |
echo "##################################################" | |
echo "This is a temporary Docker container" | |
echo "Any modifications to this container are lost when the container is shut down" | |
echo "Modify /data/.dockerimage if you need another Docker image" | |
echo "Modify /data/.dockerstart with commands to execute on container startup" | |
echo "(/data/.dockerstart blocks the initial SSH connection so that automated backups succeed when they rely on commands on the remote host)" | |
echo "Type 'touch /exit' to shut down your container'" | |
echo "##################################################" | |
) 1>&2 | |
fi | |
# symlink the users home/data directory to /root within the container | |
docker container exec "dockroot_${SUDO_USER}" /bin/sh -c 'mv /root /root.orig && ln -s /data /root' | |
# check if the user has a ~/.dockerstart file and execute that if it's executable | |
if test -x "${homedir}/.dockerstart"; then | |
echo "Executing ~/.dockerstart ..." 1>&2 | |
docker container exec "dockroot_${SUDO_USER}" /data/.dockerstart 1>&2 | |
fi | |
fi | |
if test -t 1; then | |
# execute a TTY bash if the client connected using a TTY compatible client ... | |
exec docker container exec -w /data -ti -e COLUMNS="`tput cols`" -e LINES="`tput lines`" -e TERM="${TERM}" "dockroot_${SUDO_USER}" /bin/sh "${@}" | |
else | |
# ... otherwise execute sh without TTY allocation | |
exec docker container exec -w /data -i "dockroot_${SUDO_USER}" /bin/sh "${@}" | |
fi | |
exit 255 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
username:x:1000:1000:dockrootusers:/data/homes/username:/dockroot.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%dockrootusers ALL=(ALL) NOPASSWD: /dockroot.sh |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment