1
0
ofreax 9 жил өмнө
parent
commit
53c90df3da

+ 53 - 40
CHANGELOG.md

@@ -1,79 +1,92 @@
 # Changelog
 
 ## 1.1.0
-  - Update to light-baseimage:0.2.1
-  - Use cfssl to generate ssl certs
+Update to light-baseimage:0.2.1 :
+  - Use *.yaml.setup 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
+
+Rename environment variables
 
-  - Fixes :
-    - OpenLdap container won't start when dhparam.pem is missing in bound volume #13
+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

+ 103 - 45
README.md

@@ -11,17 +11,11 @@ Support TLS, multi-master replication and quick bootstrap.
 ## Quick Start
 Run OpenLDAP docker image :
 
-	docker run --name my-openldap-container -d osixia/openldap:1.1.0
+	docker run --name my-openldap-container --detach osixia/openldap:1.1.0
 
-This start a new container with OpenLDAP running inside. Let's make our first search in our LDAP server.
+This start a new container with OpenLDAP running inside. Let's make the first search in our LDAP container:
 
-Open a bash in the container :
-
-	docker exec -it my-openldap-container bash
-
-In the container terminal run the following commands :
-
-	ldapsearch -x -h localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
+	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 :
 
@@ -38,7 +32,7 @@ This should output :
 	# numResponses: 3
 	# numEntries: 2
 
-if you have the following error, OpenLDAP is not started yet, you are too fast or your computer is too slow (it's a matter of  point of view) wait some time.
+if you have the following error, OpenLDAP is not started yet, you are too fast ;) ... wait some time.
 
 		ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)
 
@@ -53,7 +47,7 @@ It will create an empty ldap for the compagny **Example Inc.** and the domain **
 By default the admin has the password **admin**. All those default settings can be changed at the docker command line, for example :
 
 	docker run --env LDAP_ORGANISATION="My Compagny" --env LDAP_DOMAIN="my-compagny.com" \
-	--env LDAP_ADMIN_PASSWORD="JonSn0w" -d osixia/openldap
+	--env LDAP_ADMIN_PASSWORD="JonSn0w" --detach osixia/openldap:1.1.0
 
 #### Data persitance
 
@@ -71,9 +65,9 @@ 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 :
 > [https://docs.docker.com/userguide/dockervolumes/](https://docs.docker.com/userguide/dockervolumes/)
@@ -81,36 +75,36 @@ You can also use data volume containers. Please refer to :
 ### 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).
+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-compagny.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 mouting a directory containing thoses files to **/container/service/slapd/assets/certs** and adjust there 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 -h ldap.example.org -v /path/to/certifates:/container/service/slapd/assets/certs \
+	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 \
-	-d osixia/openldap
+	--detach osixia/openldap:1.1.0
+
+Other solutions are available please refer to the [Advanced User Guide](#advanced-user-guide)
 
 #### Disable TLS
 Add --env LDAP_TLS=false to the run command :
 
-	docker run --env 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 --env 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 --env 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,
@@ -122,7 +116,7 @@ That's it ! But a litle 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 !
 
@@ -149,9 +143,7 @@ A simple solution to backup your ldap server, our openldap-backup docker image :
 > [osixia/openldap-backup](https://github.com/osixia/docker-openldap-backup)
 
 ## Default Environment Variables
-Environement variables defaults are set in **image/environment/default.yaml** and **image/environment/default.yaml.startup**.
-
-Go to next point to see how to set your own environment variables.
+Environement variables defaults are set in **image/environment/default.yaml** and **image/environment/default.yaml.setup**.
 
 ### default.yaml
 Variables defined in this file are available at any time, anywhere in the container environment.
@@ -159,11 +151,12 @@ Variables defined in this file are available at any time, anywhere in the contai
 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.
 
-### default.yaml.startup
+### default.yaml.setup
 Variables defined in this file are only available during the container **first start** in **startup scripts**.
 This file is deleted right after startup scripts are processed for the first time,
-after that all theses values will not be available in the container environment.
-That helps to keep your container configuration secret.
+after that all these values will not be available in the container environment.
+
+That 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.`
@@ -193,44 +186,66 @@ Replication options :
 
 - **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="60 +" timeout=1 starttls=critical`
 
-- **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
-
+- **LDAP_REPLICATION_HOSTS**: list of replication hosts, must contains the current container hostname set by --hostname on docker run command. Defaults to :
+```yaml
+	- ldap://ldap.example.org
+	- ldap://ldap2.example.org
+```
 	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']" -d osixia/openldap
+		docker run --env LDAP_REPLICATION_HOSTS="#PYTHON2BASH:['ldap://ldap.example.org','ldap://ldap2.example.org']" --detach osixia/openldap:1.1.0
 
 	To convert yaml to python online :
 	http://yaml-online-parser.appspot.com/
 
+Other environment variables :
+- **LDAP_REMOVE_CONFIG_AFTER_SETUP**: delete config folder after setup. Defaults to `true`
+
+
 ### Set your own environment variables :
 
 #### Use command line argument
 Environment variables can be set by adding the --env argument in the command line, for example :
 
 	docker run --env LDAP_ORGANISATION="My Compagny" --env LDAP_DOMAIN="my-compagny.com" \
-	--env LDAP_ADMIN_PASSWORD="JonSn0w" -d osixia/openldap
+	--env LDAP_ADMIN_PASSWORD="JonSn0w" --detach osixia/openldap:1.1.0
 
 Be aware that environment variable added in command line will be available at any time
-in the container. In this example if an attacker manage to open a terminal in this container
+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.
 
 #### Link environment file
 
+	docker run --volume /data/my-env.yaml:/container/environment/01-custom/env.yaml \
+	--volume /data/my-env.yaml.setup:/container/environment/01-custom/env.yaml.setup \
+	--detach osixia/openldap:1.1.0
+
+Note: the container will try to delete the ***.yaml.setup** file after the first start so the file will also be deleted on the docker host.
+
+Use --volume /data/my-env.yaml.setup:/container/environment/01-custom/env.yaml.setup**:ro** to prevent that or set all variables in ***.yaml** file and don't mount ***.yaml.setup** file but all sensitive data will persists in container environment.
 
+#### Make your own image or extend this one
 
+This is the best solution if you have a private registry. Please refer to the [Advanced User Guide](#advanced-user-guide) just below.
 
-#### Make your own image
+## Advanced User Guide
 
+### Extend osixia/openldap:1.1.0 image
 
-Or by setting your own `env.yaml` file as a docker volume to `/container/environment/env.yaml`
+If you need to add your custom TLS certificate,   bootstrap config or environment files the easyest way is too extends this image.
 
-	docker run -v /data/my-env.yaml:/container/environment/env.yaml \
-	-d osixia/openldap
+Dockerfile example:
 
-## Manual build
+	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 :
 
@@ -246,13 +261,56 @@ Adapt Makefile, set your image NAME and VERSION, for example :
 	NAME = cool-guy/openldap
 	VERSION = 0.1.0
 
+Add your custom certificate, bootstrap ldif and environment files...
+
 Build your image :
 
 	make build
 
 Run your image :
 
-	docker run -d cool-guy/openldap:0.1.0
+	docker run --detach cool-guy/openldap:0.1.0
+
+### 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**
+
+### Debug
+
+The container default log level is **info**.
+Available levels: `none`, `error`, `warning`, `info`, `debug` and `trace`.
+
+Example command to run the container in `debug` mode :
+
+	docker run --detach osixia/openldap:1.1.0 /container/tool/run --loglevel debug
+
+The tool `/container/tool/run` is provided by this image baseimage : osixia/light-baseimage
+
+### osixia/light-baseimage
+
+This image is base 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 to init the container environment
+
+More info : https://github.com/osixia/docker-light-baseimage
+
+## 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 ! ;)
+
 
 ## Tests
 

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

@@ -0,0 +1,6 @@
+FROM osixia/openldap:1.1.0-dev
+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 .

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

@@ -0,0 +1,16 @@
+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

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

@@ -0,0 +1,45 @@
+# This is the default image startup configuration file
+# this file define environment variables used during the container **first start** in **startup scripts**.
+
+# This file is deleted right after startup scripts are processed for the first time,
+# after that all theses values will not be available in the container environment.
+# That 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_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

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

@@ -0,0 +1,98 @@
+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: "0"
+            - 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_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

+ 3 - 4
image/Dockerfile

@@ -10,6 +10,7 @@ RUN groupadd -r openldap && useradd -r -g openldap openldap
 
 # Install OpenLDAP, ldap-utils and cfssl from baseimage and remove default ldap db
 # https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/install-service-available
+# https://github.com/osixia/docker-light-baseimage/blob/stable/image/service-available/.cfssl
 RUN apt-get -y update \
     && /container/tool/install-service-available cfssl \
 	  && LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes --no-install-recommends \
@@ -19,10 +20,8 @@ RUN apt-get -y update \
 # Add service directory to /container/service
 ADD service /container/service
 
-# Use baseimage install-service script and clean all
-# https://github.com/osixia/docker-light-baseimage/blob/stable/image/tool/install-service
-RUN /container/tool/install-service \
-    && apt-get clean \
+# Clean tmp and apt-get files
+RUN apt-get clean \
     && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
 
 # Add default env variables

+ 4 - 0
image/environment/default.yaml.setup

@@ -39,3 +39,7 @@ 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

+ 99 - 66
image/service/slapd/container-start.sh

@@ -1,8 +1,9 @@
 #!/bin/bash -e
+set -o pipefail
 
-FIRST_START_SETUP_DONE="/container/run/state/slapd-first-start-setup-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"
+# 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
@@ -13,10 +14,19 @@ ulimit -n 1024
 chown -R openldap:openldap /var/lib/ldap
 chown -R openldap:openldap /etc/ldap
 chown -R openldap:openldap ${SERVICE_DIR}/slapd
+# the SERVICE_DIR variable is set by /container/tool/run
+# more info: https://github.com/osixia/docker-light-baseimage
+
+FIRST_START_SETUP_DONE="/container/run/state/slapd-first-start-setup-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 first start
 if [ ! -e "$FIRST_START_SETUP_DONE" ]; then
 
+  #
+  # Helpers
+  #
   function get_ldap_base_dn() {
     LDAP_BASE_DN=""
     IFS='.' read -ra LDAP_BASE_DN_TABLE <<< "$LDAP_DOMAIN"
@@ -44,6 +54,8 @@ if [ ! -e "$FIRST_START_SETUP_DONE" ]; then
     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 $LDAP_CRT $LDAP_KEY $CA_CRT
 
     # create DHParamFile if not found
@@ -54,14 +66,19 @@ if [ ! -e "$FIRST_START_SETUP_DONE" ]; then
     chown -R openldap:openldap ${SERVICE_DIR}/slapd
   }
 
+  #
+  # Global variables
+  #
   BOOTSTRAP=false
 
-  # database and config directory are empty -> set bootstrap config
+  #
+  # 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
-    echo "database and config directory are empty"
-    echo "-> set bootstrap config"
+    log-helper info "Database and config directory are empty"
 
     cat <<EOF | debconf-set-selections
 slapd slapd/internal/generated_adminpw password ${LDAP_ADMIN_PASSWORD}
@@ -81,60 +98,65 @@ 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
-    echo "Error: the database directory (/var/lib/ldap) is empty but not the config directory (/etc/ldap/slapd.d)"
+    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
-    echo "the config directory (/etc/ldap/slapd.d) is empty but not the database directory (/var/lib/ldap)"
+    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
-    # 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
-
+      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
+  #
 
-
-  function startOpenLDAP(){
-
-    if [ -n "$PREVIOUS_HOSTNAME" ]; then
-      PREVIOUS_HOSTNAME="ldap://$PREVIOUS_HOSTNAME"
-    fi
-
-    #start openldap normaly
-    echo -n "Starting openldap..."
-    slapd -h "ldap://$HOSTNAME $PREVIOUS_HOSTNAME ldap://localhost ldapi:///" -u openldap -g openldap
-    echo "[ok]"
-  }
-
-  # start OpenLDAP with previous replication configuration
+  # get previous hostname if OpenLDAP was started with replication
+  # to avoid configuration pbs
+  PREVIOUS_HOSTNAME_PARAM=""
   if [ -e "$WAS_STARTED_WITH_REPLICATION" ]; then
 
-    . $WAS_STARTED_WITH_REPLICATION
+    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
-    else
-      PREVIOUS_HOSTNAME=""
+      PREVIOUS_HOSTNAME_PARAM="ldap://$PREVIOUS_HOSTNAME"
     fi
   fi
 
-  startOpenLDAP
+  # start OpenLDAP
+  log-helper info "Start OpenLDAP..."
+  slapd -h "ldap://$HOSTNAME $PREVIOUS_HOSTNAME_PARAM ldap://localhost ldapi:///" -u openldap -g openldap
 
-  # set bootstrap config part 2
+
+  #
+  # 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
+    ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif 2>&1 | log-helper debug
 
     # convert schemas to ldif
     SCHEMAS=""
@@ -145,15 +167,14 @@ EOF
 
     # add schemas
     for f in $(find ${SERVICE_DIR}/slapd/assets/config/bootstrap/schema -name \*.ldif -type f); do
-      echo "Processing file ${f}"
+      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
-        echo "add schema ${SCHEMA}"
-        ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f $f
+        ldapadd -c -Y EXTERNAL -Q -H ldapi:/// -f $f 2>&1 | log-helper debug
       else
-        echo "schema ${f} already exists"
+        log-helper info "schema ${f} already exists"
       fi
     done
 
@@ -166,15 +187,16 @@ EOF
     sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/02-security.ldif
 
     # process config files in bootstrap directory (do no process files in subdirectories)
+    log-helper info "Add bootstrap ldif..."
     for f in $(find ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif -mindepth 1 -maxdepth 1 -type f -name \*.ldif  | sort); do
-      echo "Processing file ${f}"
-      ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f $f
+      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
 
-      echo "Add read only user"
+      log-helper info "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" ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
@@ -184,20 +206,21 @@ EOF
       sed -i --follow-symlinks "s|{{ LDAP_READONLY_USER_USERNAME }}|${LDAP_READONLY_USER_USERNAME}|g" ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
       sed -i --follow-symlinks "s|{{ LDAP_BASE_DN }}|${LDAP_BASE_DN}|g" ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
 
-      echo "Processing file ${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 ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif
+      log-helper debug "Processing file ${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 ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user.ldif 2>&1 | log-helper debug
 
-      echo "Processing file ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif"
-      ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
+      log-helper debug "Processing file ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif"
+      ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${SERVICE_DIR}/slapd/assets/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif 2>&1 | log-helper debug
 
     fi
-
   fi
 
-  # tls config
+  #
+  # TLS config
+  #
   if [ "${LDAP_TLS,,}" == "true" ]; then
 
-    echo "Use TLS"
+    log-helper info "Add TLS config..."
 
     LDAP_TLS_CA_CRT_PATH="${SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_CA_CRT_FILENAME"
     LDAP_TLS_CRT_PATH="${SERVICE_DIR}/slapd/assets/certs/$LDAP_TLS_CRT_FILENAME"
@@ -216,7 +239,7 @@ EOF
     sed -i --follow-symlinks "s|{{ LDAP_TLS_PROTOCOL_MIN }}|${LDAP_TLS_PROTOCOL_MIN}|g" ${SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
     sed -i --follow-symlinks "s|{{ LDAP_TLS_VERIFY_CLIENT }}|${LDAP_TLS_VERIFY_CLIENT}|g" ${SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
 
-    ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${SERVICE_DIR}/slapd/assets/config/tls/tls-enable.ldif
+    ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f ${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"
     touch $WAS_STARTED_WITH_TLS
@@ -236,25 +259,26 @@ EOF
     echo "TLS_KEY ${LDAP_TLS_KEY_PATH}" >> $HOME/.ldaprc
 
   else
+    log-helper info "Disable TLS config..."
 
-    echo "Don't use TLS"
-
-    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${SERVICE_DIR}/slapd/assets/config/tls/tls-disable.ldif || true
+    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${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() {
-    echo "Try to disable replication"
-    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${SERVICE_DIR}/slapd/assets/config/replication/replication-disable.ldif || true
+    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${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"
   }
 
-  # replication config
   if [ "${LDAP_REPLICATION,,}" == "true" ]; then
 
-    echo "Use replication"
+    log-helper info "Add replication config..."
     disableReplication || true
 
     i=1
@@ -276,8 +300,7 @@ EOF
     sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS_CONFIG_SYNC_REPL }}/d" ${SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
     sed -i --follow-symlinks "/{{ LDAP_REPLICATION_HOSTS_HDB_SYNC_REPL }}/d" ${SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif
 
-    echo "Enable replication"
-    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${SERVICE_DIR}/slapd/assets/config/replication/replication-enable.ldif || true
+    ldapmodify -c -Y EXTERNAL -Q -H ldapi:/// -f ${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"
     touch $WAS_STARTED_WITH_REPLICATION
@@ -286,22 +309,32 @@ EOF
 
   else
 
-    echo "Don't use replication"
+    log-helper info "Disable replication config..."
     disableReplication || true
 
   fi
 
+  #
   # stop OpenLDAP
+  #
+  log-helper info "Stop OpenLDAP..."
+
   SLAPD_PID=$(cat /run/slapd/slapd.pid)
-  echo -n "Kill slapd, pid: $SLAPD_PID..."
   kill -15 $SLAPD_PID
-  # wait until slapd is terminated
-  while [ -e /proc/$SLAPD_PID ]; do sleep 0.1; done
-  echo "[ok]"
-
-  echo "First start setup is done, remove setup files"
-  rm -rf ${SERVICE_DIR}/slapd/assets/config
+  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 ${SERVICE_DIR}/slapd/assets/config
+  fi
 
+  #
+  # setup done :)
+  #
+  log-helper info "First start setup is done :)"
   touch $FIRST_START_SETUP_DONE
 fi
 

+ 4 - 0
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