moved to ab-openldap repo

This commit is contained in:
Asif Bacchus 2020-09-15 23:30:34 -06:00
parent 1e9ab5fc45
commit 0f53e1b39f
6 changed files with 0 additions and 1347 deletions

View File

@ -1,26 +0,0 @@
#
# openLDAP backup script parameters file
# version 4.0
#
# 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

View File

@ -1,601 +0,0 @@
#!/bin/sh
#
# backup ab-openLDAP configuration and frontend database(s)
# version 4.0
# Script by Asif Bacchus
#
### 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

View File

@ -1,170 +0,0 @@
#!/bin/sh
#
# update script for ab-openldap container and utility scripts
# version 1.0.0
# script by Asif Bacchus
#
### functions
consoleError() {
printf "\n%s%s%s\n\n" "$err" "$2" "$norm"
exit "$1"
}
### text formatting presets
if command -v tput > /dev/null; then
cyan=$(tput setaf 6)
err=$(tput bold)$(tput setaf 1)
norm=$(tput sgr0)
ok=$(tput setaf 2)
yellow=$(tput setaf 11)
else
cyan=''
err=''
norm=''
ok=''
yellow=''
fi
### pre-requisites
# check if wget is installed
if ! command -v wget > /dev/null 2>&1; then
consoleError '1' "Sorry, this script requires that 'wget' is installed in order to automatically update files."
fi
# 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 pull container updates."
fi
fi
# zero counters
updatesAvailable=0
downloadFailed=0
downloadSuccess=0
updateFailed=0
updateSuccess=0
# reference constants
containerName='ab-openldap'
containerUpdatePath="docker.asifbacchus.app/ldap/$containerName:latest"
serverPath="https://asifbacchus.app/public/$containerName/"
checksumFilename='checksums.sha256'
# files to update
scriptName="$containerName-update.sh"
updateFiles="$containerName-backup.params.template $containerName-backup.sh $containerName.params.template $containerName.sh"
printf "\n%sUpdating %s%s%s:%s\n" "$cyan" "$yellow" "$containerName" "$cyan" "$norm"
### update container
printf "updating container... "
if ! docker pull "$containerUpdatePath" > /dev/null 2>&1; then
printf "%s[ERROR]\n\n" "$err"
printf "There was a problem updating the container. Please try again later.%s\n\n" "$norm"
exit 1
else
printf "%s[OK]%s\n" "$ok" "$norm"
fi
### checksums
printf "downloading latest checksums... "
if ! wget --quiet --tries=3 --timeout=10 -O "$checksumFilename" "$serverPath$checksumFilename"; then
printf "%s[ERROR]\n\n" "$err"
printf "Unable to download updated checksums. Please try again later.%s\n\n" "$norm"
exit 1
else
printf "%s[OK]%s\n" "$ok" "$norm"
fi
### script self-update
printf "checking for updates to this script... "
localScriptChecksum=$( sha256sum "./$scriptName" | grep -o '^\S*' )
repoScriptChecksum=$( grep "$scriptName" "$checksumFilename" | grep -o '^\S*' )
if [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
printf "[NONE]\n"
else
# download updated script
if ! wget --quiet --tries=3 --timeout=10 -O "$scriptName" "$serverPath$scriptName"; then
printf "%s[ERROR]\n\n" "$err"
printf "Unable to download script update. Please try again later.%s\n\n" "$norm"
exit 1
else
# verify download
localScriptChecksum=$( sha256sum "$scriptName" | grep -o '^\S*' )
if ! [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
printf "%s[ERROR]\n\n" "$err"
printf "Unable to verify checksum of updated script. Please try again later.%s\n\n" "$norm"
else
printf "%s[UPDATED]%s\n\n" "$ok" "$norm"
printf "%s*** This script has been updated. Please re-run it to load the updated version of this file. ***%s\n\n" "$yellow" "$norm"
exit 0
fi
fi
fi
## update files
# remember: do NOT quote dummy var!
set -- dummy $updateFiles
shift
for file; do
printf "checking '%s' for updates... " "$file"
repoFileChecksum=$( grep "$file" "$checksumFilename" | grep -o '^\S*' )
if [ -f "$file" ]; then
localFileChecksum=$( sha256sum "$file" | grep -o '^\S*' )
else
localFileChecksum=0
fi
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
printf "%s[AVAILABLE]%s " "$yellow" "$norm"
updatesAvailable=$((updatesAvailable+1))
# download update
if ! wget --quiet --tries=3 --timeout=10 -O "$file" "$serverPath$file"; then
printf "%s[ERROR]%s\n" "$err" "$norm"
downloadFailed=$((downloadFailed+1))
else
printf "%s[DOWNLOADED] %s" "$ok" "$norm"
downloadSuccess=$((downloadSuccess+1))
# verify download
localFileChecksum=$( sha256sum "$file" | grep -o '^\S*' )
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
printf "%s[INVALID]%s\n" "$err" "$norm"
updateFailed=$((updateFailed+1))
else
printf "%s[VERIFIED]%s\n" "$ok" "$norm"
updateSuccess=$((updateSuccess+1))
fi
fi
else
printf "[NONE]\n"
fi
done
### display results
printf "\n%sResults:%s\n" "$cyan" "$norm"
printf "\tUpdates: %s available\n" "$updatesAvailable"
if [ "$updatesAvailable" -gt '0' ]; then
if [ "$downloadFailed" -gt '0' ]; then
printf "\tDownloads: %s successful, %s%s failed%s\n" "$downloadSuccess" "$err" "$downloadFailed" "$norm"
else
printf "\tDownloads: %s successful\n" "$downloadSuccess"
fi
if [ "$updateFailed" -gt '0' ]; then
printf "\tUpdates: %s applied, %s%s failed%s\n\n" "$updateSuccess" "$err" "$updateFailed" "$norm"
else
printf "\tUpdates: %s applied\n\n" "$updateSuccess"
fi
fi
exit 0
#EOF

View File

@ -1,98 +0,0 @@
#
## openldap environment variables
# version 3.2
#
### Usage
#
# ***VERY IMPORTANT! DO NOT PUT QUOTES AROUND VALUES IN THIS FILE!!!***
# incorrect: ORG_NAME="MyOrganization"
# correct: ORG_NAME=MyOrganization
#
# Instead of typing a myriad of "-e ...", you can fill them all out in this
# file and then use "--env-file ab-openldap.params" to tell docker to source
# its variables from here. You can also combine both methods if you like.
# Most important, if you're using the convenience script, it draws all info from
# this file!
#
# You should probably protect this file via file permissions since it likely
# will contain things like passwords! Suggest restricting it to root only
# ex: chown root:root ab-openldap.parms && chmod 600 ab-openldap.parms
#
# N.B. If you change the convenience script name, you must also change this
# file's name to match.
# ex: script name is 'runldap.sh' --> this file must be 'runldap.params'
#
###
### Your timezone (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
TZ=Area/Location
### First user account (will be added to Organization DIT 'manager' role)
USER=admin
USER_PASS=admin
USER_FIRSTNAME=admin
USER_LASTNAME=admin
### Your Organization domain and name
# domain in standard (dotted) format -- not LDAP format
DOMAIN=mydomain.net
# Org name: suggest using [A-Z][a-z][0-9][-_] ONLY. Avoid spaces.
ORG_NAME=MyOrganization
### Your 'directory browser' user
BROWSER_USER=ldapbind
BROWSER_PASS=ldapbind
### Anonymous binding (enabled by default)
ANONYMOUS_BINDING=yes
### Location of your TLS files
# Note: This section is only automated if using the script file to start the
# container. If you are starting it manually and using '--env-file', you still
# have to manually bind-mount these files using '-v source:/certs/dest.file:ro'.
#
# If you're bind-mounting symlinks, remember that you have to fully expand them
# or Docker will try to bind the link instead of the target! This is most
# common with Let's Encrypt.
#
# Example that does not work (binding directory instead of files):
# /etc/letsencrypt/live/mydomain.net:/certs:ro
# This will end up copying the symlinks themselves and, since the targets are
# not available to the container, it doesn't work!
# Example of the right way (bind actual files):
# /etc/letsencrypt/live/mydomain.net/privkey.pem:/certs/privkey.pem:ro
###
#TLS_CERT=/etc/letsencrypt/live/mydomain.net/fullchain.pem
#TLS_KEY=/etc/letsencrypt/live/mydomain.net/privkey.pem
#TLS_CHAIN=/etc/letsencrypt/live/mydomain.net/chain.pem
# The container will generate Diffie-Hellman parameters automatically the first
# time it's launched with TLS certificates defined.
### Custom LDIFs
# Path to any custom LDIFs you want applied to the container. Leave this line/
# variable commented-out if you don't have any LDIFs to apply.
# MY_LDIF=/path/to/my/LDIFs
### Enable checking passwords against IMAP/S server
#
# Setting the DOMAILAUTH variable to '1' tells openLDAP to verify SASL passwords
# in the directory against an IMAP/S remote host. In other words, any user with
# a password '{SASL}user@server.tld' will have their password checked by the
# IMAP/S server using the provided email address and a 'NO/OK' reponse is fed
# back to openLDAP. Please note, the remote mailserver *must* support IMAP/S
# (i.e. secured IMAP).
#
# Specify the remote mailserver hostname using the MAILSERVER variable.
#
# If the remote mailserver implements IMAP/S (secure IMAP) on a non-standard
# port (not port 993) then supply that using the MAILAUTHPORT variable.
#
# More details can be found in the wiki.
###
#DOMAILAUTH=0
#MAILSERVER=mail.myserver.tld
#MAILAUTHPORT=imaps
#EOF

View File

@ -1,447 +0,0 @@
#!/bin/sh
#
# start ab-openldap container using params file variables
# version 4.0
# Script by Asif Bacchus
#
### functions
consoleError () {
printf "%s\n%s\n" "$err" "$2"
printf "Exiting.\n\n%s" "$norm"
exit "$1"
}
textblock () {
printf "%s\n" "$1" | fold -w "$width" -s
}
prompt_yn () {
# confirmation loop
while true; do
printf "%sAre you sure you want to continue? (y/n)%s " \
"$cyan" "$norm"
read -r yn
case "$yn" in
[Yy]*)
break
;;
[Nn]*)
printf "\n"
exit 0
;;
*)
printf "%sPlease answer 'y' or 'n'.%s\n" "$err" "$norm"
;;
esac
done
}
# text formatting presets
bold=$(tput bold)
cyan=$(tput setaf 6)
err=$(tput bold)$(tput setaf 1)
magenta=$(tput setaf 5)
norm=$(tput sgr0)
red=$(tput setaf 1)
yellow=$(tput setaf 3)
width=$(tput cols)
### parameter defaults
scriptName="$( basename "$0" )"
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"
textblock "${bold}Usage: $scriptName [parameters]${norm}"
printf "\n"
textblock "This is a simple helper script so you can avoid lengthy typing when working with the openLDAP container. The script reads the contents of '${scriptName%.*}.params' and constructs various 'docker run' commands based on that file. The biggest timesaver is working with certificates. If they are specified in the '.params' file, the script will automatically bind-mount them so openLDAP starts in 'TLS required' mode."
printf "\n"
textblock "If you run the script with no parameters, it will execute the container 'normally'. That is: Run in detached mode with openLDAP automatically launched and logging to stdout. If you specified certificates, openLDAP will require a TLS connection. All modes of operation allow you to enter the container and connect directly using UNIX sockets as root with *unrestricted* access to all DITs and objects."
printf "\n"
textblock "If you want to verify SASL passwords against an IMAP/S server, please refer to the '.params' template file and the wiki for more information."
printf "\n"
textblock "Containers run in SHELL mode are ALWAYS removed upon exit as they are meant for testing only. By default, containers run without '--rm' will be restarted automatically unless they are manually stopped via 'docker stop...'"
printf "\n"
textblock "${magenta}The script has the following parameters:${norm}"
textblock "${cyan}(parameter in cyan) ${yellow}(default in yellow)${norm}"
printf "\n"
textblock "${cyan}t|--tag ${yellow}(latest)${norm}"
textblock "Change the version of the container downloaded by specifying a particular tag. This can be useful when testing new versions or if you have to roll back to a previous container version."
printf "\n"
textblock "${cyan}-n|--name ${yellow}(ab-openldap)${norm}"
textblock "Change the name of the container. This is cosmetic and does not affect operation in any way."
printf "\n"
textblock "${cyan}--data ${yellow}(ab-openldap_data)${norm}"
textblock "Change the name of the docker volume used to persist data."
printf "\n"
textblock "${cyan}--ldif ${yellow}(ab-openldap_ldif)${norm}"
textblock "Change the name of the docker volume used to persist LDIFs."
printf "\n"
textblock "${cyan}--rm|--remove${norm}"
textblock "Switch parameter. Automatically remove the container and associated volumes (unless data is written) after it exits."
printf "\n"
textblock "${cyan}-s|--shell${norm}"
textblock "Switch parameter. Enter the container using an interactive POSIX shell. This happens after startup operations but *before* openLDAP (slapd) is started. This is a great way to test out configuration changes or run custom queries. You can combine this with '--rm' for easy configuration checks or LDIF imports."
printf "\n"
textblock "${cyan}--clean${norm}"
textblock "Switch parameter. This option will stop and remove ALL running openLDAP containers *AND DESTROY ALL VOLUMES*. This is meant to give you a 'clean start' if you've made configuration changes, etc."
printf "\n"
textblock "${cyan}--restore${norm}"
textblock "Switch parameter. Restore a 'slapcat' backup to the data and ldif volumes in preparation for mounting them in a normal container. It is strongly recommended you review your '-t' '--data' and '--ldif' settings before proceeding with this option."
printf "\n"
textblock "${cyan}--backupdir ${yellow}(./restore)${norm}"
textblock "Location of the 'slapcat' backup files to restore."
printf "\n\n"
textblock "More information about this script and the ab-openLDAP container can be found at ${magenta}https://git.asifbacchus.app/ab-docker/openldap/wiki${norm}"
printf "\n\n"
exit 0
}
### 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 '2' "You must either be root or in the 'docker' group to run this script since you must be able to actually start the container!"
fi
fi
# does the params file exist?
if [ ! -f "${scriptName%.*}.params" ]; then
consoleError '3' "Cannot find '${scriptName%.*}.params' file in the same directory as this script."
exit 3
fi
# read .params file
. ./${scriptName%.*}.params
# process startup parameters
while [ $# -gt 0 ]; do
case "$1" in
-h|-\?|--help)
# display help
scriptHelp
exit 0
;;
--rm|--remove)
# remove container on exit
remove=1
;;
-s|--shell)
# start shell instead of default CMD
shell=true
;;
--clean)
# stop if necessary, delete volumes
clean=true
;;
--restore)
# restore backup
restore=true
;;
-n|--name)
# container name
if [ -z "$2" ]; then
consoleError '1' 'No container name specified.'
fi
container_name="$2"
shift
;;
--data)
# data volume name
if [ -z "$2" ]; then
consoleError '1' 'No name specified for data volume.'
fi
volume_data="$2"
shift
;;
--ldif)
# ldif volume name
if [ -z "$2" ]; then
consoleError '1' 'No name specified for LDIF volume.'
fi
volume_ldif="$2"
shift
;;
--backupdir)
# location of backup files to restore
if [ -z "$2" ]; then
consoleError '1' 'Location of your backup files not provided.'
fi
backup_dir="$2"
shift
;;
-t|--tag)
# specify container tag
if [ -z "$2" ]; then
consoleError '1' 'No tag specified.'
fi
tag="$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
### process main operations
if [ $clean = true ]; then
# cleanup containers and volumes
# 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"
prompt_yn
# 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
consoleError '0' 'No openldap containers to remove.'
fi
# iterate containers, stop them and remove straggling volumes
set -- dummy $containers
shift
for container; do
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
# find volumes
volumes=$(docker inspect --format '{{ range .Mounts }}{{ println .Name }}{{ end }}' ${container})
# remove container
printf "\t%sRemoving container...%s\n" "$red" "$norm"
docker rm -f ${container} > /dev/null 2>&1
# 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 -f ${volume} > /dev/null 2>&1
done
printf "%s...done%s\n" "$cyan" "$norm"
done
elif [ $restore = true ]; then
# automatically restore backups using a temp container to create volumes
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 (based on --data and --ldif):\n"
printf "\t%s\n\t%s\n" "$volume_data" "$volume_ldif"
prompt_yn
# delete any conflicting volumes
docker volume rm -f ${volume_data} > /dev/null 2>&1
docker volume rm -f ${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"
elif [ -z "$TLS_CERT" ]; then
# run container without TLS
if [ $shell = true ]; then
# exec shell
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:${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:${tag} /bin/sh
fi
else
# exec normally
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:${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:${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:${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:${tag}
fi
fi
fi
elif [ "$TLS_CERT" ] && [ "$TLS_KEY" ] && [ "$TLS_CHAIN" ]; then
# run container with TLS
# verify certificate files exist
if [ "$TLS_CERT" ]; then
if [ ! -f "$TLS_CERT" ]; then
consoleError '5' 'Cannot find specified TLS certificate file.'
fi
if [ ! -f "$TLS_KEY" ]; then
consoleError '5' 'Cannot find specified TLS private key file.'
fi
if [ ! -f "$TLS_CHAIN" ]; then
consoleError '5' 'Cannot find specified TLS certificate chain file.'
fi
fi
if [ $shell = true ]; then
# exec shell
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:${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:${tag} /bin/sh
fi
else
# exec normally
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:${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:${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:${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:${tag}
fi
fi
fi
fi
### exit gracefully
exit 0
# error code reference:
# 0: exited normally, no errors
# 1: unknown startup option passed to script
# 2: current user is unauthorized to operate docker
# 3: 'params' file not found in same directory as script
# 5: specified TLS-related files (cert, key or chain) not found
#EOF

View File

@ -1,5 +0,0 @@
a4ff46220c20887c85dbd9f4cc3d455bddeb920701966693bc277fb0690e9272 ab-openldap-backup.params.template
966090212df46dcbc44f455291f39f3ac8efef81256ed6a2dfe15ca27ec9cd9d ab-openldap-backup.sh
a2ae75864833c517aa686bbef02cd22864f305a42013c02d44df0008e4f2995e ab-openldap.params.template
ea80e00f23434cae19f0fa5892b6b87a0d912d72687de14e2f27c981a220e676 ab-openldap.sh
7351bc6613c73da7e6ef4d22f302a3096acd82883c974831f6b9fe3e95400739 ab-openldap-update.sh