Compare commits
6 Commits
dcfe2d5bc8
...
7b1c660224
Author | SHA1 | Date | |
---|---|---|---|
|
7b1c660224 | ||
|
ae64bb86b1 | ||
|
e930b28043 | ||
|
ffd336e218 | ||
|
220f0bdd23 | ||
|
ce3c8e9c8c |
27
ab-openldap-backup.params.template
Normal file
27
ab-openldap-backup.params.template
Normal file
@ -0,0 +1,27 @@
|
||||
#######
|
||||
### openLDAP backup script parameters file
|
||||
#######
|
||||
|
||||
|
||||
### This file should be protected since it contains the password used to
|
||||
### encrypt your backup files!
|
||||
### recommend at least:
|
||||
### chown root:root backup.parameters
|
||||
### chmod 600 backup.parameters
|
||||
|
||||
|
||||
# password used to encrypt backup
|
||||
password='myPassword'
|
||||
|
||||
### encryption options
|
||||
|
||||
# encryption cipher
|
||||
# use 'openssl enc --ciphers' to see which ciphers are supported by your
|
||||
# openSSL installation
|
||||
encryptionCipher='aes-256-cbc'
|
||||
|
||||
# number of iterations used to derive the private key, higher is better but
|
||||
# more CPU intensive - minimum of 20000 recommended
|
||||
encryptionIterations=25000
|
||||
|
||||
#EOF
|
568
ab-openldap-backup.sh
Executable file
568
ab-openldap-backup.sh
Executable file
@ -0,0 +1,568 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
### backup openLDAP configuration and frontend database(s)
|
||||
#
|
||||
|
||||
# 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
|
||||
# 99: dependencies not installed (tar, gzip)
|
||||
|
||||
|
||||
### 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 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, it's 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 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}--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}--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
|
||||
;;
|
||||
*)
|
||||
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
|
||||
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
|
125
ab-openldap-update.sh
Normal file
125
ab-openldap-update.sh
Normal file
@ -0,0 +1,125 @@
|
||||
#!/bin/sh
|
||||
|
||||
### update script for ab-openldap utility scripts
|
||||
# version 1.0.0
|
||||
# script by Asif Bacchus
|
||||
# usage of this script is subject to the license terms found at:
|
||||
# https://git.asifbacchus.app/ab-docker/scripts/LICENSE
|
||||
|
||||
|
||||
### pre-requisites
|
||||
|
||||
# check if wget is installed
|
||||
if ! command -v wget > /dev/null 2>&1; then
|
||||
printf "\nSorry, this script requires that 'wget' is installed in order to automatically update files.\nExiting.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# zero counters
|
||||
updatesAvailable=0
|
||||
downloadFailed=0
|
||||
downloadSuccess=0
|
||||
updateFailed=0
|
||||
updateSuccess=0
|
||||
|
||||
# reference constants
|
||||
containerName='ab-openldap'
|
||||
server='https://git.asifbacchus.app/ab-docker/scripts/raw/branch/master/'
|
||||
checksumFilename='checksums.sha256'
|
||||
|
||||
# files to update
|
||||
localScriptName='update.sh'
|
||||
repoScriptName="${containerName}-update.sh"
|
||||
updateFiles="ab-openldap.sh ab-openldap.params.template ab-openldap-backup.sh ab-openldap-backup.params.template"
|
||||
|
||||
printf "\n*** Updating %s container service scripts ***\n\n" "$containerName"
|
||||
|
||||
|
||||
### download latest checksums
|
||||
printf "Getting latest checksums from ab-git server... "
|
||||
if ! wget --quiet --tries=3 --timeout=10 -N "${server}${checksumFilename}"; then
|
||||
printf "[ERROR]\n"
|
||||
printf "Unable to download checksums from ab-git server. Try again later.\n\n"
|
||||
exit 1
|
||||
else
|
||||
printf "[OK]\n"
|
||||
fi
|
||||
|
||||
|
||||
### check for updates to this script
|
||||
printf "Checking for updates to this script... "
|
||||
repoScriptChecksum=$( grep "$repoScriptName" files.sha256 | grep -o '^\S*' )
|
||||
localScriptChecksum=$( sha256sum "$localScriptName" | grep -o '^\S*' )
|
||||
if [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[NONE]\n\n"
|
||||
else
|
||||
# download updated script
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O $localScriptName "${server}${repoScriptName}"; then
|
||||
printf "[ERROR]\n"
|
||||
printf "Unable to download script update. Try again later.\n\n"
|
||||
exit 1
|
||||
else
|
||||
# verify download
|
||||
localScriptChecksum=$( sha256sum "$localScriptName" | grep -o '^\S*' )
|
||||
if ! [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[ERROR]\n"
|
||||
printf "Unable to verify checksum of updated script. Try again later.\n\n"
|
||||
else
|
||||
printf "[UPDATED]\n\n"
|
||||
printf "*** This script has been updated. Please re-run it to load the updated version of this file. ***\n\n"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
### update files
|
||||
set -- dummy $updateFiles
|
||||
shift
|
||||
for file; do
|
||||
updateTarget="$file"
|
||||
printf "Checking '%s' for updates... " "$updateTarget"
|
||||
repoFile=$( grep "$updateTarget" files.sha256 | grep -o '^\S*' )
|
||||
if [ -f "$file" ]; then
|
||||
localFile=$( sha256sum "$updateTarget" | grep -o '^\S*' )
|
||||
else
|
||||
localFile=0
|
||||
fi
|
||||
|
||||
if ! [ "$localFile" = "$repoFile" ]; then
|
||||
printf "[AVAILABLE]\n"
|
||||
updatesAvailable=$((updatesAvailable+1))
|
||||
# download update
|
||||
printf "Downloading updated '%s'... " "$updateTarget"
|
||||
# specify a name here instead of using the server name so that wget
|
||||
# overwrites the file
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O "$updateTarget" "${server}${updateTarget}"; then
|
||||
printf "[ERROR]\n"
|
||||
downloadFailed=$((downloadFailed+1))
|
||||
else
|
||||
printf "[OK]\n"
|
||||
downloadSuccess=$((downloadSuccess+1))
|
||||
# verify download
|
||||
printf "Verifying '%s'... " "$updateTarget"
|
||||
localFile=$( sha256sum "$updateTarget" | grep -o '^\S*' )
|
||||
if ! [ "$localFile" = "$repoFile" ]; then
|
||||
printf "[INVALID]\n"
|
||||
updateFailed=$((updateFailed+1))
|
||||
else
|
||||
printf "[OK]\n"
|
||||
updateSuccess=$((updateSuccess+1))
|
||||
fi
|
||||
fi
|
||||
else
|
||||
printf "[NONE]\n"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
### display results
|
||||
printf "\nResults:\n"
|
||||
printf "\tUpdates: %s available\n" "$updatesAvailable"
|
||||
printf "\tDownloads: %s successful, %s failed\n" "$downloadSuccess" "$downloadFailed"
|
||||
printf "\tUpdates: %s applied, %s failed\n" "$updateSuccess" "$updateFailed"
|
||||
|
||||
exit 0
|
265
ab-openldap.sh
265
ab-openldap.sh
@ -24,18 +24,23 @@ yellow=$(tput setaf 3)
|
||||
|
||||
### parameter defaults
|
||||
clean=false
|
||||
restore=false
|
||||
container_name="ab-openldap"
|
||||
volume_data="ab-openldap_data"
|
||||
volume_ldif="ab-openldap_ldif"
|
||||
backup_dir="$(pwd)/restore"
|
||||
remove=0
|
||||
shell=false
|
||||
tag=latest
|
||||
|
||||
|
||||
scriptHelp () {
|
||||
printf "\n${magenta}%80s\n" | tr " " "-"
|
||||
printf "${norm}This is a simple helper script so you can avoid lengthy typing when working\n"
|
||||
printf "\n%s%80s\n" "$magenta" | tr " " "-"
|
||||
printf "%sThis is a simple helper script so you can avoid lengthy typing when working\n" "$norm"
|
||||
printf "with the openLDAP container. The script reads the contents of 'ab-openldap.params'\n"
|
||||
printf "and constructs various 'docker run' commands based on that file. The biggest\n"
|
||||
printf "timesaver is working with certificates. If they are specified in the '.params',\n"
|
||||
printf "the script will automatically bind-mount them so openLDAP starts in 'TLS\n"
|
||||
printf "file, the script will automatically bind-mount them so openLDAP starts in 'TLS\n"
|
||||
printf "required' mode.\n\n"
|
||||
printf "If you run the script with no parameters, it will execute the container\n"
|
||||
printf "'normally': Run in detached mode with openLDAP automatically launched and\n"
|
||||
@ -45,29 +50,50 @@ scriptHelp () {
|
||||
printf "Containers run in SHELL mode are ALWAYS removed upon exit as they are meant for\n"
|
||||
printf "testing only. By default, containers run without '--rm' will be restarted\n"
|
||||
printf "automatically unless they are manually stopped via 'docker stop...'\n\n"
|
||||
printf "${magenta}The script has the following parameters:\n"
|
||||
printf "${cyan}(parameter in cyan) ${yellow}(default in yellow)${norm}\n\n"
|
||||
printf "${cyan}-n|--name${norm}\n"
|
||||
printf "%sThe script has the following parameters:\n" "$magenta"
|
||||
printf "%s(parameter in cyan) %s(default in yellow)%s\n\n" \
|
||||
"$cyan" "$yellow" "$norm"
|
||||
printf "%s-t|--tag%s\n" "$cyan" "$norm"
|
||||
printf "Change the version of the container downloaded by specifying a particular tag.\n"
|
||||
printf "This can be useful when testing new versions or if you have to roll back to a\n"
|
||||
printf "previous container version.\n"
|
||||
printf "%s(latest)%s\n\n" "$yellow" "$norm"
|
||||
printf "%s-n|--name%s\n" "$cyan" "$norm"
|
||||
printf "Change the name of the container. This is cosmetic and does not affect\n"
|
||||
printf "operation in any way.\n"
|
||||
printf "${yellow}(ab-openldap)${norm}\n\n"
|
||||
printf "${cyan}--rm|--remove${norm}\n"
|
||||
printf "%s(ab-openldap)%s\n\n" "$yellow" "$norm"
|
||||
printf "%s--data%s\n" "$cyan" "$norm"
|
||||
printf "Change the name of the docker volume used to persist data.\n"
|
||||
printf "%s(ab-openldap_data)%s\n\n" "$yellow" "$norm"
|
||||
printf "%s--ldif%s\n" "$cyan" "$norm"
|
||||
printf "Change the name of the docker volume used to persist LDIFs.\n"
|
||||
printf "%s(ab-openldap_ldif)%s\n\n" "$yellow" "$norm"
|
||||
printf "%s--rm|--remove%s\n" "$cyan" "$norm"
|
||||
printf "Automatically remove the container and volume (unless data is written) after it\n"
|
||||
printf "is exited.\n"
|
||||
printf "${yellow}(off: do not destroy container when stopped)${norm}\n\n"
|
||||
printf "${cyan}-s|--shell${norm}\n"
|
||||
printf "%s(off: do not destroy container when stopped)%s\n\n" \
|
||||
"$yellow" "$norm"
|
||||
printf "%s-s|--shell%s\n" "$cyan" "$norm"
|
||||
printf "Enter the container using an interactive POSIX shell. This happens after\n"
|
||||
printf "startup operations but *before* openLDAP (slapd) is actually started. This is\n"
|
||||
printf "a great way to see configuration changes possibly stopping openLDAP from\n"
|
||||
printf "starting. You can combine this with '--rm' for easy configuration checks.\n"
|
||||
printf "${yellow}(off: run in detached mode)${norm}\n\n"
|
||||
printf "${cyan}--clean${norm}\n"
|
||||
printf "%s(off: run in detached mode)%s\n\n" "$yellow" "$norm"
|
||||
printf "%s--clean%s\n" "$cyan" "$norm"
|
||||
printf "This option will stop ALL running openLDAP containers *AND DESTROY ALL\n"
|
||||
printf "VOLUMES*. This is meant to give you a 'clean start' if you've made\n"
|
||||
printf "configuration changes, etc.\n\n"
|
||||
printf "${yellow}More information can be found at:\n"
|
||||
printf "%s--restore%s\n" "$cyan" "$norm"
|
||||
printf "Restore a 'slapcat' backup to the data and ldif volume in preparation for\n"
|
||||
printf "mounting them in a normal container.\n"
|
||||
printf "It is strongly recommended you review your '-t' '--data' and '--ldif' settings\n"
|
||||
printf "before proceeding with this option.\n\n"
|
||||
printf "%s--backupdir%s\n" "$cyan" "$norm"
|
||||
printf "Location of the 'slapcat' backup files which you want to restore.\n"
|
||||
printf "%s(./restore)%s\n\n" "$yellow" "$norm"
|
||||
printf "%sMore information can be found at:\n" "$yellow"
|
||||
printf "https://git.asifbacchus.app/ab-docker/openldap/wiki\n"
|
||||
printf "${magenta}%80s\n\n" | tr " " "-"
|
||||
printf "%s%80s\n\n" "$magenta" | tr " " "-"
|
||||
exit 0
|
||||
}
|
||||
|
||||
@ -76,14 +102,14 @@ scriptHelp () {
|
||||
# is user root or in the docker group?
|
||||
if [ ! "$( id -u )" -eq 0 ]; then
|
||||
if ! id -Gn | grep docker > /dev/null; then
|
||||
printf "${err}\nYou must either be root or in the 'docker' group to run this script since you must be able to actually start the container! Exiting.\n${norm}"
|
||||
printf "%s\nYou must either be root or in the 'docker' group to run this script since you must be able to actually start the container! Exiting.\n%s" "$err" "$norm"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
# does the params file exist?
|
||||
if [ ! -f "./ab-openldap.params" ]; then
|
||||
printf "${err}\nCannot find 'ab-openldap.params' file in the same directory as this script. Exiting.\n${norm}"
|
||||
printf "%s\nCannot find 'ab-openldap.params' file in the same directory as this script. Exiting.\n%s" "$err" "$norm"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
@ -93,15 +119,18 @@ fi
|
||||
# check for certs if using TLS
|
||||
if [ "$TLS_CERT" ]; then
|
||||
if [ ! -f "$TLS_CERT" ]; then
|
||||
printf "${err}\nCannot find specified TLS certificate file. Exiting.${norm}\n"
|
||||
printf "%s\nCannot find specified TLS certificate file. Exiting.%s\n" \
|
||||
"$err" "$norm"
|
||||
exit 5
|
||||
fi
|
||||
if [ ! -f "$TLS_KEY" ]; then
|
||||
printf "${err}\nCannot find specified TLS private key file. Exiting.${norm}\n"
|
||||
printf "%s\nCannot find specified TLS private key file. Exiting.%s\n" \
|
||||
"$err" "$norm"
|
||||
exit 5
|
||||
fi
|
||||
if [ ! -f "$TLS_CHAIN" ]; then
|
||||
printf "${err}\nCannot find specified TLS certificate chain file. Exiting.${norm}\n"
|
||||
printf "%s\nCannot find specified TLS certificate chain file. Exiting.%s\n" \
|
||||
"$err" "$norm"
|
||||
exit 5
|
||||
fi
|
||||
fi
|
||||
@ -126,18 +155,63 @@ while [ $# -gt 0 ]; do
|
||||
# stop if necessary, delete volumes
|
||||
clean=true
|
||||
;;
|
||||
--restore)
|
||||
# restore backup
|
||||
restore=true
|
||||
;;
|
||||
-n|--name)
|
||||
# container name
|
||||
if [ -z "$2" ]; then
|
||||
printf "${err}\nNo container name specified. Exiting.\n${norm}"
|
||||
printf "%s\nNo container name specified. Exiting.\n%s" \
|
||||
"$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
container_name="$2"
|
||||
shift
|
||||
;;
|
||||
--data)
|
||||
# data volume name
|
||||
if [ -z "$2" ]; then
|
||||
printf "%s\nNo name specified for data volume. Exiting.\n%s" \
|
||||
"$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
volume_data="$2"
|
||||
shift
|
||||
;;
|
||||
--ldif)
|
||||
# ldif volume name
|
||||
if [ -z "$2" ]; then
|
||||
printf "%s\nNo name specified for LDIF volume. Exiting.\n%s" \
|
||||
"$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
volume_ldif="$2"
|
||||
shift
|
||||
;;
|
||||
--backupdir)
|
||||
# location of backup files to restore
|
||||
if [ -z "$2" ]; then
|
||||
printf "%s\nLocation of your backup files not provided. Exiting.\n%s" \
|
||||
"$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
backup_dir="$2"
|
||||
shift
|
||||
;;
|
||||
-t|--tag)
|
||||
# specify container tag
|
||||
if [ -z "$2" ]; then
|
||||
printf "%s\nNo tag specified. Exiting.\n%s" \
|
||||
"$err" "$norm"
|
||||
exit 1
|
||||
fi
|
||||
tag="$2"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
printf "${err}\nUnknown option: %s\n" "$1"
|
||||
printf "Use '--help' for valid options.\n\n${norm}"
|
||||
printf "%s\nUnknown option: %s\n" "$err" "$1"
|
||||
printf "Use '--help' for valid options.\n\n%s" "$norm"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@ -145,13 +219,39 @@ while [ $# -gt 0 ]; do
|
||||
done
|
||||
|
||||
|
||||
# cleanup any running containers and volumes
|
||||
# cleanup containers and volumes
|
||||
if [ $clean = true ]; then
|
||||
# display warning and confirm user's intentions
|
||||
printf "\nThis will stop and remove all ab-openldap containers %sAND REMOVE ALL PERSISTENT DATA VOLUMES%s. Please ensure you have a backup and understand how to restore your data.\n" \
|
||||
"$red" "$norm"
|
||||
printf "%sThis action CANNOT be undone!%s\n\n" \
|
||||
"$red" "$norm"
|
||||
|
||||
# confirmation loop
|
||||
while true; do
|
||||
printf "%sAre you sure you want to continue? (yes/no)%s " \
|
||||
"$cyan" "$norm"
|
||||
read -r yn
|
||||
case "$yn" in
|
||||
[Yy]*)
|
||||
break
|
||||
;;
|
||||
[Nn]*)
|
||||
printf "\n"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf "Please answer 'y' or 'n'.\n"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# get all ab-openldap containers
|
||||
containers=$(docker ps -a --no-trunc --filter "label=org.label-schema.name=ab-openldap" --format "{{ .Names }}")
|
||||
# check for null value -- no containers to remove
|
||||
if [ -z "$containers" ]; then
|
||||
printf "${err}No openldap containers to remove. Exiting.${norm}\n\n"
|
||||
printf "%sNo openldap containers to remove. Exiting.%s\n\n" \
|
||||
"$err" "$norm"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@ -159,66 +259,125 @@ if [ $clean = true ]; then
|
||||
set -- dummy $containers
|
||||
shift
|
||||
for container; do
|
||||
printf "\n${cyan}Found %s -- processing:${norm}\n" ${container}
|
||||
volume=$(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/openldap/data" }}{{ .Name }}{{ end }}{{ end }}' ${container})
|
||||
printf "\t${red}Stopping container...${norm}\n"
|
||||
printf "\n%sFound %s -- processing:%s\n" \
|
||||
"$cyan" "$container" "$norm"
|
||||
# stop container
|
||||
printf "\t%sStopping container...%s\n" "$red" "$norm"
|
||||
docker stop ${container} > /dev/null 2>&1
|
||||
printf "\t${red}Removing container...${norm}\n"
|
||||
# find volumes
|
||||
volumes=$(docker inspect --format '{{ range .Mounts }}{{ println .Name }}{{ end }}' ${container})
|
||||
# remove container
|
||||
printf "\t%sRemoving container...%s\n" "$red" "$norm"
|
||||
docker rm ${container} > /dev/null 2>&1
|
||||
printf "\t${red}Removing volume...${norm}\n"
|
||||
# pause to allow write flushing
|
||||
sleep 3
|
||||
# iterate volumes
|
||||
set -- dummy2 $volumes
|
||||
shift
|
||||
for volume; do
|
||||
printf "\t%sRemoving volume '%s'...%s\n" "$red" "$volume" "$norm"
|
||||
docker volume rm ${volume} > /dev/null 2>&1
|
||||
printf "${cyan}...done${norm}\n"
|
||||
done
|
||||
printf "%s...done%s\n" "$cyan" "$norm"
|
||||
done
|
||||
elif [ $restore = true ]; then
|
||||
# restore backup
|
||||
printf "%s\n*** Restoring Backup ***\n\n%s" "$magenta" "$norm"
|
||||
printf "To avoid errors due to existing files, this script will delete any volumes that have the following names:\n"
|
||||
printf "\t%s\n\t%s\n" "$volume_data" "$volume_ldif"
|
||||
# confirmation loop
|
||||
while true; do
|
||||
printf "%sDo you want to continue? (yes/no)%s " \
|
||||
"$cyan" "$norm"
|
||||
read -r yn
|
||||
case "$yn" in
|
||||
[Yy]*)
|
||||
break
|
||||
;;
|
||||
[Nn]*)
|
||||
printf "\n"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
printf "Please answer 'y' or 'n'.\n"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# delete any conflicting volumes
|
||||
docker volume rm ${volume_data} > /dev/null 2>&1
|
||||
docker volume rm ${volume_ldif} > /dev/null 2>&1
|
||||
# run temporary container to merge backup data into volumes
|
||||
docker run --rm \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$backup_dir":/restore \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag} \
|
||||
cat /var/openldap/data/restore.log
|
||||
printf "\nPlease review the log output on your screen to determine if the restore was successful or what errors need to be corrected. If everything was successful, your data volumes can be used in a new container started normally.\n"
|
||||
# run without TLS
|
||||
elif [ -z "$TLS_CERT" ]; then
|
||||
if [ $shell = true ]; then
|
||||
# exec shell
|
||||
printf "${cyan}\nRunning SHELL on %s...${norm}\n" "$container_name"
|
||||
printf "%s\nRunning SHELL on %s...%s\n" \
|
||||
"$cyan" "$container_name" "$norm"
|
||||
if [ -d "$MY_LDIF" ]; then
|
||||
# bind-mount custom LDIFs if specified
|
||||
docker run --rm -it --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$MY_LDIF":/etc/openldap/customLDIF \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest /bin/sh
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag} /bin/sh
|
||||
else
|
||||
docker run --rm -it --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest /bin/sh
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag} /bin/sh
|
||||
fi
|
||||
else
|
||||
# exec normally
|
||||
printf "${cyan}\nRunning OPENLDAP on %s...${norm}\n" "$container_name"
|
||||
printf "%s\nRunning OPENLDAP on %s...%s\n" \
|
||||
"$cyan" "$container_name" "$norm"
|
||||
if [ "$remove" -eq 1 ]; then
|
||||
if [ -d "$MY_LDIF" ]; then
|
||||
# bind-mount custom LDIFs if specified
|
||||
docker run --rm -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$MY_LDIF":/etc/openldap/customLDIF \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
else
|
||||
docker run --rm -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
fi
|
||||
else
|
||||
if [ -d "$MY_LDIF" ]; then
|
||||
# bind-mount custom LDIFs if specified
|
||||
docker run -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$MY_LDIF":/etc/openldap/customLDIF \
|
||||
-p 389:389 -p 636:636 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
else
|
||||
docker run -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-p 389:389 -p 636:636 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@ -226,70 +385,84 @@ elif [ -z "$TLS_CERT" ]; then
|
||||
elif [ "$TLS_CERT" ] && [ "$TLS_KEY" ] && [ "$TLS_CHAIN" ]; then
|
||||
if [ $shell = true ]; then
|
||||
# exec shell
|
||||
printf "${cyan}\nRunning SHELL on %s (TLS)...${norm}\n" "$container_name"
|
||||
printf "%s\nRunning SHELL on %s (TLS)...%s\n" \
|
||||
"$cyan" "$container_name" "$norm"
|
||||
if [ -d "$MY_LDIF" ]; then
|
||||
# bind-mount custom LDIFs if specified
|
||||
docker run --rm -it --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$MY_LDIF":/etc/openldap/customLDIF \
|
||||
-v "$TLS_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$TLS_KEY":/certs/privkey.pem:ro \
|
||||
-v "$TLS_CHAIN":/certs/chain.pem:ro \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest /bin/sh
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag} /bin/sh
|
||||
else
|
||||
docker run --rm -it --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$TLS_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$TLS_KEY":/certs/privkey.pem:ro \
|
||||
-v "$TLS_CHAIN":/certs/chain.pem:ro \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest /bin/sh
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag} /bin/sh
|
||||
fi
|
||||
else
|
||||
# exec normally
|
||||
printf "${cyan}\nRunning OPENLDAP on %s (TLS)...${norm}\n" "$container_name"
|
||||
printf "%s\nRunning OPENLDAP on %s (TLS)...%s\n" \
|
||||
"$cyan" "$container_name" "$norm"
|
||||
if [ "$remove" -eq 1 ]; then
|
||||
if [ -d "$MY_LDIF" ]; then
|
||||
# bind-mount custom LDIFs if specified
|
||||
docker run --rm -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$MY_LDIF":/etc/openldap/customLDIF \
|
||||
-v "$TLS_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$TLS_KEY":/certs/privkey.pem:ro \
|
||||
-v "$TLS_CHAIN":/certs/chain.pem:ro \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
else
|
||||
docker run --rm -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$TLS_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$TLS_KEY":/certs/privkey.pem:ro \
|
||||
-v "$TLS_CHAIN":/certs/chain.pem:ro \
|
||||
-p 389:389 -p 636:636 \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
fi
|
||||
else
|
||||
if [ -d "$MY_LDIF" ]; then
|
||||
# bind-mount custom LDIFs if specified
|
||||
docker run -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$MY_LDIF":/etc/openldap/customLDIF \
|
||||
-v "$TLS_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$TLS_KEY":/certs/privkey.pem:ro \
|
||||
-v "$TLS_CHAIN":/certs/chain.pem:ro \
|
||||
-p 389:389 -p 636:636 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
else
|
||||
docker run -d --name ${container_name} \
|
||||
--env-file ab-openldap.params \
|
||||
-v "$volume_data":/var/openldap/data \
|
||||
-v "$volume_ldif":/etc/openldap/ldif \
|
||||
-v "$TLS_CERT":/certs/fullchain.pem:ro \
|
||||
-v "$TLS_KEY":/certs/privkey.pem:ro \
|
||||
-v "$TLS_CHAIN":/certs/chain.pem:ro \
|
||||
-p 389:389 -p 636:636 \
|
||||
--restart unless-stopped \
|
||||
docker.asifbacchus.app/ldap/ab-openldap:latest
|
||||
docker.asifbacchus.app/ldap/ab-openldap:${tag}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
@ -1 +1,8 @@
|
||||
# checksums for scripts and parameter files
|
||||
|
||||
# ab-openldap
|
||||
3818e56bc2eaa33c57a10b4e7bfdee4674df0d9b41ce665d5ca3853ebdd9212b ab-openldap-backup.params.template
|
||||
14b11370f980bd10b3cd96ddf3acab73c723f7594127e38d4b90ad09660b5e0a ab-openldap-backup.sh
|
||||
5257cbc175e1f35061e419f54c953875597996d887b3c882990319ecc2371bfd ab-openldap.params.template
|
||||
79d96713f2e0a1e9d8c4192077986fc8e6efe805441595d014931ec56163c3c9 ab-openldap.sh
|
||||
690ed3a1bf7d5aa19ae4be30d8cb72a32dc2155938e1a3b8eeb5d794409b2a63 ab-openldap-update.sh
|
125
template-update.sh
Normal file
125
template-update.sh
Normal file
@ -0,0 +1,125 @@
|
||||
#!/bin/sh
|
||||
|
||||
### update script for <ab-container> utility scripts
|
||||
# version x.y.z
|
||||
# script by Asif Bacchus
|
||||
# usage of this script is subject to the license terms found at:
|
||||
# https://git.asifbacchus.app/ab-docker/scripts/LICENSE
|
||||
|
||||
|
||||
### pre-requisites
|
||||
|
||||
# check if wget is installed
|
||||
if ! command -v wget > /dev/null 2>&1; then
|
||||
printf "\nSorry, this script requires that 'wget' is installed in order to automatically update files.\nExiting.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# zero counters
|
||||
updatesAvailable=0
|
||||
downloadFailed=0
|
||||
downloadSuccess=0
|
||||
updateFailed=0
|
||||
updateSuccess=0
|
||||
|
||||
# reference constants
|
||||
containerName=''
|
||||
server='https://git.asifbacchus.app/ab-docker/scripts/raw/branch/master/'
|
||||
checksumFilename='checksums.sha256'
|
||||
|
||||
# files to update
|
||||
localScriptName='update.sh'
|
||||
repoScriptName="${containerName}-update.sh"
|
||||
updateFiles=""
|
||||
|
||||
printf "\n*** Updating %s container service scripts ***\n\n" "$containerName"
|
||||
|
||||
|
||||
### download latest checksums
|
||||
printf "Getting latest checksums from ab-git server... "
|
||||
if ! wget --quiet --tries=3 --timeout=10 -N "${server}${checksumFilename}"; then
|
||||
printf "[ERROR]\n"
|
||||
printf "Unable to download checksums from ab-git server. Try again later.\n\n"
|
||||
exit 1
|
||||
else
|
||||
printf "[OK]\n"
|
||||
fi
|
||||
|
||||
|
||||
### check for updates to this script
|
||||
printf "Checking for updates to this script... "
|
||||
repoScriptChecksum=$( grep "$repoScriptName" files.sha256 | grep -o '^\S*' )
|
||||
localScriptChecksum=$( sha256sum "$localScriptName" | grep -o '^\S*' )
|
||||
if [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[NONE]\n\n"
|
||||
else
|
||||
# download updated script
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O $localScriptName "${server}${repoScriptName}"; then
|
||||
printf "[ERROR]\n"
|
||||
printf "Unable to download script update. Try again later.\n\n"
|
||||
exit 1
|
||||
else
|
||||
# verify download
|
||||
localScriptChecksum=$( sha256sum "$localScriptName" | grep -o '^\S*' )
|
||||
if ! [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
|
||||
printf "[ERROR]\n"
|
||||
printf "Unable to verify checksum of updated script. Try again later.\n\n"
|
||||
else
|
||||
printf "[UPDATED]\n\n"
|
||||
printf "*** This script has been updated. Please re-run it to load the updated version of this file. ***\n\n"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
### update files
|
||||
set -- dummy $updateFiles
|
||||
shift
|
||||
for file; do
|
||||
updateTarget="$file"
|
||||
printf "Checking '%s' for updates... " "$updateTarget"
|
||||
repoFile=$( grep "$updateTarget" files.sha256 | grep -o '^\S*' )
|
||||
if [ -f "$file" ]; then
|
||||
localFile=$( sha256sum "$updateTarget" | grep -o '^\S*' )
|
||||
else
|
||||
localFile=0
|
||||
fi
|
||||
|
||||
if ! [ "$localFile" = "$repoFile" ]; then
|
||||
printf "[AVAILABLE]\n"
|
||||
updatesAvailable=$((updatesAvailable+1))
|
||||
# download update
|
||||
printf "Downloading updated '%s'... " "$updateTarget"
|
||||
# specify a name here instead of using the server name so that wget
|
||||
# overwrites the file
|
||||
if ! wget --quiet --tries=3 --timeout=10 -O "$updateTarget" "${server}${updateTarget}"; then
|
||||
printf "[ERROR]\n"
|
||||
downloadFailed=$((downloadFailed+1))
|
||||
else
|
||||
printf "[OK]\n"
|
||||
downloadSuccess=$((downloadSuccess+1))
|
||||
# verify download
|
||||
printf "Verifying '%s'... " "$updateTarget"
|
||||
localFile=$( sha256sum "$updateTarget" | grep -o '^\S*' )
|
||||
if ! [ "$localFile" = "$repoFile" ]; then
|
||||
printf "[INVALID]\n"
|
||||
updateFailed=$((updateFailed+1))
|
||||
else
|
||||
printf "[OK]\n"
|
||||
updateSuccess=$((updateSuccess+1))
|
||||
fi
|
||||
fi
|
||||
else
|
||||
printf "[NONE]\n"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
### display results
|
||||
printf "\nResults:\n"
|
||||
printf "\tUpdates: %s available\n" "$updatesAvailable"
|
||||
printf "\tDownloads: %s successful, %s failed\n" "$downloadSuccess" "$downloadFailed"
|
||||
printf "\tUpdates: %s applied, %s failed\n" "$updateSuccess" "$updateFailed"
|
||||
|
||||
exit 0
|
Loading…
Reference in New Issue
Block a user