Compare commits

..

No commits in common. "main" and "provider2" have entirely different histories.

11 changed files with 393 additions and 587 deletions

30
.drone.yml Normal file
View File

@ -0,0 +1,30 @@
---
kind: pipeline
name: default
steps:
- name: build image only
image: plugins/docker
settings:
repo: eumau/openldap
auto_tag: true
dry_run: true
when:
ref:
- refs/pull/**
# event no anda (?)
# event:
# - pull_request
- name: build and publish image
image: plugins/docker
settings:
repo: eumau/openldap
auto_tag: true
username:
from_secret: dockerhub_username
password:
from_secret: dockerhub_password
when:
branch:
- master

View File

@ -1,39 +0,0 @@
name: Build Docker images
on:
push:
branches:
- main
workflow_dispatch:
jobs:
docker:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
repo:
- "eumau/openldap"
tag:
- "1"
- latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push image
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ matrix.repo }}:${{ matrix.tag }}
platforms: linux/amd64,linux/arm64

View File

@ -1,4 +1,4 @@
FROM eumau/debian:bookworm-slim FROM eumau/debian:buster-slim
# admin CN => dn: cn=%%ADMIN_CN%%,%%DOMAIN_DN%% # admin CN => dn: cn=%%ADMIN_CN%%,%%DOMAIN_DN%%
ENV LDAP_ADMIN_CN="admin" ENV LDAP_ADMIN_CN="admin"
@ -18,6 +18,12 @@ ENV LDAP_DOMAIN_INDEX="cn,uid eq\nmember,memberUid eq\nobjectClass eq\nuidNumber
ENV LDAP_DOMAIN_OUS="People Alias Group" ENV LDAP_DOMAIN_OUS="People Alias Group"
# enable memberOf module # enable memberOf module
ENV LDAP_MEMBEROF="true" ENV LDAP_MEMBEROF="true"
# enable replication provider
ENV LDAP_PROVIDER="false"
# replicator CN => dn: cn=%%REPLICATOR_CN%%,%%DOMAIN_DN%%
ENV LDAP_REPLICATOR_CN="replicator"
# replicator password
ENV LDAP_REPLICATOR_PASSWORD="${LDAP_ADMIN_PASSWORD}"
# space-separated list of schemas to load # space-separated list of schemas to load
ENV LDAP_SCHEMAS="core cosine inetorgperson misc nis" ENV LDAP_SCHEMAS="core cosine inetorgperson misc nis"
@ -28,14 +34,13 @@ RUN apt-get update \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
ADD setup /start.d
ADD confd /etc/confd/
ADD entrypoint.sh / ADD entrypoint.sh /
ADD ldap_backup ldap_restore /usr/local/sbin/
EXPOSE 389 EXPOSE 389
VOLUME ["/etc/ldap/schema", "/etc/ldap/slapd.d", "/var/lib/ldap", "/var/backups/ldap"] VOLUME ["/etc/ldap/schema", "/etc/ldap/slapd.d", "/var/lib/ldap", "/var/backups/ldap"]
ENTRYPOINT ["/entrypoint.sh"]
# log level info: # log level info:
CMD ["slapd", "-d", "32768", "-u", "openldap", "-g", "openldap"] CMD ["slapd", "-d", "32768", "-u", "openldap", "-g", "openldap"]

View File

@ -1,11 +0,0 @@
[template]
src = "add_ldap_group.tmpl"
prefix = "/ldap"
dest = "/usr/local/bin/add_ldap_group"
mode = "0755"
keys = [
"/admin/cn",
"/admin/password",
"/domain",
"/domain/dn",
]

View File

@ -1,11 +0,0 @@
[template]
src = "add_ldap_user.tmpl"
prefix = "/ldap"
dest = "/usr/local/bin/add_ldap_user"
mode = "0755"
keys = [
"/admin/cn",
"/admin/password",
"/domain",
"/domain/dn",
]

View File

@ -1,100 +0,0 @@
#!/bin/bash
assert(){ [[ $? -eq 0 ]] || { [[ -n ${1} ]] && echo ${@} ; exit 1 ; } }
usage() {
cat <<EOF
usage: docker exec [...] add_ldap_group [-c COMMON_NAME] [-u UID] [-p PASSWORD] [-e EMAIL]
Unset options will be prompted interactively.
EOF
}
COMMON_NAME=
USER_UID=
USER_EMAIL=
USER_PASS=
SURNAME=
while getopts "c: u: e: p:" OPCION
do
case ${OPCION} in
"c")
COMMON_NAME=${OPTARG}
;;
"s")
SURNAME=${OPTARG}
;;
"u")
USER_UID=${OPTARG}
;;
"e")
USER_EMAIL=${OPTARG}
;;
"p")
USER_PASS=${OPTARG}
;;
*)
usage
exit 2
;;
esac
done
LDAP_ADMIN_CN="{{ getv "/admin/cn" }}"
LDAP_ADMIN_PASSWORD="{{ getv "/admin/password" }}"
LDAP_DOMAIN="{{ getv "/domain" }}"
LDAP_DOMAIN_DN="{{ getv "/domain/dn" }}"
DN0="dc=${LDAP_DOMAIN//./,dc=}"
LDAP_DOMAIN_DN=${LDAP_DOMAIN_DN:=${DN0}}
[[ -n ${USER_UID} ]] || {
echo -n "Enter user UID (e.g. jdoe) > "
read USER_UID
}
# echo "Check if uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN} exists"
RES_DN=$(ldapsearch -LLL -H ldap:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base \
-b "uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN}" \
"(objectClass=*)" 2>/dev/null \
| egrep '^dn: ' | sed -e 's/^dn: //g' )
[[ -z ${RES_DN} ]]
assert "User already present. Please choose a different UID."
[[ -n ${COMMON_NAME} ]] || {
echo -n "Enter user CN (e.g. John Doe) > "
read COMMON_NAME
}
[[ -n ${SURNAME} ]] || {
echo -n "Enter user SN (e.g. Doe) > "
read SURNAME
}
[[ -n ${USER_PASS} ]] || {
echo -n "Enter user password (will not be echoed) > "
read -s USER_PASS
echo ""
}
[[ -n ${USER_EMAIL} ]] || {
echo -n "Enter user email (leave blank for ${USER_UID}@${LDAP_DOMAIN}) > "
read USER_EMAIL
}
USER_EMAIL="${USER_EMAIL:=${USER_UID}@${LDAP_DOMAIN}}"
PWHASH=$(slappasswd -h "{SSHA}" -s "${USER_PASS}")
echo "Creating user uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN}"
ldapadd -H ldap:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN}
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: ${COMMON_NAME}
sn: ${SURNAME}
uid: ${USER_UID}
userPassword: ${PWHASH}
mail: ${USER_EMAIL}
EOF
assert "Error adding user!"

View File

@ -1,100 +0,0 @@
#!/bin/bash
assert(){ [[ $? -eq 0 ]] || { [[ -n ${1} ]] && echo ${@} ; exit 1 ; } }
usage() {
cat <<EOF
usage: docker exec [...] add_ldap_user [-c COMMON_NAME] [-s SURNAME] [-u UID] [-p PASSWORD] [-e EMAIL]
Unset options will be prompted interactively.
EOF
}
COMMON_NAME=
USER_UID=
USER_EMAIL=
USER_PASS=
SURNAME=
while getopts "c: u: e: p:" OPCION
do
case ${OPCION} in
"c")
COMMON_NAME=${OPTARG}
;;
"s")
SURNAME=${OPTARG}
;;
"u")
USER_UID=${OPTARG}
;;
"e")
USER_EMAIL=${OPTARG}
;;
"p")
USER_PASS=${OPTARG}
;;
*)
usage
exit 2
;;
esac
done
LDAP_ADMIN_CN="{{ getv "/admin/cn" }}"
LDAP_ADMIN_PASSWORD="{{ getv "/admin/password" }}"
LDAP_DOMAIN="{{ getv "/domain" }}"
LDAP_DOMAIN_DN="{{ getv "/domain/dn" }}"
DN0="dc=${LDAP_DOMAIN//./,dc=}"
LDAP_DOMAIN_DN=${LDAP_DOMAIN_DN:=${DN0}}
[[ -n ${USER_UID} ]] || {
echo -n "Enter user UID (e.g. jdoe) > "
read USER_UID
}
# echo "Check if uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN} exists"
RES_DN=$(ldapsearch -LLL -H ldap:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base \
-b "uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN}" \
"(objectClass=*)" 2>/dev/null \
| egrep '^dn: ' | sed -e 's/^dn: //g' )
[[ -z ${RES_DN} ]]
assert "User already present. Please choose a different UID."
[[ -n ${COMMON_NAME} ]] || {
echo -n "Enter user CN (e.g. John Doe) > "
read COMMON_NAME
}
[[ -n ${SURNAME} ]] || {
echo -n "Enter user SN (e.g. Doe) > "
read SURNAME
}
[[ -n ${USER_PASS} ]] || {
echo -n "Enter user password (will not be echoed) > "
read -s USER_PASS
echo ""
}
[[ -n ${USER_EMAIL} ]] || {
echo -n "Enter user email (leave blank for ${USER_UID}@${LDAP_DOMAIN}) > "
read USER_EMAIL
}
USER_EMAIL="${USER_EMAIL:=${USER_UID}@${LDAP_DOMAIN}}"
PWHASH=$(slappasswd -h "{SSHA}" -s "${USER_PASS}")
echo "Creating user uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN}"
ldapadd -H ldap:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: uid=${USER_UID},ou=People,${LDAP_DOMAIN_DN}
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: ${COMMON_NAME}
sn: ${SURNAME}
uid: ${USER_UID}
userPassword: ${PWHASH}
mail: ${USER_EMAIL}
EOF
assert "Error adding user!"

View File

@ -1,6 +1,356 @@
#!/bin/bash #!/bin/bash
assert(){ [[ $? -eq 0 ]] || { [[ -n ${1} ]] && echo ${@} ; exit 1 ; } }
# from https://github.com/dinkel/docker-openldap/blob/master/entrypoint.sh:
# When not limiting the open file descritors limit, the memory consumption of
# slapd is absurdly high. See https://github.com/docker/docker/issues/8231
ulimit -n 8192
slapd -u openldap -g openldap -h ldapi:///
assert "FATAL: sldapd died unexpectedly!"
PIDFILE=$(ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b "cn=config" -s base \
"" olcPidFile | grep olcPidFile | awk "{print $2}")
echo "slapd running. pidfile = ${PIDFILE}"
[[ -n "${LDAP_DOMAIN}" ]]
assert "FATAL: Please set LDAP_DOMAIN and retry."
DN0="dc=${LDAP_DOMAIN//./,dc=}"
LDAP_DOMAIN_DN=${LDAP_DOMAIN_DN:=${DN0}}
echo "setting up domain = ${LDAP_DOMAIN}, dn = ${LDAP_DOMAIN_DN}"
[[ -n "${LDAP_CONFIG_PASSWORD}" ]]
assert "FATAL: Please set LDAP_CONFIG_PASSWORD and retry."
LDAP_CONFIG_PWHASH=$(slappasswd -h "{SSHA}" -s "${LDAP_CONFIG_PASSWORD}")
[[ -n "${LDAP_ADMIN_PASSWORD}" ]]
assert "FATAL: Please set LDAP_ADMIN_PASSWORD and retry."
LDAP_ADMIN_PWHASH=$(slappasswd -h "{SSHA}" -s "${LDAP_ADMIN_PASSWORD}")
# TODO: verify password before updating =======================================
echo "Setting cn=admin,cn=config password"
ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: ${LDAP_CONFIG_PWHASH}
EOF
assert "FATAL: error setting cn=admin,cn=config password"
# SCHEMAS ---------------------------------------------------------------------
eval "declare -A LOADED_SCHEMAS=( $(ldapsearch -LLL -Y EXTERNAL -H ldapi:/// \
-b "cn=schema,cn=config" -s one cn \
| sed -n 's/^cn:.*[{].*[}]\(.*\)$/[\1]=loaded/p') )"
echo "Loaded schemas: ${!LOADED_SCHEMAS[@]}"
# load schemas
# built-in: core, cosine, nis, inetorgperson
# available: collective, corba, duaconf, dyngroup, java, misc, nis, openldap, pmi, ppolicy
for schema in ${LDAP_SCHEMAS}
do
[[ -z "${LOADED_SCHEMAS[$schema]}" ]] || continue;
echo "Loading ${schema} schema"
[[ -f /etc/ldap/schema/${schema}.ldif ]]
assert "FATAL: schema file /etc/ldap/schema/${schema}.ldif not found!"
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/${schema}.ldif
assert "FATAL: error loading schema ${schema}!"
done
# END SCHEMAS -----------------------------------------------------------------
# MEMBEROF MODULE -------------------------------------------------------------
if ${LDAP_MEMBEROF}
then
echo "Enabling memberof module"
ldapmodify -Y EXTERNAL -H ldapi:/// <<-EOF
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: memberof
EOF
RES=$?
[[ $RES -eq 0 ]] || [[ $RES -eq 20 ]]
assert "FATAL: error loading memberof module (return status ${RES})"
unset RES
fi
# END MEMBEROF MODULE ---------------------------------------------------------
# REPLICATION PROVIDER --------------------------------------------------------
if ${LDAP_PROVIDER}
then
echo "Enabling syncprov module"
ldapmodify -Y EXTERNAL -H ldapi:/// <<-EOF
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: syncprov
EOF
RES=$?
[[ $RES -eq 0 ]] || [[ $RES -eq 20 ]]
assert "FATAL: error loading syncprov module (return status ${RES})"
echo "Enabling accesslog module"
ldapmodify -Y EXTERNAL -H ldapi:/// <<-EOF
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: accesslog
EOF
RES=$?
[[ $RES -eq 0 ]] || [[ $RES -eq 20 ]]
assert "FATAL: error loading accesslog module (return status ${RES})"
unset RES
if ldapsearch -LLL -H ldapi:/// -Y EXTERNAL -s one -b "cn=config" \
"(&(olcSuffix=\"cn=accesslog\")(olcDatabase=mdb))" | \
egrep -q '^dn: '
then
echo "Found cn=config entry for cn=accesslog"
else
echo "No cn=config entry for cn=accesslog."
echo "Creating directory /var/lib/ldap/cn=accesslog"
mkdir "/var/lib/ldap/cn=accesslog"
chown -R openldap:openldap "/var/lib/ldap/cn=accesslog"
echo "Creating cn=config entry for cn=accesslog"
ldapadd -Y EXTERNAL -H ldapi:/// <<-EOF
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcRootDN: cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}
olcRootPW: ${LDAP_ADMIN_PWHASH}
olcDbMaxSize: 8589934592
olcSuffix: cn=accesslog
olcDbDirectory: /var/lib/ldap/cn=accesslog
olcAccess: {0}to * by dn="cn=${LDAP_REPLICATOR_CN},${LDAP_DOMAIN_DN}" read
olcLimits: {0}to dn.exact="cn=${LDAP_REPLICATOR_CN},${LDAP_DOMAIN_DN}" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
olcLimits: {1}to dn.exact="cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
EOF
fi
if ldapsearch -LLL -H ldapi:/// -Y EXTERNAL -s one -b "cn=config" \
"(&(olcSuffix=\"cn=accesslog\")(olcDatabase=mdb))" | \
egrep -q '^dn: '
then
echo "Found cn=config entry for cn=accesslog"
else
echo "No cn=config entry for cn=accesslog."
echo "Creating directory /var/lib/ldap/cn=accesslog"
mkdir "/var/lib/ldap/cn=accesslog"
chown -R openldap:openldap "/var/lib/ldap/cn=accesslog"
echo "Creating cn=config entry for cn=accesslog"
ldapadd -Y EXTERNAL -H ldapi:/// <<-EOF
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcRootDN: cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}
olcRootPW: ${LDAP_ADMIN_PWHASH}
olcDbMaxSize: 8589934592
olcSuffix: cn=accesslog
olcDbDirectory: /var/lib/ldap/cn=accesslog
olcAccess: {0}to * by dn="cn=${LDAP_REPLICATOR_CN},${LDAP_DOMAIN_DN}" read
olcLimits: {0}to dn.exact="cn=${LDAP_REPLICATOR_CN},${LDAP_DOMAIN_DN}" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
olcLimits: {1}to dn.exact="cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
EOF
fi
echo "Get DN of cn=config entry for cn=accesslog"
CN_CONFIG_DN=$(ldapsearch -LLL -H ldapi:/// -Y EXTERNAL -s one -b cn=config \
"(&(olcSuffix=cn=accesslog)(olcDatabase=mdb))" \
| egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${CN_CONFIG_DN} ]]
then echo "Found DN = ${CN_CONFIG_DN}"
else
echo "FATAL: could not find cn=config entry for cn=accesslog"
echo "PLEASE NOTE: only MDB database format is supported (PR welcome :)"
exit 1
fi
# TODO: olcOverlay=syncprov ===============================================
# TODO: replication users (on domain setup?) ==============================
fi
# END REPLICATION PROVIDER ----------------------------------------------------
# DOMAIN SETUP ----------------------------------------------------------------
if ldapsearch -LLL -H ldapi:/// -Y EXTERNAL -s one -b "cn=config" \
"(&(olcSuffix=\"${LDAP_DOMAIN_DN}\")(olcDatabase=mdb))" | \
egrep -q '^dn: '
then
echo "Found cn=config entry for ${LDAP_DOMAIN_DN}"
else
echo "No cn=config entry for ${LDAP_DOMAIN_DN}."
echo "Creating directory /var/lib/ldap/${LDAP_DOMAIN_DN}"
mkdir "/var/lib/ldap/${LDAP_DOMAIN_DN}"
chown -R openldap:openldap "/var/lib/ldap/${LDAP_DOMAIN_DN}"
echo "Creating cn=config entry for ${LDAP_DOMAIN_DN}"
ldapadd -Y EXTERNAL -H ldapi:/// <<-EOF
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDbMaxSize: 1073741824
olcSuffix: ${LDAP_DOMAIN_DN}
olcDbDirectory: /var/lib/ldap/${LDAP_DOMAIN_DN}
olcRootDN: cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}
olcRootPW: ${LDAP_ADMIN_PWHASH}
$(echo -ne "${LDAP_DOMAIN_ACCESS}" | sed -e 's/^/olcAccess: /g')
olcDbCheckpoint: 512 30
olcLastMod: TRUE
$(echo -ne "${LDAP_DOMAIN_INDEX}" | sed -e 's/^/olcDbIndex: /g')
$(echo -ne "${LDAP_DOMAIN_LIMITS}" | sed -e 's/^/olcLimits: /g')
EOF
fi
echo "Get cn=config entry for ${LDAP_DOMAIN_DN}"
CN_CONFIG_DN=$(ldapsearch -LLL -H ldapi:/// -Y EXTERNAL -s one -b "cn=config" \
"(&(olcSuffix=${LDAP_DOMAIN_DN})(olcDatabase=mdb))" \
| egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${CN_CONFIG_DN} ]]
then echo "Found DN = ${CN_CONFIG_DN}"
else
echo "FATAL: could not find cn=config entry for ${LDAP_DOMAIN_DN}"
echo "PLEASE NOTE: only MDB database format is supported (PR welcome :)"
exit 1
fi
# TODO: verify admin password before updating =================================
echo "Setting domain administrator password"
ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
dn: ${CN_CONFIG_DN}
changetype: modify
replace: olcRootPW
olcRootPW: ${LDAP_ADMIN_PWHASH}
EOF
assert "FATAL: could not set administrator password!"
# END DOMAIN SETUP ------------------------------------------------------------
# MEMBEROF OVERLAY ------------------------------------------------------------
if [[ ${LDAP_MEMBEROF} ]]
then
echo "Check if memberOf overlay is enabled"
MEMBEROF_DN=$(ldapsearch -LLL -H ldapi:/// -Y EXTERNAL -s one -b \
"${CN_CONFIG_DN}" "(olcOverlay=memberOf)" | \
egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${MEMBEROF_DN} ]]
then echo "memberOf overlay already enabled for ${CN_CONFIG_DN}"
else
echo "Enabling memberOf overlay"
ldapadd -Y EXTERNAL -H ldapi:/// <<-EOF
dn: olcOverlay=memberof,${CN_CONFIG_DN}
objectClass: olcOverlayConfig
objectClass: olcConfig
objectClass: olcMemberOf
olcMemberOfDangling: ignore
olcMemberOfRefInt: FALSE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf
EOF
fi
fi
# END MEMBEROF OVERLAY --------------------------------------------------------
# DIT ENTRIES -----------------------------------------------------------------
echo "Check if ${LDAP_DOMAIN_DN} exists"
DOM_DN=$(ldapsearch -LLL -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base -b "${LDAP_DOMAIN_DN}" \
"(objectClass=*)" | egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${DOM_DN} ]]
then echo "${LDAP_DOMAIN_DN} already present"
else
echo "Creating ${LDAP_DOMAIN_DN}"
ldapadd -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: ${LDAP_DOMAIN_DN}
objectClass: dcObject
objectClass: organization
objectClass: top
dc: $(echo -n "${LDAP_DOMAIN_DN#dc=}" | sed 's/,.*$//g')
o: ${LDAP_DOMAIN}
EOF
fi
# Admin user
echo "Check if cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} exists"
ADM_DN=$(ldapsearch -LLL -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base -b \
"cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}" "(objectClass=*)" \
| egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${ADM_DN} ]]
then echo "cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} already present"
else
echo "Creating cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}"
ldapadd -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}
objectClass: organizationalRole
objectClass: simpleSecurityObject
cn: ${LDAP_ADMIN_CN}
description: LDAP Administrator role for domain ${LDAP_DOMAIN}
userPassword: ${ADMIN_PW_HASH}
EOF
fi
# TODO: update admin password =================================================
# create OUs
for OU in ${LDAP_DOMAIN_OUS}
do
echo "Check if ou=${OU},${LDAP_DOMAIN_DN} exists"
OU_DN=$(ldapsearch -LLL -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base \
-b "ou=${OU},${LDAP_DOMAIN_DN}" "(objectClass=*)" \
| egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${OU_DN} ]]
then echo "ou=${OU} already present in ${LDAP_DOMAIN_DN}"
else
echo "Creating ou=${OU},${LDAP_DOMAIN_DN}"
ldapadd -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: ou=${OU},${LDAP_DOMAIN_DN}
objectClass: organizationalUnit
objectClass: top
ou: ${OU}
EOF
fi
done
# -------------------------------------------
# kill slapd after initial setup
echo "Killing initial server"
kill -INT $(cat ${PIDFILE})
# unset sensitive variables
unset LDAP_ADMIN_PASSWORD LDAP_CONFIG_PASSWORD LDAP_ADMIN_PWHASH \
LDAP_CONFIG_PWHASH LOADED_SCHEMAS PIDFILE
# run Dockerfile CMD
echo "Running CMD $@"
set -e set -e
/usr/local/bin/confd -onetime -backend env exec "$@"
run-parts -v /start.d
ulimit -n 1024
exec ${@}

View File

@ -1,15 +0,0 @@
#!/bin/bash
assert(){ [[ $? -eq 0 ]] || { [[ -n ${1} ]] && echo ${@} ; exit 1 ; } }
[[ -n "${LDAP_CONFIG_PASSWORD}" ]]
assert "FATAL: Please set LDAP_CONFIG_PASSWORD and retry."
# Count databases
DB_COUNT=$(ldapsearch -D cn=admin,cn=config -w "${LDAP_CONFIG_PASSWORD}" -b cn=config -LLL "(olcDatabase=mdb)" dn | tr -s '\n' | wc -l)
# Perform backup
for i in $(seq 0 ${DB_COUNT})
do slapcat -n ${i} -l /var/backups/ldap/${i}.ldif
done
echo "Backed up ${DB_COUNT} databases in /var/backups/ldap."

View File

@ -1,53 +0,0 @@
#!/bin/bash
assert(){ [[ $? -eq 0 ]] || { [[ -n ${1} ]] && echo ${@} ; exit 1 ; } }
[[ -f /var/backups/ldap/0.ldif ]]
assert "Unable to restore backup. Missing /var/backups/ldap/0.ldif backup of cn=config."
[[ -f /var/backups/ldap/1.ldif ]]
assert "Unable to restore backup. Missing /var/backups/ldap/1.ldif backup of first database."
[[ -n "${LDAP_DOMAIN}" ]]
assert "FATAL: Please set LDAP_DOMAIN and retry."
DN0="dc=${LDAP_DOMAIN//./,dc=}"
LDAP_DOMAIN_DN=${LDAP_DOMAIN_DN:=${DN0}}
# Backup and clean existing config directory
tar czf /var/backups/ldap/etc_ldap_slapd_d-$(date '+%Y-%m-%d').tar.gz /etc/ldap/slapd.d
assert "FATAL: could not backup /etc/ldap/slapd.d before restoring."
find /etc/ldap/slapd.d -mindepth 1 -delete
assert "FATAL: could not clean /etc/ldap/slapd.d before restoring."
# Backup and clean existing data directory
tar czf /var/backups/ldap/var_lib_ldap-$(date '+%Y-%m-%d').tar.gz /var/lib/ldap
assert "FATAL: could not backup /var/lib/ldap before restoring."
find /var/lib/ldap -mindepth 1 -delete
assert "FATAL: could not clean /var/lib/ldap before restoring."
mkdir "/var/lib/ldap/${LDAP_DOMAIN_DN}"
assert "FATAL: could not create /var/lib/ldap/${LDAP_DOMAIN_DN}."
# Restore cn=config
echo "Restoring cn=config..."
slapadd -n 0 -F /etc/ldap/slapd.d -l /var/backups/ldap/0.ldif
assert "FATAL: error restoring cn=config using slapadd."
chown -R openldap:openldap /etc/ldap/slapd.d
assert "FATAL: could not fix /etc/ldap/slapd.d permissions."
for LDIF in /var/backups/ldap/*.ldif
do
# Check if it's cn=config backup
if [[ "${LDIF}" == "/var/backups/ldap/0.ldif" ]]
then continue
else
INDEX=$(basename "${LDIF}" | sed 's/.ldif$//g')
[[ "${INDEX}" =~ ^[0-9]+$ ]]
assert "FATAL: could not determine the DB index for ${LDIF}."
echo "Restoring database ${INDEX}..."
slapadd -n ${INDEX} -F /etc/ldap/slapd.d -l "${LDIF}"
assert "FATAL: error restoring database ${INDEX} using slapadd."
fi
done
chown -R openldap:openldap /var/lib/ldap
assert "FATAL: could not fix /var/lib/ldap permissions."

250
setup
View File

@ -1,250 +0,0 @@
#!/bin/bash
assert(){ [[ $? -eq 0 ]] || { [[ -n ${1} ]] && echo ${@} ; exit 1 ; } }
# from https://github.com/dinkel/docker-openldap/blob/master/entrypoint.sh:
# When not limiting the open file descritors limit, the memory consumption of
# slapd is absurdly high. See https://github.com/docker/docker/issues/8231
ulimit -n 1024
chown -R openldap:openldap /var/lib/ldap
assert "FATAL: could not set required directory permissions"
slapd -u openldap -g openldap -h ldapi:///
assert "FATAL: sldapd died unexpectedly!"
PIDFILE=$(ldapsearch -LLL -QY EXTERNAL -H ldapi:/// -b "cn=config" -s base \
olcPidFile | grep olcPidFile | awk '{print $2}')
echo "slapd running. pidfile = ${PIDFILE}"
[[ -n "${LDAP_DOMAIN}" ]]
assert "FATAL: Please set LDAP_DOMAIN and retry."
DN0="dc=${LDAP_DOMAIN//./,dc=}"
LDAP_DOMAIN_DN=${LDAP_DOMAIN_DN:=${DN0}}
echo "setting up domain = ${LDAP_DOMAIN}, dn = ${LDAP_DOMAIN_DN}"
[[ -n "${LDAP_CONFIG_PASSWORD}" ]]
assert "FATAL: Please set LDAP_CONFIG_PASSWORD and retry."
LDAP_CONFIG_PWHASH=$(slappasswd -h "{SSHA}" -s "${LDAP_CONFIG_PASSWORD}")
[[ -n "${LDAP_ADMIN_PASSWORD}" ]]
assert "FATAL: Please set LDAP_ADMIN_PASSWORD and retry."
LDAP_ADMIN_PWHASH=$(slappasswd -h "{SSHA}" -s "${LDAP_ADMIN_PASSWORD}")
# TODO: verify password before updating =======================================
echo "Setting cn=admin,cn=config password"
ldapmodify -QY EXTERNAL -H ldapi:/// <<EOF
dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: ${LDAP_CONFIG_PWHASH}
EOF
assert "FATAL: error setting cn=admin,cn=config password"
# SCHEMAS ---------------------------------------------------------------------
eval "declare -A LOADED_SCHEMAS=( $(ldapsearch -QLLL -Y EXTERNAL -H ldapi:/// \
-b "cn=schema,cn=config" -s one cn \
| sed -n 's/^cn:.*[{].*[}]\(.*\)$/[\1]=loaded/p') )"
echo "Loaded schemas: ${!LOADED_SCHEMAS[@]}"
# load schemas
# built-in: core, cosine, nis, inetorgperson
# available: collective, corba, duaconf, dyngroup, java, misc, nis, openldap, pmi, ppolicy
for schema in ${LDAP_SCHEMAS}
do
[[ -z "${LOADED_SCHEMAS[$schema]}" ]] || continue;
echo "Loading ${schema} schema"
[[ -f /etc/ldap/schema/${schema}.ldif ]]
assert "FATAL: schema file /etc/ldap/schema/${schema}.ldif not found!"
ldapadd -QY EXTERNAL -H ldapi:/// -f /etc/ldap/schema/${schema}.ldif
assert "FATAL: error loading schema ${schema}!"
done
# END SCHEMAS -----------------------------------------------------------------
# MEMBEROF MODULE -------------------------------------------------------------
if ${LDAP_MEMBEROF}
then
echo "Enabling memberof module"
ldapmodify -QY EXTERNAL -H ldapi:/// <<-EOF
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: memberof
EOF
RES=$?
[[ $RES -eq 0 ]] || [[ $RES -eq 20 ]]
assert "FATAL: error loading memberof module (return status ${RES})"
unset RES
fi
# END MEMBEROF MODULE ---------------------------------------------------------
# DOMAIN SETUP ----------------------------------------------------------------
if ldapsearch -LLL -H ldapi:/// -QY EXTERNAL -s one -b "cn=config" \
"(&(olcSuffix=\"${LDAP_DOMAIN_DN}\")(olcDatabase=mdb))" | \
egrep -q '^dn: '
then
echo "Found cn=config entry for ${LDAP_DOMAIN_DN}"
else
echo "No cn=config entry for ${LDAP_DOMAIN_DN}."
echo "Creating directory /var/lib/ldap/${LDAP_DOMAIN_DN}"
mkdir "/var/lib/ldap/${LDAP_DOMAIN_DN}"
chown -R openldap:openldap "/var/lib/ldap/${LDAP_DOMAIN_DN}"
echo "Creating cn=config entry for ${LDAP_DOMAIN_DN}"
ldapadd -QY EXTERNAL -H ldapi:/// <<-EOF
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDbMaxSize: 1073741824
olcSuffix: ${LDAP_DOMAIN_DN}
olcDbDirectory: /var/lib/ldap/${LDAP_DOMAIN_DN}
olcRootDN: cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}
olcRootPW: ${LDAP_ADMIN_PWHASH}
$(echo -ne "${LDAP_DOMAIN_ACCESS}" | sed -e 's/^/olcAccess: /g')
olcDbCheckpoint: 512 30
olcLastMod: TRUE
$(echo -ne "${LDAP_DOMAIN_INDEX}" | sed -e 's/^/olcDbIndex: /g')
$(echo -ne "${LDAP_DOMAIN_LIMITS}" | sed -e 's/^/olcLimits: /g')
EOF
fi
echo "Get cn=config entry for ${LDAP_DOMAIN_DN}"
CN_CONFIG_DN=$(ldapsearch -LLL -H ldapi:/// -QY EXTERNAL -s one -b "cn=config" \
"(&(olcSuffix=${LDAP_DOMAIN_DN})(olcDatabase=mdb))" \
| egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${CN_CONFIG_DN} ]]
then echo "Found DN = ${CN_CONFIG_DN}"
else
echo "FATAL: could not find cn=config entry for ${LDAP_DOMAIN_DN}"
echo "PLEASE NOTE: only MDB database format is supported (PR welcome :)"
exit 1
fi
# TODO: verify admin password before updating =================================
echo "Setting domain administrator password"
ldapmodify -QY EXTERNAL -H ldapi:/// <<EOF
dn: ${CN_CONFIG_DN}
changetype: modify
replace: olcRootPW
olcRootPW: ${LDAP_ADMIN_PWHASH}
EOF
assert "FATAL: could not set administrator password!"
# END DOMAIN SETUP ------------------------------------------------------------
# MEMBEROF OVERLAY ------------------------------------------------------------
if [[ ${LDAP_MEMBEROF} ]]
then
echo "Check if memberOf overlay is enabled"
MEMBEROF_DN=$(ldapsearch -LLL -H ldapi:/// -QY EXTERNAL -s one -b \
"${CN_CONFIG_DN}" "(olcOverlay=memberOf)" | \
egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${MEMBEROF_DN} ]]
then echo "memberOf overlay already enabled for ${CN_CONFIG_DN}"
else
echo "Enabling memberOf overlay"
ldapadd -QY EXTERNAL -H ldapi:/// <<-EOF
dn: olcOverlay=memberof,${CN_CONFIG_DN}
objectClass: olcOverlayConfig
objectClass: olcConfig
objectClass: olcMemberOf
olcMemberOfDangling: ignore
olcMemberOfRefInt: FALSE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf
EOF
fi
fi
# END MEMBEROF OVERLAY --------------------------------------------------------
# DIT ENTRIES -----------------------------------------------------------------
echo "Check if ${LDAP_DOMAIN_DN} exists"
DOM_DN=$(ldapsearch -LLL -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base -b "${LDAP_DOMAIN_DN}" \
"(objectClass=*)" | egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${DOM_DN} ]]
then echo "${LDAP_DOMAIN_DN} already present"
else
echo "Creating ${LDAP_DOMAIN_DN}"
ldapadd -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: ${LDAP_DOMAIN_DN}
objectClass: dcObject
objectClass: organization
objectClass: top
dc: $(echo -n "${LDAP_DOMAIN_DN#dc=}" | sed 's/,.*$//g')
o: ${LDAP_DOMAIN}
EOF
fi
# Admin user
echo "Check if cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} exists"
ADM_DN=$(ldapsearch -LLL -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base -b \
"cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}" "(objectClass=*)" \
| egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${ADM_DN} ]]
then echo "cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} already present"
else
echo "Creating cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}"
ldapadd -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN}
objectClass: organizationalRole
objectClass: simpleSecurityObject
cn: ${LDAP_ADMIN_CN}
description: LDAP Administrator role for domain ${LDAP_DOMAIN}
userPassword: ${ADMIN_PW_HASH}
EOF
fi
# TODO: update admin password =================================================
# create OUs
for OU in ${LDAP_DOMAIN_OUS}
do
echo "Check if ou=${OU},${LDAP_DOMAIN_DN} exists"
OU_DN=$(ldapsearch -LLL -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" -s base \
-b "ou=${OU},${LDAP_DOMAIN_DN}" "(objectClass=*)" \
| egrep '^dn: ' | sed -e 's/^dn: //g')
if [[ -n ${OU_DN} ]]
then echo "ou=${OU} already present in ${LDAP_DOMAIN_DN}"
else
echo "Creating ou=${OU},${LDAP_DOMAIN_DN}"
ldapadd -H ldapi:/// -D cn=${LDAP_ADMIN_CN},${LDAP_DOMAIN_DN} \
-w "${LDAP_ADMIN_PASSWORD}" <<-EOF
dn: ou=${OU},${LDAP_DOMAIN_DN}
objectClass: organizationalUnit
objectClass: top
ou: ${OU}
EOF
fi
done
# -------------------------------------------
# kill slapd after initial setup
echo "Killing initial server"
kill -INT $(cat ${PIDFILE})
# unset sensitive variables
unset LDAP_ADMIN_PASSWORD LDAP_CONFIG_PASSWORD LDAP_ADMIN_PWHASH \
LDAP_CONFIG_PWHASH LOADED_SCHEMAS PIDFILE