container-start.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #!/bin/bash -e
  2. FIRST_START_DONE="/etc/docker-openldap-first-start-done"
  3. WAS_STARTED_WITH_TLS="/etc/ldap/slapd.d/docker-openldap-was-started-with-tls"
  4. WAS_STARTED_WITH_REPLICATION="/etc/ldap/slapd.d/docker-openldap-was-started-with-replication"
  5. # Reduce maximum number of number of open file descriptors to 1024
  6. # otherwise slapd consumes two orders of magnitude more of RAM
  7. # see https://github.com/docker/docker/issues/8231
  8. ulimit -n 1024
  9. # fix file permissions
  10. chown -R openldap:openldap /var/lib/ldap
  11. chown -R openldap:openldap /etc/ldap
  12. chown -R openldap:openldap /container/service/slapd
  13. # container first start
  14. if [ ! -e "$FIRST_START_DONE" ]; then
  15. function get_ldap_base_dn() {
  16. LDAP_BASE_DN=""
  17. IFS='.' read -ra LDAP_BASE_DN_TABLE <<< "$LDAP_DOMAIN"
  18. for i in "${LDAP_BASE_DN_TABLE[@]}"; do
  19. EXT="dc=$i,"
  20. LDAP_BASE_DN=$LDAP_BASE_DN$EXT
  21. done
  22. LDAP_BASE_DN=${LDAP_BASE_DN::-1}
  23. }
  24. function is_new_schema() {
  25. local COUNT=$(ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config cn | grep -c $1)
  26. if [ "$COUNT" -eq 0 ]; then
  27. echo 1
  28. else
  29. echo 0
  30. fi
  31. }
  32. function check_tls_files() {
  33. local CA_CRT=$1
  34. local LDAP_CRT=$2
  35. local LDAP_KEY=$3
  36. # check certificat and key or create it
  37. /sbin/ssl-helper "/container/service/slapd/assets/certs/$LDAP_CRT" "/container/service/slapd/assets/certs/$LDAP_KEY" --ca-crt=/container/service/slapd/assets/certs/$CA_CRT --gnutls
  38. # create DHParamFile if not found
  39. [ -f /container/service/slapd/assets/certs/dhparam.pem ] || certtool --generate-dh-param --sec-param=high --outfile=/container/service/slapd/assets/certs/dhparam.pem
  40. chmod 600 /container/service/slapd/assets/certs/dhparam.pem
  41. # fix file permissions
  42. chown -R openldap:openldap /container/service/slapd
  43. }
  44. BOOTSTRAP=false
  45. # database and config directory are empty -> set bootstrap config
  46. if [ -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
  47. BOOTSTRAP=true
  48. echo "database and config directory are empty"
  49. echo "-> set bootstrap config"
  50. cat <<EOF | debconf-set-selections
  51. slapd slapd/internal/generated_adminpw password ${LDAP_ADMIN_PASSWORD}
  52. slapd slapd/internal/adminpw password ${LDAP_ADMIN_PASSWORD}
  53. slapd slapd/password2 password ${LDAP_ADMIN_PASSWORD}
  54. slapd slapd/password1 password ${LDAP_ADMIN_PASSWORD}
  55. slapd slapd/dump_database_destdir string /var/backups/slapd-VERSION
  56. slapd slapd/domain string ${LDAP_DOMAIN}
  57. slapd shared/organization string ${LDAP_ORGANISATION}
  58. slapd slapd/backend string HDB
  59. slapd slapd/purge_database boolean true
  60. slapd slapd/move_old_database boolean true
  61. slapd slapd/allow_ldap_v2 boolean false
  62. slapd slapd/no_configuration boolean false
  63. slapd slapd/dump_database select when needed
  64. EOF
  65. dpkg-reconfigure -f noninteractive slapd
  66. elif [ -z "$(ls -A /var/lib/ldap)" ] && [ ! -z "$(ls -A /etc/ldap/slapd.d)" ]; then
  67. echo "Error: the database directory (/var/lib/ldap) is empty but not the config directory (/etc/ldap/slapd.d)"
  68. exit 1
  69. elif [ ! -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
  70. echo "the config directory (/etc/ldap/slapd.d) is empty but not the database directory (/var/lib/ldap)"
  71. exit 1
  72. else
  73. # there is an existing database and config
  74. # if the config was bootstraped with TLS
  75. # to avoid error (#6) we check tls files
  76. if [ -e "$WAS_STARTED_WITH_TLS" ]; then
  77. . $WAS_STARTED_WITH_TLS
  78. check_tls_files $PREVIOUS_LDAP_TLS_CA_CRT_FILENAME $PREVIOUS_LDAP_TLS_CRT_FILENAME $PREVIOUS_LDAP_TLS_KEY_FILENAME
  79. fi
  80. fi
  81. # start OpenLDAP
  82. echo "Starting openldap..."
  83. # start OpenLDAP with previous replication configuration
  84. if [ -e "$WAS_STARTED_WITH_REPLICATION" ]; then
  85. . $WAS_STARTED_WITH_REPLICATION
  86. echo "127.0.0.2 $PREVIOUS_HOSTNAME" >> /etc/hosts
  87. slapd -h "ldap://$HOSTNAME ldap://$PREVIOUS_HOSTNAME ldap://localhost ldapi:///" -u openldap -g openldap
  88. else
  89. #start openldap normaly
  90. slapd -h "ldap://$HOSTNAME ldap://localhost ldapi:///" -u openldap -g openldap
  91. fi
  92. echo "[ok]"
  93. # set bootstrap config part 2
  94. if $BOOTSTRAP; then
  95. # add ppolicy schema
  96. ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif
  97. # convert schemas to ldif
  98. SCHEMAS=""
  99. for f in $(find /container/service/slapd/assets/config/bootstrap/schema -name \*.schema -type f); do
  100. SCHEMAS="$SCHEMAS ${f}"
  101. done
  102. /container/service/slapd/assets/schema-to-ldif.sh "$SCHEMAS"
  103. # add schemas
  104. for f in $(find /container/service/slapd/assets/config/bootstrap/schema -name \*.ldif -type f); do
  105. echo "Processing file ${f}"
  106. # add schema if not already exists
  107. SCHEMA=$(basename "${f}" .ldif)
  108. ADD_SCHEMA=$(is_new_schema $SCHEMA)
  109. if [ "$ADD_SCHEMA" -eq 1 ]; then
  110. echo "add schema ${SCHEMA}"
  111. ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f $f
  112. else
  113. echo "schema ${f} already exists"
  114. fi
  115. done
  116. # set config password
  117. LDAP_CONFIG_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_CONFIG_PASSWORD)
  118. sed -i "s|{{ LDAP_CONFIG_PASSWORD_ENCRYPTED }}|${LDAP_CONFIG_PASSWORD_ENCRYPTED}|g" /container/service/slapd/assets/config/bootstrap/ldif/01-config-password.ldif
  119. # adapt security config file
  120. get_ldap_base_dn
  121. sed -i "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" /container/service/slapd/assets/config/bootstrap/ldif/02-security.ldif
  122. # process config files in bootstrap directory (do no process files in subdirectories)
  123. for f in $(find /container/service/slapd/assets/config/bootstrap/ldif -name \*.ldif -mindepth 1 -maxdepth 1 -type f | sort); do
  124. echo "Processing file ${f}"
  125. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f $f
  126. done
  127. # read only user
  128. if [ "${LDAP_READONLY_USER,,}" == "true" ]; then
  129. echo "Add read only user"
  130. LDAP_READONLY_USER_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_READONLY_USER_PASSWORD)
  131. sed -i "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
  132. sed -i "s|{{ LDAP_READONLY_USER_PASSWORD_ENCRYPTED }}|${LDAP_READONLY_USER_PASSWORD_ENCRYPTED}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
  133. sed -i "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
  134. sed -i "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
  135. sed -i "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
  136. echo "Processing file /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif"
  137. ldapmodify -h localhost -p 389 -D cn=admin,$LDAP_BASE_DN -w $LDAP_ADMIN_PASSWORD -f /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
  138. echo "Processing file /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif"
  139. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
  140. fi
  141. fi
  142. # tls config
  143. if [ "${LDAP_TLS,,}" == "true" ]; then
  144. echo "Use TLS"
  145. check_tls_files $LDAP_TLS_CA_CRT_FILENAME $LDAP_TLS_CRT_FILENAME $LDAP_TLS_KEY_FILENAME
  146. # adapt tls ldif
  147. sed -i "s|{{ LDAP_TLS_CA_CRT_FILENAME }}|${LDAP_TLS_CA_CRT_FILENAME}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
  148. sed -i "s|{{ LDAP_TLS_CRT_FILENAME }}|${LDAP_TLS_CRT_FILENAME}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
  149. sed -i "s|{{ LDAP_TLS_KEY_FILENAME }}|${LDAP_TLS_KEY_FILENAME}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
  150. sed -i "s|{{ LDAP_TLS_CIPHER_SUITE }}|${LDAP_TLS_CIPHER_SUITE}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
  151. sed -i "s|{{ LDAP_TLS_PROTOCOL_MIN }}|${LDAP_TLS_PROTOCOL_MIN}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
  152. sed -i "s|{{ LDAP_TLS_VERIFY_CLIENT }}|${LDAP_TLS_VERIFY_CLIENT}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
  153. ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/tls/tls-enable.ldif
  154. [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
  155. touch $WAS_STARTED_WITH_TLS
  156. echo "export PREVIOUS_LDAP_TLS_CA_CRT_FILENAME=${LDAP_TLS_CA_CRT_FILENAME}" >> $WAS_STARTED_WITH_TLS
  157. echo "export PREVIOUS_LDAP_TLS_CRT_FILENAME=${LDAP_TLS_CRT_FILENAME}" >> $WAS_STARTED_WITH_TLS
  158. echo "export PREVIOUS_LDAP_TLS_KEY_FILENAME=${LDAP_TLS_KEY_FILENAME}" >> $WAS_STARTED_WITH_TLS
  159. chmod +x $WAS_STARTED_WITH_TLS
  160. # ldap client config
  161. sed -i "s,TLS_CACERT.*,TLS_CACERT /container/service/slapd/assets/certs/${LDAP_TLS_CA_CRT_FILENAME},g" /etc/ldap/ldap.conf
  162. echo "TLS_REQCERT demand" >> /etc/ldap/ldap.conf
  163. [[ -f "$HOME/.ldaprc" ]] && rm -f $HOME/.ldaprc
  164. touch $HOME/.ldaprc
  165. echo "TLS_CERT /container/service/slapd/assets/certs/${LDAP_TLS_CRT_FILENAME}" >> $HOME/.ldaprc
  166. echo "TLS_KEY /container/service/slapd/assets/certs/${LDAP_TLS_KEY_FILENAME}" >> $HOME/.ldaprc
  167. else
  168. echo "Don't use TLS"
  169. ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/tls/tls-disable.ldif || true
  170. [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
  171. fi
  172. function disableReplication() {
  173. echo "Try to disable replication if needed"
  174. ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/replication/replication-disable.ldif || true
  175. [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
  176. }
  177. # replication config
  178. if [ "${LDAP_REPLICATION,,}" == "true" ]; then
  179. echo "Use replication"
  180. disableReplication || true
  181. LDAP_REPLICATION_HOSTS=($LDAP_REPLICATION_HOSTS)
  182. i=1
  183. for host in "${LDAP_REPLICATION_HOSTS[@]}"
  184. do
  185. # host var contain a variable name, we access to the variable value
  186. host=${!host}
  187. sed -i "s|{{ LDAP_REPLICATION_HOSTS }}|olcServerID: $i ${host}\n{{ LDAP_REPLICATION_HOSTS }}|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
  188. sed -i "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/slapd/assets/config/replication/replication-enable.ldif
  189. sed -i "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/slapd/assets/config/replication/replication-enable.ldif
  190. ((i++))
  191. done
  192. get_ldap_base_dn
  193. sed -i "s|\$LDAP_BASE_DN|$LDAP_BASE_DN|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
  194. sed -i "s|\$LDAP_ADMIN_PASSWORD|$LDAP_ADMIN_PASSWORD|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
  195. sed -i "s|\$LDAP_CONFIG_PASSWORD|$LDAP_CONFIG_PASSWORD|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
  196. sed -i "/{{ LDAP_REPLICATION_HOSTS }}/d" /container/service/slapd/assets/config/replication/replication-enable.ldif
  197. sed -i "/{{ LDAP_REPLICATION_HOSTS_CONFIG_SYNC_REPL }}/d" /container/service/slapd/assets/config/replication/replication-enable.ldif
  198. sed -i "/{{ LDAP_REPLICATION_HOSTS_HDB_SYNC_REPL }}/d" /container/service/slapd/assets/config/replication/replication-enable.ldif
  199. echo "Enable replication"
  200. ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/replication/replication-enable.ldif || true
  201. [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
  202. touch $WAS_STARTED_WITH_REPLICATION
  203. echo "export PREVIOUS_HOSTNAME=${HOSTNAME}" >> $WAS_STARTED_WITH_REPLICATION
  204. chmod +x $WAS_STARTED_WITH_REPLICATION
  205. else
  206. echo "Don't use replication"
  207. disableReplication || true
  208. fi
  209. # stop OpenLDAP
  210. SLAPD_PID=$(cat /run/slapd/slapd.pid)
  211. echo "Kill slapd, pid: $SLAPD_PID"
  212. kill -9 $SLAPD_PID
  213. echo "[ok]"
  214. sleep 3
  215. touch $FIRST_START_DONE
  216. fi
  217. exit 0