600 lines
24 KiB
Bash
Executable File
600 lines
24 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
#
|
|
### backup openLDAP configuration and frontend database(s)
|
|
# version 3.2
|
|
#
|
|
|
|
|
|
### text formatting presets
|
|
|
|
# set colours for various log message types
|
|
bold=$(tput bold)
|
|
err=$(tput bold)$(tput setaf 1)
|
|
info=$(tput sgr0)
|
|
norm=$(tput sgr0)
|
|
ok=$(tput setaf 2)
|
|
|
|
# define other colours used
|
|
cyan=$(tput bold)$(tput setaf 6)
|
|
magenta=$(tput sgr0)$(tput setaf 5)
|
|
yellow=$(tput sgr0)$(tput setaf 3)
|
|
|
|
|
|
### parameter defaults
|
|
width=$(tput cols)
|
|
scriptPath="$( CDPATH='' cd -- "$( dirname -- "$0" )" && pwd -P )"
|
|
scriptName="$( basename "$0" )"
|
|
# logfile default: same location and name as this script, with '.log' extension
|
|
logfile="$scriptPath/${scriptName%.*}.log"
|
|
# encryption parameters file default: same location and name as this script,
|
|
# with '.params' extension
|
|
encParams="$scriptPath/${scriptName%.*}.params"
|
|
# backup mode by default
|
|
unset removeTLS
|
|
unset backupFile
|
|
extract=false
|
|
decrypt=false
|
|
# encryption enabled by default
|
|
noEncryption=0
|
|
tempDir="$(date '+%s')"
|
|
fileDate="$(date '+%F_%T')"
|
|
outputLocation="$scriptPath/"
|
|
# frontend starts at '1', so this number should always be the number of
|
|
# frontend databases + 1 -- default to only 1 frontend db
|
|
numFrontEnd=2
|
|
|
|
|
|
### functions
|
|
|
|
cleanup () {
|
|
logInfo 'task' 'Cleaning up'
|
|
if ! docker exec "$container" rm -rf "$tempDir" \
|
|
>> "$logfile" 2>&1; then
|
|
logInfo 'err'
|
|
exitError 3 'Unable to remove temporary files in container.' 'nc'
|
|
fi
|
|
logInfo 'done'
|
|
}
|
|
|
|
consoleError () {
|
|
printf "%s\n%s\n" "$err" "$2"
|
|
printf "Exiting.\n\n%s" "$norm"
|
|
exit "$1"
|
|
}
|
|
|
|
decryptionNote () {
|
|
printf "\n"
|
|
textblock "${bold}${magenta}Decrypting your backup archive:${norm}"
|
|
printf "\n"
|
|
|
|
textblock 'To decrypt and extract your backup file, you need the following information:'
|
|
textblock '1. The password used to encrypt the file'
|
|
textblock '2. The encryption cipher used (default: AES-256-CBC)'
|
|
textblock '3. The number of iterations used to create the private key (default: 25000)'
|
|
printf "\n"
|
|
textblock "Run the following command, replacing the ${cyan}[cyan stuff in square brackets]${norm} with values appropriate to your environment."
|
|
printf "\n"
|
|
textblock "openssl enc -d -${cyan}[cipher-here]${norm} -iter +${cyan}[iterations]${norm} -k ${cyan}[password]${norm} -in ${cyan}[backup_archive.tar.gz]${norm} | tar -xz -C ${cyan}[destinationDirectory]${norm}"
|
|
printf "\n"
|
|
textblock 'NOTE: The output directory must already exist or tar will throw an error.'
|
|
printf "\n"
|
|
textblock "${magenta}Example:${norm}"
|
|
textblock "openssl enc -d -${cyan}aes-256-cbc${norm} -iter +${cyan}25000${norm} -k ${cyan}mypassword${norm} -in ${cyan}~/ldap-2020-03-10_17:31:34.tar.gz${norm} | tar -xz -C ${cyan}~/ldapRestore${norm}"
|
|
printf "\n"
|
|
textblock 'Note: Using this script with the --decrypt option handles this for you and can create target directories automatically.'
|
|
printf "\n\n"
|
|
exit 0
|
|
}
|
|
|
|
exitError () {
|
|
# cleanup temp directory unless 'nc' passed
|
|
if [ ! "$3" = "nc" ]; then cleanup; fi
|
|
|
|
# log error
|
|
printf "%s[%s] -- [ERROR] code %s: %s --%s\n" \
|
|
"$err" "$(stamp)" "$1" "$2" "$norm" >> "$logfile"
|
|
printf "%s[%s] --- %s terminated with errors ---\n%s" \
|
|
"$err" "$(stamp)" "$scriptName" "$norm" >> "$logfile"
|
|
|
|
# exit with proper error code
|
|
exit "$1"
|
|
}
|
|
|
|
logInfo () {
|
|
if [ "$1" = 'task' ]; then
|
|
printf "%s[%s] -- [INFO] %s... " \
|
|
"$info" "$(stamp)" "$2" >> "$logfile"
|
|
elif [ "$1" = 'done' ]; then
|
|
if [ -z "$2" ]; then
|
|
printf "%sdone%s --%s\n" \
|
|
"$ok" "$info" "$norm" >> "$logfile"
|
|
else
|
|
printf "%s%s%s --%s\n" \
|
|
"$ok" "$2" "$info" "$norm" >> "$logfile"
|
|
fi
|
|
elif [ "$1" = 'err' ]; then
|
|
printf "%serror%s --%s\n" \
|
|
"$err" "$info" "$norm" >> "$logfile"
|
|
else
|
|
printf "%s[%s] -- [INFO] %s --%s\n" \
|
|
"$info" "$(stamp)" "$1" "$norm" >> "$logfile"
|
|
fi
|
|
}
|
|
|
|
logSuccess () {
|
|
printf "%s[%s] -- [SUCCESS] %s --%s\n" \
|
|
"$ok" "$(stamp)" "$1" "$norm" >> "$logfile"
|
|
}
|
|
|
|
scriptHelp () {
|
|
printf "\n"
|
|
textblock "${bold}${magenta}Usage: ${scriptName} [parameters]${norm}"
|
|
printf "\n"
|
|
textblock "${cyan}Parameters ${yellow}(default value):${norm}"
|
|
textblock "There are NO mandatory parameters. By default the script will run in 'backup' mode and save an encrypted backup archive to the current directory. If a parameter is not supplied, its default value will be used. In the case of a switch parameter, it will remain deactivated if not specified."
|
|
printf "\n"
|
|
textblock "${bold}*** Common parameters ***${norm}"
|
|
printf "\n"
|
|
textblock "${cyan}-l, --log ${yellow}(scriptPath/scriptName.log)${norm}"
|
|
textblock "FULL path to write log file. If you supply a path ending with a slash ('/') it will be assumed you mean a directory and the log file will be written to that directory using the format 'path/scriptname.log'. If you supply only a filename (no slashes anywhere), it will be assumed you want to save the log using that name in the script directory. The script will attempt to create any provided paths/directories if they do not exist."
|
|
printf "\n"
|
|
textblock "${cyan}-o, --output ${yellow}(scriptPath/)${norm}"
|
|
textblock "Location where the output files should be saved on this machine. You should only specify a *directory* here (trailing slash optional). File names are automatic and cannot be changed via this script. All restore operations will create a 'restore' subdirectory in this specified directory."
|
|
printf "\n"
|
|
textblock "${cyan}-p, --params ${yellow}(scriptPath/scriptName.params)${norm}"
|
|
textblock "Location of the encryption parameters file. This file contains the password and encryption options that should be used. By default, the script looks in the script directory for a file named the same as the script but with a '.params' extension."
|
|
printf "\n"
|
|
textblock "${cyan}-h, -? | -??, --help${norm}"
|
|
textblock "Quick-help screen. | This (detailed) help screen."
|
|
printf "\n"
|
|
textblock "${bold}*** Encryption parameters ***${norm}"
|
|
printf "\n"
|
|
textblock "${cyan}-n, --num, --frontend ${yellow}(1)${norm}"
|
|
textblock "Number of frontend databases to backup. If you specify a number here greater than actually exist, openLDAP will generate an error and your backup will fail."
|
|
printf "\n"
|
|
textblock "${cyan}--no-encryption${norm}"
|
|
textblock "Switch parameter. Specify this if you DO NOT want the backup archive tar.gz file encrypted. Careful!"
|
|
printf "\n"
|
|
textblock "${bold}*** Decryption/Extraction parameters ***${norm}"
|
|
printf "\n"
|
|
textblock "${cyan}-b, --backupfile${norm}"
|
|
textblock "FULL path of the backup file you want to decrypt/extract. MUST be supplied if using the --decrypt or --extract switches."
|
|
printf "\n"
|
|
textblock "${cyan}-d, --decrypt ${yellow}(implies --extract)${norm}"
|
|
textblock "Switch parameter. Decrypt and extract your backup file (MUST be supplied using the --backupfile parameter) to the 'restore' subdirectory of the current directory or as specified using the '--output' parameter. This switch will log error code 8 if you try to decrypt an unencrypted backup archive."
|
|
printf "\n"
|
|
textblock "${cyan}-e, --extract${norm}"
|
|
textblock "Switch parameter. Extract your backup file (MUST be supplied using the --backupfile parameter) to the 'restore' subdirectory of the current directory or as specified using the '--output' parameter. This switch will log error code 8 if you try to extract an encrypted backup archive. In that case, use --decrypt instead."
|
|
printf "\n"
|
|
textblock "${cyan}--removeTLS${norm}"
|
|
textblock "Switch parameter. Remove olcTLS configuration parameters from your config DIT LDIF file. This is the only approved way to disable/change your TLS settings. Consult the openLDAP documentation or the repo wiki for more information."
|
|
printf "\n"
|
|
textblock "${cyan}--manualdecryption${norm}"
|
|
textblock "Display instructions on how to manually decrypt and extract your backup archive."
|
|
printf "\n\n"
|
|
textblock "More details and examples of script usage can be found in the repo wiki at ${magenta}https://git.asifbacchus.app/ab-docker/openldap/wiki${norm}"
|
|
printf "\n"
|
|
}
|
|
|
|
stamp () {
|
|
(date +%F' '%T)
|
|
}
|
|
|
|
textblock () {
|
|
printf "%s\n" "$1" | fold -w "$width" -s
|
|
}
|
|
|
|
quickHelp () {
|
|
textblock "${bold}${magenta}Usage: ${scriptName} [parameters]${norm}"
|
|
printf "\n"
|
|
textblock "${cyan}Parameters ${yellow}(default value):${norm}"
|
|
printf "\n"
|
|
textblock "${bold}*** Common parameters ***${norm}"
|
|
textblock "${cyan}-l, --log ${yellow}(scriptPath/scriptName.log)${norm}"
|
|
textblock "FULL path to write log file. Path ending with '/' will be treated as a directory. Filename only will be saved in script directory."
|
|
textblock "${cyan}-o, --output ${yellow}(scriptPath/)${norm}"
|
|
textblock "Directory to save output files on this machine."
|
|
textblock "${cyan}-p, --params ${yellow}(scriptPath/scriptName.params)${norm}"
|
|
textblock "Location of the encryption parameters file."
|
|
textblock "${cyan}-h, -? | -??, --help${norm}"
|
|
textblock "This help screen. | Detailed help."
|
|
printf "\n"
|
|
textblock "${bold}*** Encryption parameters ***${norm}"
|
|
textblock "${cyan}-n, --num, --frontend ${yellow}(1)${norm}"
|
|
textblock "Number of frontend databases to backup."
|
|
textblock "${cyan}--no-encryption${norm}"
|
|
textblock "Switch: DO NOT encrypt backup tar.gz."
|
|
printf "\n"
|
|
textblock "${bold}*** Decryption/Extraction parameters ***${norm}"
|
|
textblock "${cyan}-b, --backupfile${norm}"
|
|
textblock "FULL path of the backup file to be decrypted/extracted."
|
|
textblock "${cyan}-d, --decrypt ${yellow}(implies --extract)${norm}"
|
|
textblock "Decrypt and extract specified backup file to 'restore' subdirectory of current path/specified path (--output parameter)."
|
|
textblock "${cyan}-e, --extract${norm}"
|
|
textblock "Extract specified backup file to 'restore' subdirectory of current path/specified path (--output parameter)."
|
|
textblock "${cyan}--removeTLS${norm}"
|
|
textblock "Remove all olcTLS configuration settings from your config DIT LDIF restore file."
|
|
textblock "${cyan}--manualdecryption${norm}"
|
|
textblock "Display instructions on manually decrypting and extracting your backup archive."
|
|
printf "\n"
|
|
textblock "Run script with '-?? or --help' for detailed help. More details and examples of script usage can be found in the repo wiki at:"
|
|
printf "%s\thttps://git.asifbacchus.app/ab-docker/openldap/wiki%s\n\n" \
|
|
"$magenta" "$norm"
|
|
}
|
|
|
|
|
|
### pre-requisite checks
|
|
|
|
# is user root or in the docker group?
|
|
if [ ! "$( id -u )" -eq 0 ]; then
|
|
if ! id -Gn | grep docker > /dev/null; then
|
|
consoleError '1' "You must either be root or in the 'docker' group to run this script since you must be able to run 'docker exec' commands against the container!"
|
|
fi
|
|
fi
|
|
|
|
# is tar installed?
|
|
if ! command -v tar > /dev/null; then
|
|
consoleError '99' 'It appears that tar is not installed. This script requires tar in order to package and process backup files.'
|
|
fi
|
|
|
|
# is gzip installed?
|
|
if ! command -v gzip > /dev/null ; then
|
|
consoleError '99' 'It appears that gzip is not installed. This script requires gzip in order to compress/decompress backup tarball files.'
|
|
fi
|
|
|
|
# process startup parameters
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-b|--backupfile)
|
|
# name of backup file to decrypt/extract
|
|
if [ -z "$2" ]; then
|
|
consoleError '1' 'Backup file name cannot be null.'
|
|
elif [ ! -f "$2" ]; then
|
|
consoleError '1' "Specified backup file does not exist ($2)."
|
|
fi
|
|
backupFile="$2"
|
|
shift
|
|
;;
|
|
-d|--decrypt)
|
|
# decrypt and extract backup file (implies '-e')
|
|
decrypt=true
|
|
extract=true
|
|
;;
|
|
-e|--extract)
|
|
# extract gzipped tarball
|
|
extract=true
|
|
;;
|
|
-h|-\?)
|
|
# display brief help
|
|
quickHelp
|
|
exit 0
|
|
;;
|
|
-\?\?|--help)
|
|
# display full help
|
|
scriptHelp
|
|
exit 0
|
|
;;
|
|
-l|--log)
|
|
# location of log file
|
|
if [ -z "$2" ]; then
|
|
consoleError '1' 'Log file path cannot be null. Leave unspecified to save log in the same directory as this script.'
|
|
fi
|
|
logfile="$2"
|
|
shift
|
|
;;
|
|
--manualdecryption)
|
|
decryptionNote
|
|
exit 0
|
|
;;
|
|
-n|--num|--frontend)
|
|
# number of frontend databases
|
|
if [ -z "$2" ]; then
|
|
consoleError '1' 'Number of frontend databases cannot be null.'
|
|
fi
|
|
numFrontEnd=$(($2+1))
|
|
shift
|
|
;;
|
|
--no-encryption)
|
|
# disable encryption, switch parameter
|
|
noEncryption=1
|
|
# switches do not require an internal 'shift'
|
|
;;
|
|
-o|--output)
|
|
# directory on host to save output files
|
|
if [ -z "$2" ]; then
|
|
consoleError '1' 'Output destination location cannot be null.'
|
|
fi
|
|
outputLocation="$2"
|
|
shift
|
|
;;
|
|
-p|--params)
|
|
# path to encryption parameters file
|
|
if [ -z "$2" ]; then
|
|
consoleError '1' 'Path to encryption parameters file cannot be null.'
|
|
fi
|
|
encParams="$2"
|
|
shift
|
|
;;
|
|
--removeTLS)
|
|
# remove olcTLS entries from cn=config
|
|
removeTLS=true
|
|
;;
|
|
*)
|
|
printf "%s\nUnknown option: %s\n" "$err" "$1"
|
|
printf "Use '--help' for valid options.\n\n%s" "$norm"
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
|
|
### start logging
|
|
# logfile checks
|
|
if ! printf "%s" "$logfile" | grep -o / > /dev/null; then
|
|
# filename provided, save in scriptdir
|
|
logfile="$scriptPath/$logfile"
|
|
elif [ "$( printf "%s" "$logfile" | tail -c 1 )" = '/' ]; then
|
|
# directory provided, does it exist?
|
|
if [ -d "$logfile" ]; then
|
|
logfile="${logfile}${scriptName%.*}.log"
|
|
else
|
|
if ! mkdir -p "$logfile" > /dev/null 2>&1; then
|
|
consoleError '1' 'Unable to make specified log file directory.'
|
|
fi
|
|
logfile="${logfile}${scriptName%.*}.log"
|
|
fi
|
|
else
|
|
# full path provided, does the parent directory exist?
|
|
if [ ! -d "${logfile%/*}" ]; then
|
|
# make parent path
|
|
if ! mkdir -p "${logfile%/*}" > /dev/null 2>&1; then
|
|
consoleError '1' 'Unable to make specified log file path.'
|
|
fi
|
|
fi
|
|
fi
|
|
# write initial log entries for script run
|
|
if ! printf "%s[%s] --- Start %s execution ---%s\n" \
|
|
"$magenta" "$(stamp)" "$scriptName" "$norm" >> "$logfile"; then
|
|
consoleError '1' "Unable to write to log file ($logfile)"
|
|
fi
|
|
logInfo "Log located at $logfile"
|
|
|
|
|
|
### process output directory
|
|
if [ -d "$outputLocation" ]; then
|
|
# touch test to ensure we can write here
|
|
if ! touch "${outputLocation%/}/test.touch" > /dev/null 2>&1; then
|
|
exitError '1' "Unable to write to output location: $outputLocation" 'nc'
|
|
else
|
|
logInfo "Writing output to: $outputLocation"
|
|
rm -f "${outputLocation%/}/test.touch" > /dev/null 2>&1
|
|
fi
|
|
else
|
|
# create directory
|
|
if ! mkdir -p "${outputLocation%/}" > /dev/null 2>&1; then
|
|
exitError '1' "Unable to create output path: $outputLocation" 'nc'
|
|
else
|
|
logInfo "Writing output to: $outputLocation"
|
|
fi
|
|
fi
|
|
|
|
|
|
### source encryption parameters file
|
|
|
|
# check if file exists (unless encryption disabled), otherwise exit
|
|
if [ $noEncryption = 1 ]; then
|
|
logInfo 'Backup archive will NOT be encrypted!'
|
|
elif [ $noEncryption = 0 ] && [ ! -f "$encParams" ]; then
|
|
exitError 1 'Encryption parameters file does not exist.' 'nc'
|
|
else
|
|
# import encryption parameters file
|
|
case "${encParams}" in
|
|
/*)
|
|
# absolute path, no need to rewrite
|
|
. "${encParams}"
|
|
;;
|
|
*)
|
|
# relative path, need to rewrite assuming current directory
|
|
. "./${encParams}"
|
|
;;
|
|
esac
|
|
logInfo "Imported: '$encParams'"
|
|
|
|
# verify import
|
|
logInfo 'task' 'Verify encryption password'
|
|
if [ -z "$password" ]; then
|
|
logInfo 'err'
|
|
exitError 1 "Imported null value for encryption 'password'." 'nc'
|
|
else
|
|
logInfo 'done'
|
|
fi
|
|
logInfo 'task' 'Verify encryption cipher'
|
|
if [ -z "$encryptionCipher" ]; then
|
|
logInfo 'err'
|
|
exitError 1 "Imported null value for 'encryptionCipher'." 'nc'
|
|
else
|
|
logInfo 'done' "$encryptionCipher"
|
|
fi
|
|
logInfo 'task' 'Verify encryption key iterations'
|
|
if [ -z "$encryptionIterations" ]; then
|
|
logInfo 'err'
|
|
exitError 1 "Imported null value for 'encryptionIterations'." 'nc'
|
|
else
|
|
logInfo 'done' "$encryptionIterations"
|
|
fi
|
|
fi
|
|
|
|
|
|
if [ $extract = 'true' ]; then
|
|
# ensure backupFile has been specifed
|
|
if [ -z "$backupFile" ]; then
|
|
exitError '1' 'backupFile (-b|--backupFile) must be specified when using script in Extract mode.' 'nc'
|
|
fi
|
|
|
|
# extract backupFile to outputLocation
|
|
logInfo "Extracting backup file ($backupFile)"
|
|
|
|
# create extraction target directory
|
|
if [ ! -d "${outputLocation%/}/restore" ]; then
|
|
# create subdirectory for restored files
|
|
if ! mkdir "${outputLocation%/}/restore" > /dev/null 2>&1; then
|
|
exitError '7' 'Could not create target subdirectory in output location.' 'nc'
|
|
else
|
|
logInfo "Extracted files will be written to '${outputLocation%/}/restore/'"
|
|
fi
|
|
else
|
|
# ensure we can write to subdirectory for restored files
|
|
if ! touch "${outputLocation%/}/restore/test.touch" > /dev/null 2>&1; then
|
|
exitError '1' "Unable to write to output location: ${outputLocation%/}/restore/" 'nc'
|
|
else
|
|
rm -f "${outputLocation%/}/restore/test.touch" > /dev/null 2>&1
|
|
fi
|
|
fi
|
|
|
|
# extract/decrypt backup file
|
|
if [ "$decrypt" = 'true' ]; then
|
|
logInfo 'Decrypting backup file before extraction'
|
|
if ! openssl enc -d -"${encryptionCipher}" -iter +"${encryptionIterations}" -k "${password}" -in "${backupFile}" 2>> "$logfile" | tar --overwrite -xz -C "${outputLocation%/}/restore/" 2>> "$logfile"; then
|
|
exitError '8' 'There was a problem extracting the backup file. Perhaps the file is NOT encrypted? If so, please run with the --extract flag instead of the --decrypt flag.' 'nc'
|
|
else
|
|
logSuccess "Backup extracted to '${outputLocation%/}/restore/'"
|
|
fi
|
|
else
|
|
if ! tar --overwrite -xzf "$backupFile" -C "${outputLocation%/}/restore/" 2>> "$logfile"; then
|
|
exitError '8' 'There was a problem extracting the backup file. Perhaps it is encrypted? If so, please run with --decrypt flag.' 'nc'
|
|
else
|
|
logSuccess "Backup extracted to '${outputLocation%/}/restore/'"
|
|
fi
|
|
fi
|
|
|
|
# remove TLS configuration
|
|
if [ "$removeTLS" = 'true' ]; then
|
|
# get newest config-? file in outputLocation/restore directory
|
|
cnConfigFile=$( ls -Adt ${outputLocation%/}/restore/config-* | head -n1 )
|
|
# remove TLS configuration entries
|
|
logInfo 'task' "Removing TLS configuration from '$cnConfigFile'"
|
|
sed -i -e '/^olcTLS/d' "$cnConfigFile" 2>> "$logfile"
|
|
# check our work
|
|
if ! grep -q '^olcTLS' "$cnConfigFile" 2>> "$logfile"; then
|
|
logInfo 'done'
|
|
else
|
|
logInfo 'err'
|
|
exitError '20' 'olcTLS entries could not be removed from restored config DIT LDIF file. You will have to do it manually.' 'nc'
|
|
fi
|
|
fi
|
|
elif [ $extract = 'false' ]; then
|
|
### process backup operations
|
|
|
|
## find ab-openldap container
|
|
container=$(docker ps -a --no-trunc --filter "label=org.label-schema.name=ab-openldap" --format "{{ .Names }}")
|
|
|
|
# check for null value -- cannot find container
|
|
if [ -z "$container" ]; then
|
|
exitError 2 'Cannot find ab-openldap container. Exiting.' 'nc'
|
|
fi
|
|
|
|
# check for multiple containers, exit if that's the case
|
|
# N.B. do NOT quote $container or this loop will NOT work!!!
|
|
set -- dummy $container
|
|
shift
|
|
containerCount=0
|
|
for c; do
|
|
containerCount=$((containerCount+1))
|
|
logInfo "Found container($containerCount): $c"
|
|
done
|
|
if [ "$containerCount" -gt 1 ]; then
|
|
exitError 2 'Multiple containers found. Exiting.' 'nc'
|
|
fi
|
|
|
|
## backup databases to ldif
|
|
|
|
# create temp working directory
|
|
if ! docker exec "$container" mkdir "/$tempDir" >> "$logfile" 2>&1; then
|
|
exitError 3 'Could not create temporary working directory.' 'nc'
|
|
fi
|
|
|
|
# backend to ldif
|
|
logInfo 'task' 'Backup configuration database'
|
|
if ! docker exec "$container" sh -c \
|
|
"slapcat -F /etc/openldap/ldif -n 0 -l ${tempDir}/config-${fileDate}.ldif" \
|
|
>> "$logfile" 2>&1; then
|
|
logInfo 'err'
|
|
exitError 4 'Could not backup configuration database.'
|
|
fi
|
|
logInfo 'done'
|
|
|
|
# iterate frontend databases and export to ldif
|
|
i=1
|
|
while [ "$i" -ne "$numFrontEnd" ]; do
|
|
logInfo 'task' "Backup frontend database $i"
|
|
if ! docker exec "$container" sh -c \
|
|
"slapcat -F /etc/openldap/ldif -n ${i} -l ${tempDir}/mdb${i}-${fileDate}.ldif" \
|
|
>> "$logfile" 2>&1; then
|
|
logInfo 'err'
|
|
exitError 4 "Could not backup frontend database $i."
|
|
else
|
|
logInfo 'done'
|
|
fi
|
|
i=$((i+1))
|
|
done
|
|
|
|
# compress and encrypt exported ldif files
|
|
if [ $noEncryption = 0 ]; then
|
|
logInfo 'task' 'Compressing and encrypting backup'
|
|
if ! docker exec -w "/$tempDir" "$container" sh -c \
|
|
"tar -czf - * | openssl enc -e -${encryptionCipher} -iter +${encryptionIterations} -k ${password} -out ./ldap-${fileDate}.tar.gz" \
|
|
>> "$logfile" 2>&1; then
|
|
logInfo 'err'
|
|
exitError 5 'Could not securely archive backup files.'
|
|
fi
|
|
logInfo 'done'
|
|
elif [ $noEncryption = 1 ]; then
|
|
logInfo 'task' 'Compressing backup'
|
|
if ! docker exec -w "/$tempDir" "$container" sh -c \
|
|
"tar -czf ldap-${fileDate}.tar.gz *" \
|
|
>> "$logfile" 2>&1; then
|
|
logInfo 'err'
|
|
exitError 5 'Could not archive backup files.'
|
|
fi
|
|
logInfo 'done'
|
|
fi
|
|
|
|
## copy file to output location on host
|
|
logInfo 'task' 'Copying archive from docker container to host'
|
|
if ! docker cp "$container:/$tempDir/ldap-${fileDate}.tar.gz" "$outputLocation/" \
|
|
>> "$logfile" 2>&1; then
|
|
logInfo 'err'
|
|
exitError 6 'Unable to copy backup archive from container to host.'
|
|
fi
|
|
logInfo 'done'
|
|
logInfo "Backup file: ${outputLocation%/}/ldap-${fileDate}.tar.gz"
|
|
|
|
## cleanup and log success
|
|
cleanup
|
|
logSuccess 'Backup completed successfully.'
|
|
fi
|
|
|
|
### exit gracefully
|
|
logSuccess 'All processes completed'
|
|
printf "%s[%s] --- %s execution completed ---\n%s" \
|
|
"$magenta" "$(stamp)" "$scriptName" "$norm" >> "$logfile"
|
|
exit 0
|
|
|
|
|
|
# error code reference:
|
|
# 0: exited normally, no errors
|
|
# 1: parameter or permissions error
|
|
# 2: unsupported number of containers (0 or more than 1)
|
|
# 3: could not create/remove temporary directory/files
|
|
# 4: problem exporting database(s)
|
|
# 5: problem compressing/encrypting tar.gz archive
|
|
# 6: problem copying encrypted archive to host
|
|
# 7: problem creating target subdirectory in outputLocation
|
|
# 8: problem extracting gzipped tarball file
|
|
# 20: problem removing TLS entries
|
|
# 99: dependencies not installed (tar, gzip)
|
|
|
|
|
|
#EOF |