1
0
Fork 0
mirror of https://github.com/yavook/kiwi-backup.git synced 2024-11-21 22:43:01 +00:00

better handling of secrets and their documentation

This commit is contained in:
Jörn-Michael Miehe 2020-09-23 14:58:14 +02:00
parent 18bf8be22b
commit 105afbf4e3
3 changed files with 115 additions and 69 deletions

View file

@ -96,6 +96,7 @@ ENV \
SCHEDULE_RMINCR="36 05 * * SUN" \ SCHEDULE_RMINCR="36 05 * * SUN" \
BACKUP_VOLSIZE=1024 \ BACKUP_VOLSIZE=1024 \
BACKUP_TARGET="file:///backup/target" \ BACKUP_TARGET="file:///backup/target" \
OPTIONS_ALL="" \
OPTIONS_BACKUP="" \ OPTIONS_BACKUP="" \
OPTIONS_CLEANUP="" \ OPTIONS_CLEANUP="" \
OPTIONS_RMFULL="" \ OPTIONS_RMFULL="" \

View file

@ -79,6 +79,37 @@ backup:
KEEP_NUM_FULL_CHAINS: "2" KEEP_NUM_FULL_CHAINS: "2"
``` ```
### Handling Secrets
`duplicity` usually handles secrets by [reading its environment](http://duplicity.nongnu.org/vers7/duplicity.1.html#sect6). Some of its backends also accept secrets via environment, [notably the AWS S3 backend](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html).
There are three major ways to for inject secrets into `kiwi-backup` environments:
#### Container environment
Just fire up your container using `docker run -e "FTP_PASSWORD=my_secret_here" ldericher/kiwi-backup`
#### Image environment
Create a simple `Dockerfile` from following template.
```Dockerfile
FROM ldericher/kiwi-backup
ENV FTP_PASSWORD="my_secret_here"
```
#### "Secrets" file in container
Create a shell script:
```sh
#!/bin/sh
export FTP_PASSWORD="my_secret_here"
```
Then, include that file as `/root/duplicity_secrets` into your container by building a custom `Dockerfile` or by mounting it as a (read-only) volume.
### Additional options ### Additional options
There's more environment variables for further customization. You'll likely know if you need to change these. There's more environment variables for further customization. You'll likely know if you need to change these.
@ -105,6 +136,9 @@ backup:
# default: some docker volume # default: some docker volume
BACKUP_TARGET: "file:///backup/target" BACKUP_TARGET: "file:///backup/target"
# Additional options for all "duplicity" commands
OPTIONS_ALL: ""
# Additional options for "duplicity --full-if-older-than" command # Additional options for "duplicity --full-if-older-than" command
OPTIONS_BACKUP: "" OPTIONS_BACKUP: ""

View file

@ -5,42 +5,13 @@
############# #############
# commands # commands
env_exe="$(command -v env)" this_exe="$(command -v "${0}")"
ionice_exe="$(command -v ionice)" ionice_exe="$(command -v ionice)"
duplicity_exe="$(command -v duplicity)" duplicity_exe="$(command -v duplicity)"
# files # files
duplicity_secrets_file='/root/duplicity_secrets' duplicity_secrets_file='/root/duplicity_secrets'
###############
# ENVIRONMENT #
###############
# load secrets file
if [ -f "${duplicity_secrets_file}" ]; then
# shellcheck disable=SC1090
. "${duplicity_secrets_file}"
fi
env_changes=""
# check if uses encryption
if [ -n "${GPG_KEY_ID}" ]; then
# gpg key given
env_changes="${env_changes} PASSPHRASE='${GPG_PASSPHRASE}'"
encrypt_opts="--encrypt-key='${GPG_KEY_ID}'"
else
# no key given
encrypt_opts="--no-encryption"
fi
# check if uses AWS
if [ -n "${AWS_ACCESS_KEY_ID}" ]; then
# export AWS credentials
env_changes="${env_changes} AWS_ACCESS_KEY_ID='${AWS_ACCESS_KEY_ID}'"
env_changes="${env_changes} AWS_SECRET_ACCESS_KEY='${AWS_SECRET_ACCESS_KEY}'"
fi
############# #############
# FUNCTIONS # # FUNCTIONS #
############# #############
@ -50,15 +21,14 @@ append_options() {
ao_options="${2}" ao_options="${2}"
shift 1 shift 1
# remove leading whitespace characters if [ -n "${ao_cmdline}" ] && [ -n "${ao_options}" ]; then
ao_options="${ao_options#"${ao_options%%[![:space:]]*}"}" # if both are given, stitch together with a space
# remove trailing whitespace characters
ao_options="${ao_options%"${ao_options##*[![:space:]]}"}"
# if options are given, stitch together with a space
if [ -n "${ao_options}" ]; then
echo "${ao_cmdline} ${ao_options}" echo "${ao_cmdline} ${ao_options}"
elif [ -n "${ao_options}" ]; then
# if only options are given, output them
echo "${ao_options}"
else else
# if at most a cmdline is given, output that
echo "${ao_cmdline}" echo "${ao_cmdline}"
fi fi
} }
@ -67,33 +37,30 @@ print_command() {
pc_task="${1}" pc_task="${1}"
shift 1 shift 1
# if environment should be changed, call with "env" pc_cmdline="${ionice_exe} -c 3 ${duplicity_exe}"
if [ -n "${env_changes}" ]; then pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_ALL}" )"
pc_cmdline="${env_exe}${env_changes} "
else
pc_cmdline=""
fi
pc_cmdline="${pc_cmdline}${ionice_exe} -c 3 ${duplicity_exe} ${encrypt_opts}"
case "${pc_task}" in case "${pc_task}" in
backup) backup)
pc_cmdline="${pc_cmdline} --allow-source-mismatch --volsize ${BACKUP_VOLSIZE} --full-if-older-than ${FULL_BACKUP_FREQUENCY}" pc_cmdline="$( append_options "${pc_cmdline}" "--allow-source-mismatch" )"
pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_BACKUP} /backup/source" )" pc_cmdline="$( append_options "${pc_cmdline}" "--volsize ${BACKUP_VOLSIZE}" )"
pc_cmdline="$( append_options "${pc_cmdline}" "--full-if-older-than ${FULL_BACKUP_FREQUENCY}" )"
pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_BACKUP}" )"
pc_cmdline="$( append_options "${pc_cmdline}" "/backup/source" )"
;; ;;
cleanup) cleanup)
pc_cmdline="${pc_cmdline} cleanup --force" pc_cmdline="$( append_options "${pc_cmdline}" "cleanup --force" )"
pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_CLEAN}" )" pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_CLEAN}" )"
;; ;;
rmfull) rmfull)
pc_cmdline="${pc_cmdline} remove-older-than ${BACKUP_RETENTION_TIME} --force" pc_cmdline="$( append_options "${pc_cmdline}" "remove-older-than ${BACKUP_RETENTION_TIME} --force" )"
pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_RMFULL}" )" pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_RMFULL}" )"
;; ;;
rmincr) rmincr)
pc_cmdline="${pc_cmdline} remove-all-inc-of-but-n-full ${KEEP_NUM_FULL_CHAINS} --force" pc_cmdline="$( append_options "${pc_cmdline}" "remove-all-inc-of-but-n-full ${KEEP_NUM_FULL_CHAINS} --force" )"
pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_RMINCR}" )" pc_cmdline="$( append_options "${pc_cmdline}" "${OPTIONS_RMINCR}" )"
;; ;;
esac esac
@ -122,42 +89,86 @@ print_crontab() {
# don't split the '#' from 'min' # don't split the '#' from 'min'
print_cron_schedule '#_min hour day month weekday' 'command' | tr '_' ' ' print_cron_schedule '#_min hour day month weekday' 'command' | tr '_' ' '
print_cron_schedule "${SCHEDULE_BACKUP}" "$( print_command backup )" print_cron_schedule "${SCHEDULE_BACKUP}" "${this_exe} backup"
print_cron_schedule "${SCHEDULE_CLEANUP}" "$( print_command cleanup )" print_cron_schedule "${SCHEDULE_CLEANUP}" "${this_exe} cleanup"
print_cron_schedule "${SCHEDULE_RMFULL}" "$( print_command rmfull )" print_cron_schedule "${SCHEDULE_RMFULL}" "${this_exe} rmfull"
print_cron_schedule "${SCHEDULE_RMINCR}" "$( print_command rmincr )" print_cron_schedule "${SCHEDULE_RMINCR}" "${this_exe} rmincr"
} }
###############
# ENVIRONMENT #
###############
# load secrets file
if [ -f "${duplicity_secrets_file}" ]; then
# shellcheck disable=SC1090
. "${duplicity_secrets_file}"
fi
# check if uses encryption
if [ -n "${GPG_KEY_ID}" ]; then
# gpg key given
OPTIONS_ALL="$( append_options "${OPTIONS_ALL}" "--encrypt-key='${GPG_KEY_ID}'" )"
# handle more verbose "GPG_PASSPHRASE" env_var
PASSPHRASE="${GPG_PASSPHRASE:-${PASSPHRASE}}"
export PASSPHRASE
unset GPG_PASSPHRASE
else
# no key given
OPTIONS_ALL="$( append_options "${OPTIONS_ALL}" "--no-encryption" )"
fi
######## ########
# MAIN # # MAIN #
######## ########
if [ "${#}" -gt 0 ]; then if [ "${#}" -gt 0 ]; then
# run a command
case "${1}" in # CLI
print-crontab) task="${1}"
shift 1
# run task
case "${task}" in
print-*)
task="${task##*-}"
case "${task}" in
# print out the crontab
crontab)
print_crontab print_crontab
;; ;;
print-backup|print-cleanup|print-rmfull|print-rmincr) # print out a task
print_command "${1##*-}"
;;
# execute single command
backup|cleanup|rmfull|rmincr) backup|cleanup|rmfull|rmincr)
print_command "${1}" print_command "${task}"
cmd="$(print_command "${1}")"
${cmd}
;; ;;
# unknown task
*) *)
>&2 echo "Unknown command '${1}'." >&2 echo "Cannot print '${task}'."
>&2 echo "Choose from: crontab, backup, cleanup, rmfull, rmincr"
exit 1 exit 1
;; ;;
esac esac
;;
# execute single task
backup|cleanup|rmfull|rmincr)
# shellcheck disable=SC2091
$(print_command "${task}")
;;
# unknown task
*)
>&2 echo "Unknown task '${task}'."
>&2 echo "Choose from: backup, cleanup, rmfull, rmincr"
exit 1
;;
esac
else else
# default run: replace crontab, then start crond # default run: replace crontab, then start crond
print_crontab | crontab - print_crontab | crontab -
crond -fl 8 crond -fl 8