startup.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. #!/bin/bash -e
  2. set -o pipefail
  3. # set -x (bash debug) if log level is trace
  4. # https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/log-helper
  5. log-helper level eq trace && set -x
  6. # Reduce maximum number of number of open file descriptors to 1024
  7. # otherwise slapd consumes two orders of magnitude more of RAM
  8. # see https://github.com/docker/docker/issues/8231
  9. ulimit -n 1024
  10. # fix file permissions
  11. chown -R openldap:openldap /var/lib/ldap
  12. chown -R openldap:openldap /etc/ldap
  13. chown -R openldap:openldap ${CONTAINER_SERVICE_DIR}/slapd
  14. FIRST_START_DONE="${CONTAINER_STATE_DIR}/slapd-first-start-done"
  15. WAS_STARTED_WITH_TLS="/etc/ldap/slapd.d/docker-openldap-was-started-with-tls"
  16. WAS_STARTED_WITH_REPLICATION="/etc/ldap/slapd.d/docker-openldap-was-started-with-replication"
  17. # CONTAINER_SERVICE_DIR and CONTAINER_STATE_DIR variables are set by
  18. # the baseimage run tool more info : https://github.com/osixia/docker-light-baseimage
  19. # container first start
  20. if [ ! -e "$FIRST_START_DONE" ]; then
  21. #
  22. # Helpers
  23. #
  24. function get_ldap_base_dn() {
  25. LDAP_BASE_DN=""
  26. IFS='.' read -ra LDAP_BASE_DN_TABLE <<< "$LDAP_DOMAIN"
  27. for i in "${LDAP_BASE_DN_TABLE[@]}"; do
  28. EXT="dc=$i,"
  29. LDAP_BASE_DN=$LDAP_BASE_DN$EXT
  30. done
  31. LDAP_BASE_DN=${LDAP_BASE_DN::-1}
  32. }
  33. function is_new_schema() {
  34. local COUNT=$(ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config cn | grep -c $1)
  35. if [ "$COUNT" -eq 0 ]; then
  36. echo 1
  37. else
  38. echo 0
  39. fi
  40. }
  41. function check_tls_files() {
  42. local CA_CRT=$1
  43. local LDAP_CRT=$2
  44. local LDAP_KEY=$3
  45. local DH_PARAM=$4
  46. # generate a certificate and key with cfssl tool if LDAP_CRT and LDAP_KEY files don't exists
  47. # https://github.com/osixia/docker-light-baseimage/blob/stable/image/service-available/.cfssl/assets/tool/cfssl-helper
  48. cfssl-helper ldap $LDAP_CRT $LDAP_KEY $CA_CRT
  49. # create DHParamFile if not found
  50. [ -f ${DH_PARAM} ] || openssl dhparam -out ${DH_PARAM} 2048
  51. chmod 600 ${DH_PARAM}
  52. # fix file permissions
  53. chown -R openldap:openldap ${CONTAINER_SERVICE_DIR}/slapd
  54. }
  55. #
  56. # Global variables
  57. #
  58. BOOTSTRAP=false
  59. #
  60. # database and config directory are empty
  61. # setup bootstrap config - Part 1
  62. #
  63. if [ -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
  64. BOOTSTRAP=true
  65. log-helper info "Database and config directory are empty"
  66. cat <<EOF | debconf-set-selections
  67. slapd slapd/internal/generated_adminpw password ${LDAP_ADMIN_PASSWORD}
  68. slapd slapd/internal/adminpw password ${LDAP_ADMIN_PASSWORD}
  69. slapd slapd/password2 password ${LDAP_ADMIN_PASSWORD}
  70. slapd slapd/password1 password ${LDAP_ADMIN_PASSWORD}
  71. slapd slapd/dump_database_destdir string /var/backups/slapd-VERSION
  72. slapd slapd/domain string ${LDAP_DOMAIN}
  73. slapd shared/organization string ${LDAP_ORGANISATION}
  74. slapd slapd/backend string HDB
  75. slapd slapd/purge_database boolean true
  76. slapd slapd/move_old_database boolean true
  77. slapd slapd/allow_ldap_v2 boolean false
  78. slapd slapd/no_configuration boolean false
  79. slapd slapd/dump_database select when needed
  80. EOF
  81. dpkg-reconfigure -f noninteractive slapd
  82. #
  83. # Error: the database directory (/var/lib/ldap) is empty but not the config directory (/etc/ldap/slapd.d)
  84. #
  85. elif [ -z "$(ls -A /var/lib/ldap)" ] && [ ! -z "$(ls -A /etc/ldap/slapd.d)" ]; then
  86. log-helper error "Error: the database directory (/var/lib/ldap) is empty but not the config directory (/etc/ldap/slapd.d)"
  87. exit 1
  88. #
  89. # Error: the config directory (/etc/ldap/slapd.d) is empty but not the database directory (/var/lib/ldap)
  90. #
  91. elif [ ! -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
  92. log-helper error "Error: the config directory (/etc/ldap/slapd.d) is empty but not the database directory (/var/lib/ldap)"
  93. exit 1
  94. #
  95. # An existing database and config are provided
  96. #
  97. else
  98. # if the config was bootstraped with TLS
  99. # to avoid error (#6) we check tls files
  100. if [ -e "$WAS_STARTED_WITH_TLS" ]; then
  101. source $WAS_STARTED_WITH_TLS
  102. check_tls_files $PREVIOUS_LDAP_TLS_CA_CRT_PATH $PREVIOUS_LDAP_TLS_CRT_PATH $PREVIOUS_LDAP_TLS_KEY_PATH $PREVIOUS_LDAP_TLS_DH_PARAM_PATH
  103. fi
  104. fi
  105. #
  106. # start OpenLDAP
  107. #
  108. # get previous hostname if OpenLDAP was started with replication
  109. # to avoid configuration pbs
  110. PREVIOUS_HOSTNAME_PARAM=""
  111. if [ -e "$WAS_STARTED_WITH_REPLICATION" ]; then
  112. source $WAS_STARTED_WITH_REPLICATION
  113. # if previous hostname != current hostname
  114. # set previous hostname to a loopback ip in /etc/hosts
  115. if [ "$PREVIOUS_HOSTNAME" != "$HOSTNAME" ]; then
  116. echo "127.0.0.2 $PREVIOUS_HOSTNAME" >> /etc/hosts
  117. PREVIOUS_HOSTNAME_PARAM="ldap://$PREVIOUS_HOSTNAME"
  118. fi
  119. fi
  120. # start OpenLDAP
  121. log-helper info "Start OpenLDAP..."
  122. slapd -h "ldap://$HOSTNAME $PREVIOUS_HOSTNAME_PARAM ldap://localhost ldapi:///" -u openldap -g openldap
  123. #
  124. # setup bootstrap config - Part 2
  125. #
  126. if $BOOTSTRAP; then
  127. log-helper info "Add bootstrap schemas..."
  128. # add ppolicy schema
  129. ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif 2>&1 | log-helper debug
  130. # convert schemas to ldif
  131. SCHEMAS=""
  132. for f in $(find ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/schema -name \*.schema -type f); do
  133. SCHEMAS="$SCHEMAS ${f}"
  134. done
  135. ${CONTAINER_SERVICE_DIR}/slapd/assets/schema-to-ldif.sh "$SCHEMAS"
  136. # add converted schemas
  137. for f in $(find ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/schema -name \*.ldif -type f); do
  138. log-helper debug "Processing file ${f}"
  139. # add schema if not already exists
  140. SCHEMA=$(basename "${f}" .ldif)
  141. ADD_SCHEMA=$(is_new_schema $SCHEMA)
  142. if [ "$ADD_SCHEMA" -eq 1 ]; then
  143. ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f $f 2>&1 | log-helper debug
  144. else
  145. log-helper info "schema ${f} already exists"
  146. fi
  147. done
  148. # set config password
  149. LDAP_CONFIG_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_CONFIG_PASSWORD)
  150. sed -i --follow-symlinks "s|{{ LDAP_CONFIG_PASSWORD_ENCRYPTED }}|${LDAP_CONFIG_PASSWORD_ENCRYPTED}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/01-config-password.ldif
  151. # adapt security config file
  152. get_ldap_base_dn
  153. sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/02-security.ldif
  154. # process config files (*.ldif) in bootstrap directory (do no process files in subdirectories)
  155. log-helper info "Add bootstrap ldif..."
  156. for f in $(find ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif -mindepth 1 -maxdepth 1 -type f -name \*.ldif | sort); do
  157. log-helper debug "Processing file ${f}"
  158. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f $f 2>&1 | log-helper debug || ldapmodify -h localhost -p 389 -D cn=admin,$LDAP_BASE_DN -w $LDAP_ADMIN_PASSWORD -f $f 2>&1 | log-helper debug
  159. done
  160. # read only user
  161. if [ "${LDAP_READONLY_USER,,}" == "true" ]; then
  162. log-helper info "Add read only user..."
  163. LDAP_READONLY_USER_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_READONLY_USER_PASSWORD)
  164. sed -i --follow-symlinks "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
  165. sed -i --follow-symlinks "s|{{ LDAP_READONLY_USER_PASSWORD_ENCRYPTED }}|${LDAP_READONLY_USER_PASSWORD_ENCRYPTED}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
  166. sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
  167. sed -i --follow-symlinks "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
  168. sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
  169. log-helper debug "Processing file ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif"
  170. ldapmodify -h localhost -p 389 -D cn=admin,$LDAP_BASE_DN -w $LDAP_ADMIN_PASSWORD -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif 2>&1 | log-helper debug
  171. log-helper debug "Processing file ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif"
  172. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif 2>&1 | log-helper debug
  173. fi
  174. fi
  175. #
  176. # TLS config
  177. #
  178. if [ "${LDAP_TLS,,}" == "true" ]; then
  179. log-helper info "Add TLS config..."
  180. LDAP_TLS_CA_CRT_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_CA_CRT_FILENAME"
  181. LDAP_TLS_CRT_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_CRT_FILENAME"
  182. LDAP_TLS_KEY_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_KEY_FILENAME"
  183. LDAP_TLS_DH_PARAM_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/dhparam.pem"
  184. check_tls_files $LDAP_TLS_CA_CRT_PATH $LDAP_TLS_CRT_PATH $LDAP_TLS_KEY_PATH $LDAP_TLS_DH_PARAM_PATH
  185. # adapt tls ldif
  186. sed -i --follow-symlinks "s|{{ LDAP_TLS_CA_CRT_PATH }}|${LDAP_TLS_CA_CRT_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
  187. sed -i --follow-symlinks "s|{{ LDAP_TLS_CRT_PATH }}|${LDAP_TLS_CRT_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
  188. sed -i --follow-symlinks "s|{{ LDAP_TLS_KEY_PATH }}|${LDAP_TLS_KEY_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
  189. sed -i --follow-symlinks "s|{{ LDAP_TLS_DH_PARAM_PATH }}|${LDAP_TLS_DH_PARAM_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
  190. sed -i --follow-symlinks "s|{{ LDAP_TLS_CIPHER_SUITE }}|${LDAP_TLS_CIPHER_SUITE}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
  191. sed -i --follow-symlinks "s|{{ LDAP_TLS_PROTOCOL_MIN }}|${LDAP_TLS_PROTOCOL_MIN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
  192. sed -i --follow-symlinks "s|{{ LDAP_TLS_VERIFY_CLIENT }}|${LDAP_TLS_VERIFY_CLIENT}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
  193. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif 2>&1 | log-helper debug
  194. [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
  195. touch $WAS_STARTED_WITH_TLS
  196. echo "export PREVIOUS_LDAP_TLS_CA_CRT_PATH=${LDAP_TLS_CA_CRT_PATH}" >> $WAS_STARTED_WITH_TLS
  197. echo "export PREVIOUS_LDAP_TLS_CRT_PATH=${LDAP_TLS_CRT_PATH}" >> $WAS_STARTED_WITH_TLS
  198. echo "export PREVIOUS_LDAP_TLS_KEY_PATH=${LDAP_TLS_KEY_PATH}" >> $WAS_STARTED_WITH_TLS
  199. echo "export PREVIOUS_LDAP_TLS_DH_PARAM_PATH=${LDAP_TLS_DH_PARAM_PATH}" >> $WAS_STARTED_WITH_TLS
  200. # ldap client config
  201. sed -i --follow-symlinks "s,TLS_CACERT.*,TLS_CACERT ${LDAP_TLS_CA_CRT_PATH},g" /etc/ldap/ldap.conf
  202. echo "TLS_REQCERT ${LDAP_TLS_VERIFY_CLIENT}" >> /etc/ldap/ldap.conf
  203. [[ -f "$HOME/.ldaprc" ]] && rm -f $HOME/.ldaprc
  204. touch $HOME/.ldaprc
  205. echo "TLS_CERT ${LDAP_TLS_CRT_PATH}" >> $HOME/.ldaprc
  206. echo "TLS_KEY ${LDAP_TLS_KEY_PATH}" >> $HOME/.ldaprc
  207. # enforce TLS
  208. if [ "${LDAP_TLS_ENFORCE,,}" == "true" ]; then
  209. log-helper info "Add enforce TLS..."
  210. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enforce-enable.ldif 2>&1 | log-helper debug
  211. # disable tls enforcing
  212. else
  213. log-helper info "Disable enforce TLS..."
  214. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enforce-disable.ldif 2>&1 | log-helper debug || true
  215. fi
  216. else
  217. log-helper info "Disable TLS config..."
  218. ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-disable.ldif 2>&1 | log-helper debug || true
  219. [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
  220. fi
  221. #
  222. # Replication config
  223. #
  224. function disableReplication() {
  225. ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-disable.ldif 2>&1 | log-helper debug || true
  226. [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
  227. }
  228. if [ "${LDAP_REPLICATION,,}" == "true" ]; then
  229. log-helper info "Add replication config..."
  230. disableReplication || true
  231. i=1
  232. for host in $(complex-bash-env iterate "${LDAP_REPLICATION_HOSTS}")
  233. do
  234. sed -i --follow-symlinks "s|{{ LDAP_REPLICATION_HOSTS }}|olcServerID: $i ${host}\n{{ LDAP_REPLICATION_HOSTS }}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  235. sed -i --follow-symlinks "s|{{ LDAP_REPLICATION_HOSTS_CONFIG_SYNC_REPL }}|olcSyncRepl: rid=00$i provider=${host} ${LDAP_REPLICATION_CONFIG_SYNCPROV}\n{{ LDAP_REPLICATION_HOSTS_CONFIG_SYNC_REPL }}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  236. sed -i --follow-symlinks "s|{{ LDAP_REPLICATION_HOSTS_HDB_SYNC_REPL }}|olcSyncRepl: rid=10$i provider=${host} ${LDAP_REPLICATION_HDB_SYNCPROV}\n{{ LDAP_REPLICATION_HOSTS_HDB_SYNC_REPL }}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  237. ((i++))
  238. done
  239. get_ldap_base_dn
  240. sed -i --follow-symlinks "s|\$LDAP_BASE_DN|$LDAP_BASE_DN|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  241. sed -i --follow-symlinks "s|\$LDAP_ADMIN_PASSWORD|$LDAP_ADMIN_PASSWORD|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  242. sed -i --follow-symlinks "s|\$LDAP_CONFIG_PASSWORD|$LDAP_CONFIG_PASSWORD|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  243. sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS }}/d" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  244. sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS_CONFIG_SYNC_REPL }}/d" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  245. sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS_HDB_SYNC_REPL }}/d" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
  246. ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif 2>&1 | log-helper debug || true
  247. [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
  248. touch $WAS_STARTED_WITH_REPLICATION
  249. echo "export PREVIOUS_HOSTNAME=${HOSTNAME}" >> $WAS_STARTED_WITH_REPLICATION
  250. else
  251. log-helper info "Disable replication config..."
  252. disableReplication || true
  253. fi
  254. #
  255. # stop OpenLDAP
  256. #
  257. log-helper info "Stop OpenLDAP..."
  258. SLAPD_PID=$(cat /run/slapd/slapd.pid)
  259. kill -15 $SLAPD_PID
  260. while [ -e /proc/$SLAPD_PID ]; do sleep 0.1; done # wait until slapd is terminated
  261. #
  262. # remove config files
  263. #
  264. if [ "${LDAP_REMOVE_CONFIG_AFTER_SETUP,,}" == "true" ]; then
  265. log-helper info "Remove config files..."
  266. rm -rf ${CONTAINER_SERVICE_DIR}/slapd/assets/config
  267. fi
  268. #
  269. # setup done :)
  270. #
  271. log-helper info "First start is done..."
  272. touch $FIRST_START_DONE
  273. fi
  274. exit 0