فهرست منبع

Merge branch 'release-1.1.0' into stable

Bertrand Gouny 9 سال پیش
والد
کامیت
d619bd5109
36فایلهای تغییر یافته به همراه2222 افزوده شده و 477 حذف شده
  1. 55 38
      CHANGELOG.md
  2. 1 1
      Makefile
  3. 220 89
      README.md
  4. 6 0
      example/extend-osixia-openldap/Dockerfile
  5. 12 0
      example/extend-osixia-openldap/Makefile
  6. 15 0
      example/extend-osixia-openldap/bootstrap/ldif/billy.ldif
  7. 833 0
      example/extend-osixia-openldap/bootstrap/schema/asterisk.schema
  8. 270 0
      example/extend-osixia-openldap/bootstrap/schema/sendmail.schema
  9. 18 0
      example/extend-osixia-openldap/certs/ca.crt
  10. 18 0
      example/extend-osixia-openldap/certs/cert.crt
  11. 6 0
      example/extend-osixia-openldap/certs/cert.key
  12. 8 0
      example/extend-osixia-openldap/certs/dhparam.pem
  13. 10 0
      example/extend-osixia-openldap/environment/my-env.yaml
  14. 46 0
      example/extend-osixia-openldap/environment/my-env.yaml.startup
  15. 100 0
      example/kubernetes/simple/ldap-rc.yaml
  16. 11 0
      example/kubernetes/simple/ldap-svc.yaml
  17. 10 0
      example/kubernetes/using-secrets/environment/file-to-base64.sh
  18. 10 0
      example/kubernetes/using-secrets/environment/my-env.yaml
  19. 46 0
      example/kubernetes/using-secrets/environment/my-env.yaml.startup
  20. 68 0
      example/kubernetes/using-secrets/ldap-rc.yaml
  21. 10 0
      example/kubernetes/using-secrets/ldap-secret.yaml
  22. 11 0
      example/kubernetes/using-secrets/ldap-svc.yaml
  23. 12 12
      image/Dockerfile
  24. 10 0
      image/environment/default.yaml
  25. 15 3
      image/environment/default.yaml.startup
  26. 1 1
      image/service/slapd/assets/certs/README.md
  27. 4 4
      image/service/slapd/assets/config/tls/tls-enable.ldif
  28. 4 0
      image/service/slapd/assets/config/tls/tls-enforce-disable.ldif
  29. 4 0
      image/service/slapd/assets/config/tls/tls-enforce-enable.ldif
  30. 19 15
      image/service/slapd/assets/schema-to-ldif.sh
  31. 0 304
      image/service/slapd/container-start.sh
  32. 5 0
      image/service/slapd/install.sh
  33. 4 0
      image/service/slapd/process.sh
  34. 354 0
      image/service/slapd/startup.sh
  35. 2 2
      test/test.bats
  36. 4 8
      test/test_helper.bash

+ 55 - 38
CHANGELOG.md

@@ -1,75 +1,92 @@
 # Changelog
 
+## 1.1.0
+Update to light-baseimage:0.2.1 :
+  - Use \*.yaml.startup environment files to keep configuration secrets
+  - Use cfssl tool to generate tls certs
+  - Use log-helper to write leveled log messages
+  - Allow copy of /container/service and mounted files to /container/run/service dir usefull for write only filesystems and avoid file permissions problems
+
+New feature :
+  - Add enforcing TLS options (#26)
+
+Fix :
+  - Should SSL certs be copied on load? (#25)
+
 ## 1.0.9
-  - Update to light-baseimage:0.2.0
-  - Makefile with build no cache
+Update to light-baseimage:0.2.0
+
+Makefile with build no cache
 
 ## 1.0.8
-  - Fix an other startup bug ! whuhu
+Fix an other startup bug ! whuhu
 
 ## 1.0.7
-  - Fix startup bug
+Fix startup bug
 
 ## 1.0.6
-  - Use light-baseimage:0.1.5
+Use light-baseimage:0.1.5
 
 ## 1.0.5
-  - Use light-baseimage:0.1.4
-  - Fix replication bug when the hostname was changed
+Use light-baseimage:0.1.4
+
+Fix replication bug when the hostname was changed
 
 ## 1.0.4
-  - Use light-baseimage:0.1.3
+Use light-baseimage:0.1.3
 
 ## 1.0.3
-  - Use light-baseimage:0.1.2
-  - Fixes :
-    - Re-running container with volumes won't start #19
+Use light-baseimage:0.1.2
+
+Fix :
+  - Re-running container with volumes won't start #19
 
 ## 1.0.2
 
-  - Add TLS environment variable :
-      - LDAP_TLS_CIPHER_SUITE
-      - LDAP_TLS_PROTOCOL_MIN
-      - LDAP_TLS_VERIFY_CLIENT
+Add TLS environment variable :
+  - LDAP_TLS_CIPHER_SUITE
+  - LDAP_TLS_PROTOCOL_MIN
+  - LDAP_TLS_VERIFY_CLIENT
 
 ## 1.0.1
 
-  - Upgrade baseimage: light-baseimage:0.1.1
-  - Rename environment variables
+Upgrade baseimage: light-baseimage:0.1.1
 
-  - Fixes :
-    - OpenLdap container won't start when dhparam.pem is missing in bound volume #13
+Rename environment variables
+
+Fix :
+  - OpenLdap container won't start when dhparam.pem is missing in bound volume #13
 
 ## 1.0.0
 
-  - Use light-baseimage
-  - Improve documentation
+Use light-baseimage
+
+Improve documentation
 
 ## 0.10.2
 
-  - New features:
-    - Bootstrap config, only on non existing slapd config
-    - Limit max open file descriptors to fix slapd memory usage (#9)
-    - Don't disable network access from outside (#8)
-    - Make log level configurable via environment variable (#7)
-    - Support for ldaps (#10)
+New features :
+  - Bootstrap config, only on non existing slapd config
+  - Limit max open file descriptors to fix slapd memory usage (#9)
+  - Don't disable network access from outside (#8)
+  - Make log level configurable via environment variable (#7)
+  - Support for ldaps (#10)
 
 
-  - Fixes:
-    - Unable to start container with the following invocation. (#6)
+Fix :
+  - Unable to start container with the following invocation. (#6)
 
 ## 0.10.1
 
-  - New features:
-    - Add ldapi
-    - Add ldapi
-    - Add custom ldap schema
-    - Auto convert .schema to .ldif
+New features :
+  - Add ldapi
+  - Add custom ldap schema
+  - Auto convert .schema to .ldif
 
 
-  - Fixes :
-    - Docker VOLUME is not needed to be able to stop a container without losing data (#2)
-    - starting from old data (#3)
+Fix :
+  - Docker VOLUME is not needed to be able to stop a container without losing data (#2)
+  - starting from old data (#3)
 
 ## 0.10.0
-  - New version initial release
+New version initial release

+ 1 - 1
Makefile

@@ -1,5 +1,5 @@
 NAME = osixia/openldap
-VERSION = 1.0.9
+VERSION = 1.1.0
 
 .PHONY: all build build-nocache test tag_latest release
 

+ 220 - 89
README.md

@@ -1,35 +1,59 @@
 # osixia/openldap
 
-[![](https://badge.imagelayers.io/osixia/openldap:latest.svg)](https://imagelayers.io/?images=osixia/openldap:latest 'Get your own badge on imagelayers.io')
+[![](https://badge.imagelayers.io/osixia/openldap:latest.svg)](https://imagelayers.io/?images=osixia/openldap:latest 'Get your own badge on imagelayers.io') | Latest release: 1.1.0 - OpenLDAP 2.4.40 -  [Changelog](CHANGELOG.md) | [Docker Hub](https://hub.docker.com/r/osixia/openldap/) 
 
 A docker image to run OpenLDAP.
-> [www.openldap.org](http://www.openldap.org/)
 
-Fork of Nick Stenning docker-slapd :
-https://github.com/nickstenning/docker-slapd
-
-Add support of TLS, multi master replication and easy bootstrap.
-
-## Quick start
-Run OpenLDAP docker image :
-
-	docker run -d osixia/openldap
-
-This start a new container with a OpenLDAP server running inside.
-The odd string printed by this command is the `CONTAINER_ID`.
-We are going to use this `CONTAINER_ID` to execute some commands inside the container.
-
-Then run a terminal on this container,
-make sure to replace `CONTAINER_ID` by your container id :
-
-	docker exec -it CONTAINER_ID bash
-
-You should now be in the container terminal,
-and we can search on the ldap server :
-
-	ldapsearch -x -h localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
-
-This should output :
+> OpenLDAP website : [www.openldap.org](http://www.openldap.org/)
+
+- [Contributing](#contributing)
+- [Quick Start](#quick-start)
+- [Beginner Guide](#beginner-guide)
+	- [Create new ldap server](#create-new-ldap-server)
+		- [Data persistence](#data-persistence)
+		- [Edit your server configuration](#)
+	- [Use an existing ldap database](#use-an-existing-ldap-database)
+	- [Backup](#backup)
+	- [Administrate your ldap server](#administrate-your-ldap-server)
+	- [TLS](#tls)
+		- [Use auto-generated certificate](#use-auto-generated-certificate)
+		- [Use your own certificate](#use-your-own-certificate)
+		- [Disable TLS](#disable-tls)
+	- [Multi master replication](#multi-master-replication)
+	- [Debug](#debug)
+- [Environment Variables](#environment-variables)
+	- [Default.yaml](#defaultyaml)
+	- [Default.yaml.startup](#defaultyamlstartup)
+	- [Set your own environment variables](#set-your-own-environment-variables)
+		- [Use command line argument](#use-command-line-argument)
+		- [Link environment file](#link-environment-file)
+		- [Make your own image or extend this image](#make-your-own-image-or-extend-this-image)
+- [Advanced User Guide](#advanced-user-guide)
+	- [Extend osixia/openldap:1.1.0 image](#extend-osixiaopenldap110-image)
+	- [Make your own openldap image](#make-your-own-openldap-image)
+	- [Tests](#tests)
+	- [Kubernetes](#kubernetes)
+	- [Under the hood: osixia/light-baseimage](#under-the-hood-osixialight-baseimage)
+- [Changelog](#changelog)
+
+## Contributing
+
+If you find this image useful here's how you can help:
+
+- Send a pull request with your kickass new features and bug fixes
+- Help new users with [issues](https://github.com/osixia/docker-openldap/issues) they may encounter
+- Support the development of this image and star this repo !
+
+## Quick Start
+Run OpenLDAP docker image:
+
+	docker run --name my-openldap-container --detach osixia/openldap:1.1.0
+
+This start a new container with OpenLDAP running inside. Let's make the first search in our LDAP container:
+
+	docker exec my-openldap-container ldapsearch -x -h localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
+
+This should output:
 
 	# extended LDIF
 	#
@@ -44,32 +68,36 @@ This should output :
 	# numResponses: 3
 	# numEntries: 2
 
-if you have the following error, OpenLDAP is not started yet, wait some time.
+If you have the following error, OpenLDAP is not started yet, maybe you are too fast or maybe your computer is to slow, as you want... but wait some time before retrying.
 
 		ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)
 
 
-## Examples
+## Beginner Guide
 
 ### Create new ldap server
 
-This is the default behaviour when you run the image.
-It will create an empty ldap for the compagny **Example Inc.** and the domain **example.org**.
+This is the default behavior when you run this image.
+It will create an empty ldap for the company **Example Inc.** and the domain **example.org**.
 
-By default the admin has the password **admin**. All those default settings can be changed at the docker command line, for example :
+By default the admin has the password **admin**. All those default settings can be changed at the docker command line, for example:
 
-	docker run -e LDAP_ORGANISATION="My Compagny" -e LDAP_DOMAIN="my-compagny.com" \
-	-e LDAP_ADMIN_PASSWORD="JonSn0w" -d osixia/openldap
+	docker run --env LDAP_ORGANISATION="My Company" --env LDAP_DOMAIN="my-company.com" \
+	--env LDAP_ADMIN_PASSWORD="JonSn0w" --detach osixia/openldap:1.1.0
 
-#### Data persitance
+#### Data persistence
 
 The directories `/var/lib/ldap` (LDAP database files) and `/etc/ldap/slapd.d`  (LDAP config files) has been declared as volumes, so your ldap files are saved outside the container in data volumes.
 
-For more information about docker data volume, please refer to :
+For more information about docker data volume, please refer to:
 
 > [https://docs.docker.com/userguide/dockervolumes/](https://docs.docker.com/userguide/dockervolumes/)
 
 
+#### Edit your server configuration
+
+Do not edit slapd.conf it's not used. To modify your server configuration use ldap utils: **ldapmodify / ldapadd / ldapdelete**
+
 ### Use an existing ldap database
 
 This can be achieved by mounting host directories as volume.
@@ -77,46 +105,54 @@ Assuming you have a LDAP database on your docker host in the directory `/data/sl
 and the corresponding LDAP config files on your docker host in the directory `/data/slapd/config`
 simply mount this directories as a volume to `/var/lib/ldap` and `/etc/ldap/slapd.d`:
 
-	docker run -v /data/slapd/database:/var/lib/ldap \
-	-v /data/slapd/config:/etc/ldap/slapd.d
-	-d osixia/openldap
+	docker run --volume /data/slapd/database:/var/lib/ldap \
+	--volume /data/slapd/config:/etc/ldap/slapd.d
+	--detach osixia/openldap:1.1.0
 
-You can also use data volume containers. Please refer to :
+You can also use data volume containers. Please refer to:
 > [https://docs.docker.com/userguide/dockervolumes/](https://docs.docker.com/userguide/dockervolumes/)
 
+### Backup
+A simple solution to backup your ldap server, is our openldap-backup docker image:
+> [osixia/openldap-backup](https://github.com/osixia/docker-openldap-backup)
+
+### Administrate your ldap server
+If you are looking for a simple solution to administrate your ldap server you can take a look at our phpLDAPadmin docker image:
+> [osixia/phpldapadmin](https://github.com/osixia/docker-phpLDAPadmin)
+
 ### TLS
 
-#### Use autogenerated certificate
-By default TLS is enable, a certificate is created with the container hostname (it can be set by docker run -h option eg: ldap.example.org).
+#### Use auto-generated certificate
+By default TLS is enable, a certificate is created with the container hostname (it can be set by docker run --hostname option eg: ldap.example.org).
 
-	docker run -h ldap.my-compagny.com -d osixia/openldap
+	docker run --hostname ldap.my-company.com --detach osixia/openldap:1.1.0
 
 #### Use your own certificate
 
-Add your custom certificate, private key and CA certificate in the directory **image/service/slapd/assets/certs** adjust filename in **image/env.yaml** and rebuild the image ([see manual build](#manual-build)).
+You can set your custom certificate at run time, by mounting a directory containing those files to **/container/service/slapd/assets/certs** and adjust their name with the following environment variables:
 
-Or you can set your custom certificate at run time, by mouting a directory containing thoses files to **/container/service/slapd/assets/certs** and adjust there name with the following environment variables :
+	docker run --hostname ldap.example.org --volume /path/to/certifates:/container/service/slapd/assets/certs \
+	--env LDAP_TLS_CRT_FILENAME=my-ldap.crt \
+	--env LDAP_TLS_KEY_FILENAME=my-ldap.key \
+	--env LDAP_TLS_CA_CRT_FILENAME=the-ca.crt \
+	--detach osixia/openldap:1.1.0
 
-	docker run -h ldap.example.org -v /path/to/certifates:/container/service/slapd/assets/certs \
-	-e LDAP_TLS_CRT_FILENAME=my-ldap.crt \
-	-e LDAP_TLS_KEY_FILENAME=my-ldap.key \
-	-e LDAP_TLS_CA_CRT_FILENAME=the-ca.crt \
-	-d osixia/openldap
+Other solutions are available please refer to the [Advanced User Guide](#advanced-user-guide)
 
 #### Disable TLS
-Add -e LDAP_TLS=false to the run command :
+Add --env LDAP_TLS=false to the run command:
 
-	docker run -e LDAP_TLS=false -d osixia/openldap
+	docker run --env LDAP_TLS=false --detach osixia/openldap:1.1.0
 
 ### Multi master replication
 Quick example, with the default config.
 
 	#Create the first ldap server, save the container id in LDAP_CID and get its IP:
-	LDAP_CID=$(docker run -h ldap.example.org -e LDAP_REPLICATION=true -d osixia/openldap)
+	LDAP_CID=$(docker run --hostname ldap.example.org --env LDAP_REPLICATION=true --detach osixia/openldap:1.1.0)
 	LDAP_IP=$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" $LDAP_CID)
 
 	#Create the second ldap server, save the container id in LDAP2_CID and get its IP:
-	LDAP2_CID=$(docker run -h ldap2.example.org -e LDAP_REPLICATION=true -d osixia/openldap)
+	LDAP2_CID=$(docker run --hostname ldap2.example.org --env LDAP_REPLICATION=true --detach osixia/openldap:1.1.0)
 	LDAP2_IP=$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" $LDAP2_CID)
 
 	#Add the pair "ip hostname" to /etc/hosts on each containers,
@@ -124,13 +160,13 @@ Quick example, with the default config.
 	docker exec $LDAP_CID bash -c "echo $LDAP2_IP ldap2.example.org >> /etc/hosts"
 	docker exec $LDAP2_CID bash -c "echo $LDAP_IP ldap.example.org >> /etc/hosts"
 
-That's it ! But a litle test to be sure :
+That's it! But a little test to be sure:
 
 Add a new user "billy" on the first ldap server
 
-	docker exec $LDAP_CID ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin -f /container/service/slapd/assets/test/new-user.ldif -h ldap.example.org -ZZ
+	docker exec $LDAP_CID ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin -f /container/service/slapd/assets/test/new-user.ldif --hostname ldap.example.org -ZZ
 
-Search on the second ldap server, and billy should show up !
+Search on the second ldap server, and billy should show up!
 
 	docker exec $LDAP2_CID ldapsearch -x -h ldap2.example.org -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin -ZZ
 
@@ -146,22 +182,39 @@ Search on the second ldap server, and billy should show up !
 	objectClass: inetOrgPerson
 	[...]
 
-## Administrate your ldap server
-If you are looking for a simple solution to administrate your ldap server you can take a look at our phpLDAPadmin docker image :
-> [osixia/phpldapadmin](https://github.com/osixia/docker-phpLDAPadmin)
+### Debug
+
+The container default log level is **info**.
+Available levels are: `none`, `error`, `warning`, `info`, `debug` and `trace`.
+
+Example command to run the container in `debug` mode:
+
+	docker run --detach osixia/openldap:1.1.0 --loglevel debug
+
+See all command line options:
+
+	docker run osixia/openldap:1.1.0 --help
 
-## Backup
-A simple solution to backup your ldap server, our openldap-backup docker image :
-> [osixia/openldap-backup](https://github.com/osixia/docker-openldap-backup)
 
 ## Environment Variables
+Environment variables defaults are set in **image/environment/default.yaml** and **image/environment/default.yaml.startup**.
+
+See how to [set your own environment variables](#set-your-own-environment-variables)
 
-Environement variables defaults are set in **image/env.yaml**. You can modify environment variable values directly in this file and rebuild the image ([see manual build](#manual-build)). You can also override those values at run time with -e argument or by setting your own env.yaml file as a docker volume to `/container/environment/env.yaml`. See examples below.
+### Default.yaml
+Variables defined in this file are available at anytime in the container environment.
 
-General container configuration :
+General container configuration:
 - **LDAP_LOG_LEVEL**: Slap log level. defaults to  `256`. See table 5.1 in http://www.openldap.org/doc/admin24/slapdconf2.html for the available log levels.
 
-Required and used for new ldap server only :
+### Default.yaml.startup
+Variables defined in this file are only available during the container **first start** in **startup files**.
+This file is deleted right after startup files are processed for the first time,
+then all of these values will not be available in the container environment.
+
+This helps to keep your container configuration secret. If you don't care all environment variables can be defined in **default.yaml** and everything will work fine.
+
+Required and used for new ldap server only:
 - **LDAP_ORGANISATION**: Organisation name. Defaults to `Example Inc.`
 - **LDAP_DOMAIN**: Ldap domain. Defaults to `example.org`
 - **LDAP_ADMIN_PASSWORD** Ldap Admin password. Defaults to `admin`
@@ -171,69 +224,147 @@ Required and used for new ldap server only :
 - **LDAP_READONLY_USER_USERNAME** Read only user username. Defaults to `readonly`
 - **LDAP_READONLY_USER_PASSWORD** Read only user password. Defaults to `readonly`
 
-TLS options :
+TLS options:
 - **LDAP_TLS**: Add openldap TLS capabilities. Defaults to `true`
 - **LDAP_TLS_CRT_FILENAME**: Ldap ssl certificate filename. Defaults to `ldap.crt`
 - **LDAP_TLS_KEY_FILENAME**: Ldap ssl certificate private key filename. Defaults to `ldap.key`
 - **LDAP_TLS_CA_CRT_FILENAME**: Ldap ssl CA certificate  filename. Defaults to `ca.crt`
+- **LDAP_TLS_ENFORCE**: Enforce TLS. Defaults to `false`
 - **LDAP_TLS_CIPHER_SUITE**: TLS cipher suite. Defaults to `SECURE256:-VERS-SSL3.0`
 - **LDAP_TLS_PROTOCOL_MIN**: TLS min protocol. Defaults to `3.1`
 - **LDAP_TLS_VERIFY_CLIENT**: TLS verify client. Defaults to `demand`
 
 	Help: http://www.openldap.org/doc/admin24/tls.html
 
-Replication options :
+Replication options:
 - **LDAP_REPLICATION**: Add openldap replication capabilities. Defaults to `false`
 
-- **LDAP_REPLICATION_CONFIG_SYNCPROV**: olcSyncRepl options used for the config database. Without **rid** and **provider** which are automaticaly added based on LDAP_REPLICATION_HOSTS.  Defaults to `binddn="cn=admin,cn=config" bindmethod=simple credentials=$LDAP_CONFIG_PASSWORD searchbase="cn=config" type=refreshAndPersist retry="5 5 300 5" timeout=1 starttls=critical`
+- **LDAP_REPLICATION_CONFIG_SYNCPROV**: olcSyncRepl options used for the config database. Without **rid** and **provider** which are automatically added based on LDAP_REPLICATION_HOSTS.  Defaults to `binddn="cn=admin,cn=config" bindmethod=simple credentials=$LDAP_CONFIG_PASSWORD searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1 starttls=critical`
+
+- **LDAP_REPLICATION_HDB_SYNCPROV**: olcSyncRepl options used for the HDB database. Without **rid** and **provider** which are automatically added based on LDAP_REPLICATION_HOSTS.  Defaults to `binddn="cn=admin,$LDAP_BASE_DN" bindmethod=simple credentials=$LDAP_ADMIN_PASSWORD searchbase="$LDAP_BASE_DN" type=refreshAndPersist interval=00:00:00:10 retry="60 +" timeout=1 starttls=critical`
+
+- **LDAP_REPLICATION_HOSTS**: list of replication hosts, must contain the current container hostname set by --hostname on docker run command. Defaults to :
+	```yaml
+	- ldap://ldap.example.org
+  - ldap://ldap2.example.org
+	```
 
-- **LDAP_REPLICATION_HDB_SYNCPROV**: olcSyncRepl options used for the HDB database. Without **rid** and **provider** which are automaticaly added based on LDAP_REPLICATION_HOSTS.  Defaults to `binddn="cn=admin,$LDAP_BASE_DN" bindmethod=simple credentials=$LDAP_ADMIN_PASSWORD searchbase="$LDAP_BASE_DN" type=refreshAndPersist interval=00:00:00:10 retry="5 5 300 5" timeout=1  starttls=critical`
+	If you want to set this variable at docker run command add the tag `#PYTHON2BASH:` and convert the yaml in python:
 
+		docker run --env LDAP_REPLICATION_HOSTS="#PYTHON2BASH:['ldap://ldap.example.org','ldap://ldap2.example.org']" --detach osixia/openldap:1.1.0
 
-- **LDAP_REPLICATION_HOSTS**: list of replication hosts, must contains the current container hostname set by -h on docker run command. Defaults to `['ldap://ldap.example.org', 'ldap://ldap2.example.org']`
+	To convert yaml to python online: http://yaml-online-parser.appspot.com/
 
-### Set environment variables at run time :
+Other environment variables:
+- **LDAP_REMOVE_CONFIG_AFTER_SETUP**: delete config folder after setup. Defaults to `true`
+- **LDAP_CFSSL_PREFIX**: cfssl environment variables prefix. Defaults to `ldap`, cfssl-helper first search config from LDAP_CFSSL_* variables, before CFSSL_* variables.
 
-Environment variable can be set directly by adding the -e argument in the command line, for example :
 
-	docker run -e LDAP_ORGANISATION="My Compagny" -e LDAP_DOMAIN="my-compagny.com" \
-	-e LDAP_ADMIN_PASSWORD="JonSn0w" -d osixia/openldap
+### Set your own environment variables
 
-Or by setting your own `env.yaml` file as a docker volume to `/container/environment/env.yaml`
+#### Use command line argument
+Environment variables can be set by adding the --env argument in the command line, for example:
 
-	docker run -v /data/my-env.yaml:/container/environment/env.yaml \
-	-d osixia/openldap
+	docker run --env LDAP_ORGANISATION="My company" --env LDAP_DOMAIN="my-company.com" \
+	--env LDAP_ADMIN_PASSWORD="JonSn0w" --detach osixia/openldap:1.1.0
 
-## Manual build
+Be aware that environment variable added in command line will be available at any time
+in the container. In this example if someone manage to open a terminal in this container
+he will be able to read the admin password in clear text from environment variables.
 
-Clone this project :
+#### Link environment file
+
+For example if your environment files **my-env.yaml** and **my-env.yaml.startup** are in /data/ldap/environment
+
+	docker run --volume /data/ldap/environment:/container/environment/01-custom \
+	--detach osixia/openldap:1.1.0
+
+Take care to link your environment files folder to `/container/environment/XX-somedir` (with XX < 99 so they will be processed before default environment files) and not  directly to `/container/environment` because this directory contains predefined baseimage environment files to fix container environment (INITRD, LANG, LANGUAGE and LC_CTYPE).
+
+Note: the container will try to delete the **\*.yaml.startup** file after the end of startup files so the file will also be deleted on the docker host. To prevent that : use --volume /data/ldap/environment:/container/environment/01-custom**:ro** or set all variables in **\*.yaml** file and don't use **\*.yaml.startup**:
+
+	docker run --volume /data/ldap/environment/my-env.yaml:/container/environment/01-custom/env.yaml \
+	--detach osixia/openldap:1.1.0
+
+#### Make your own image or extend this image
+
+This is the best solution if you have a private registry. Please refer to the [Advanced User Guide](#advanced-user-guide) just below.
+
+## Advanced User Guide
+
+### Extend osixia/openldap:1.1.0 image
+
+If you need to add your custom TLS certificate, bootstrap config or environment files the easiest way is to extends this image.
+
+Dockerfile example:
+
+	FROM osixia/openldap:1.1.0
+	MAINTAINER Your Name <[email protected]>
+
+	ADD bootstrap /container/service/slapd/assets/config/bootstrap
+	ADD certs /container/service/slapd/assets/certs
+	ADD environment /container/environment/01-custom
+
+See complete example in **example/extend-osixia-openldap**
+
+### Make your own openldap image
+
+Clone this project:
 
 	git clone https://github.com/osixia/docker-openldap
 	cd docker-openldap
 
-Adapt Makefile, set your image NAME and VERSION, for example :
+Adapt Makefile, set your image NAME and VERSION, for example:
 
 	NAME = osixia/openldap
-	VERSION = 1.0.2
+	VERSION = 1.1.0
 
-	becomes :
-	NAME = billy-the-king/openldap
+	become:
+	NAME = cool-guy/openldap
 	VERSION = 0.1.0
 
-Build your image :
+Add your custom certificate, bootstrap ldif and environment files...
+
+Build your image:
 
 	make build
 
-Run your image :
+Run your image:
 
-	docker run -d billy-the-king/openldap:0.1.0
+	docker run --detach cool-guy/openldap:0.1.0
 
-## Tests
+### Tests
 
 We use **Bats** (Bash Automated Testing System) to test this image:
 
 > [https://github.com/sstephenson/bats](https://github.com/sstephenson/bats)
 
-Install Bats, and in this project directory run :
+Install Bats, and in this project directory run:
 
 	make test
+
+### Kubernetes
+
+Kubernetes is an open source system for managing containerized applications across multiple hosts, providing basic mechanisms for deployment, maintenance, and scaling of applications.
+
+More information:
+- http://kubernetes.io
+- https://github.com/kubernetes/kubernetes
+
+osixia-openldap kubernetes examples are available in **example/kubernetes**
+
+### Under the hood: osixia/light-baseimage
+
+This image is based on osixia/light-baseimage.
+It uses the following features:
+
+- **cfssl** service to generate tls certificates
+- **log-helper** tool to print log messages based on the log level
+- **run** tool as entrypoint to init the container environment
+
+To fully understand how this image works take a look at:
+https://github.com/osixia/docker-light-baseimage
+
+## Changelog
+
+Please refer to: [CHANGELOG.md](CHANGELOG.md)

+ 6 - 0
example/extend-osixia-openldap/Dockerfile

@@ -0,0 +1,6 @@
+FROM osixia/openldap:1.1.0
+MAINTAINER Your Name <[email protected]>
+
+ADD bootstrap /container/service/slapd/assets/config/bootstrap
+ADD certs /container/service/slapd/assets/certs
+ADD environment /container/environment/01-custom

+ 12 - 0
example/extend-osixia-openldap/Makefile

@@ -0,0 +1,12 @@
+NAME = osixia/extend-osixia-openldap
+VERSION = 0.1.0
+
+.PHONY: all build build-nocache
+
+all: build
+
+build:
+	docker build -t $(NAME):$(VERSION) --rm .
+
+build-nocache:
+	docker build -t $(NAME):$(VERSION) --no-cache --rm .

+ 15 - 0
example/extend-osixia-openldap/bootstrap/ldif/billy.ldif

@@ -0,0 +1,15 @@
+dn: uid=billy,dc=example,dc=org
+changetype: add
+uid: billy
+cn: billy
+sn: 3
+objectClass: top
+objectClass: posixAccount
+objectClass: inetOrgPerson
+loginShell: /bin/bash
+homeDirectory: /home/billy
+uidNumber: 14583102
+gidNumber: 14564100
+userPassword: {SSHA}j3lBh1Seqe4rqF1+NuWmjhvtAni1JC5A
+mail: [email protected]
+gecos: Billy User

+ 833 - 0
example/extend-osixia-openldap/bootstrap/schema/asterisk.schema

@@ -0,0 +1,833 @@
+#
+# Copyright (c) 2007-2009 Suretec Systems Ltd. - <http://www.suretecsystems.com/>
+#
+# Version: 3.2.2
+#
+# Changes:
+
+# - Added AsteriskDialplan, AsteriskAccount and AsteriskMailbox objectClasses
+#   to allow standalone dialplan, account and mailbox entries (STRUCTURAL)
+# - Added new Fields
+#   * AstAccountLanguage, AstAccountTransport, AstAccountPromiscRedir,
+#   * AstAccountAccountCode, AstAccountSetVar, AstAccountAllowOverlap,
+#   * AstAccountVideoSupport, AstAccountIgnoreSDPVersion
+#   Removed redundant IPaddr (there's already IPAddress)
+# - Fixed typo - 13/08/2009
+# - https://issues.asterisk.org/view.php?id=13725 - 12/08/2009
+# - Added AsteriskVoiceMail Object class and AstAccountCallLimit attribute - 28/05/2009
+#   https://issues.asterisk.org/view.php?id=15155
+# - Added AstAccountLastQualifyMilliseconds - 28/05/2009
+#   https://issues.asterisk.org/view.php?id=15156
+# - https://issues.asterisk.org/view.php?id=12860 - 04/07/2008
+# - Fixed wrong DESC - 07/05/2008
+#
+# Author: Gavin Henry - <[email protected]>
+#         Michael Kromer - <[email protected]>
+#
+# Asterisk LDAP Schema
+#
+# Digium root OID (http://www.iana.org/assignments/enterprise-numbers)
+#
+#  1.3.6.1.4.1.22736
+#  1.3.6.1.4.1.22736.5      LDAP elements
+#  1.3.6.1.4.1.22736.5.4    Attribute Types
+#  1.3.6.1.4.1.22736.5.5    Object Classes
+#
+objectIdentifier AsteriskRoot 1.3.6.1.4.1.22736
+objectIdentifier AsteriskLDAP AsteriskRoot:5
+
+#############################################################################
+# Attribute group OIDs.  e.g.: objectIdentifier AstAttrType AsteriskLDAP:4
+#############################################################################
+objectIdentifier AstAttrType AsteriskLDAP:4
+
+#############################################################################
+# Attribute OIDs e.g.: objectIdentifier AstContext AstAttrType:1
+#############################################################################
+objectIdentifier AstContext AstAttrType:1
+objectIdentifier AstExtension AstAttrType:2
+objectIdentifier AstPriority AstAttrType:3
+objectIdentifier AstApplication AstAttrType:4
+objectIdentifier AstApplicationData AstAttrType:5
+objectIdentifier AstAccountAMAFlags AstAttrType:6
+objectIdentifier AstAccountCallerID AstAttrType:7
+objectIdentifier AstAccountContext AstAttrType:8
+objectIdentifier AstAccountMailbox AstAttrType:9
+objectIdentifier AstMD5secret AstAttrType:10
+objectIdentifier AstAccountDeny AstAttrType:11
+objectIdentifier AstAccountPermit AstAttrType:12
+objectIdentifier AstAccountQualify AstAttrType:13
+objectIdentifier AstAccountType AstAttrType:14
+objectIdentifier AstAccountDisallowedCodec AstAttrType:15
+objectIdentifier AstAccountExpirationTimestamp AstAttrType:16
+objectIdentifier AstAccountRegistrationContext AstAttrType:17
+objectIdentifier AstAccountRegistrationExten AstAttrType:18
+objectIdentifier AstAccountNoTransfer AstAttrType:19
+objectIdentifier AstAccountCallGroup AstAttrType:20
+objectIdentifier AstAccountCanReinvite AstAttrType:21
+objectIdentifier AstAccountDTMFMode AstAttrType:22
+objectIdentifier AstAccountFromUser AstAttrType:23
+objectIdentifier AstAccountFromDomain AstAttrType:24
+objectIdentifier AstAccountFullContact AstAttrType:25
+objectIdentifier AstAccountHost AstAttrType:26
+objectIdentifier AstAccountInsecure AstAttrType:27
+objectIdentifier AstAccountNAT AstAttrType:28
+objectIdentifier AstAccountPickupGroup AstAttrType:29
+objectIdentifier AstAccountPort AstAttrType:30
+objectIdentifier AstAccountRestrictCID AstAttrType:31
+objectIdentifier AstAccountRTPTimeout AstAttrType:32
+objectIdentifier AstAccountRTPHoldTimeout AstAttrType:33
+objectIdentifier AstAccountRealmedPassword AstAttrType:34
+objectIdentifier AstAccountAllowedCodec AstAttrType:35
+objectIdentifier AstAccountMusicOnHold AstAttrType:36
+objectIdentifier AstAccountCanCallForward AstAttrType:37
+objectIdentifier AstAccountSecret AstAttrType:38
+objectIdentifier AstAccountName AstAttrType:39
+objectIdentifier AstConfigFilename AstAttrType:40
+objectIdentifier AstConfigCategory AstAttrType:41
+objectIdentifier AstConfigCategoryMetric AstAttrType:42
+objectIdentifier AstConfigVariableName AstAttrType:43
+objectIdentifier AstConfigVariableValue AstAttrType:44
+objectIdentifier AstConfigCommented AstAttrType:45
+objectIdentifier AstAccountIPAddress AstAttrType:46
+objectIdentifier AstAccountDefaultUser AstAttrType:47
+objectIdentifier AstAccountRegistrationServer AstAttrType:48
+objectIdentifier AstAccountLastQualifyMilliseconds AstAttrType:49
+objectIdentifier AstAccountCallLimit AstAttrType:50
+objectIdentifier AstVoicemailMailbox AstAttrType:51
+objectIdentifier AstVoicemailPassword AstAttrType:52
+objectIdentifier AstVoicemailFullname AstAttrType:53
+objectIdentifier AstVoicemailEmail AstAttrType:54
+objectIdentifier AstVoicemailPager AstAttrType:55
+objectIdentifier AstVoicemailOptions AstAttrType:56
+objectIdentifier AstVoicemailTimestamp AstAttrType:57
+objectIdentifier AstVoicemailContext AstAttrType:58
+objectIdentifier AstAccountSubscribeContext AstAttrType:59
+objectIdentifier AstAccountUserAgent AstAttrType:61
+objectIdentifier AstAccountLanguage AstAttrType:62
+objectIdentifier AstAccountTransport AstAttrType:63
+objectIdentifier AstAccountPromiscRedir AstAttrType:64
+objectIdentifier AstAccountAccountCode AstAttrType:65
+objectIdentifier AstAccountSetVar AstAttrType:66
+objectIdentifier AstAccountAllowOverlap AstAttrType:67
+objectIdentifier AstAccountVideoSupport AstAttrType:68
+objectIdentifier AstAccountIgnoreSDPVersion AstAttrType:69
+
+
+#############################################################################
+# Object Class OIDs
+#############################################################################
+objectIdentifier AstObjectClass AsteriskLDAP:2
+objectIdentifier AsteriskExtension AstObjectClass:1
+objectIdentifier AsteriskIAXUser AstObjectClass:2
+objectIdentifier AsteriskSIPUser AstObjectClass:3
+objectIdentifier AsteriskConfig AstObjectClass:4
+objectIdentifier AsteriskVoiceMail AstObjectClass:5
+objectIdentifier AsteriskDialplan AstObjectClass:6
+objectIdentifier AsteriskAccount AstObjectClass:7
+objectIdentifier AsteriskMailbox AstObjectClass:8
+
+
+#############################################################################
+# attribute definitions
+#
+# OID (the first arg) comes from the objectIdentifier defined above
+#
+# NAME should be the same as objectIdentifier
+#
+# DESC should be the description of the attribute
+#
+# EQUALITY is the rule to use when doing a search/compare for an
+# attribute value.
+#
+# SUBSTR is the rule to use when doing a substring search (*foo*)
+#
+# SYNTAX is the syntax (i.e., type) of the attribute. We should
+# probably stick to syntaxes:
+#
+#       1.3.6.1.4.1.1466.115.121.1.15   -> directoryString (UTF-8 string)
+#       1.3.6.1.4.1.1466.115.121.1.26   -> IA5String (ASCII String)
+#       1.3.6.1.4.1.1466.115.121.1.27   -> integer (Integer value)
+#
+# SINGLE-VALUE should be present if only one instance of this
+# attribute is allowed within an entry.
+#
+# {32} is the allowed length
+#
+# e.g.:
+#
+# attributetype ( AstExample
+#    NAME ( 'AstExample' )
+#    DESC 'Asterisk Example Attribute'
+#    EQUALITY caseIgnoreMatch
+#    SUBSTR caseIgnoreSubstringsMatch
+#    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32}
+#    SINGLE-VALUE )
+#
+#############################################################################
+
+attributetype ( AstContext
+        NAME 'AstContext'
+        DESC 'Asterisk Context'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstExtension
+        NAME 'AstExtension'
+        DESC 'Asterisk Extension'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstPriority
+        NAME 'AstPriority'
+        DESC 'Asterisk Priority'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstApplication
+        NAME 'AstApplication'
+        DESC 'Asterisk Application'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstApplicationData
+        NAME 'AstApplicationData'
+        DESC 'Asterisk Application Data'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountAMAFlags
+        NAME 'AstAccountAMAFlags'
+        DESC 'Asterisk Account AMA Flags'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountCallerID
+        NAME 'AstAccountCallerID'
+        DESC 'Asterisk Account CallerID'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountContext
+        NAME 'AstAccountContext'
+        DESC 'Asterisk Account Context'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountMailbox
+        NAME 'AstAccountMailbox'
+        DESC 'Asterisk Account Mailbox'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstMD5secret
+        NAME 'AstMD5secret'
+        DESC 'Asterisk Account MD5 Secret'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountDeny
+        NAME 'AstAccountDeny'
+        DESC 'Asterisk Account Deny'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountPermit
+        NAME 'AstAccountPermit'
+        DESC 'Asterisk Account Permit'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountQualify
+        NAME 'AstAccountQualify'
+        DESC 'Asterisk Account Qualify'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountType
+        NAME 'AstAccountType'
+        DESC 'Asterisk Account Type'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountDisallowedCodec
+        NAME 'AstAccountDisallowedCodec'
+        DESC 'Asterisk Account Disallowed Codec'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountExpirationTimestamp
+        NAME 'AstAccountExpirationTimestamp'
+        DESC 'Asterisk Account Expiration Timestamp'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountRegistrationContext
+        NAME 'AstAccountRegistrationContext'
+        DESC 'Asterisk Account Registration Context'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountRegistrationExten
+        NAME 'AstAccountRegistrationExten'
+        DESC 'Asterisk Account Registration Extension'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountNoTransfer
+        NAME 'AstAccountNoTransfer'
+        DESC 'Asterisk Account No Transfer'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountCallGroup
+        NAME 'AstAccountCallGroup'
+        DESC 'Asterisk Account Call Group'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountCanReinvite
+        NAME 'AstAccountCanReinvite'
+        DESC 'Asterisk Account Can Reinvite'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountDTMFMode
+        NAME 'AstAccountDTMFMode'
+        DESC 'Asterisk Account DTMF Flags'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountFromUser
+        NAME 'AstAccountFromUser'
+        DESC 'Asterisk Account From User'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountFromDomain
+        NAME 'AstAccountFromDomain'
+        DESC 'Asterisk Account From Domain'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountFullContact
+        NAME 'AstAccountFullContact'
+        DESC 'Asterisk Account Full Contact'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountHost
+        NAME 'AstAccountHost'
+        DESC 'Asterisk Account Host'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountInsecure
+        NAME 'AstAccountInsecure'
+        DESC 'Asterisk Account Insecure'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountNAT
+        NAME 'AstAccountNAT'
+        DESC 'Asterisk Account NAT'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountPickupGroup
+        NAME 'AstAccountPickupGroup'
+        DESC 'Asterisk Account PickupGroup'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountPort
+        NAME 'AstAccountPort'
+        DESC 'Asterisk Account Port'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountRestrictCID
+        NAME 'AstAccountRestrictCID'
+        DESC 'Asterisk Account Restrict CallerID'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountRTPTimeout
+        NAME 'AstAccountRTPTimeout'
+        DESC 'Asterisk Account RTP Timeout'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountRTPHoldTimeout
+        NAME 'AstAccountRTPHoldTimeout'
+        DESC 'Asterisk Account RTP Hold Timeout'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountRealmedPassword
+        NAME 'AstAccountRealmedPassword'
+        DESC 'Asterisk Account Realmed Password'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountAllowedCodec
+        NAME 'AstAccountAllowedCodec'
+        DESC 'Asterisk Account Allowed Codec'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountMusicOnHold
+        NAME 'AstAccountMusicOnHold'
+        DESC 'Asterisk Account Music On Hold'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountCanCallForward
+        NAME 'AstAccountCanCallForward'
+        DESC 'Asterisk Account Can Call Forward'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountSecret
+        NAME 'AstAccountSecret'
+        DESC 'Asterisk Account Secret'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountName
+        NAME 'AstAccountName'
+        DESC 'Asterisk Account Username'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstConfigFilename
+        NAME 'AstConfigFilename'
+        DESC 'Asterisk LDAP Configuration Filename'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstConfigCategory
+        NAME 'AstConfigCategory'
+        DESC 'Asterisk LDAP Configuration Category'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstConfigCategoryMetric
+        NAME 'AstConfigCategoryMetric'
+        DESC 'Asterisk LDAP Configuration Category Metric'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstConfigVariableName
+        NAME 'AstConfigVariableName'
+        DESC 'Asterisk LDAP Configuration Variable Name'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstConfigVariableValue
+        NAME 'AstConfigVariableValue'
+        DESC 'Asterisk LDAP Configuration Variable Value'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstConfigCommented
+        NAME 'AstConfigCommented'
+        DESC 'Asterisk LDAP Configuration Commented'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountIPAddress
+        NAME 'AstAccountIPAddress'
+        DESC 'Asterisk Account IP Address'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountDefaultUser
+        NAME 'AstAccountDefaultUser'
+        DESC 'Asterisk Account Default User'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountRegistrationServer
+        NAME 'AstAccountRegistrationServer'
+        DESC 'Asterisk Account Registration Server'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountLastQualifyMilliseconds
+        NAME 'AstAccountLastQualifyMilliseconds'
+        DESC 'Asterisk Account Last Qualify Milliseconds'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountCallLimit
+        NAME 'AstAccountCallLimit'
+        DESC 'Asterisk Account Call Limit'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailMailbox
+        NAME 'AstVoicemailMailbox'
+        DESC 'Asterisk voicemail mailbox'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailPassword
+        NAME 'AstVoicemailPassword'
+        DESC 'Asterisk voicemail password'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailFullname
+        NAME 'AstVoicemailFullname'
+        DESC 'Asterisk voicemail fullname'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailEmail
+        NAME 'AstVoicemailEmail'
+        DESC 'Asterisk voicemail email'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailPager
+        NAME 'AstVoicemailPager'
+        DESC 'Asterisk voicemail pager'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailOptions
+        NAME 'AstVoicemailOptions'
+        DESC 'Asterisk voicemail options'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailTimestamp
+        NAME 'AstVoicemailTimestamp'
+        DESC 'Asterisk voicemail timestamp'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstVoicemailContext
+        NAME 'AstVoicemailContext'
+        DESC 'Asterisk voicemail context'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountSubscribeContext
+        NAME 'AstAccountSubscribeContext'
+        DESC 'Asterisk subscribe context'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountUserAgent
+        NAME 'AstAccountUserAgent'
+        DESC 'Asterisk account user context'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountLanguage
+        NAME 'AstAccountLanguage'
+        DESC 'Asterisk account user language'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountTransport
+        NAME 'AstAccountTransport'
+        DESC 'Asterisk account transport type'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountPromiscRedir
+        NAME 'AstAccountPromiscRedir'
+        DESC 'Asterisk account promiscous redirects'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountAccountCode
+        NAME 'AstAccountAccountCode'
+        DESC 'Asterisk account billing code'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountSetVar
+        NAME 'AstAccountSetVar'
+        DESC 'Asterisk account setvar'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountAllowOverlap
+        NAME 'AstAccountAllowOverlap'
+        DESC 'Asterisk account allow overlap dialing'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountVideoSupport
+        NAME 'AstAccountVideoSupport'
+        DESC 'Asterisk account video support'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+attributetype ( AstAccountIgnoreSDPVersion
+        NAME 'AstAccountIgnoreSDPVersion'
+        DESC 'Asterisk account ignore SDP version'
+        EQUALITY caseIgnoreMatch
+        SUBSTR caseIgnoreSubstringsMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+
+#############################################################################
+# Object Class definitions
+#
+# This is where to define the object classes. Object classes are used
+# to define which attribute MAY (optional) or MUST (required) belong
+# to an entry.
+#
+# Classes can be AUXILIARY or STRUCTURAL. An entry in the directory
+# must have one and only one structural class, but can have many
+# AUXILIARY classes.
+#
+#############################################################################
+
+objectclass ( AsteriskExtension
+    NAME 'AsteriskExtension'
+    DESC 'PBX Extension Information for Asterisk'
+    SUP top AUXILIARY
+    MUST cn
+    MAY (
+        AstContext $
+        AstExtension $
+        AstPriority $
+        AstApplication $
+        AstApplicationData
+    )
+    )
+
+#############################################################################
+#
+# AsteriskIAXUser and AsteriskSIPUser extend AsteriskExtension. These
+# represent real accounts in Asterisk.
+#
+# NOTE: They are defined as AUXILIARY in case they need to be mixed with an
+# existing directory deployment.
+#
+#############################################################################
+
+objectclass ( AsteriskIAXUser
+    NAME 'AsteriskIAXUser'
+    DESC 'IAX2 User information for Asterisk'
+    SUP AsteriskExtension AUXILIARY
+    MUST cn
+    MAY (
+        AstAccountAMAFlags $
+        AstAccountCallerID $
+        AstAccountContext $
+        AstAccountFullContact $
+        AstAccountHost $
+        AstAccountMailbox $
+        AstMD5secret $
+        AstAccountDeny $
+        AstAccountPermit $
+        AstAccountPort $
+        AstAccountQualify $
+        AstAccountType $
+        AstAccountLanguage $
+        AstAccountDisallowedCodec $
+        AstAccountExpirationTimestamp $
+        AstAccountRegistrationContext $
+        AstAccountRegistrationExten $
+        AstAccountNoTransfer $
+        AstAccountName $
+        AstAccountLastQualifyMilliseconds $
+        AstAccountCallLimit $
+        AstAccountSubscribeContext $
+        AstAccountIPAddress $
+        AstAccountUserAgent
+    )
+    )
+
+objectclass ( AsteriskSIPUser
+    NAME 'AsteriskSIPUser'
+    DESC 'SIP User information for Asterisk'
+    SUP AsteriskExtension AUXILIARY
+    MUST cn
+    MAY (
+        AstAccountAccountCode $
+        AstAccountAllowOverlap $
+        AstAccountAllowedCodec $
+        AstAccountAMAFlags $
+        AstAccountCallGroup $
+        AstAccountCallLimit $
+        AstAccountCallerID $
+        AstAccountCanCallForward $
+        AstAccountCanReinvite $
+        AstAccountContext $
+        AstAccountDTMFMode $
+        AstAccountDefaultUser $
+        AstAccountDeny $
+        AstAccountDisallowedCodec $
+        AstAccountExpirationTimestamp $
+        AstAccountFromDomain $
+        AstAccountFromUser $
+        AstAccountFullContact $
+        AstAccountHost $
+        AstAccountIgnoreSDPVersion $
+        AstAccountInsecure $
+        AstAccountIPAddress $
+        AstAccountLanguage $
+        AstAccountLastQualifyMilliseconds $
+        AstAccountMailbox $
+        AstAccountMusicOnHold $
+        AstAccountNAT $
+        AstAccountName $
+        AstAccountPermit $
+        AstAccountPickupGroup $
+        AstAccountPort $
+        AstAccountPromiscRedir $
+        AstAccountQualify $
+        AstAccountRTPHoldTimeout $
+        AstAccountRTPTimeout $
+        AstAccountRealmedPassword $
+        AstAccountRegistrationContext $
+        AstAccountRegistrationExten $
+        AstAccountRegistrationServer $
+        AstAccountRestrictCID $
+        AstAccountSecret $
+        AstAccountSetVar $
+        AstAccountSubscribeContext $
+        AstAccountTransport $
+        AstAccountType $
+        AstAccountUserAgent $
+        AstAccountVideoSupport
+    )
+    )
+
+#############################################################################
+#
+# AsteriskConfig and AsteriskVoiceMail extend AsteriskExtension. These
+# represent real accounts in Asterisk.
+#
+# NOTE: They are defined as AUXILIARY in case they need to be mixed with an
+# existing directory deployment.
+#
+#############################################################################
+
+objectclass ( AsteriskConfig
+    NAME 'AsteriskConfig'
+    DESC 'Asterisk configuration Information'
+    SUP top AUXILIARY
+    MUST cn
+    MAY (
+        AstConfigFilename $
+        AstConfigCategory $
+        AstConfigCategoryMetric $
+        AstConfigVariableName $
+        AstConfigVariableValue $
+        AstConfigCommented
+    )
+    )
+
+objectclass ( AsteriskVoiceMail
+    NAME 'AsteriskVoiceMail'
+    DESC 'Asterisk voicemail information'
+    SUP top AUXILIARY
+    MUST (
+    cn $
+    AstContext $
+    AstVoicemailMailbox $
+    AstVoicemailPassword
+    )
+    MAY (
+    AstVoicemailFullname $
+    AstVoicemailEmail $
+    AstVoicemailPager $
+    AstVoicemailOptions $
+    AstVoicemailTimestamp $
+    AstVoicemailContext
+    )
+    )
+
+objectClass (
+	AsteriskDialplan
+	NAME 'AsteriskDialplan'
+	DESC 'Asterisk Dialplan Information'
+	SUP top STRUCTURAL
+	MUST ( AstExtension ) )
+
+objectClass (
+	AsteriskAccount
+	NAME 'AsteriskAccount'
+	DESC 'Asterisk Account Information'
+	SUP top STRUCTURAL
+	MUST ( AstAccountName ) )
+
+objectClass (
+	AsteriskMailbox
+	NAME 'AsteriskMailbox'
+	DESC 'Asterisk Mailbox Information'
+	SUP top STRUCTURAL
+	MUST ( AstVoicemailMailbox ) )

+ 270 - 0
example/extend-osixia-openldap/bootstrap/schema/sendmail.schema

@@ -0,0 +1,270 @@
+# Copyright (c) 2000-2002, 2005 Sendmail, Inc. and its suppliers.
+#	All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+# $Id: sendmail.schema,v 8.22 2005/09/16 20:18:14 ca Exp $
+
+# Note that this schema is experimental at this point as it has had little
+# public review.  Therefore, it may change in future versions.  Feedback
+# via [email protected] is encouraged (replace YYYY with
+# the current year, e.g., 2005).
+
+# OID arcs for Sendmail
+# enterprise:		1.3.6.1.4.1
+# sendmail:		enterprise.6152
+# sendmail-at:		sendmail.3.1
+# sendmail-oc:		sendmail.3.2
+
+###########################################################################
+#
+# The Sendmail MTA attributes and objectclass
+#
+###########################################################################
+
+# attribute sendmailMTACluster	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.10
+	NAME 'sendmailMTACluster'
+	DESC 'cluster name associated with a set of MTAs'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+# attribute sendmailMTAHost	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.11
+	NAME 'sendmailMTAHost'
+	DESC 'host name associated with a MTA cluster'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+#objectClass sendmailMTA
+#	requires
+#		objectClass
+#	allows
+#		sendmailMTACluster,
+#		sendmailMTAHost,
+#		Description
+
+objectclass ( 1.3.6.1.4.1.6152.10.3.2.10
+	NAME 'sendmailMTA'
+	SUP top STRUCTURAL
+	DESC 'Sendmail MTA definition'
+	MAY ( sendmailMTACluster $ sendmailMTAHost $ Description ) )
+
+###########################################################################
+#
+# The Sendmail MTA shared attributes
+#
+###########################################################################
+
+# attribute sendmailMTAKey	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.13
+	NAME 'sendmailMTAKey'
+	DESC 'key (left hand side) of an aliases or map entry'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+###########################################################################
+#
+# The Sendmail MTA Map attributes and objectclasses
+#
+###########################################################################
+
+# attribute sendmailMTAMapName	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.14
+	NAME 'sendmailMTAMapName'
+	DESC 'identifier for the particular map'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} SINGLE-VALUE )
+
+# attribute sendmailMTAMapValue	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.16
+	NAME 'sendmailMTAMapValue'
+	DESC 'value (right hand side) of a map entry'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+# attribute sendmailMTAMapSearch cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.24
+	NAME 'sendmailMTAMapSearch'
+	DESC 'recursive search for values of a map entry'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+# attribute sendmailMTAMapURL cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.25
+	NAME 'sendmailMTAMapURL'
+	DESC 'recursive search URL for values of a map entry'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+#objectClass sendmailMTAMap
+#	requires
+#		objectClass,
+#		sendmailMTAMapName,
+#	allows
+#		sendmailMTACluster,
+#		sendmailMTAHost,
+#		Description
+
+objectclass ( 1.3.6.1.4.1.6152.10.3.2.11
+	NAME 'sendmailMTAMap'
+	SUP sendmailMTA STRUCTURAL
+	DESC 'Sendmail MTA map definition'
+	MUST sendmailMTAMapName
+	MAY ( sendmailMTACluster $ sendmailMTAHost $ Description ) )
+
+#objectClass sendmailMTAObject
+#	requires
+#		objectClass,
+#		sendmailMTAMapName,
+#		sendmailMTAKey,
+#	allows
+#		sendmailMTACluster,
+#		sendmailMTAHost,
+#		sendmailMTAMapValue,
+#		sendmailMTAMapSearch,
+#		sendmailMTAMapURL,
+#		Description
+
+objectclass ( 1.3.6.1.4.1.6152.10.3.2.12
+	NAME 'sendmailMTAMapObject'
+	SUP sendmailMTAMap STRUCTURAL
+	DESC 'Sendmail MTA map object'
+	MUST ( sendmailMTAMapName $ sendmailMTAKey )
+	MAY ( sendmailMTACluster $ sendmailMTAHost $
+		sendmailMTAMapValue $ sendmailMTAMapSearch $
+		sendmailMTAMapURL $ Description ) )
+
+
+###########################################################################
+#
+# The Sendmail MTA Alias attributes and objectclasses
+#
+###########################################################################
+
+# attribute sendmailMTAAliasGrouping	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.18
+	NAME 'sendmailMTAAliasGrouping'
+	DESC 'name that identifies a particular aliases grouping'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+# attribute sendmailMTAAliasValue	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.20
+	NAME 'sendmailMTAAliasValue'
+	DESC 'value (right hand side) of an alias'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# attribute sendmailMTAAliasSearch cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.26
+	NAME 'sendmailMTAAliasSearch'
+	DESC 'recursive search for values of an alias'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+# attribute sendmailMTAAliasURL cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.27
+	NAME 'sendmailMTAAliasURL'
+	DESC 'recursive search URL for values of an alias'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+#objectClass sendmailMTAAlias
+#	requires
+#		objectClass,
+#	allows
+#		sendmailMTAAliasGrouping,
+#		sendmailMTACluster,
+#		sendmailMTAHost,
+#		Description
+
+objectclass ( 1.3.6.1.4.1.6152.10.3.2.13
+	NAME 'sendmailMTAAlias'
+	SUP sendmailMTA STRUCTURAL
+	DESC 'Sendmail MTA alias definition'
+	MAY ( sendmailMTAAliasGrouping $
+		sendmailMTACluster $ sendmailMTAHost $ Description ) )
+
+#objectClass sendmailMTAAliasObject
+#	requires
+#		objectClass,
+#		sendmailMTAKey,
+#	allows
+#		sendmailMTAAliasGrouping,
+#		sendmailMTACluster,
+#		sendmailMTAHost,
+#		sendmailMTAAliasValue,
+#		sendmailMTAAliasSearch,
+#		sendmailMTAAliasURL,
+#		Description
+
+objectclass ( 1.3.6.1.4.1.6152.10.3.2.14
+	NAME 'sendmailMTAAliasObject'
+	SUP sendmailMTAAlias STRUCTURAL
+	DESC 'Sendmail MTA alias object'
+	MUST sendmailMTAKey
+	MAY ( sendmailMTAAliasGrouping $ sendmailMTACluster $
+		sendmailMTAHost $ sendmailMTAAliasValue $
+		sendmailMTAAliasSearch $ sendmailMTAAliasURL $ Description ) )
+
+###########################################################################
+#
+# The Sendmail MTA Class attributes and objectclass
+#
+###########################################################################
+
+# attribute sendmailMTAClassName	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.22
+	NAME 'sendmailMTAClassName'
+	DESC 'identifier for the class'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} SINGLE-VALUE )
+
+# attribute sendmailMTAClassValue	cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.23
+	NAME 'sendmailMTAClassValue'
+	DESC 'member of a class'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# attribute sendmailMTAClassSearch cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.28
+	NAME 'sendmailMTAClassSearch'
+	DESC 'recursive search for members of a class'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+# attribute sendmailMTAClassURL cis
+attributetype ( 1.3.6.1.4.1.6152.10.3.1.29
+	NAME 'sendmailMTAClassURL'
+	DESC 'recursive search URL for members of a class'
+	EQUALITY caseExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+#objectClass sendmailMTAClass
+#	requires
+#		objectClass,
+#		sendmailMTAClassName,
+#	allows
+#		sendmailMTACluster,
+#		sendmailMTAHost,
+#		sendmailMTAClassValue,
+#		sendmailMTAClassSearch,
+#		sendmailMTAClassURL,
+#		Description
+
+objectclass ( 1.3.6.1.4.1.6152.10.3.2.15
+	NAME 'sendmailMTAClass'
+	SUP sendmailMTA STRUCTURAL
+	DESC 'Sendmail MTA class definition'
+	MUST sendmailMTAClassName
+	MAY ( sendmailMTACluster $ sendmailMTAHost $
+		sendmailMTAClassValue $ sendmailMTAClassSearch $
+		sendmailMTAClassURL $ Description ) )

+ 18 - 0
example/extend-osixia-openldap/certs/ca.crt

@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC0zCCAlmgAwIBAgIUCfQ+m0pgZ/BjYAJvxrn/bdGNZokwCgYIKoZIzj0EAwMw
+gZYxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxBMUEgQ2FyIFdhc2gxJDAiBgNVBAsT
+G0luZm9ybWF0aW9uIFRlY2hub2xvZ3kgRGVwLjEUMBIGA1UEBxMLQWxidXF1ZXJx
+dWUxEzARBgNVBAgTCk5ldyBNZXhpY28xHzAdBgNVBAMTFmRvY2tlci1saWdodC1i
+YXNlaW1hZ2UwHhcNMTUxMjIzMTM1MzAwWhcNMjAxMjIxMTM1MzAwWjCBljELMAkG
+A1UEBhMCVVMxFTATBgNVBAoTDEExQSBDYXIgV2FzaDEkMCIGA1UECxMbSW5mb3Jt
+YXRpb24gVGVjaG5vbG9neSBEZXAuMRQwEgYDVQQHEwtBbGJ1cXVlcnF1ZTETMBEG
+A1UECBMKTmV3IE1leGljbzEfMB0GA1UEAxMWZG9ja2VyLWxpZ2h0LWJhc2VpbWFn
+ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMZf/12pupAgl8Sm+j8GmjNeNbSFAZWW
+oTmIvf2Mu4LWPHy4bTldkQgHUbBpT3xWz8f0lB/ru7596CHsGoL2A28hxuclq5hb
+Ux1yrIt3bJIY3TuiX25HGTe6kGCJPB1aLaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG
+A1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFE+l6XolXDAYnGLTl4W6ULKHrm74
+MB8GA1UdIwQYMBaAFE+l6XolXDAYnGLTl4W6ULKHrm74MAoGCCqGSM49BAMDA2gA
+MGUCMQCXLZj8okyxW6UTL7hribUUbu63PbjuwIXnwi420DdNsvA9A7fcQEXScWFL
+XAGC8rkCMGcqwXZPSRfwuI9r+R11gTrP92hnaVxs9sjRikctpkQpOyNlIXFPopFK
+8FdfWPypvA==
+-----END CERTIFICATE-----

+ 18 - 0
example/extend-osixia-openldap/certs/cert.crt

@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC8TCCAnegAwIBAgIIXM3vfP16npQwCgYIKoZIzj0EAwMwgZYxCzAJBgNVBAYT
+AlVTMRUwEwYDVQQKEwxBMUEgQ2FyIFdhc2gxJDAiBgNVBAsTG0luZm9ybWF0aW9u
+IFRlY2hub2xvZ3kgRGVwLjEUMBIGA1UEBxMLQWxidXF1ZXJxdWUxEzARBgNVBAgT
+Ck5ldyBNZXhpY28xHzAdBgNVBAMTFmRvY2tlci1saWdodC1iYXNlaW1hZ2UwHhcN
+MTYwMTEwMDk1OTAwWhcNMTcwMTA5MDk1OTAwWjCBjDELMAkGA1UEBhMCVVMxFTAT
+BgNVBAoTDEExQSBDYXIgV2FzaDEkMCIGA1UECxMbSW5mb3JtYXRpb24gVGVjaG5v
+bG9neSBEZXAuMRQwEgYDVQQHEwtBbGJ1cXVlcnF1ZTETMBEGA1UECBMKTmV3IE1l
+eGljbzEVMBMGA1UEAxMMZTNkMTNlZmQ5YjMxMHYwEAYHKoZIzj0CAQYFK4EEACID
+YgAElkKdHmSbyRwpEGkaMW4Hq9XHpEWLnet7mkqpigQMCMNhuUKLThKYWOm8ZLK3
+Yo21jeb/dXF2LiXgd/Jjaenas3KXkb/FMJESQVTvZ3dwcQwOgyEpCTbjs2GSbiK7
+1JuNo4GZMIGWMA4GA1UdDwEB/wQEAwIAoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
+KwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUtXICfw5YqIkZi83qxOpB
+P5UaHXcwHwYDVR0jBBgwFoAUT6XpeiVcMBicYtOXhbpQsoeubvgwFwYDVR0RBBAw
+DoIMZTNkMTNlZmQ5YjMxMAoGCCqGSM49BAMDA2gAMGUCMQC20jjmVWusnspeGSOr
+Yk+pWNdbTKzNLaU8mR3X2gCs07xrws6cFJBdx/lx8KxE05YCMEaD5kdea/HkaBzy
+5xJZJAuIMpj56AR3J4od9aa3x74NDpgOObRDc4Y7ErAWqjsf3A==
+-----END CERTIFICATE-----

+ 6 - 0
example/extend-osixia-openldap/certs/cert.key

@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDAXhGbcS1lHXUJ6cvJZHlm/nHmjJ+wzj+REhgIlQUhf+mDELlwgJEJo
+Hnag8Ow0xMygBwYFK4EEACKhZANiAASWQp0eZJvJHCkQaRoxbger1cekRYud63ua
+SqmKBAwIw2G5QotOEphY6bxksrdijbWN5v91cXYuJeB38mNp6dqzcpeRv8UwkRJB
+VO9nd3BxDA6DISkJNuOzYZJuIrvUm40=
+-----END EC PRIVATE KEY-----

+ 8 - 0
example/extend-osixia-openldap/certs/dhparam.pem

@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA7adhygsX/CvbcQBlSEKBmm0D0+hVfIttcftyFTuDPNok4yDJUBUF
+zzc7X/i3PUMzANhShBrngBaXbOhVk3QcjMC623TPhFmILx0r236+aQEUGnlwN73M
+RUFM6EblYgH4+E4nv+JLwzHdO72+qMAd92rtzVMiaDlCWghH6wdAFoasTsT6Posc
+F5T8WCkzFAZeVhNGRKPP6k3l2BjvRJzkwYMMJrxaIYznMEK6H5CYIqZcpeAB3d2B
+NaZXLxFCemLrSS16UHrH1modEe8yjrOaE5+ZesGAA9onsNRZkAJp0x/pRaO/+rHn
+Q5QVCQCzxY16UsLzH0q/P80xPMU7BMoocwIBAg==
+-----END DH PARAMETERS-----

+ 10 - 0
example/extend-osixia-openldap/environment/my-env.yaml

@@ -0,0 +1,10 @@
+# This is the default image configuration file
+# These values will persists in container environment.
+
+# All environment variables used after the container first start
+# must be defined here.
+# more information : https://github.com/osixia/docker-light-baseimage
+
+# General container configuration
+# see table 5.1 in http://www.openldap.org/doc/admin24/slapdconf2.html for the available log levels.
+LDAP_LOG_LEVEL: 0

+ 46 - 0
example/extend-osixia-openldap/environment/my-env.yaml.startup

@@ -0,0 +1,46 @@
+# This is the default image startup configuration file
+# this file define environment variables used during the container **first start** in **startup files**.
+
+# This file is deleted right after startup files are processed for the first time,
+# after that all these values will not be available in the container environment.
+# This helps to keep your container configuration secret.
+# more information : https://github.com/osixia/docker-light-baseimage
+
+# Required and used for new ldap server only
+LDAP_ORGANISATION: Example Inc.
+LDAP_DOMAIN: example.org
+LDAP_ADMIN_PASSWORD: Adm1n!
+LDAP_CONFIG_PASSWORD: c0nfig
+
+LDAP_READONLY_USER: true
+LDAP_READONLY_USER_USERNAME: readonly
+LDAP_READONLY_USER_PASSWORD: passwr0rd!
+
+# Tls
+LDAP_TLS: true
+LDAP_TLS_CRT_FILENAME: cert.crt
+LDAP_TLS_KEY_FILENAME: cert.key
+LDAP_TLS_CA_CRT_FILENAME: ca.crt
+
+LDAP_TLS_ENFORCE: false
+LDAP_TLS_CIPHER_SUITE: SECURE256:-VERS-SSL3.0
+LDAP_TLS_PROTOCOL_MIN: 3.1
+LDAP_TLS_VERIFY_CLIENT: never
+
+# Replication
+LDAP_REPLICATION: false
+# variables $LDAP_BASE_DN, $LDAP_ADMIN_PASSWORD, $LDAP_CONFIG_PASSWORD
+# are automaticaly replaced at run time
+
+# if you want to add replication to an existing ldap
+# adapt LDAP_REPLICATION_CONFIG_SYNCPROV and LDAP_REPLICATION_HDB_SYNCPROV to your configuration
+# avoid using $LDAP_BASE_DN, $LDAP_ADMIN_PASSWORD and $LDAP_CONFIG_PASSWORD variables
+LDAP_REPLICATION_CONFIG_SYNCPROV: binddn="cn=admin,cn=config" bindmethod=simple credentials=$LDAP_CONFIG_PASSWORD searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1 starttls=critical
+LDAP_REPLICATION_HDB_SYNCPROV: binddn="cn=admin,$LDAP_BASE_DN" bindmethod=simple credentials=$LDAP_ADMIN_PASSWORD searchbase="$LDAP_BASE_DN" type=refreshAndPersist interval=00:00:00:10 retry="60 +" timeout=1 starttls=critical
+LDAP_REPLICATION_HOSTS:
+  - ldap://ldap.example.org # The order must be the same on all ldap servers
+  - ldap://ldap2.example.org
+
+
+# Remove config after setup
+LDAP_REMOVE_CONFIG_AFTER_SETUP: false

+ 100 - 0
example/kubernetes/simple/ldap-rc.yaml

@@ -0,0 +1,100 @@
+apiVersion: v1
+kind: ReplicationController
+metadata:
+  name: ldap-controller
+  labels:
+    app: ldap
+spec:
+  replicas: 1
+  selector:
+    app: ldap
+  template:
+    metadata:
+      labels:
+        app: ldap
+    spec:
+      containers:
+        - name: ldap
+          image: osixia/openldap:1.1.0
+          volumeMounts:
+            - name: ldap-data
+              mountPath: /var/lib/ldap
+            - name: ldap-config
+              mountPath: /etc/ldap/slapd.d
+            - name: ldap-certs
+              mountPath: /container/service/slapd/assets/certs
+          ports:
+            - containerPort: 389
+              name: openldap
+          env:
+            - name: LDAP_LOG_LEVEL
+              value: "256"
+            - name: LDAP_ORGANISATION
+              value: "Example Inc."
+            - name: LDAP_DOMAIN
+              value: "example.org"
+            - name: LDAP_ADMIN_PASSWORD
+              value: "admin"
+            - name: LDAP_CONFIG_PASSWORD
+              value: "config"
+            - name: LDAP_READONLY_USER
+              value: "false"
+            - name: LDAP_READONLY_USER_USERNAME
+              value: "readonly"
+            - name: LDAP_READONLY_USER_PASSWORD
+              value: "readonly"
+            - name: LDAP_TLS
+              value: "true"
+            - name: LDAP_TLS_CRT_FILENAME
+              value: "ldap.crt"
+            - name: LDAP_TLS_KEY_FILENAME
+              value: "ldap.key"
+            - name: LDAP_TLS_CA_CRT_FILENAME
+              value: "ca.crt"
+            - name: LDAP_TLS_ENFORCE
+              value: "false"
+            - name: LDAP_TLS_CIPHER_SUITE
+              value: "SECURE256:-VERS-SSL3.0"
+            - name: LDAP_TLS_PROTOCOL_MIN
+              value: "3.1"
+            - name: LDAP_TLS_VERIFY_CLIENT
+              value: "demand"
+            - name: LDAP_REPLICATION
+              value: "false"
+            - name: LDAP_REPLICATION_CONFIG_SYNCPROV
+              value: "binddn=\"cn=admin,cn=config\" bindmethod=simple credentials=$LDAP_CONFIG_PASSWORD searchbase=\"cn=config\" type=refreshAndPersist retry=\"60 +\" timeout=1 starttls=critical"
+            - name: LDAP_REPLICATION_HDB_SYNCPROV
+              value: "binddn=\"cn=admin,$LDAP_BASE_DN\" bindmethod=simple credentials=$LDAP_ADMIN_PASSWORD searchbase=\"$LDAP_BASE_DN\" type=refreshAndPersist interval=00:00:00:10 retry=\"60 +\" timeout=1 starttls=critical"
+            - name: LDAP_REPLICATION_HOSTS
+              value: "#PYTHON2BASH:['ldap://ldap-one-service', 'ldap://ldap-two-service']"
+            - name: LDAP_REMOVE_CONFIG_AFTER_SETUP
+              value: "true"
+        - name: ldap-backup
+          image: osixia/openldap-backup:0.1.7
+          volumeMounts:
+            - name: ldap-data
+              mountPath: /var/lib/ldap
+            - name: ldap-config
+              mountPath: /etc/ldap/slapd.d
+            - name: ldap-backup
+              mountPath: /data/backup
+          env:
+            - name: LDAP_BACKUP_CONFIG_CRON_EXP
+              value: "15 1 * * *"
+            - name: LDAP_BACKUP_DATA_CRON_EXP
+              value: "20 1 * * *"
+            - name: LDAP_BACKUP_TTL
+              value: "15"
+      volumes:
+        - name: ldap-data
+          hostPath:
+            path: "/data/ldap/db"
+        - name: ldap-config
+          hostPath:
+            path: "/data/ldap/config"
+        - name: ldap-backup
+          hostPath:
+            path: "/data/ldap/backup"
+        - name: ldap-certs
+          hostPath:
+            path: "/data/ldap/certs"

+ 11 - 0
example/kubernetes/simple/ldap-svc.yaml

@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app: ldap
+  name: ldap-service
+spec:
+  ports:
+    - port: 389
+  selector:
+    app: ldap

+ 10 - 0
example/kubernetes/using-secrets/environment/file-to-base64.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# print a file encode into base64
+
+FILE=$1
+
+FILE_ENCODED=$(cat $FILE | base64)
+FILE_ENCODED=`echo ${FILE_ENCODED} | tr -d '\n'`
+FILE_ENCODED=`echo ${FILE_ENCODED} | tr -d ' '`
+echo  $FILE_ENCODED

+ 10 - 0
example/kubernetes/using-secrets/environment/my-env.yaml

@@ -0,0 +1,10 @@
+# This is the default image configuration file
+# These values will persists in container environment.
+
+# All environment variables used after the container first start
+# must be defined here.
+# more information : https://github.com/osixia/docker-light-baseimage
+
+# General container configuration
+# see table 5.1 in http://www.openldap.org/doc/admin24/slapdconf2.html for the available log levels.
+LDAP_LOG_LEVEL: 0

+ 46 - 0
example/kubernetes/using-secrets/environment/my-env.yaml.startup

@@ -0,0 +1,46 @@
+# This is the default image startup configuration file
+# this file define environment variables used during the container **first start** in **startup files**.
+
+# This file is deleted right after startup files are processed for the first time,
+# after that all these values will not be available in the container environment.
+# This helps to keep your container configuration secret.
+# more information : https://github.com/osixia/docker-light-baseimage
+
+# Required and used for new ldap server only
+LDAP_ORGANISATION: Example Inc.
+LDAP_DOMAIN: example.org
+LDAP_ADMIN_PASSWORD: Adm1n!
+LDAP_CONFIG_PASSWORD: c0nfig
+
+LDAP_READONLY_USER: true
+LDAP_READONLY_USER_USERNAME: readonly
+LDAP_READONLY_USER_PASSWORD: passwr0rd!
+
+# Tls
+LDAP_TLS: true
+LDAP_TLS_CRT_FILENAME: cert.crt
+LDAP_TLS_KEY_FILENAME: cert.key
+LDAP_TLS_CA_CRT_FILENAME: ca.crt
+
+LDAP_TLS_ENFORCE: false
+LDAP_TLS_CIPHER_SUITE: SECURE256:-VERS-SSL3.0
+LDAP_TLS_PROTOCOL_MIN: 3.1
+LDAP_TLS_VERIFY_CLIENT: never
+
+# Replication
+LDAP_REPLICATION: false
+# variables $LDAP_BASE_DN, $LDAP_ADMIN_PASSWORD, $LDAP_CONFIG_PASSWORD
+# are automaticaly replaced at run time
+
+# if you want to add replication to an existing ldap
+# adapt LDAP_REPLICATION_CONFIG_SYNCPROV and LDAP_REPLICATION_HDB_SYNCPROV to your configuration
+# avoid using $LDAP_BASE_DN, $LDAP_ADMIN_PASSWORD and $LDAP_CONFIG_PASSWORD variables
+LDAP_REPLICATION_CONFIG_SYNCPROV: binddn="cn=admin,cn=config" bindmethod=simple credentials=$LDAP_CONFIG_PASSWORD searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1 starttls=critical
+LDAP_REPLICATION_HDB_SYNCPROV: binddn="cn=admin,$LDAP_BASE_DN" bindmethod=simple credentials=$LDAP_ADMIN_PASSWORD searchbase="$LDAP_BASE_DN" type=refreshAndPersist interval=00:00:00:10 retry="60 +" timeout=1 starttls=critical
+LDAP_REPLICATION_HOSTS:
+  - ldap://ldap.example.org # The order must be the same on all ldap servers
+  - ldap://ldap2.example.org
+
+
+# Remove config after setup
+LDAP_REMOVE_CONFIG_AFTER_SETUP: false

+ 68 - 0
example/kubernetes/using-secrets/ldap-rc.yaml

@@ -0,0 +1,68 @@
+apiVersion: v1
+kind: ReplicationController
+metadata:
+  name: ldap-controller
+  labels:
+    app: ldap
+spec:
+  replicas: 1
+  selector:
+    app: ldap
+  template:
+    metadata:
+      labels:
+        app: ldap
+    spec:
+      containers:
+        - name: ldap
+          image: osixia/openldap:1.1.0
+          command:
+          - --copy-service
+          volumeMounts:
+            - name: ldap-data
+              mountPath: /var/lib/ldap
+            - name: ldap-config
+              mountPath: /etc/ldap/slapd.d
+            - name: ldap-certs
+              mountPath: /container/service/slapd/assets/certs
+            - name: secret-volume
+              mountPath: /container/environment/01-custom
+            - name: container-run
+              mountPath: /container/run
+          ports:
+            - containerPort: 389
+              name: openldap
+        - name: ldap-backup
+          image: osixia/openldap-backup:0.1.7
+          volumeMounts:
+            - name: ldap-data
+              mountPath: /var/lib/ldap
+            - name: ldap-config
+              mountPath: /etc/ldap/slapd.d
+            - name: ldap-backup
+              mountPath: /data/backup
+          env:
+            - name: LDAP_BACKUP_CONFIG_CRON_EXP
+              value: "15 1 * * *"
+            - name: LDAP_BACKUP_DATA_CRON_EXP
+              value: "20 1 * * *"
+            - name: LDAP_BACKUP_TTL
+              value: "15"
+      volumes:
+        - name: ldap-data
+          hostPath:
+            path: "/data/ldap/db"
+        - name: ldap-config
+          hostPath:
+            path: "/data/ldap/config"
+        - name: ldap-backup
+          hostPath:
+            path: "/data/ldap/backup"
+        - name: ldap-certs
+          hostPath:
+            path: "/data/ldap/certs"
+        - name: "secret-volume"
+          secret:
+            secretName: "ldap-secret"
+        - name: container-run
+          emptyDir: {}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 10 - 0
example/kubernetes/using-secrets/ldap-secret.yaml


+ 11 - 0
example/kubernetes/using-secrets/ldap-svc.yaml

@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app: ldap
+  name: ldap-service
+spec:
+  ports:
+    - port: 389
+  selector:
+    app: ldap

+ 12 - 12
image/Dockerfile

@@ -1,20 +1,20 @@
-FROM osixia/light-baseimage:0.2.0
+# Use osixia/light-baseimage
+# sources: https://github.com/osixia/docker-light-baseimage
+FROM osixia/light-baseimage:0.2.1
 MAINTAINER Bertrand Gouny <[email protected]>
 
-# Use baseimage's init system.
-# https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/run
-CMD ["/container/tool/run"]
-
 # Add openldap user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
 RUN groupadd -r openldap && useradd -r -g openldap openldap
 
-# Install OpenLDAP, ldap-utils and ssl-helper from baseimage and remove default ldap db
-# https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/install-service-available
+# Install OpenLDAP, ldap-utils and cfssl from baseimage
+# sources: https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/add-service-available
+#          https://github.com/osixia/docker-light-baseimage/blob/stable/image/service-available/:cfssl/download.sh
 RUN apt-get -y update \
-    && /container/tool/install-service-available ssl-helper-gnutls \
+    && /container/tool/add-service-available :cfssl \
 	  && LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes --no-install-recommends \
-	     slapd ldap-utils \
-	  && rm -rf /var/lib/ldap /etc/ldap/slapd.d
+       ldap-utils \
+       openssl \
+       slapd
 
 # Add service directory to /container/service
 ADD service /container/service
@@ -26,10 +26,10 @@ RUN /container/tool/install-service \
     && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
 
 # Add default env variables
-ADD env.yaml /container/environment/env.yaml
+ADD environment /container/environment/99-default
 
 # Set OpenLDAP data and config directories in a data volume
 VOLUME ["/var/lib/ldap", "/etc/ldap/slapd.d"]
 
-# Expose default ports for ldap and ldaps
+# Expose default ldap and ldaps ports
 EXPOSE 389 636

+ 10 - 0
image/environment/default.yaml

@@ -0,0 +1,10 @@
+# This is the default image configuration file
+# These values will persists in container environment.
+
+# All environment variables used after the container first start
+# must be defined here.
+# more information : https://github.com/osixia/docker-light-baseimage
+
+# General container configuration
+# see table 5.1 in http://www.openldap.org/doc/admin24/slapdconf2.html for the available log levels.
+LDAP_LOG_LEVEL: 256

+ 15 - 3
image/env.yaml → image/environment/default.yaml.startup

@@ -1,6 +1,10 @@
-# General container configuration
-# see table 5.1 in http://www.openldap.org/doc/admin24/slapdconf2.html for the available log levels.
-LDAP_LOG_LEVEL: 256
+# This is the default image startup configuration file
+# this file define environment variables used during the container **first start** in **startup files**.
+
+# This file is deleted right after startup files are processed for the first time,
+# after that all these values will not be available in the container environment.
+# This helps to keep your container configuration secret.
+# more information : https://github.com/osixia/docker-light-baseimage
 
 # Required and used for new ldap server only
 LDAP_ORGANISATION: Example Inc.
@@ -18,6 +22,7 @@ LDAP_TLS_CRT_FILENAME: ldap.crt
 LDAP_TLS_KEY_FILENAME: ldap.key
 LDAP_TLS_CA_CRT_FILENAME: ca.crt
 
+LDAP_TLS_ENFORCE: false
 LDAP_TLS_CIPHER_SUITE: SECURE256:-VERS-SSL3.0
 LDAP_TLS_PROTOCOL_MIN: 3.1
 LDAP_TLS_VERIFY_CLIENT: demand
@@ -35,3 +40,10 @@ LDAP_REPLICATION_HDB_SYNCPROV: binddn="cn=admin,$LDAP_BASE_DN" bindmethod=simple
 LDAP_REPLICATION_HOSTS:
   - ldap://ldap.example.org # The order must be the same on all ldap servers
   - ldap://ldap2.example.org
+
+
+# Remove config after setup
+LDAP_REMOVE_CONFIG_AFTER_SETUP: true
+
+# cfssl environment variables prefix
+LDAP_CFSSL_PREFIX: ldap # cfssl-helper first search config from LDAP_CFSSL_* variables, before CFSSL_* variables.

+ 1 - 1
image/service/slapd/assets/certs/README.md

@@ -1,2 +1,2 @@
 Add your tls server certificate, key and the CA certificate (if any) here
-or during docker run mount a data volume with thoses files to /container/service/slapd/assets/certs
+or during docker run mount a data volume with those files to /container/service/slapd/assets/certs

+ 4 - 4
image/service/slapd/assets/config/tls/tls-enable.ldif

@@ -7,16 +7,16 @@ replace: olcTLSProtocolMin
 olcTLSProtocolMin: {{ LDAP_TLS_PROTOCOL_MIN }}
 -
 replace: olcTLSCACertificateFile
-olcTLSCACertificateFile: /container/service/slapd/assets/certs/{{ LDAP_TLS_CA_CRT_FILENAME }}
+olcTLSCACertificateFile: {{ LDAP_TLS_CA_CRT_PATH }}
 -
 replace: olcTLSCertificateFile
-olcTLSCertificateFile: /container/service/slapd/assets/certs/{{ LDAP_TLS_CRT_FILENAME }}
+olcTLSCertificateFile: {{ LDAP_TLS_CRT_PATH }}
 -
 replace: olcTLSCertificateKeyFile
-olcTLSCertificateKeyFile: /container/service/slapd/assets/certs/{{ LDAP_TLS_KEY_FILENAME }}
+olcTLSCertificateKeyFile: {{ LDAP_TLS_KEY_PATH }}
 -
 replace: olcTLSDHParamFile
-olcTLSDHParamFile: /container/service/slapd/assets/certs/dhparam.pem
+olcTLSDHParamFile: {{ LDAP_TLS_DH_PARAM_PATH }}
 -
 replace: olcTLSVerifyClient
 olcTLSVerifyClient: {{ LDAP_TLS_VERIFY_CLIENT }}

+ 4 - 0
image/service/slapd/assets/config/tls/tls-enforce-disable.ldif

@@ -0,0 +1,4 @@
+dn: cn=config
+changetype:  modify
+delete: olcSecurity
+olcSecurity: tls=1

+ 4 - 0
image/service/slapd/assets/config/tls/tls-enforce-enable.ldif

@@ -0,0 +1,4 @@
+dn: cn=config
+changetype:  modify
+add: olcSecurity
+olcSecurity: tls=1

+ 19 - 15
image/service/slapd/assets/schema-to-ldif.sh

@@ -1,5 +1,9 @@
 #!/bin/bash
 
+# set -x (bash debug) if log level is trace
+# https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/log-helper
+log-helper level eq trace && set -x
+
 SCHEMAS=$1
 
 tmpd=`mktemp -d`
@@ -17,8 +21,8 @@ done
 slaptest -f convert.dat -F .
 
 if [ $? -ne 0 ] ; then
-    echo "slaptest conversion failed"
-    exit 
+    log-helper error "slaptest conversion failed"
+    exit
 fi
 
 for schema in ${SCHEMAS} ; do
@@ -27,24 +31,24 @@ for schema in ${SCHEMAS} ; do
     schema_dir=`dirname ${fullpath}`
     ldif_file=${schema_name}.ldif
 
-    find . -name *${schema_name}.ldif -exec mv '{}' ./${ldif_file} \;
+    find . -name *\}${schema_name}.ldif -exec mv '{}' ./${ldif_file} \;
 
     # TODO: these sed invocations could all be combined
-    sed -i --follow-symlinks "/dn:/ c dn: cn=${schema_name},cn=schema,cn=config" ${ldif_file}
-    sed -i --follow-symlinks "/cn:/ c cn: ${schema_name}" ${ldif_file}
-    sed -i --follow-symlinks '/structuralObjectClass/ d' ${ldif_file}
-    sed -i --follow-symlinks '/entryUUID/ d' ${ldif_file}
-    sed -i --follow-symlinks '/creatorsName/ d' ${ldif_file}
-    sed -i --follow-symlinks '/createTimestamp/ d' ${ldif_file}
-    sed -i --follow-symlinks '/entryCSN/ d' ${ldif_file}
-    sed -i --follow-symlinks '/modifiersName/ d' ${ldif_file}
-    sed -i --follow-symlinks '/modifyTimestamp/ d' ${ldif_file}
-    
+    sed -i "/dn:/ c dn: cn=${schema_name},cn=schema,cn=config" ${ldif_file}
+    sed -i "/cn:/ c cn: ${schema_name}" ${ldif_file}
+    sed -i '/structuralObjectClass/ d' ${ldif_file}
+    sed -i '/entryUUID/ d' ${ldif_file}
+    sed -i '/creatorsName/ d' ${ldif_file}
+    sed -i '/createTimestamp/ d' ${ldif_file}
+    sed -i '/entryCSN/ d' ${ldif_file}
+    sed -i '/modifiersName/ d' ${ldif_file}
+    sed -i '/modifyTimestamp/ d' ${ldif_file}
+
     # slapd seems to be very sensitive to how a file ends. There should be no blank lines.
-    sed -i --follow-symlinks '/^ *$/d' ${ldif_file}
+    sed -i '/^ *$/d' ${ldif_file}
 
     mv ${ldif_file} ${schema_dir}
 done
 
 popd >>/dev/null
-rm -rf $tmpd
+rm -rf $tmpd

+ 0 - 304
image/service/slapd/container-start.sh

@@ -1,304 +0,0 @@
-#!/bin/bash -e
-
-FIRST_START_DONE="/etc/docker-openldap-first-start-done"
-WAS_STARTED_WITH_TLS="/etc/ldap/slapd.d/docker-openldap-was-started-with-tls"
-WAS_STARTED_WITH_REPLICATION="/etc/ldap/slapd.d/docker-openldap-was-started-with-replication"
-
-# Reduce maximum number of number of open file descriptors to 1024
-# otherwise slapd consumes two orders of magnitude more of RAM
-# see https://github.com/docker/docker/issues/8231
-ulimit -n 1024
-
-# fix file permissions
-chown -R openldap:openldap /var/lib/ldap
-chown -R openldap:openldap /etc/ldap
-chown -R openldap:openldap /container/service/slapd
-
-# container first start
-if [ ! -e "$FIRST_START_DONE" ]; then
-
-  function get_ldap_base_dn() {
-    LDAP_BASE_DN=""
-    IFS='.' read -ra LDAP_BASE_DN_TABLE <<< "$LDAP_DOMAIN"
-    for i in "${LDAP_BASE_DN_TABLE[@]}"; do
-      EXT="dc=$i,"
-      LDAP_BASE_DN=$LDAP_BASE_DN$EXT
-    done
-
-    LDAP_BASE_DN=${LDAP_BASE_DN::-1}
-  }
-
-  function is_new_schema() {
-    local COUNT=$(ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config cn | grep -c $1)
-    if [ "$COUNT" -eq 0 ]; then
-      echo 1
-    else
-      echo 0
-    fi
-  }
-
-  function check_tls_files() {
-
-    local CA_CRT=$1
-    local LDAP_CRT=$2
-    local LDAP_KEY=$3
-
-    # check certificat and key or create it
-    /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
-
-    # create DHParamFile if not found
-    [ -f /container/service/slapd/assets/certs/dhparam.pem ] || certtool --generate-dh-param --sec-param=high --outfile=/container/service/slapd/assets/certs/dhparam.pem
-    chmod 600 /container/service/slapd/assets/certs/dhparam.pem
-
-    # fix file permissions
-    chown -R openldap:openldap /container/service/slapd
-  }
-
-
-  BOOTSTRAP=false
-
-  # database and config directory are empty -> set bootstrap config
-  if [ -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
-
-    BOOTSTRAP=true
-    echo "database and config directory are empty"
-    echo "-> set bootstrap config"
-
-    cat <<EOF | debconf-set-selections
-slapd slapd/internal/generated_adminpw password ${LDAP_ADMIN_PASSWORD}
-slapd slapd/internal/adminpw password ${LDAP_ADMIN_PASSWORD}
-slapd slapd/password2 password ${LDAP_ADMIN_PASSWORD}
-slapd slapd/password1 password ${LDAP_ADMIN_PASSWORD}
-slapd slapd/dump_database_destdir string /var/backups/slapd-VERSION
-slapd slapd/domain string ${LDAP_DOMAIN}
-slapd shared/organization string ${LDAP_ORGANISATION}
-slapd slapd/backend string HDB
-slapd slapd/purge_database boolean true
-slapd slapd/move_old_database boolean true
-slapd slapd/allow_ldap_v2 boolean false
-slapd slapd/no_configuration boolean false
-slapd slapd/dump_database select when needed
-EOF
-
-    dpkg-reconfigure -f noninteractive slapd
-
-  elif [ -z "$(ls -A /var/lib/ldap)" ] && [ ! -z "$(ls -A /etc/ldap/slapd.d)" ]; then
-    echo "Error: the database directory (/var/lib/ldap) is empty but not the config directory (/etc/ldap/slapd.d)"
-    exit 1
-  elif [ ! -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
-    echo "the config directory (/etc/ldap/slapd.d) is empty but not the database directory (/var/lib/ldap)"
-    exit 1
-
-  else
-    # there is an existing database and config
-
-    # if the config was bootstraped with TLS
-    # to avoid error (#6) we check tls files
-    if [ -e "$WAS_STARTED_WITH_TLS" ]; then
-
-      . $WAS_STARTED_WITH_TLS
-
-      check_tls_files $PREVIOUS_LDAP_TLS_CA_CRT_FILENAME $PREVIOUS_LDAP_TLS_CRT_FILENAME $PREVIOUS_LDAP_TLS_KEY_FILENAME
-    fi
-  fi
-
-  # start OpenLDAP
-
-
-  function startOpenLDAP(){
-
-    if [ -n "$PREVIOUS_HOSTNAME" ]; then
-      PREVIOUS_HOSTNAME="ldap://$PREVIOUS_HOSTNAME"
-    fi
-
-    #start openldap normaly
-    echo "Starting openldap..."
-    slapd -h "ldap://$HOSTNAME $PREVIOUS_HOSTNAME ldap://localhost ldapi:///" -u openldap -g openldap
-    echo "[ok]"
-  }
-
-  # start OpenLDAP with previous replication configuration
-  if [ -e "$WAS_STARTED_WITH_REPLICATION" ]; then
-
-    . $WAS_STARTED_WITH_REPLICATION
-
-    if [ "$PREVIOUS_HOSTNAME" != "$HOSTNAME" ]; then
-      echo "127.0.0.2 $PREVIOUS_HOSTNAME" >> /etc/hosts
-    else
-      PREVIOUS_HOSTNAME=""
-    fi
-  fi
-
-  startOpenLDAP
-
-  # set bootstrap config part 2
-  if $BOOTSTRAP; then
-
-    # add ppolicy schema
-    ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif
-
-    # convert schemas to ldif
-    SCHEMAS=""
-    for f in $(find /container/service/slapd/assets/config/bootstrap/schema -name \*.schema -type f); do
-      SCHEMAS="$SCHEMAS ${f}"
-    done
-    /container/service/slapd/assets/schema-to-ldif.sh "$SCHEMAS"
-
-    # add schemas
-    for f in $(find /container/service/slapd/assets/config/bootstrap/schema -name \*.ldif -type f); do
-      echo "Processing file ${f}"
-      # add schema if not already exists
-      SCHEMA=$(basename "${f}" .ldif)
-      ADD_SCHEMA=$(is_new_schema $SCHEMA)
-      if [ "$ADD_SCHEMA" -eq 1 ]; then
-        echo "add schema ${SCHEMA}"
-        ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f $f
-      else
-        echo "schema ${f} already exists"
-      fi
-    done
-
-    # set config password
-    LDAP_CONFIG_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_CONFIG_PASSWORD)
-    sed -i --follow-symlinks "s|{{ LDAP_CONFIG_PASSWORD_ENCRYPTED }}|${LDAP_CONFIG_PASSWORD_ENCRYPTED}|g" /container/service/slapd/assets/config/bootstrap/ldif/01-config-password.ldif
-
-    # adapt security config file
-    get_ldap_base_dn
-    sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" /container/service/slapd/assets/config/bootstrap/ldif/02-security.ldif
-
-    # process config files in bootstrap directory (do no process files in subdirectories)
-    for f in $(find /container/service/slapd/assets/config/bootstrap/ldif  -name \*.ldif -mindepth 1 -maxdepth 1 -type f | sort); do
-      echo "Processing file ${f}"
-      ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f $f
-    done
-
-    # read only user
-    if [ "${LDAP_READONLY_USER,,}" == "true" ]; then
-
-      echo "Add read only user"
-
-      LDAP_READONLY_USER_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_READONLY_USER_PASSWORD)
-      sed -i --follow-symlinks "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
-      sed -i --follow-symlinks "s|{{ LDAP_READONLY_USER_PASSWORD_ENCRYPTED }}|${LDAP_READONLY_USER_PASSWORD_ENCRYPTED}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
-      sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
-
-      sed -i --follow-symlinks "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
-      sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
-
-      echo "Processing file /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif"
-      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
-
-      echo "Processing file /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif"
-      ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
-
-    fi
-
-  fi
-
-  # tls config
-  if [ "${LDAP_TLS,,}" == "true" ]; then
-
-    echo "Use TLS"
-
-    check_tls_files $LDAP_TLS_CA_CRT_FILENAME $LDAP_TLS_CRT_FILENAME $LDAP_TLS_KEY_FILENAME
-
-    # adapt tls ldif
-    sed -i --follow-symlinks "s|{{ LDAP_TLS_CA_CRT_FILENAME }}|${LDAP_TLS_CA_CRT_FILENAME}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
-    sed -i --follow-symlinks "s|{{ LDAP_TLS_CRT_FILENAME }}|${LDAP_TLS_CRT_FILENAME}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
-    sed -i --follow-symlinks "s|{{ LDAP_TLS_KEY_FILENAME }}|${LDAP_TLS_KEY_FILENAME}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
-
-    sed -i --follow-symlinks "s|{{ LDAP_TLS_CIPHER_SUITE }}|${LDAP_TLS_CIPHER_SUITE}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
-    sed -i --follow-symlinks "s|{{ LDAP_TLS_PROTOCOL_MIN }}|${LDAP_TLS_PROTOCOL_MIN}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
-    sed -i --follow-symlinks "s|{{ LDAP_TLS_VERIFY_CLIENT }}|${LDAP_TLS_VERIFY_CLIENT}|g" /container/service/slapd/assets/config/tls/tls-enable.ldif
-
-    ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/tls/tls-enable.ldif
-
-    [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
-    touch $WAS_STARTED_WITH_TLS
-    echo "export PREVIOUS_LDAP_TLS_CA_CRT_FILENAME=${LDAP_TLS_CA_CRT_FILENAME}" >> $WAS_STARTED_WITH_TLS
-    echo "export PREVIOUS_LDAP_TLS_CRT_FILENAME=${LDAP_TLS_CRT_FILENAME}" >> $WAS_STARTED_WITH_TLS
-    echo "export PREVIOUS_LDAP_TLS_KEY_FILENAME=${LDAP_TLS_KEY_FILENAME}" >> $WAS_STARTED_WITH_TLS
-    chmod +x $WAS_STARTED_WITH_TLS
-
-    # ldap client config
-    sed -i --follow-symlinks "s,TLS_CACERT.*,TLS_CACERT /container/service/slapd/assets/certs/${LDAP_TLS_CA_CRT_FILENAME},g" /etc/ldap/ldap.conf
-    echo "TLS_REQCERT demand" >> /etc/ldap/ldap.conf
-
-    [[ -f "$HOME/.ldaprc" ]] && rm -f $HOME/.ldaprc
-    touch $HOME/.ldaprc
-    echo "TLS_CERT /container/service/slapd/assets/certs/${LDAP_TLS_CRT_FILENAME}" >> $HOME/.ldaprc
-    echo "TLS_KEY /container/service/slapd/assets/certs/${LDAP_TLS_KEY_FILENAME}" >> $HOME/.ldaprc
-
-  else
-
-    echo "Don't use TLS"
-
-    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/tls/tls-disable.ldif || true
-    [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
-
-  fi
-
-
-  function disableReplication() {
-    echo "Try to disable replication if needed"
-    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/replication/replication-disable.ldif || true
-    [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
-  }
-
-  # replication config
-  if [ "${LDAP_REPLICATION,,}" == "true" ]; then
-
-    echo "Use replication"
-    disableReplication || true
-
-    LDAP_REPLICATION_HOSTS=($LDAP_REPLICATION_HOSTS)
-    i=1
-    for host in "${LDAP_REPLICATION_HOSTS[@]}"
-    do
-
-      # host var contain a variable name, we access to the variable value
-      host=${!host}
-
-      sed -i --follow-symlinks "s|{{ LDAP_REPLICATION_HOSTS }}|olcServerID: $i ${host}\n{{ LDAP_REPLICATION_HOSTS }}|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
-      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/slapd/assets/config/replication/replication-enable.ldif
-      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/slapd/assets/config/replication/replication-enable.ldif
-
-      ((i++))
-    done
-
-    get_ldap_base_dn
-    sed -i --follow-symlinks "s|\$LDAP_BASE_DN|$LDAP_BASE_DN|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
-    sed -i --follow-symlinks "s|\$LDAP_ADMIN_PASSWORD|$LDAP_ADMIN_PASSWORD|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
-    sed -i --follow-symlinks "s|\$LDAP_CONFIG_PASSWORD|$LDAP_CONFIG_PASSWORD|g" /container/service/slapd/assets/config/replication/replication-enable.ldif
-
-    sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS }}/d" /container/service/slapd/assets/config/replication/replication-enable.ldif
-    sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS_CONFIG_SYNC_REPL }}/d" /container/service/slapd/assets/config/replication/replication-enable.ldif
-    sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS_HDB_SYNC_REPL }}/d" /container/service/slapd/assets/config/replication/replication-enable.ldif
-
-    echo "Enable replication"
-    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f /container/service/slapd/assets/config/replication/replication-enable.ldif || true
-
-    [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
-    touch $WAS_STARTED_WITH_REPLICATION
-    echo "export PREVIOUS_HOSTNAME=${HOSTNAME}" >> $WAS_STARTED_WITH_REPLICATION
-    chmod +x $WAS_STARTED_WITH_REPLICATION
-
-  else
-
-    echo "Don't use replication"
-    disableReplication || true
-
-  fi
-
-  # stop OpenLDAP
-  SLAPD_PID=$(cat /run/slapd/slapd.pid)
-  echo "Kill slapd, pid: $SLAPD_PID"
-  kill -9 $SLAPD_PID
-  echo "[ok]"
-
-  sleep 3
-
-  touch $FIRST_START_DONE
-fi
-
-exit 0

+ 5 - 0
image/service/slapd/install.sh

@@ -0,0 +1,5 @@
+#!/bin/bash -e
+# this script is run during the image build
+
+# remove default ldap db
+rm -rf /var/lib/ldap /etc/ldap/slapd.d

+ 4 - 0
image/service/slapd/daemon.sh → image/service/slapd/process.sh

@@ -1,5 +1,9 @@
 #!/bin/bash -e
 
+# set -x (bash debug) if log level is trace
+# https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/log-helper
+log-helper level eq trace && set -x
+
 # Reduce maximum number of number of open file descriptors to 1024
 # otherwise slapd consumes two orders of magnitude more of RAM
 # see https://github.com/docker/docker/issues/8231

+ 354 - 0
image/service/slapd/startup.sh

@@ -0,0 +1,354 @@
+#!/bin/bash -e
+set -o pipefail
+
+# set -x (bash debug) if log level is trace
+# https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/log-helper
+log-helper level eq trace && set -x
+
+# Reduce maximum number of number of open file descriptors to 1024
+# otherwise slapd consumes two orders of magnitude more of RAM
+# see https://github.com/docker/docker/issues/8231
+ulimit -n 1024
+
+# fix file permissions
+chown -R openldap:openldap /var/lib/ldap
+chown -R openldap:openldap /etc/ldap
+chown -R openldap:openldap ${CONTAINER_SERVICE_DIR}/slapd
+
+FIRST_START_DONE="${CONTAINER_STATE_DIR}/slapd-first-start-done"
+WAS_STARTED_WITH_TLS="/etc/ldap/slapd.d/docker-openldap-was-started-with-tls"
+WAS_STARTED_WITH_REPLICATION="/etc/ldap/slapd.d/docker-openldap-was-started-with-replication"
+
+# CONTAINER_SERVICE_DIR and CONTAINER_STATE_DIR variables are set by
+# the baseimage run tool more info : https://github.com/osixia/docker-light-baseimage
+
+# container first start
+if [ ! -e "$FIRST_START_DONE" ]; then
+
+  #
+  # Helpers
+  #
+  function get_ldap_base_dn() {
+    LDAP_BASE_DN=""
+    IFS='.' read -ra LDAP_BASE_DN_TABLE <<< "$LDAP_DOMAIN"
+    for i in "${LDAP_BASE_DN_TABLE[@]}"; do
+      EXT="dc=$i,"
+      LDAP_BASE_DN=$LDAP_BASE_DN$EXT
+    done
+
+    LDAP_BASE_DN=${LDAP_BASE_DN::-1}
+  }
+
+  function is_new_schema() {
+    local COUNT=$(ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config cn | grep -c $1)
+    if [ "$COUNT" -eq 0 ]; then
+      echo 1
+    else
+      echo 0
+    fi
+  }
+
+  function check_tls_files() {
+
+    local CA_CRT=$1
+    local LDAP_CRT=$2
+    local LDAP_KEY=$3
+    local DH_PARAM=$4
+
+    # generate a certificate and key with cfssl tool if LDAP_CRT and LDAP_KEY files don't exists
+    # https://github.com/osixia/docker-light-baseimage/blob/stable/image/service-available/:cfssl/assets/tool/cfssl-helper
+    cfssl-helper $LDAP_CFSSL_PREFIX $LDAP_CRT $LDAP_KEY $CA_CRT
+
+    # create DHParamFile if not found
+    [ -f ${DH_PARAM} ] || openssl dhparam -out ${DH_PARAM} 2048
+    chmod 600 ${DH_PARAM}
+
+    # fix file permissions
+    chown -R openldap:openldap ${CONTAINER_SERVICE_DIR}/slapd
+  }
+
+  #
+  # Global variables
+  #
+  BOOTSTRAP=false
+
+  #
+  # database and config directory are empty
+  # setup bootstrap config - Part 1
+  #
+  if [ -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
+
+    BOOTSTRAP=true
+    log-helper info "Database and config directory are empty..."
+    log-helper info "Init new ldap server..."
+
+    cat <<EOF | debconf-set-selections
+slapd slapd/internal/generated_adminpw password ${LDAP_ADMIN_PASSWORD}
+slapd slapd/internal/adminpw password ${LDAP_ADMIN_PASSWORD}
+slapd slapd/password2 password ${LDAP_ADMIN_PASSWORD}
+slapd slapd/password1 password ${LDAP_ADMIN_PASSWORD}
+slapd slapd/dump_database_destdir string /var/backups/slapd-VERSION
+slapd slapd/domain string ${LDAP_DOMAIN}
+slapd shared/organization string ${LDAP_ORGANISATION}
+slapd slapd/backend string HDB
+slapd slapd/purge_database boolean true
+slapd slapd/move_old_database boolean true
+slapd slapd/allow_ldap_v2 boolean false
+slapd slapd/no_configuration boolean false
+slapd slapd/dump_database select when needed
+EOF
+
+    dpkg-reconfigure -f noninteractive slapd
+
+  #
+  # Error: the database directory (/var/lib/ldap) is empty but not the config directory (/etc/ldap/slapd.d)
+  #
+  elif [ -z "$(ls -A /var/lib/ldap)" ] && [ ! -z "$(ls -A /etc/ldap/slapd.d)" ]; then
+    log-helper error "Error: the database directory (/var/lib/ldap) is empty but not the config directory (/etc/ldap/slapd.d)"
+    exit 1
+
+  #
+  # Error: the config directory (/etc/ldap/slapd.d) is empty but not the database directory (/var/lib/ldap)
+  #
+  elif [ ! -z "$(ls -A /var/lib/ldap)" ] && [ -z "$(ls -A /etc/ldap/slapd.d)" ]; then
+    log-helper error "Error: the config directory (/etc/ldap/slapd.d) is empty but not the database directory (/var/lib/ldap)"
+    exit 1
+
+  #
+  # An existing database and config are provided
+  #
+  else
+    # if the config was bootstraped with TLS
+    # to avoid error (#6) we check tls files
+    if [ -e "$WAS_STARTED_WITH_TLS" ]; then
+      source $WAS_STARTED_WITH_TLS
+      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
+    fi
+  fi
+
+  #
+  # start OpenLDAP
+  #
+
+  # get previous hostname if OpenLDAP was started with replication
+  # to avoid configuration pbs
+  PREVIOUS_HOSTNAME_PARAM=""
+  if [ -e "$WAS_STARTED_WITH_REPLICATION" ]; then
+
+    source $WAS_STARTED_WITH_REPLICATION
+
+    # if previous hostname != current hostname
+    # set previous hostname to a loopback ip in /etc/hosts
+    if [ "$PREVIOUS_HOSTNAME" != "$HOSTNAME" ]; then
+      echo "127.0.0.2 $PREVIOUS_HOSTNAME" >> /etc/hosts
+      PREVIOUS_HOSTNAME_PARAM="ldap://$PREVIOUS_HOSTNAME"
+    fi
+  fi
+
+  # start OpenLDAP
+  log-helper info "Start OpenLDAP..."
+  slapd -h "ldap://$HOSTNAME $PREVIOUS_HOSTNAME_PARAM ldap://localhost ldapi:///" -u openldap -g openldap
+
+
+  #
+  # setup bootstrap config - Part 2
+  #
+  if $BOOTSTRAP; then
+
+    log-helper info "Add bootstrap schemas..."
+
+    # add ppolicy schema
+    ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif 2>&1 | log-helper debug
+
+    # convert schemas to ldif
+    SCHEMAS=""
+    for f in $(find ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/schema -name \*.schema -type f); do
+      SCHEMAS="$SCHEMAS ${f}"
+    done
+    ${CONTAINER_SERVICE_DIR}/slapd/assets/schema-to-ldif.sh "$SCHEMAS"
+
+    # add converted schemas
+    for f in $(find ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/schema -name \*.ldif -type f); do
+      log-helper debug "Processing file ${f}"
+      # add schema if not already exists
+      SCHEMA=$(basename "${f}" .ldif)
+      ADD_SCHEMA=$(is_new_schema $SCHEMA)
+      if [ "$ADD_SCHEMA" -eq 1 ]; then
+        ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f $f 2>&1 | log-helper debug
+      else
+        log-helper info "schema ${f} already exists"
+      fi
+    done
+
+    # set config password
+    LDAP_CONFIG_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_CONFIG_PASSWORD)
+    sed -i "s|{{ LDAP_CONFIG_PASSWORD_ENCRYPTED }}|${LDAP_CONFIG_PASSWORD_ENCRYPTED}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/01-config-password.ldif
+
+    # adapt security config file
+    get_ldap_base_dn
+    sed -i "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/02-security.ldif
+
+    # process config files (*.ldif) in bootstrap directory (do no process files in subdirectories)
+    log-helper info "Add bootstrap ldif..."
+    for f in $(find ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif -mindepth 1 -maxdepth 1 -type f -name \*.ldif  | sort); do
+      log-helper debug "Processing file ${f}"
+      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
+    done
+
+    # read only user
+    if [ "${LDAP_READONLY_USER,,}" == "true" ]; then
+
+      log-helper info "Add read only user..."
+
+      LDAP_READONLY_USER_PASSWORD_ENCRYPTED=$(slappasswd -s $LDAP_READONLY_USER_PASSWORD)
+      sed -i "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
+      sed -i "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
+      sed -i "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
+
+      sed -i "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
+      sed -i "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
+
+      log-helper debug "Processing file ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif"
+      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
+
+      log-helper debug "Processing file ${CONTAINER_SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif"
+      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
+
+    fi
+  fi
+
+  #
+  # TLS config
+  #
+  if [ "${LDAP_TLS,,}" == "true" ]; then
+
+    log-helper info "Add TLS config..."
+
+    LDAP_TLS_CA_CRT_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_CA_CRT_FILENAME"
+    LDAP_TLS_CRT_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_CRT_FILENAME"
+    LDAP_TLS_KEY_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_KEY_FILENAME"
+    LDAP_TLS_DH_PARAM_PATH="${CONTAINER_SERVICE_DIR}/slapd/assets/certs/dhparam.pem"
+
+    check_tls_files $LDAP_TLS_CA_CRT_PATH $LDAP_TLS_CRT_PATH $LDAP_TLS_KEY_PATH $LDAP_TLS_DH_PARAM_PATH
+
+    # adapt tls ldif
+    sed -i "s|{{ LDAP_TLS_CA_CRT_PATH }}|${LDAP_TLS_CA_CRT_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+    sed -i "s|{{ LDAP_TLS_CRT_PATH }}|${LDAP_TLS_CRT_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+    sed -i "s|{{ LDAP_TLS_KEY_PATH }}|${LDAP_TLS_KEY_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+    sed -i "s|{{ LDAP_TLS_DH_PARAM_PATH }}|${LDAP_TLS_DH_PARAM_PATH}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+
+    sed -i "s|{{ LDAP_TLS_CIPHER_SUITE }}|${LDAP_TLS_CIPHER_SUITE}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+    sed -i "s|{{ LDAP_TLS_PROTOCOL_MIN }}|${LDAP_TLS_PROTOCOL_MIN}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+    sed -i "s|{{ LDAP_TLS_VERIFY_CLIENT }}|${LDAP_TLS_VERIFY_CLIENT}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+
+    ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif 2>&1 | log-helper debug
+
+    [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
+    echo "export PREVIOUS_LDAP_TLS_CA_CRT_PATH=${LDAP_TLS_CA_CRT_PATH}" > $WAS_STARTED_WITH_TLS
+    echo "export PREVIOUS_LDAP_TLS_CRT_PATH=${LDAP_TLS_CRT_PATH}" >> $WAS_STARTED_WITH_TLS
+    echo "export PREVIOUS_LDAP_TLS_KEY_PATH=${LDAP_TLS_KEY_PATH}" >> $WAS_STARTED_WITH_TLS
+    echo "export PREVIOUS_LDAP_TLS_DH_PARAM_PATH=${LDAP_TLS_DH_PARAM_PATH}" >> $WAS_STARTED_WITH_TLS
+
+    # ldap client config
+    sed -i --follow-symlinks "s,TLS_CACERT.*,TLS_CACERT ${LDAP_TLS_CA_CRT_PATH},g" /etc/ldap/ldap.conf
+    echo "TLS_REQCERT ${LDAP_TLS_VERIFY_CLIENT}" >> /etc/ldap/ldap.conf
+    cp -f /etc/ldap/ldap.conf ${CONTAINER_SERVICE_DIR}/slapd/assets/ldap.conf
+
+    [[ -f "$HOME/.ldaprc" ]] && rm -f $HOME/.ldaprc
+    echo "TLS_CERT ${LDAP_TLS_CRT_PATH}" > $HOME/.ldaprc
+    echo "TLS_KEY ${LDAP_TLS_KEY_PATH}" >> $HOME/.ldaprc
+    cp -f $HOME/.ldaprc ${CONTAINER_SERVICE_DIR}/slapd/assets/.ldaprc
+
+    # enforce TLS
+    if [ "${LDAP_TLS_ENFORCE,,}" == "true" ]; then
+      log-helper info "Add enforce TLS..."
+      ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enforce-enable.ldif 2>&1 | log-helper debug
+
+    # disable tls enforcing
+    else
+      log-helper info "Disable enforce TLS..."
+      ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-enforce-disable.ldif 2>&1 | log-helper debug || true
+    fi
+
+  else
+    log-helper info "Disable TLS config..."
+
+    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/tls/tls-disable.ldif 2>&1 | log-helper debug || true
+    [[ -f "$WAS_STARTED_WITH_TLS" ]] && rm -f "$WAS_STARTED_WITH_TLS"
+  fi
+
+
+
+  #
+  # Replication config
+  #
+
+  function disableReplication() {
+    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-disable.ldif 2>&1 | log-helper debug || true
+    [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
+  }
+
+  if [ "${LDAP_REPLICATION,,}" == "true" ]; then
+
+    log-helper info "Add replication config..."
+    disableReplication || true
+
+    i=1
+    for host in $(complex-bash-env iterate LDAP_REPLICATION_HOSTS)
+    do
+      sed -i "s|{{ LDAP_REPLICATION_HOSTS }}|olcServerID: $i ${!host}\n{{ LDAP_REPLICATION_HOSTS }}|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
+      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_DIR}/slapd/assets/config/replication/replication-enable.ldif
+      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_DIR}/slapd/assets/config/replication/replication-enable.ldif
+
+      ((i++))
+    done
+
+    get_ldap_base_dn
+    sed -i "s|\$LDAP_BASE_DN|$LDAP_BASE_DN|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
+    sed -i "s|\$LDAP_ADMIN_PASSWORD|$LDAP_ADMIN_PASSWORD|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
+    sed -i "s|\$LDAP_CONFIG_PASSWORD|$LDAP_CONFIG_PASSWORD|g" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
+
+    sed -i "/{{ LDAP_REPLICATION_HOSTS }}/d" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
+    sed -i "/{{ LDAP_REPLICATION_HOSTS_CONFIG_SYNC_REPL }}/d" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
+    sed -i "/{{ LDAP_REPLICATION_HOSTS_HDB_SYNC_REPL }}/d" ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
+
+    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${CONTAINER_SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif 2>&1 | log-helper debug || true
+
+    [[ -f "$WAS_STARTED_WITH_REPLICATION" ]] && rm -f "$WAS_STARTED_WITH_REPLICATION"
+    echo "export PREVIOUS_HOSTNAME=${HOSTNAME}" > $WAS_STARTED_WITH_REPLICATION
+
+  else
+
+    log-helper info "Disable replication config..."
+    disableReplication || true
+
+  fi
+
+  #
+  # stop OpenLDAP
+  #
+  log-helper info "Stop OpenLDAP..."
+
+  SLAPD_PID=$(cat /run/slapd/slapd.pid)
+  kill -15 $SLAPD_PID
+  while [ -e /proc/$SLAPD_PID ]; do sleep 0.1; done # wait until slapd is terminated
+
+  #
+  # remove config files
+  #
+  if [ "${LDAP_REMOVE_CONFIG_AFTER_SETUP,,}" == "true" ]; then
+    log-helper info "Remove config files..."
+    rm -rf ${CONTAINER_SERVICE_DIR}/slapd/assets/config
+  fi
+
+  #
+  # setup done :)
+  #
+  log-helper info "First start is done..."
+  touch $FIRST_START_DONE
+fi
+
+ln -sf ${CONTAINER_SERVICE_DIR}/slapd/assets/.ldaprc $HOME/.ldaprc
+ln -sf ${CONTAINER_SERVICE_DIR}/slapd/assets/ldap.conf /etc/ldap/ldap.conf
+
+exit 0

+ 2 - 2
test/test.bats

@@ -62,13 +62,13 @@ load test_helper
   tmp_file="$BATS_TMPDIR/docker-test"
 
   # replication ldap server
-  LDAP_REPL_CID=$(docker run -h ldap2.example.org -e LDAP_REPLICATION=true -e IS_REPLICATION_TEST=true -d $NAME:$VERSION)
+  LDAP_REPL_CID=$(docker run -h ldap2.example.org -e LDAP_REPLICATION=true -d $NAME:$VERSION)
   LDAP_REPL_IP=$(get_container_ip_by_cid $LDAP_REPL_CID)
 
   sleep 2
 
   # ldap server
-  run_image -h ldap.example.org -e LDAP_REPLICATION=true -e IS_REPLICATION_TEST=true
+  run_image -h ldap.example.org -e LDAP_REPLICATION=true
 
   # add route to hosts
   docker exec $CONTAINER_ID bash -c "echo $LDAP_REPL_IP ldap2.example.org >> /etc/hosts"

+ 4 - 8
test/test_helper.bash

@@ -83,19 +83,17 @@ is_service_running_by_cid() {
 }
 
 is_file_exists_by_cid() {
-  docker exec $1 cat "/etc/my_init_startup_files_completed" > /dev/null 2>&1
+  docker exec $1 cat $2 > /dev/null 2>&1
 }
 
 wait_service_by_cid() {
 
   cid=$1
 
-  sleep 1
-
   # first wait image init end
-  while ! is_file_exists_by_cid $cid /etc/my_init_startup_files_completed
+  while ! is_file_exists_by_cid $cid /container/run/state/startup-done
   do
-    sleep 1
+    sleep 0.5
   done
 
   for service in "${@:2}"
@@ -103,9 +101,7 @@ wait_service_by_cid() {
     # wait service
     while ! is_service_running_by_cid $cid $service
     do
-      sleep 1
+      sleep 0.5
     done
   done
-
-  sleep 5
 }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است