From e6fe7dcf0cfb622793e598493ed8cc52425d641c Mon Sep 17 00:00:00 2001 From: Yann Autissier Date: Sun, 10 Apr 2022 02:21:44 +0000 Subject: [PATCH] add ssh ecryptfs auto mount --- docker/x2go/xfce-debian/Dockerfile | 19 ++++--- docker/x2go/xfce-debian/run.sh | 16 +++--- docker/x2go/xfce-debian/setup_ecryptfs.sh | 18 +++---- .../xfce-debian/setup_ecryptfs_sshagent.sh | 50 +++++++++++++++++++ docker/x2go/xfce-debian/setup_locales.sh | 3 +- docker/x2go/xfce-debian/setup_sshd.sh | 1 + docker/x2go/xfce-debian/setup_timezone.sh | 1 + docker/x2go/xfce-debian/setup_users.sh | 35 +++++++++---- stack/x2go/xfce_debian.yml | 29 ++++++++--- 9 files changed, 133 insertions(+), 39 deletions(-) create mode 100755 docker/x2go/xfce-debian/setup_ecryptfs_sshagent.sh diff --git a/docker/x2go/xfce-debian/Dockerfile b/docker/x2go/xfce-debian/Dockerfile index 68584ff..7aae745 100644 --- a/docker/x2go/xfce-debian/Dockerfile +++ b/docker/x2go/xfce-debian/Dockerfile @@ -8,16 +8,23 @@ RUN apt-get update \ ecryptfs-utils \ fail2ban \ iptables \ + less \ + libpam-script \ neovim \ + python3-pip \ + && pip install ssh-crypt \ && apt-get clean \ && rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* -COPY ${DOCKER_BUILD_DIR}/run.sh /app -COPY ${DOCKER_BUILD_DIR}/setup_ecryptfs.sh /app -COPY ${DOCKER_BUILD_DIR}/setup_locales.sh /app -COPY ${DOCKER_BUILD_DIR}/setup_sshd.sh /app -COPY ${DOCKER_BUILD_DIR}/setup_timezone.sh /app -COPY ${DOCKER_BUILD_DIR}/setup_users.sh /app +RUN cp /usr/share/doc/libpam-script/examples/logscript /usr/share/libpam-script \ + && sed -i 's/LOGFILE=\/tmp/LOGFILE=\/var\/log/' /usr/share/libpam-script/logscript \ + && for script in auth acct passwd ses_open ses_close; do \ + ln -s /usr/share/libpam-script/logscript "/usr/share/libpam-script/pam_script_${script}"; \ + done \ + && ln -s /usr/share/libpam-script /etc/pam-script + +WORKDIR /app +COPY ${DOCKER_BUILD_DIR}/*.sh /app/ CMD [] ENTRYPOINT ["/app/run.sh"] diff --git a/docker/x2go/xfce-debian/run.sh b/docker/x2go/xfce-debian/run.sh index 13d58df..c2cd08e 100755 --- a/docker/x2go/xfce-debian/run.sh +++ b/docker/x2go/xfce-debian/run.sh @@ -1,4 +1,5 @@ #!/bin/sh +[ -n "${DEBUG}" ] && set -x ### every exit != 0 fails the script set -eu @@ -9,8 +10,9 @@ if [ ! -f /app/.setup_done ]; then /app/setup_timezone.sh fi -# /home is mounted in RAM and does not survive on restart -/app/setup_ecryptfs.sh +/app/setup_ecryptfs.sh /dev/shm +# /shared encryption will not survive on restart +/app/setup_ecryptfs.sh /shared /app/setup_users.sh ## Start-up our services manually (since Docker container will not invoke all init scripts). @@ -24,28 +26,30 @@ service dbus start service rsyslog start # prevent fail2ban to fail starting touch /var/log/auth.log +# prevent tail -f to fail starting +touch /var/log/pam-script.log # prevent fail2ban to fail restarting rm -f /var/run/fail2ban/fail2ban.sock # Start fail2ban (for security reasons) service fail2ban start cleanup() { - /bin/umount -fl /home + /bin/umount -fl /home ||: service dbus stop service fail2ban stop service rsyslog stop service ssh stop - kill $PID 2>/dev/null + kill "$PID" 2>/dev/null exit } trap "cleanup" INT TERM if [ $# -eq 0 ]; then - exec tail -f /dev/null & + exec tail -f /var/log/fail2ban.log /var/log/syslog /var/log/auth.log /var/log/pam-script.log & PID=$! && wait else # WARNING: cleanup is not called - exec /bin/bash -c "set -e && $@" + exec /bin/bash -c "set -e && $*" fi cleanup diff --git a/docker/x2go/xfce-debian/setup_ecryptfs.sh b/docker/x2go/xfce-debian/setup_ecryptfs.sh index fe3d503..9b33716 100755 --- a/docker/x2go/xfce-debian/setup_ecryptfs.sh +++ b/docker/x2go/xfce-debian/setup_ecryptfs.sh @@ -1,21 +1,19 @@ #!/bin/sh +[ -n "${DEBUG}" ] && set -x set -eu CIPHER="${ECRYPTFS_CIPHER:-aes}" -KEY_BYTES="${ECRYPTFS_KEY_BYTES:-32}" -LOWER_DIR="${ECRYPTFS_LOWER_DIR:-/home}" +KEY_BYTES="${ECRYPTFS_KEY_BYTES:-16}" +LOWER_DIR="${1:-${ECRYPTFS_LOWER_DIR:-/home}}" UPPER_DIR="${ECRYPTFS_UPPER_DIR:-${LOWER_DIR}}" -ALIAS="${ECRYPTFS_ALIAS:-${LOWER_DIR##*/}}" PASSPHRASE="${ECRYPTFS_PASSPHRASE:-$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)}" KEY="${ECRYPTFS_KEY:-passphrase:passphrase_passwd=${PASSPHRASE}}" -SIG="${ECRYPTFS_SIG:-$(printf "%s" "${PASSPHRASE}" |/usr/bin/ecryptfs-add-passphrase - |/usr/bin/awk '$5 == "sig" {print substr($6,2,16); exit;}')}" FNEK_SIG="${ECRYPTFS_FNEK_SIG:-$(printf "%s" "${PASSPHRASE}" |/usr/bin/ecryptfs-add-passphrase --fnek - |/usr/bin/awk '$5 == "sig" && NR == 2 {print substr($6,2,16)}')}" -mkdir -p ${LOWER_DIR} ${UPPER_DIR} ${HOME}/.ecryptfs -printf "%s\n" "${LOWER_DIR} ${UPPER_DIR} ecryptfs" > ${HOME}/.ecryptfs/${ALIAS}.conf -printf "%s\n" "${SIG}" > ${HOME}/.ecryptfs/${ALIAS}.sig -printf "%s\n" "${FNEK_SIG}" >> ${HOME}/.ecryptfs/${ALIAS}.sig -# mount.ecryptfs_private ${ALIAS} +# ecryptfs already mounted ? +grep -q "${LOWER_DIR} ${UPPER_DIR} ecryptfs " /proc/mounts 2>/dev/null && break + +mkdir -p "${LOWER_DIR}" "${UPPER_DIR}" /bin/mount -t ecryptfs -o \ key="${KEY}",\ @@ -30,5 +28,7 @@ ecryptfs_unlink_sigs\ "${LOWER_DIR}" "${UPPER_DIR}" 1>/dev/null # Overwrite sensible variables with random data +ECRYPTFS_KEY="$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)" ECRYPTFS_PASSPHRASE="$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)" +KEY="$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)" PASSPHRASE="$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)" diff --git a/docker/x2go/xfce-debian/setup_ecryptfs_sshagent.sh b/docker/x2go/xfce-debian/setup_ecryptfs_sshagent.sh new file mode 100755 index 0000000..772f117 --- /dev/null +++ b/docker/x2go/xfce-debian/setup_ecryptfs_sshagent.sh @@ -0,0 +1,50 @@ +#!/bin/sh +[ -n "${DEBUG}" ] && set -x + +[ ! -f "${HOME}/.ecryptfs/auto-mount" ] && break + +LOWER_DIR="${1:-${ECRYPTFS_LOWER_DIR:-${HOME}/Secure}}" +UPPER_DIR="${ECRYPTFS_UPPER_DIR:-${LOWER_DIR}}" +ALIAS="${ECRYPTFS_ALIAS:-${LOWER_DIR##*/}}" +mkdir -p "${LOWER_DIR}" "${UPPER_DIR}" + +# ecryptfs already mounted ? +grep -q "${LOWER_DIR} ${UPPER_DIR} ecryptfs " /proc/mounts 2>/dev/null && break + +# we should always use the same key when multiple keys are loaded in ssh-agent +if [ -f "${HOME}/.ecryptfs/${ALIAS}.key" ]; then + ssh_key_fingerprint=$(cat "${HOME}/.ecryptfs/${ALIAS}.key") +else + ssh_key_fingerprint=$(/usr/bin/ssh-add -l 2>/dev/null |awk '{print $2; exit;}') + [ -n "${ssh_key_fingerprint}" ] && printf "%s\n" "${ssh_key_fingerprint}" > "${HOME}/.ecryptfs/${ALIAS}.key" +fi +# select ssh key +ssh_key=$(/usr/bin/ssh-add -l 2>/dev/null |awk '$2 == "'${ssh_key_fingerprint:-undef}'" {print $3}') +[ -z "${ssh_key}" ] && echo "WARNING: Unable to find ssh key ${ssh_key} in ssh agent ${SSH_AUTH_SOCK}" && break + +if [ -f "${HOME}/.ecryptfs/${ALIAS}.ssh" ]; then + PASSPHRASE=$(/usr/local/bin/ssh-crypt -b -d -k "${ssh_key}" -i "${HOME}/.ecryptfs/${ALIAS}.ssh") +else + PASSPHRASE="${ECRYPTFS_PASSPHRASE:-$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)}" + printf "%s" "${PASSPHRASE}" |/usr/local/bin/ssh-crypt -b -e -k "${ssh_key}" -o "${HOME}/.ecryptfs/${ALIAS}.ssh" +fi +SIG="${ECRYPTFS_SIG:-$(printf "%s" "${PASSPHRASE}" |/usr/bin/ecryptfs-add-passphrase - |/usr/bin/awk '$5 == "sig" {print substr($6,2,16); exit;}')}" +FNEK_SIG="${ECRYPTFS_FNEK_SIG:-$(printf "%s" "${PASSPHRASE}" |/usr/bin/ecryptfs-add-passphrase --fnek - |/usr/bin/awk '$5 == "sig" && NR == 2 {print substr($6,2,16)}')}" + +# Overwrite sensible variables with random data +ECRYPTFS_PASSPHRASE="$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)" +PASSPHRASE="$(/usr/bin/base64 /dev/urandom |/usr/bin/head -c 64)" + +if [ ! -f "${HOME}/.ecryptfs/${ALIAS}.conf" ]; then + printf "%s %s ecryptfs\n" "${LOWER_DIR}" "${UPPER_DIR}" > "${HOME}/.ecryptfs/${ALIAS}.conf" +fi + +if [ ! -f "${HOME}/.ecryptfs/${ALIAS}.sig" ]; then + printf "%s\n" "${SIG}" > "${HOME}/.ecryptfs/${ALIAS}.sig" + printf "%s\n" "${FNEK_SIG}" >> "${HOME}/.ecryptfs/${ALIAS}.sig" +else + grep "${SIG}" "${HOME}/.ecryptfs/${ALIAS}.sig" >/dev/null + grep "${FNEK_SIG}" "${HOME}/.ecryptfs/${ALIAS}.sig" >/dev/null +fi + +/sbin/mount.ecryptfs_private "${ALIAS}" diff --git a/docker/x2go/xfce-debian/setup_locales.sh b/docker/x2go/xfce-debian/setup_locales.sh index a5b17d0..f06866b 100755 --- a/docker/x2go/xfce-debian/setup_locales.sh +++ b/docker/x2go/xfce-debian/setup_locales.sh @@ -1,9 +1,10 @@ #!/bin/sh +[ -n "${DEBUG}" ] && set -x set -eu LANG=${LANG:-C.UTF-8} LOCALES=${LOCALES:-${LANG} ${LANG##*.}} printf "LANG=%s\n" "${LANG}" > /etc/default/locale -rm /etc/locale.gen && printf "%s\n" "${LOCALES}" |while read locale; do +rm /etc/locale.gen && printf "%s\n" "${LOCALES}" |while read -r locale; do printf "%s\n" "${locale}" >> /etc/locale.gen done && locale-gen diff --git a/docker/x2go/xfce-debian/setup_sshd.sh b/docker/x2go/xfce-debian/setup_sshd.sh index 44778df..f3b8e98 100755 --- a/docker/x2go/xfce-debian/setup_sshd.sh +++ b/docker/x2go/xfce-debian/setup_sshd.sh @@ -1,4 +1,5 @@ #!/bin/sh +[ -n "${DEBUG}" ] && set -x set -eu sed -i "s/^#\?PasswordAuthentication.*/PasswordAuthentication no/g" /etc/ssh/sshd_config diff --git a/docker/x2go/xfce-debian/setup_timezone.sh b/docker/x2go/xfce-debian/setup_timezone.sh index 5e56ba0..5052b77 100755 --- a/docker/x2go/xfce-debian/setup_timezone.sh +++ b/docker/x2go/xfce-debian/setup_timezone.sh @@ -1,4 +1,5 @@ #!/bin/sh +[ -n "${DEBUG}" ] && set -x set -eu TZ="${TZ:-UTC}" diff --git a/docker/x2go/xfce-debian/setup_users.sh b/docker/x2go/xfce-debian/setup_users.sh index 9a1c9a8..67cc24d 100755 --- a/docker/x2go/xfce-debian/setup_users.sh +++ b/docker/x2go/xfce-debian/setup_users.sh @@ -1,16 +1,33 @@ #!/bin/sh +[ -n "${DEBUG}" ] && set -x set -eu for user in ${USERS:-${USERNAME}}; do - id ${user} > /dev/null 2>&1 || useradd -ms /bin/bash ${user} - usermod -a -G x2gouser ${user} - mkdir -p /home/${user}/.ssh - wget -qO /home/${user}/.ssh/authorized_keys https://gitlab.com/${user}.keys 2>/dev/null \ - || wget -qO /home/${user}/.ssh/authorized_keys https://github.com/${user}.keys 2>/dev/null - chown -R ${user} /home/${user}/.ssh - chmod 0750 /home/${user} + id "${user}" > /dev/null 2>&1 || useradd -s /bin/bash "${user}" + [ ! -d "/home/${user}" ] \ + && mkdir -p "/home/${user}" \ + && chown "${user}" "/home/${user}" \ + && chmod 0750 "/home/${user}" + for file in .bash_logout .bashrc .profile; do + [ ! -f "/home/${user}/${file}" ] \ + && cp "/etc/skel/${file}" "/home/${user}" \ + && chown "${user}" "/home/${user}/${file}" + done + usermod -a -G x2gouser "${user}" + mkdir -p "/home/${user}/.ssh" + wget -qO "/home/${user}/.ssh/authorized_keys" "https://gitlab.com/${user}.keys" 2>/dev/null \ + || wget -qO "/home/${user}/.ssh/authorized_keys" "https://github.com/${user}.keys" 2>/dev/null \ + || echo "WARNING: Unable to fetch ssh public keys for user ${user}." + chown "${user}" "/home/${user}/.ssh" "/home/${user}/.ssh/authorized_keys" done for sudoer in ${SUDOERS:-}; do - usermod -a -G sudo ${sudoer} + usermod -a -G sudo "${sudoer}" done -mkdir -p /home/shared && chmod 1777 /home/shared +for ecrypter in ${ECRYPTERS:-}; do + mkdir -p "/home/${ecrypter}/.ecryptfs" + touch "/home/${ecrypter}/.ecryptfs/auto-mount" + touch "/home/${ecrypter}/.ecryptfs/auto-umount" + chown -R "${ecrypter}" "/home/${ecrypter}/.ecryptfs" +done +ln -s /app/setup_ecryptfs_sshagent.sh /etc/profile.d/ +mkdir -p /shared && chmod 1777 /shared diff --git a/stack/x2go/xfce_debian.yml b/stack/x2go/xfce_debian.yml index 165cc4e..e585daf 100644 --- a/stack/x2go/xfce_debian.yml +++ b/stack/x2go/xfce_debian.yml @@ -13,6 +13,8 @@ services: - NET_RAW # iptables - SYS_ADMIN # ecryptfs environment: + - DEBUG=${VDI_DEBUG} + - ECRYPTERS=${VDI_ECRYPTERS} - LANG=${VDI_LANG} - SUDOERS=${VDI_SUDOERS} - TZ=${VDI_TZ} @@ -25,11 +27,22 @@ services: - seccomp=unconfined # ecryptfs tty: true volumes: - - type: tmpfs - target: /home - tmpfs: - size: 8589934592 # 8GB - - type: tmpfs - target: /dev/shm - tmpfs: - size: 2147483648 # 2GB + - home:/home:delegated + - shared:/shared:cached + - shm:/dev/shm:delegated + + +volumes: + home: + shared: + driver: local + driver_opts: + type: none + device: /mnt/shared + o: bind + shm: + driver: local + driver_opts: + type: tmpfs + device: tmpfs + o: mode=1777,size=2147483648 # 2GB