Added integrity check option(--checksum)
This commit is contained in:
115
backup.sh
115
backup.sh
@@ -13,19 +13,23 @@
|
||||
# logs=/var/log/
|
||||
#
|
||||
# After that you can launch the script with(sample usage):
|
||||
# sudo ./backup.sh --backup sources.bk /home/john badpw1234
|
||||
# sudo ./backup.sh --checksum --backup sources.bk /home/john badpw1234
|
||||
#
|
||||
# This will create an encrypted tar archive(password: 'badpw1234')
|
||||
# in '/home/john/backup-<hostname>-<YYYMMDD>.tar.gz.enc' containing
|
||||
# in '/home/john/backup-<hostname>-<YYYYMMDD>.tar.gz.enc' containing
|
||||
# the following three directories:
|
||||
# backup-nginx-<YYYYMMDD>
|
||||
# backup-ssh-<YYYYMMDD>
|
||||
# backup-logs-<YYYYMMDD>
|
||||
#
|
||||
# You can then decrypt it using:
|
||||
# ./backup.sh --extract backup-<hostname>-<YYYMMDD>.tar.gz.enc badpw1234
|
||||
# as well as a SHA256 file('/home/john/backup-<hostname>-<YYYYMMDD>.sha256')
|
||||
# containing the file hashes of the backup.
|
||||
#
|
||||
# You can read the full guide on https://github.com/ice-bit/backup.sh
|
||||
# You can then decrypt it using:
|
||||
# ./backup.sh --checksum --extract backup-<hostname>-<YYYYMMDD>.tar.gz.enc badpw1234 $PWD/backup-<hostname>-<YYYYMMDD>.sha256
|
||||
# which will also check the integrity of the backup(optional feature).
|
||||
#
|
||||
# You can read the full guide on https://github.com/ceticamarco/backup.sh
|
||||
# or on the manual page.
|
||||
# Copyright (c) 2018,2023,2024 Marco Cetica <email@marcocetica.com>
|
||||
#
|
||||
@@ -47,29 +51,23 @@ checkdeps() {
|
||||
fi
|
||||
}
|
||||
|
||||
checksum() {
|
||||
BACKUP_SH_FILENAME="$1"
|
||||
BACKUP_SH_OS="$(uname | tr '[:lower:]' '[:upper:]')"
|
||||
|
||||
if [ "$BACKUP_SH_OS" = "LINUX" ]; then
|
||||
RES="$(md5sum "$BACKUP_SH_FILENAME" | awk '{print $1}')"
|
||||
else
|
||||
RES="$(md5 -q "$BACKUP_SH_FILENAME")"
|
||||
fi
|
||||
|
||||
echo "$RES"
|
||||
}
|
||||
|
||||
# $1: sources.bk file
|
||||
# $2: output path
|
||||
# $3: password
|
||||
# $4: compute sha256(0,1)
|
||||
make_backup() {
|
||||
BACKUP_SH_SOURCES_PATH="$1"
|
||||
BACKUP_SH_OUTPATH="$2"
|
||||
BACKUP_SH_PASS="$3"
|
||||
BACKUP_SH_SHA256="$4"
|
||||
|
||||
BACKUP_SH_COMMAND="rsync -aPhrq --delete"
|
||||
BACKUP_SH_DATE="$(date +'%Y%m%d')"
|
||||
BACKUP_SH_FOLDER="backup.sh.tmp"
|
||||
BACKUP_SH_OUTPUT="$BACKUP_SH_OUTPATH/$BACKUP_SH_FOLDER"
|
||||
BACKUP_SH_START_TIME="$(date +%s)"
|
||||
BACKUP_SH_FILENAME="$BACKUP_SH_OUTPATH/backup-$(uname -n)-$BACKUP_SH_DATE.tar.gz.enc"
|
||||
BACKUP_SH_CHECKSUM_FILE="$BACKUP_SH_OUTPATH/backup-$(uname -n)-$BACKUP_SH_DATE.sha256"
|
||||
|
||||
# Check for root permissions
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
@@ -96,6 +94,13 @@ make_backup() {
|
||||
mkdir -p "$BACKUP_SH_SUBDIR"
|
||||
|
||||
printf "Copying %s(%s/%s)\n" "$label" "$BACKUP_SH_PROGRESS" "$BACKUP_SH_TOTAL"
|
||||
|
||||
# Compute SHA256 of all files of the current directory
|
||||
if [ "$BACKUP_SH_SHA256" -eq 1 ]; then
|
||||
find "$path" -type f -exec sha256sum {} + | sort -k 2 | awk '{print $1}' >> "$BACKUP_SH_CHECKSUM_FILE"
|
||||
fi
|
||||
|
||||
# Copy files
|
||||
$BACKUP_SH_COMMAND "$path" "$BACKUP_SH_SUBDIR"
|
||||
BACKUP_SH_PROGRESS=$((BACKUP_SH_PROGRESS+1))
|
||||
done < "$BACKUP_SH_SOURCES_PATH"
|
||||
@@ -124,20 +129,24 @@ make_backup() {
|
||||
BACKUP_SH_END_TIME="$(date +%s)"
|
||||
BACKUP_SH_FILE_SIZE="$(find "$BACKUP_SH_FILENAME" -exec ls -l {} \; | awk '{print $5}')"
|
||||
BACKUP_SH_FILE_SIZE_H="$(find "$BACKUP_SH_FILENAME" -exec ls -lh {} \; | awk '{print $5}')"
|
||||
BACKUP_SH_HASH="$(checksum "$BACKUP_SH_FILENAME")"
|
||||
|
||||
echo "File name: $BACKUP_SH_FILENAME"
|
||||
[ "$BACKUP_SH_SHA256" -eq 1 ] && { echo "Checksum file: $BACKUP_SH_CHECKSUM_FILE"; }
|
||||
echo "File size: $BACKUP_SH_FILE_SIZE($BACKUP_SH_FILE_SIZE_H)"
|
||||
echo "File hash: $BACKUP_SH_HASH"
|
||||
printf "Elapsed time: %s seconds.\n" "$((BACKUP_SH_END_TIME - BACKUP_SH_START_TIME))"
|
||||
}
|
||||
|
||||
# $1: archive file
|
||||
# $2: archive password
|
||||
# $3: sha256 file(optional)
|
||||
extract_backup() {
|
||||
BACKUP_SH_ARCHIVE_PATH="$1"
|
||||
BACKUP_SH_ARCHIVE_PW="$2"
|
||||
BACKUP_SH_SHA256_FILE="$3"
|
||||
|
||||
# Decrypt the archive
|
||||
gpg -a \
|
||||
--quiet \
|
||||
--decrypt \
|
||||
--no-symkey-cache \
|
||||
--pinentry-mode=loopback \
|
||||
@@ -148,7 +157,20 @@ extract_backup() {
|
||||
# Extract archive
|
||||
tar -xzf backup.sh.tar.gz 1> /dev/null 2>&1
|
||||
|
||||
# Remove temporary files
|
||||
# If specified, use SHA256 file to compute checksum of files
|
||||
if [ -n "$BACKUP_SH_SHA256_FILE" ]; then
|
||||
for file in $(find "backup.sh.tmp" -type f | sort -k 2); do
|
||||
# Compute sha256 for current file
|
||||
sha256="$(sha256sum "$file" | awk '{print $1}')"
|
||||
# Check if checksum file contains hash
|
||||
if ! grep -wq "$sha256" "$BACKUP_SH_SHA256_FILE"; then
|
||||
printf "[FATAL] - integrity error for '%s'.\n" "$file"
|
||||
rm -rf backup.sh.tar.gz backup.sh.tmp
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
rm -rf backup.sh.tar.gz
|
||||
}
|
||||
|
||||
@@ -158,13 +180,14 @@ helper() {
|
||||
cat <<EOF
|
||||
backup.sh - POSIX compliant, modular and lightweight backup utility.
|
||||
|
||||
Syntax: $CLI_NAME [-b|-e|-h]
|
||||
Syntax: $CLI_NAME [-b|-c|-e|-h]
|
||||
options:
|
||||
-b|--backup SOURCES DEST PASS Backup folders from SOURCES file.
|
||||
-e|--extract ARCHIVE PASS Extract ARCHIVE using PASS.
|
||||
-h|--help Show this helper.
|
||||
-b|--backup SOURCES DEST PASS Backup folders from SOURCES file.
|
||||
-c|--checksum Generate/check SHA256 of a backup.
|
||||
-e|--extract ARCHIVE PASS Extract ARCHIVE using PASS.
|
||||
-h|--help Show this helper.
|
||||
|
||||
General help with the software: https://github.com/ice-bit/backup.sh
|
||||
General help with the software: https://github.com/ceticamarco/backup.sh
|
||||
Report bugs to: Marco Cetica(<email@marcocetica.com>)
|
||||
EOF
|
||||
}
|
||||
@@ -179,6 +202,7 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CHECKSUM_FLAG=0
|
||||
# Parse CLI arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
@@ -192,19 +216,46 @@ main() {
|
||||
echo "For more informatio, try --help"
|
||||
exit 1
|
||||
fi
|
||||
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD"
|
||||
|
||||
if [ "$CHECKSUM_FLAG" -eq 1 ]; then
|
||||
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 1
|
||||
else
|
||||
make_backup "$BACKUP_SH_SOURCES_PATH" "$BACKUP_SH_OUTPATH" "$BACKUP_SH_PASSWORD" 0
|
||||
fi
|
||||
|
||||
exit 0
|
||||
;;
|
||||
-c|--checksum)
|
||||
[ $# -eq 1 ] && { echo "Use this option with '--backup' or '--extract'"; exit 1; }
|
||||
CHECKSUM_FLAG=1
|
||||
shift 1
|
||||
;;
|
||||
-e|--extract)
|
||||
BACKUP_SH_ARCHIVE_PATH="$2"
|
||||
BACKUP_SH_ARCHIVE_PW="$3"
|
||||
BACKUP_SH_SHA256_FILE="$4"
|
||||
|
||||
if [ -z "$BACKUP_SH_ARCHIVE_PATH" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ]; then
|
||||
echo "Please, specify an encrypted archive and a password."
|
||||
echo "For more informatio, try --help"
|
||||
exit 1
|
||||
if [ "$CHECKSUM_FLAG" -eq 1 ]; then
|
||||
if [ -z "$BACKUP_SH_ARCHIVE_PATH" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ] || [ -z "$BACKUP_SH_SHA256_FILE" ]; then
|
||||
echo "Please, specify an encrypted archive, a password and a SHA256 file."
|
||||
echo "For more informatio, try --help"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [ -z "$BACKUP_SH_ARCHIVE_PATH" ] || [ -z "$BACKUP_SH_ARCHIVE_PW" ]; then
|
||||
echo "Please, specify an encrypted archive and a password."
|
||||
echo "For more informatio, try --help"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
extract_backup "$BACKUP_SH_ARCHIVE_PATH" "$BACKUP_SH_ARCHIVE_PW"
|
||||
|
||||
if [ "$CHECKSUM_FLAG" -eq 1 ]; then
|
||||
[ -e "$BACKUP_SH_SHA256_FILE" ] || { echo "Checksum file does not exist"; exit 1; }
|
||||
extract_backup "$BACKUP_SH_ARCHIVE_PATH" "$BACKUP_SH_ARCHIVE_PW" "$BACKUP_SH_SHA256_FILE"
|
||||
else
|
||||
extract_backup "$BACKUP_SH_ARCHIVE_PATH" "$BACKUP_SH_ARCHIVE_PW"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
;;
|
||||
-h|--help)
|
||||
|
||||
Reference in New Issue
Block a user