Merge branch 'master' into debian

This commit is contained in:
Jérémy Lecour 2020-05-03 11:14:45 +02:00 committed by Jérémy Lecour
commit 64144d9462
18 changed files with 111 additions and 46 deletions

View file

@ -18,6 +18,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Security
## [2.3.2] - 2020-05-03
### Changed
* Display help message if mandatory arguments are missing.
* Don't recreate jail on sync if it already exists
* Don't sync the whole firewall file, just remake rules for the current jail
* On sync, if local jail is running, reload remote jail if already running, start if not
## [2.3.1] - 2020-04-22
### Added

17
bkctld
View file

@ -52,17 +52,30 @@ case "${subcommand}" in
;;
"init" | "is-on")
jail_name="${2:-}"
"${LIBDIR}/bkctld-${subcommand}" "${jail_name}"
if [ -z "${jail_name}" ]; then
"${LIBDIR}/bkctld-help"
exit 1
else
"${LIBDIR}/bkctld-${subcommand}" "${jail_name}"
fi
;;
"key" | "port" | "ip")
jail_name="${2:-}"
option="${3:-}"
"${LIBDIR}/bkctld-${subcommand}" "${jail_name}" "${option}"
if [ "${jail_name}" = "all" ] || [ -z "${jail_name}" ]; then
"${LIBDIR}/bkctld-help"
exit 1
else
"${LIBDIR}/bkctld-${subcommand}" "${jail_name}" "${option}"
fi
;;
"start" | "stop" | "reload" | "restart" | "sync" | "update" | "remove" | "firewall")
jail_name="${2:-}"
if [ "${jail_name}" = "all" ]; then
"${LIBDIR}/bkctld-list" | xargs --no-run-if-empty --max-args=1 --max-procs=0 "${LIBDIR}/bkctld-${subcommand}"
elif [ -z "${jail_name}" ]; then
"${LIBDIR}/bkctld-help"
exit 1
else
"${LIBDIR}/bkctld-${subcommand}" "${jail_name}"
fi

View file

@ -15,7 +15,7 @@ if [ ! -n "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
jail_sshd_config="${jail_path}/${SSHD_CONFIG}"

View file

@ -14,16 +14,17 @@ if [ -z "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
jail_pid_file="${jail_path}/${SSHD_PID}"
return=1
# Error codes are references in "includes" file
return=100
if [ -f "${jail_pid_file}" ]; then
pid=$(cat "${jail_pid_file}")
ps -p "${pid}" > /dev/null && return=0
fi
if [ "${return}" -eq 1 ]; then
if [ "${return}" -gt 0 ]; then
rm -f "${jail_pid_file}"
grep -q "${jail_path}/proc" /proc/mounts && umount --lazy "${jail_path}/proc/"
grep -q "${jail_path}/dev" /proc/mounts && umount --lazy --recursive "${jail_path}/dev"

View file

@ -15,7 +15,7 @@ if [ ! -n "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
if [ -z "${keyfile}" ]; then
if [ -f "${jail_path}/${AUTHORIZED_KEYS}" ]; then

View file

@ -15,7 +15,7 @@ if [ ! -n "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
jail_sshd_config="${jail_path}/${SSHD_CONFIG}"

View file

@ -13,7 +13,7 @@ if [ -z "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
"${LIBDIR}/bkctld-is-on" "${jail_name}" || exit 0

View file

@ -14,7 +14,7 @@ fi
jail_path=$(jail_path "${jail_name}")
incs_path=$(incs_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
"${LIBDIR}/bkctld-is-on" "${jail_name}" && "${LIBDIR}/bkctld-stop" "${jail_name}"

View file

@ -15,7 +15,7 @@ if [ -z "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
"${LIBDIR}/bkctld-is-on" "${jail_name}" && "${LIBDIR}/bkctld-stop" "${jail_name}"
"${LIBDIR}/bkctld-start" "${jail_name}"

View file

@ -26,7 +26,7 @@ kill_or_clean_lockfile() {
warning "Process not found at PID \`${pid}'. Ignoring lock file \`${lock_file}'."
fi
else
error "Empty lockfile \`${lock_file}'. It should contain a PID."
warning "Empty lockfile \`${lock_file}'. It should contain a PID."
fi
# Remove the lock file
rm -f ${lock_file}

View file

@ -13,7 +13,7 @@ if [ -z "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
"${LIBDIR}/bkctld-is-on" "${jail_name}" && exit 0

View file

@ -16,7 +16,7 @@ touch "${INDEX_DIR}/.lastrun.duc"
EOF
[ ! -f "${INDEX_DIR}/.lastrun.duc" ] && notice "First run of DUC always in progress ..." && exit 0
[ ! -f ${IDX_FILE} ] && error "Index file do not exits !"
[ ! -f ${IDX_FILE} ] && error "Index file doesn't exits !"
printf "Last update of index file : "
stat --format=%Y "${INDEX_DIR}/.lastrun.duc" | xargs -i -n1 date -R -d "@{}"

View file

@ -13,7 +13,7 @@ if [ -z "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
"${LIBDIR}/bkctld-is-on" "${jail_name}" || exit 0

View file

@ -14,28 +14,54 @@ fi
jail_path=$(jail_path "${jail_name}")
jail_config_dir=$(jail_config_dir "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
[ -n "${NODE}" ] || error "Sync need config of \$NODE in /etc/default/bkctld !"
# Init jail on remote server
ssh "${NODE}" "${LIBDIR}/bkctld-init" "${jail_name}" | debug
ssh "${NODE}" "${LIBDIR}/bkctld-is-on ${jail_name} 2>/dev/null"
# return code 2 is for "missing jail" error
if [ "$?" -eq 2 ]; then
# Init jail on remote server
ssh "${NODE}" "${LIBDIR}/bkctld-init ${jail_name}" | debug
fi
# Sync Jail structure and configuration on remote server
# Sync jail structure and configuration on remote server
rsync -a "${jail_path}/" "${NODE}:${jail_path}/" --exclude proc/* --exclude sys/* --exclude dev/* --exclude run --exclude var/backup/*
# New config directory
rsync -a "${jail_config_dir}" "${NODE}:${jail_config_dir}"
# Old incs policy config file
rsync -a "${CONFDIR}/${jail_name}" "${NODE}:${CONFDIR}/${jail_name}"
# Sync state on remote server
if "${LIBDIR}/bkctld-is-on" "${jail_name}"; then
ssh "${NODE}" "${LIBDIR}/bkctld-start" "${jail_name}" | debug
# Sync config (new structure)
if [ -d "${jail_config_dir}" ]; then
rsync -a --delete "${jail_config_dir}" "${NODE}:${jail_config_dir}"
else
ssh "${NODE}" "${LIBDIR}/bkctld-stop" "${jail_name}" | debug
ssh "${NODE}" "rm -rf ${jail_config_dir}" | debug
fi
# Sync config (legacy structure)
if [ -e "${CONFDIR}/${jail_name}" ]; then
rsync -a "${CONFDIR}/${jail_name}" "${NODE}:${CONFDIR}/${jail_name}"
else
ssh "${NODE}" "rm -f ${CONFDIR}/${jail_name}" | debug
fi
if [ -n "${FIREWALL_RULES}" ]; then
rsync -a "${FIREWALL_RULES}" "${NODE}:${FIREWALL_RULES}"
ssh "${NODE}" /etc/init.d/minifirewall restart | debug
ssh "${NODE}" "${LIBDIR}/bkctld-firewall ${jail_name}" | debug
ssh "${NODE}" "test -x /etc/init.d/minifirewall && /etc/init.d/minifirewall restart" | debug
fi
# Sync state on remote server
if "${LIBDIR}/bkctld-is-on" "${jail_name}"; then
# fetch state of remote jail
ssh "${NODE}" "${LIBDIR}/bkctld-is-on ${jail_name} 2>/dev/null"
case "$?" in
0)
# jail is already running : reload it
ssh "${NODE}" "${LIBDIR}/bkctld-reload ${jail_name}" | debug
;;
100)
# jail is stopped : start it
ssh "${NODE}" "${LIBDIR}/bkctld-start ${jail_name}" | debug
;;
*)
error "Error evaluating jail \`${jail_name}' state. bkctld-is-on exited with \`$?'"
;;
esac
else
ssh "${NODE}" "${LIBDIR}/bkctld-stop ${jail_name}" | debug
fi

View file

@ -13,7 +13,7 @@ if [ ! -n "${jail_name}" ]; then
fi
jail_path=$(jail_path "${jail_name}")
test -d "${jail_path}" || error "${jail_name}: jail not found"
test -d "${jail_path}" || error "${jail_name}: jail not found" 2
"${LIBDIR}/bkctld-is-on" "${jail_name}" && "${LIBDIR}/bkctld-stop" "${jail_name}"

View file

@ -59,15 +59,19 @@ warning() {
logger -t bkctld -p daemon.warning "$(process_name) ${msg}"
fi
}
# Return codes
# 1 : generic error
# 2 : jail not found
# > 100 : subcommands specific errors
error() {
msg="${1:-$(cat /dev/stdin)}"
rc="${2:-1}"
tty -s && echo "$(log_date) ERROR $(process_name) ${msg}" >&2
if [ "${LOGLEVEL}" -ge 5 ]; then
tty -s || echo "$(log_date) ERROR $(process_name) ${msg}" >&2
logger -t bkctld -p daemon.error "$(process_name) ${msg}"
fi
exit 1
exit ${rc}
}
dry_run() {

View file

@ -9,11 +9,11 @@ setup() {
set_variable "/etc/default/bkctld" "BACKUP_DISK" "/dev/vdb"
JAILNAME=$(tr -cd '[:alnum:]' < /dev/urandom | fold -w15 | head -n1)
JAILNAME=$(random_jail_name)
JAILPATH="/backup/jails/${JAILNAME}"
INCSPATH="/backup/incs/${JAILNAME}"
PORT=$(awk -v min=2222 -v max=2999 'BEGIN{srand(); print int(min+rand()*(max-min+1))}')
INC_NAME=$(date +"%Y-%m-%d-%H")
PORT=$(random_port)
INC_NAME=$(inc_name_today)
/usr/lib/bkctld/bkctld-init "${JAILNAME}"
}
@ -23,6 +23,16 @@ teardown() {
/usr/lib/bkctld/bkctld-remove "${JAILNAME}" && rm -rf "${INCSPATH}"
}
random_jail_name() {
tr -cd '[:alnum:]' < /dev/urandom | fold -w15 | head -n1
}
random_port() {
awk -v min=2222 -v max=2999 'BEGIN{srand(); print int(min+rand()*(max-min+1))}'
}
inc_name_today() {
date +"%Y-%m-%d-%H"
}
set_variable() {
file=${1:?}
var_name=${2:?}

View file

@ -83,7 +83,7 @@ test_server() {
else
# SSH connection failed
new_error=$(printf "Failed to connect to \`%s' within %s seconds" "${item}" "${SSH_CONNECT_TIMEOUT}")
SERVERS_SSH_ERRORS=$(printf "%s\n%s" "${SERVERS_SSH_ERRORS}" "${new_error}" | sed -e '/^$/d')
SERVERS_SSH_ERRORS=$(printf "%s\\n%s" "${SERVERS_SSH_ERRORS}" "${new_error}" | sed -e '/^$/d')
return 1
fi
@ -96,16 +96,16 @@ pick_server() {
if [ "${increment}" -ge "${list_length}" ]; then
# We've reached the end of the list
new_error="No more server available"
SERVERS_SSH_ERRORS=$(printf "%s\n%s" "${SERVERS_SSH_ERRORS}" "${new_error}" | sed -e '/^$/d')
SERVERS_SSH_ERRORS=$(printf "%s\\n%s" "${SERVERS_SSH_ERRORS}" "${new_error}" | sed -e '/^$/d')
# Log errors to stderr
printf "%s\n" "${SERVERS_SSH_ERRORS}" >&2
printf "%s\\n" "${SERVERS_SSH_ERRORS}" >&2
# Log errors to logfile
printf "%s\n" "${SERVERS_SSH_ERRORS}" >> $LOGFILE
printf "%s\\n" "${SERVERS_SSH_ERRORS}" >> $LOGFILE
return 1
fi
# Extract the day of month, without leading 0 (which would give an octal based number)
# Extract the day of month, without leading 0 (which would give an octal based number)
today=$(date +%e)
# A salt is useful to randomize the starting point in the list
# but stay identical each time it's called for a server (based on hostname).
@ -123,14 +123,14 @@ pick_server() {
if [ -e "${PIDFILE}" ]; then
pid=$(cat "${PIDFILE}")
# Does process still exist ?
if kill -0 ${pid} 2> /dev/null; then
if kill -0 "${pid}" 2> /dev/null; then
# Killing the childs of evobackup.
for ppid in $(pgrep -P "${pid}"); do
kill -9 "${ppid}";
done
# Then kill the main PID.
kill -9 "${pid}"
printf "%s is still running (PID %s). Process has been killed" "$0" "${pid}\n" >&2
printf "%s is still running (PID %s). Process has been killed" "$0" "${pid}\\n" >&2
else
rm -f ${PIDFILE}
fi
@ -299,7 +299,7 @@ if [ "${LOCAL_TASKS}" = "1" ]; then
## Dump findmnt(8) output
FINDMNT_BIN=$(command -v findmnt)
if [ -x ${FINDMNT_BIN} ]; then
if [ -x "${FINDMNT_BIN}" ]; then
${FINDMNT_BIN} > ${LOCAL_BACKUP_DIR}/findmnt.txt
fi
else
@ -366,6 +366,8 @@ if [ "${SYNC_TASKS}" = "1" ]; then
# Remote shell command
RSH_COMMAND="ssh -p ${SSH_PORT} -o 'ConnectTimeout ${SSH_CONNECT_TIMEOUT}'"
# ignore check because we want it to split the different arguments to $rep
# shellcheck disable=SC2086
rsync -avzh --stats --delete --delete-excluded --force --ignore-errors --partial \
--exclude "lost+found" \
--exclude ".nfs.*" \
@ -410,11 +412,11 @@ fi
END=$(/bin/date +"%d-%m-%Y ; %H:%M")
printf "EvoBackup - %s - START %s ON %s (LOCAL_TASKS=%s SYNC_TASKS=%s)\n" \
printf "EvoBackup - %s - START %s ON %s (LOCAL_TASKS=%s SYNC_TASKS=%s)\\n" \
"${HOSTNAME}" "${BEGINNING}" "${SSH_SERVER}" "${LOCAL_TASKS}" "${SYNC_TASKS}" \
>> $LOGFILE
printf "EvoBackup - %s - STOP %s ON %s (LOCAL_TASKS=%s SYNC_TASKS=%s)\n" \
printf "EvoBackup - %s - STOP %s ON %s (LOCAL_TASKS=%s SYNC_TASKS=%s)\\n" \
"${HOSTNAME}" "${END}" "${SSH_SERVER}" "${LOCAL_TASKS}" "${SYNC_TASKS}" \
>> $LOGFILE