vegardit-docker-openldap/image/run.sh
2020-04-02 13:03:15 +02:00

239 lines
8 KiB
Bash

#!/usr/bin/env bash
#
# Copyright 2019-2020 by Vegard IT GmbH, Germany, https://vegardit.com
# SPDX-License-Identifier: Apache-2.0
#
# @author Sebastian Thomschke, Vegard IT GmbH
#
# https://github.com/vegardit/docker-openldap
#
set -e -u
if [ -z "${BASH_VERSINFO:-}" ]; then /usr/bin/env bash "$0" "$@"; exit; fi
set -o pipefail
trap 'echo >&2 "$(date +%H:%M:%S) Error - exited with status $? at line $LINENO:"; pr -tn $0 | tail -n+$((LINENO - 3)) | head -n7' ERR
if [ "${DEBUG_RUN_SH:-}" == "1" ]; then
set -x
fi
cat <<'EOF'
_ __ __ __________
| | / /__ ____ _____ __________/ / / _/_ __/
| | / / _ \/ __ `/ __ `/ ___/ __ / / / / /
| |/ / __/ /_/ / /_/ / / / /_/ / _/ / / /
|___/\___/\__, /\__,_/_/ \__,_/ /___/ /_/
/____/
EOF
cat /opt/build_info
echo
if [ -f "$INIT_SH_FILE" ]; then
source "$INIT_SH_FILE"
fi
function log() {
if [ -p /dev/stdin ]; then
while read line; do
echo "[$(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}:${BASH_LINENO}] $line"
done
else
echo "[$(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}:${BASH_LINENO}] ${@}"
fi
}
# display slapd build info
slapd -VVV 2>&1 | log || true
# Limit maximum number of open file descriptors otherwise slapd consumes two
# orders of magnitude more of RAM, see https://github.com/docker/docker/issues/8231
ulimit -n $LDAP_NOFILE_LIMIT
#################################################################
# Adjust UID/GID and file permissions based on env var config
#################################################################
if [ -n "${LDAP_OPENLDAP_UID:-}" ]; then
effective_uid=$(id -u openldap)
if [ "$LDAP_OPENLDAP_UID" != "$effective_uid" ]; then
log "Changing UID of openldap user from $effective_uid to $LDAP_OPENLDAP_UID..."
usermod -o -u "$LDAP_OPENLDAP_UID" openldap
fi
fi
if [ -n "${LDAP_OPENLDAP_GID:-}" ]; then
effective_gid=$(id -g openldap)
if [ "$LDAP_OPENLDAP_GID" != "$effective_gid" ]; then
log "Changing GID of openldap user from $effective_gid to $LDAP_OPENLDAP_GID..."
usermod -o -u "$LDAP_OPENLDAP_GID" openldap
fi
fi
chown -R openldap:openldap /etc/ldap
chown -R openldap:openldap /var/lib/ldap
chown -R openldap:openldap /var/lib/ldap_orig
chown -R openldap:openldap /var/run/slapd
#################################################################
# Configure LDAP server on initial container launch
#################################################################
if [ ! -e /etc/ldap/slapd.d/initialized ]; then
function interpolate_vars() {
# https://stackoverflow.com/a/40167919
local line lineEscaped
while IFS= read -r line || [ -n "$line" ]; do # the `||` clause ensures that the last line is read even if it doesn't end with \n
# escape all chars that could trigger an expansion
IFS= read -r lineEscaped < <(echo "$line" | tr '`([$' '\1\2\3\4')
# selectively re-enable ${ references
lineEscaped=${lineEscaped//$'\4'{/\${}
# escape embedded double quotes to preserve them
lineEscaped=${lineEscaped//\"/\\\"}
eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$'
done
}
function substr_before() {
echo "${1%%$2*}"
}
function str_replace() {
IFS= read -r -d $'\0' str
echo "${str/$1/$2}"
}
function ldif() {
log "--------------------------------------------"
local action=$1 && shift
local file=${!#}
log "Loading [$file]..."
interpolate_vars < $file > /tmp/$(basename $file)
ldap$action -H ldapi:/// "${@:1:${#}-1}" -f /tmp/$(basename $file)
}
# interpolate variable placeholders in env vars starting with "LDAP_INIT_"
for name in ${!LDAP_INIT_*}; do
declare "${name}=$(echo "${!name}" | interpolate_vars)"
done
# pre-populate folders in case they are empty
for folder in "/var/lib/ldap" "/etc/ldap/slapd.d"; do
if [ "$folder" -ef "${folder}_orig" ]; then
continue
fi
if [ -z "$(ls $folder)" ]; then
log "Initializing [$folder]..."
cp -r --preserve=all ${folder}_orig/. $folder
fi
done
LDAP_INIT_ROOT_USER_PW_HASHED=$(slappasswd -s "${LDAP_INIT_ROOT_USER_PW}")
/etc/init.d/slapd start
sleep 3
if [ "${LDAP_INIT_RFC2307BIS_SCHEMA:-}" == "1" ]; then
log "Replacing NIS (RFC2307) schema with RFC2307bis schema..."
ldapdelete -Y EXTERNAL cn={2}nis,cn=schema,cn=config
ldif add -Y EXTERNAL /opt/ldifs/schema_rfc2307bis02.ldif
fi
ldif add -Y EXTERNAL /etc/ldap/schema/ppolicy.ldif
ldif add -Y EXTERNAL /opt/ldifs/schema_sudo.ldif
ldif add -Y EXTERNAL /opt/ldifs/schema_ldapPublicKey.ldif
ldif modify -Y EXTERNAL /opt/ldifs/init_frontend.ldif
ldif add -Y EXTERNAL /opt/ldifs/init_module_memberof.ldif
ldif modify -Y EXTERNAL /opt/ldifs/init_mdb.ldif
ldif modify -Y EXTERNAL /opt/ldifs/init_mdb_acls.ldif
ldif modify -Y EXTERNAL /opt/ldifs/init_mdb_indexes.ldif
ldif add -Y EXTERNAL /opt/ldifs/init_module_unique.ldif
ldif add -Y EXTERNAL /opt/ldifs/init_module_ppolicy.ldif
LDAP_INIT_ORG_DN_ATTR=$(substr_before $LDAP_INIT_ORG_DN "," | str_replace "=" ": ") # referenced by init_org_tree.ldif
ldif add -x -D "$LDAP_INIT_ROOT_USER_DN" -w "$LDAP_INIT_ROOT_USER_PW" /opt/ldifs/init_org_tree.ldif
ldif add -x -D "$LDAP_INIT_ROOT_USER_DN" -w "$LDAP_INIT_ROOT_USER_PW" /opt/ldifs/init_org_ppolicy.ldif
ldif add -x -D "$LDAP_INIT_ROOT_USER_DN" -w "$LDAP_INIT_ROOT_USER_PW" /opt/ldifs/init_org_entries.ldif
log "--------------------------------------------"
echo "1" > /etc/ldap/slapd.d/initialized
rm -f /tmp/*.ldif
log "Creating periodic LDAP backup at [$LDAP_BACKUP_FILE]..."
slapcat -n 1 -l $LDAP_BACKUP_FILE || true
/etc/init.d/slapd stop
sleep 3
fi
echo "$LDAP_PPOLICY_PQCHECKER_RULE" > /etc/ldap/pqchecker/pqparams.dat
#################################################################
# Configure LDAP backup task
#################################################################
if [ -n "${LDAP_BACKUP_TIME:-}" ]; then
log "--------------------------------------------"
log "Configuring LDAP backup task to run daily: time=[${LDAP_BACKUP_TIME}] file=[$LDAP_BACKUP_FILE]..."
function backup_ldap() {
while true; do
while [ "$(date +%H:%M)" != "${LDAP_BACKUP_TIME}" ]; do
sleep 10s
done
log "Creating periodic LDAP backup at [$LDAP_BACKUP_FILE]..."
slapcat -n 1 -l $LDAP_BACKUP_FILE || true
sleep 23h
done
}
backup_ldap &
fi
#################################################################
# Start LDAP service
#################################################################
log "--------------------------------------------"
log "Starting OpenLDAP: slapd..."
#required for propagating SIGTERM from docker to service process
#https://unix.stackexchange.com/questions/146756/forward-sigterm-to-child-in-bash/444676#444676
function trap_handler() {
local signal=$1
if [ -n "${service_process_pid:-}" ]; then
log "Sending [$signal] to PID [$service_process_pid] ..."
kill -s $signal $service_process_pid 2>/dev/null
else
log "Received [$signal] before service started."
sig_received_before_service_started=$signal
fi
}
trap 'trap_handler TERM' SIGTERM SIGINT SIGHUP # https://github.com/openldap/openldap/search?q=SIGTERM
trap 'trap_handler QUIT' SIGQUIT
trap 'trap_handler USR1' SIGUSR1 # https://github.com/openldap/openldap/search?q=SIGUSR1
trap 'trap_handler USR2' SIGUSR2 # https://github.com/openldap/openldap/search?q=SIGUSR2
/usr/sbin/slapd \
$(for logLevel in ${LDAP_LOG_LEVELS:-}; do echo -n "-d $logLevel "; done) \
-h "ldap:/// ldapi:///" \
-u openldap -g openldap \
-F /etc/ldap/slapd.d 2>&1 | log &
service_process_pid=$(jobs -p | tail -1)
log "OpenLDAP PID: $service_process_pid"
if [ -n "${sig_received_before_service_started:-}" ]; then
kill -s $sig_received_before_service_started $service_process_pid 2>/dev/null
fi
wait $service_process_pid
trap - TERM INT
wait $service_process_pid
exit_status=$?
exit $exit_status