From 720754a50446df9c158c14919ea2959d70c9c9fe Mon Sep 17 00:00:00 2001 From: Kevin McCormick Date: Thu, 9 Mar 2017 11:55:57 -0800 Subject: [PATCH] ssh mode: use forced backup-zfs-shell Ensure the backup connection to the SSH server can't do anything other than designed. Uses ssh's authorized_keys command= statement to launch backup-zfs-shell, which then supports only the handful of operations required to perform backups. $destpath is no longer used, but still included in the documentation until it can be entirely written out. --- backup-zfs | 20 ++++++++++---------- backup-zfs-shell | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 10 deletions(-) create mode 100755 backup-zfs-shell diff --git a/backup-zfs b/backup-zfs index b37f1fc..ea33b21 100755 --- a/backup-zfs +++ b/backup-zfs @@ -148,7 +148,7 @@ if $tossh ; then ### get newest snapshot on dest - it must exist on src ### #last="$(ZFS "$desthost" list -d 1 -t snapshot -H -S creation -o name $destfs/$srcbase | head -n1 | cut -f2 -d@)" - last="$(ssh "$desthost" cat "$destpath/.last")" + last="$(ssh "$desthost" zfslast)" ### ### send @@ -166,14 +166,14 @@ if $tossh ; then if [[ -n $gpgid ]] ; then ZFS "$srchost" send $send_opts -R -I "$last" "$cur" \ | gpg --trust-model always --encrypt --recipient "$gpgid" \ - | ssh "$desthost" "cat > \"$destpath/${tag}_$date.zfssnap.gpg\"" \ + | ssh "$desthost" zfswrite "${tag}_$date.zfssnap.gpg" \ || die $? "zfs incremental send failed" - ssh "$desthost" "echo \"$snap\" > \"$destpath/.last\"" + ssh "$desthost" zfslast "$snap" else ZFS "$srchost" send $send_opts -R -I "$last" "$cur" \ - | ssh "$desthost" "cat > \"$destpath/${tag}_$date.zfssnap\"" \ + | ssh "$desthost" zfswrite "${tag}_$date.zfssnap" \ || die $? "zfs incremental send failed" - ssh "$desthost" "echo \"$snap\" > \"$destpath/.last\"" + ssh "$desthost" zfslast "$snap" fi fi @@ -201,13 +201,13 @@ elif $fromssh ; then ### log "receiving incremental snapshot from $src to $dest" #ZFS "$srchost" send $send_opts -R -I "$last" "$cur" | ZFS "$desthost" receive $recv_opts -Fue "$destfs" || die $? "zfs incremental send failed" - for file in $(ssh "$srchost" "find \"$srcpath\" -name \"*.zfssnap\" -o -name \"*.zfssnap.gpg\"") ; do + for file in $(ssh "$srchost" zfsfind "$srcpath" | sort) ; do if [[ $file =~ \.gpg$ ]] ; then - ssh "$srchost" "cat \"$file\"" | gpg | ZFS "$desthost" receive $recv_opts -Fue "$dest" \ - && ssh "$srchost" "rm \"$file\"" + ssh "$srchost" zfsget "$file" | gpg | ZFS "$desthost" receive $recv_opts -Fue "$dest" \ + && ssh "$srchost" rm "$file" else - ssh "$srchost" "cat \"$file\"" | ZFS "$desthost" receive $recv_opts -Fue "$dest" \ - && ssh "$srchost" "rm \"$file\"" + ssh "$srchost" zfsget "$file" | ZFS "$desthost" receive $recv_opts -Fue "$dest" \ + && ssh "$srchost" rm "$file" fi done diff --git a/backup-zfs-shell b/backup-zfs-shell new file mode 100755 index 0000000..e897435 --- /dev/null +++ b/backup-zfs-shell @@ -0,0 +1,33 @@ +#!/bin/bash + +# A restricted shell for backup-zfs's SSH mode. Must be installed on the +# SSH server, and then configured with command="/path/to/backup-zfs-shell" +# in the user's authorized_keys file. +# TODO: tag & dest should support better customization +dest=zfssnap.nobackup +tag=frodo + +case "$SSH_ORIGINAL_COMMAND" in + zfslast) + exec cat $dest/.last ;; + zfslast\ ${tag}_20[12][0-9]-[01][0-9]-[0-3][0-9]_[012][0-9]:[0-5][0-9]:[0-5][0-9]) + exec echo "${SSH_ORIGINAL_COMMAND/zfslast /}" > "$dest/.last" ;; + zfswrite\ ${tag}_20[12][0-9]-[01][0-9]-[0-3][0-9]_[012][0-9]:[0-5][0-9]:[0-5][0-9].zfssnap.gpg) + exec cat > "$dest/${SSH_ORIGINAL_COMMAND/zfswrite /}" ;; + zfswrite\ ${tag}_20[12][0-9]-[01][0-9]-[0-3][0-9]_[012][0-9]:[0-5][0-9]:[0-5][0-9].zfssnap) + exec cat > "$dest/${SSH_ORIGINAL_COMMAND/zfswrite /}" ;; + zfsget\ $dest/${tag}_20[12][0-9]-[01][0-9]-[0-3][0-9]_[012][0-9]:[0-5][0-9]:[0-5][0-9].zfssnap.gpg) + exec cat "${SSH_ORIGINAL_COMMAND/zfsget /}" ;; + zfsget\ $dest/${tag}_20[12][0-9]-[01][0-9]-[0-3][0-9]_[012][0-9]:[0-5][0-9]:[0-5][0-9].zfssnap) + exec cat "${SSH_ORIGINAL_COMMAND/zfsget /}" ;; + zfsfind) + exec find "$dest" -name "*.zfssnap" -o -name "*zfssnap.gpg" ;; + rm\ $dest/${tag}_20[12][0-9]-[01][0-9]-[0-3][0-9]_[012][0-9]:[0-5][0-9]:[0-5][0-9].zfssnap.gpg) + exec rm "${SSH_ORIGINAL_COMMAND/rm /}" ;; + rm\ $dest/${tag}_20[12][0-9]-[01][0-9]-[0-3][0-9]_[012][0-9]:[0-5][0-9]:[0-5][0-9].zfssnap) + exec rm "${SSH_ORIGINAL_COMMAND/rm /}" ;; + *) + echo "Command not allowed: $SSH_ORIGINAL_COMMAND" >&2 + exit 1 + ;; +esac