357 lines
12 KiB
Bash
Executable File
357 lines
12 KiB
Bash
Executable File
#!/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
|
|
exec "$@"
|