diff --git a/rsync-backup-target/build/Dockerfile b/rsync-backup-target/build/Dockerfile index 554f34b..5415bdc 100644 --- a/rsync-backup-target/build/Dockerfile +++ b/rsync-backup-target/build/Dockerfile @@ -2,14 +2,15 @@ FROM alpine:3.9 MAINTAINER Valentin Lab -RUN apk add rsync sudo bash openssh-server +## coreutils is for ``date`` support of ``--rfc-3339=seconds`` argument. +RUN apk add rsync sudo bash openssh-server coreutils RUN ssh-keygen -A ## New user/group rsync/rsync with home dir in /var/lib/rsync -RUN mkdir -p /var/lib/rsync && \ +RUN mkdir -p /var/lib/rsync /var/log/rsync && \ addgroup -S rsync && \ adduser -S rsync -h /var/lib/rsync -G rsync && \ - chown rsync:rsync /var/lib/rsync + chown rsync:rsync /var/lib/rsync /var/log/rsync ## Without this, account is concidered locked by SSH RUN sed -ri 's/^rsync:!:/rsync:*NP*:/g' /etc/shadow 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 index e1940b2..415f8b5 100755 --- a/rsync-backup-target/build/src/usr/local/sbin/ssh-cmd-validate +++ b/rsync-backup-target/build/src/usr/local/sbin/ssh-cmd-validate @@ -5,14 +5,32 @@ exname=$(basename "$0") +mkdir -p /var/log/rsync + +LOG="/var/log/rsync/$exname.log" + + +ssh_connection=(${SSH_CONNECTION}) +SSH_SOURCE_IP="${ssh_connection[0]}:${ssh_connection[1]}" + +log() { + printf "%s [%s] %s - %s\n" \ + "$(date --rfc-3339=seconds)" "$$" "$SSH_SOURCE_IP" "$*" \ + >> "$LOG" +} + +log "NEW CONNECTION" + if [ -z "$1" ] || ! [[ "$1" =~ ^[a-zA-Z0-9._-]+$ ]]; then - logger -t "$exname" "INVALID SETUP, ARG IS: '$1'" + log "INVALID SETUP, ARG IS: '$1'" echo "Your command has been rejected. Contact administrator." exit 1 fi +ident="$1" + reject() { - logger -t "$exname" "REJECTED: $SSH_ORIGINAL_COMMAND" + log "REJECTED: $SSH_ORIGINAL_COMMAND" # echo "ORIG: $SSH_ORIGINAL_COMMAND" >&2 echo "Your command has been rejected and reported to sys admin." >&2 exit 1 @@ -20,15 +38,25 @@ reject() { if [[ "$SSH_ORIGINAL_COMMAND" =~ [\&\(\{\;\<\>\`\$\}] ]]; then + log "BAD CHARS DETECTED" # echo "Bad chars: $SSH_ORIGINAL_COMMAND" >&2 reject fi -if [[ "$SSH_ORIGINAL_COMMAND" =~ ^"rsync --server -"[vloHgDtpArRzCeiLsfx\.]+(" --"[a-z-]+|" --partial-dir .rsync-partial")*" . /var/mirror/$1"$ ]]; then - logger -t "$exname" "ACCEPTED: $SSH_ORIGINAL_COMMAND" +if [[ "$SSH_ORIGINAL_COMMAND" =~ ^"rsync --server -"[vloHgDtpArRzCeiLsfx\.]+(" --"[a-z=%-]+|" --partial-dir .rsync-partial")*" . /var/mirror/$ident"$ ]]; then + log "ACCEPTED: $SSH_ORIGINAL_COMMAND" + + ## Interpret \ to allow passing spaces (want to avoid possible issue with \n) + #read -a ssh_args <<< "${SSH_ORIGINAL_COMMAND}" + ssh_args=(${SSH_ORIGINAL_COMMAND}) + # echo "Would accept: $SSH_ORIGINAL_COMMAND" >&2 - exec sudo $SSH_ORIGINAL_COMMAND + exec sudo "${ssh_args[@]::3}" \ + "--log-file=/var/log/rsync/target_$1_rsync.log" \ + "--log-file-format=%i %o %f %l %b" \ + "${ssh_args[@]:3}" else + log "NO MATCH ACCEPTED COMMAND" reject fi diff --git a/rsync-backup-target/hooks/log_rotate-relation-joined b/rsync-backup-target/hooks/log_rotate-relation-joined new file mode 100755 index 0000000..a7372e1 --- /dev/null +++ b/rsync-backup-target/hooks/log_rotate-relation-joined @@ -0,0 +1,67 @@ +#!/bin/bash + +## Should be executable N time in a row with same result. + +. lib/common + +set -e + +uid=$(docker_get_uid "$SERVICE_NAME" "rsync") + + +LOGS=/var/log/rsync +mkdir -p "$SERVICE_DATASTORE/$LOGS" +touch "$SERVICE_DATASTORE/$LOGS/ssh-cmd-validate.log" +chown -v "$uid" "$SERVICE_DATASTORE/$LOGS" "$SERVICE_DATASTORE/$LOGS/ssh-cmd-validate.log" + +rotated_count=$(relation-get rotated-count 2>/dev/null) || true +rotated_count=${rotated_count:-52} + + +## XXXvlab: a lot of this intelligence should be moved away into ``logrotate`` charm +DST="$CONFIGSTORE/$TARGET_SERVICE_NAME/etc/logrotate.d/$SERVICE_NAME" +file_put "$DST" <