diff --git a/rsync-backup-target/build/Dockerfile b/rsync-backup-target/build/Dockerfile new file mode 100644 index 0000000..e5d2e39 --- /dev/null +++ b/rsync-backup-target/build/Dockerfile @@ -0,0 +1,31 @@ +FROM debian:jessie + +MAINTAINER Valentin Lab + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install --force-yes -y --no-install-recommends openssh-server sudo rsync && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + + +COPY ./src/usr/local/sbin/* /usr/local/sbin/ + +## New user/group rsync/rsync with home dir in /var/lib/rsync +RUN mkdir -p /var/lib/rsync && \ + groupadd -r rsync && \ + useradd -r rsync -d /var/lib/rsync -g rsync && \ + chown rsync:rsync /var/lib/rsync + + +## Allow rsync to access /var/mirror +COPY /src/etc/sudoers.d/rsync /etc/sudoers.d/rsync + +RUN chmod 440 /etc/sudoers.d/* + +RUN mkdir /var/run/sshd + +COPY ./entrypoint.sh /entrypoint.sh + +EXPOSE 22 + +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/rsync-backup-target/build/entrypoint.sh b/rsync-backup-target/build/entrypoint.sh new file mode 100755 index 0000000..11583bc --- /dev/null +++ b/rsync-backup-target/build/entrypoint.sh @@ -0,0 +1,23 @@ +#!/bin/bash + + +## +## code +## + +chmod 440 /etc/sudoers.d/* -R + +KEYS=/etc/rsync/keys/ +RSYNC_HOME=/var/lib/rsync + +mkdir -p "$RSYNC_HOME/.ssh" + +for f in "$KEYS"/*; do + [ -e "$f" ] || continue + content=$(cat "$f") + echo "command=\"/usr/local/sbin/ssh-cmd-validate\" $content" +done > "$RSYNC_HOME"/.ssh/authorized_keys +chown rsync:rsync -R "$RSYNC_HOME"/.ssh -R + +## Give back PID 1 so that ssh can receive signals +exec /usr/sbin/sshd -D diff --git a/rsync-backup-target/build/src/etc/sudoers.d/rsync b/rsync-backup-target/build/src/etc/sudoers.d/rsync new file mode 100644 index 0000000..325e594 --- /dev/null +++ b/rsync-backup-target/build/src/etc/sudoers.d/rsync @@ -0,0 +1,10 @@ +## allow rsync to access /var/mirror + +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtprRz --delete . /var/mirror/* +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtprRze.iLs --delete . /var/mirror/* +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtprRze.iLsf --delete . /var/mirror/* +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtprRze.iLsf --bwlimit=200 --delete . /var/mirror/* +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtpArRze.iLsf --delete . /var/mirror/* +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtpArRze.iLsf --bwlimit=200 --delete . /var/mirror/* +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtpArRze.iLsfx --delete --partial-dir .rsync-partial --numeric-ids . /var/mirror/* +rsync ALL=(root) NOPASSWD: /usr/bin/rsync --server -vlogDtpArze.iLsfx --delete --partial-dir .rsync-partial --numeric-ids . /var/mirror/* diff --git a/rsync-backup-target/build/src/usr/local/sbin/ssh-cmd-validate b/rsync-backup-target/build/src/usr/local/sbin/ssh-cmd-validate new file mode 100755 index 0000000..50f91e9 --- /dev/null +++ b/rsync-backup-target/build/src/usr/local/sbin/ssh-cmd-validate @@ -0,0 +1,22 @@ +#!/bin/sh + +exname=$(basename "$0") + +reject() { + logger -t "$exname" "REJECTED: $SSH_ORIGINAL_COMMAND" + echo "Your command has been rejected and reported to sys admin." +} + +case "$SSH_ORIGINAL_COMMAND" in + *\&* | *\(* | *\{* | *\;* | *\<* | *\`*) + reject + ;; + md5sum\ /var/mirror/*|find\ /var/mirror/*|rsync\ --server*) + echo "ACCEPTED: $SSH_ORIGINAL_COMMAND" >/tmp/accepted + logger -t "$exname" "ACCEPTED: $SSH_ORIGINAL_COMMAND" + sudo $SSH_ORIGINAL_COMMAND + ;; + *) + reject + ;; +esac diff --git a/rsync-backup-target/hooks/init b/rsync-backup-target/hooks/init new file mode 100755 index 0000000..2068833 --- /dev/null +++ b/rsync-backup-target/hooks/init @@ -0,0 +1,40 @@ +#!/bin/bash + +## Init is run on host +## For now it is run every time the script is launched, but +## it should be launched only once after build. + +## Accessible variables are: +## - SERVICE_NAME Name of current service +## - DOCKER_BASE_IMAGE Base image from which this service might be built if any +## - SERVICE_DATASTORE Location on host of the DATASTORE of this service +## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service + + +set -e + +service_def=$(get_compose_service_def "$SERVICE_NAME") + +keys=$(echo "$service_def" | shyaml get-value options.keys 2>/dev/null) || true + +[ "$keys" ] || exit 0 + +local_path_key=/etc/rsync/keys +host_path_key="$SERVICE_CONFIGSTORE${local_path_key}" +key_nb=0 + +volume_keys=() +while read-0 key; do + debug "Creating access key ${key_nb}" || true + echo "$key" | file_put "$host_path_key/key_${key_nb}.pub" + ((key_nb++)) || true +done < <(echo "$keys" | shyaml get-values-0) + +volume_keys+=("$host_path_key:$local_path_key:ro") + +init-config-add "\ +$SERVICE_NAME: + volumes: + - $host_path_key:$local_path_key:ro +" + diff --git a/rsync-backup-target/metadata.yml b/rsync-backup-target/metadata.yml new file mode 100644 index 0000000..5cface6 --- /dev/null +++ b/rsync-backup-target/metadata.yml @@ -0,0 +1,3 @@ +description: Backup Rsync over SSH Target +data-resources: + - /var/mirror