OpenLDAP image

Image built atop osixia/openldap-backup image. Original image contains cron scheduler for backup operations. We did not want the container to manage them, so we forked the image and disabled those features.

We also added LDAP schema and contents versioning mechanism similar to Flyway versioning for SQL databases.

There is an user uid=admin,ou=users,$LDAP_BASE_DN who has his password set to admin. Change his password or delete the user after container is initialized.

Image versioning

Naming scheme is pretty simple: bcv-openldap:OSIXIA_BASEIMAGE_VERSION-rIMAGE_VERSION.

  • Image name is bcv-openldap.

  • OSIXIA_BASEIMAGE_VERSION is a version of baseimage we used and tweaked. This does not reference version of OpenLDAP in any way. For example, osixia/openldap-backup:1.4.0 contains OpenLDAP 2.4.50.

  • IMAGE_VERSION is an image release version written as a serial number, starting at 0. When images have the same OSIXIA_BASEIMAGE_VERSION versions but different image versions it means there were some tweaks to the baseimage (setup scripts, etc.) but baseimage which we spinned off of did not change.

Version numbering example
bcv-openldap:1.4.0-r0     // first release of tweaked osixia/openldap:1.4.0 image
bcv-openldap:1.4.0-r1    // second release of tweaked osixia/openldap:1.4.0 image (we made some other changes)
bcv-openldap:1.4.7-r0    // first release of tweaked osixia/openldap:1.4.7 image

Building

Simply cd to the directory which contains the Dockerfile and issue docker build -t <image tag here> ./.

The build process:

  1. Pulls official osixia/openldap-backup:XXX image. This image is copied from BCV repo, but those images are identical to what you find on Docker HUB.

  2. Disables its internal cronjobs which make backups. We expect backup is scheduled from outside of the container.

  3. Disables backup retention. We expect backup retention is managed from outside of the container.

  4. Disables possibility to upload backups onto AWS S3 bucket.

No engine sizing is performed.

Use

  • Use in the same way as original image.

  • Set up following mandatory variables.

    • LDAP_ORGANISATION

    • LDAP_DOMAIN

    • LDAP_BASE_DN

Environment variables

See baseimage doc.

Extra variables added in this image are:

  • LDAP_ENCRYPT_SYMKEY_FILE - Location of symmetric key for backup encryption.

  • LDAP_ENCRYPT_BACKUP - Flag that turns on/off the backup encryption. Format true/false.

Versioning of LDAP schema

This image has mechanism which automatically applies changescripts on startup. All applied versions are stored inside the LDAP databse in the ou=versions,$LDAP_BASE_DN entry. Each applied version has its own value in a multivalued attribute appliedVersion.

On startup, all LDIF files inside /changefiles/ directory are checked against the list of already applied versions. If they were not already applied, the startup routine applies them and marks them into the appliedVersion attribute.

Our LDIF files have special header that allows you to customize their behavior a bit or steer the execution flow. This feature is intended mainly for dealing with upgrade process on deployments - where there can be objects added by hand, custom schema changes, etc. Those directives also offer some basic ability to template changefiles, which allows you to deal with natural numbering ({0},{1},{2}, …​) used by slapd on some of its entries.

For more details on those directives, see TEMPLATE.ldif.tpl in the changefiles directory in this repo.

Container lifecycle

  • Startup

    1. entrypoint.sh creates DHparam file for the slapd daemon.

    2. entrypoint.sh starts runc daemon from the original Osixia image and enters the readiness-check loop.

      • This is implemented as probing slapd with ldapsearch periodically. After 5 consecutive successes, the slapd is considered started. If more than 30 attempts fail, container startup fails.

    3. Once the slapd is up and running, the entrypoint.sh processes LDIF changes.

    4. The entrypoint.sh script waits until /container/tool/run finishes.

  • Shutdown

    1. Running container receives SIGTERM from the Docker daemon.

    2. entrypoint.sh script forwards it to the runc and enters the wait-loop.

      • If waiting more than 30 seconds, the entrypoint.sh terminates.

    3. runc takes care of all services it has running as its children processes.

    4. runc exits.

    5. entrypoint.sh exits, terminating the container.

Backups

Container can make a persistent backup of the database, using slapcat, producing gzipped LDIF. If encryption is set then gzipped LDIF will be encrypted. To make a backup of the database, simly run

  • docker exec -it openldap /sbin/slapd-backup-config to backup config

  • docker exec -it openldap /sbin/slapd-backup-data to backup data

from outside the container.

How to generate encryption key for backups

If you create a key, add it to secrets/enc folder and mount it in docker-compose file. See the section below.

openssl rand -base64 32 > enc_backup_symkey.key

Restore

There are always two backups made, a backup of LDAP configuration and a backup of LDAP data. They can be restored independently. If you do not do many changes to OpenLDAP configuration, you usually need to restore just the "data" part. To fully restore the state of LDAP server, restore both backups.

Restore configuration

  1. Enter the container

    [fiisch@dockerhost ~]$ docker exec -it openldap bash
  2. Double check the backup was created/exists

    [fiisch@dockerhost ~]$ ls /data/backup/
  3. Delete current configuration

    root@openldap:/# rm -r /etc/ldap/slapd.d/cn*
  4. Use supplied script to restore from backup (script expects the file to be in /data/backup)

    • For not encrypted:

      /sbin/slapd-restore-config 20210204T090611-config.gz
    • For encrypted backed use gz.e file extension.

      /sbin/slapd-restore-config 20210204T090611-config.gz.e

Restore data

  1. Enter the container

    [fiisch@dockerhost ~]$ docker exec -it openldap bash
  2. Double check the backup was created/exists

    [fiisch@dockerhost ~]$ ls /data/backup/
  3. Delete contents of the data directory

    root@openldap:/# rm /var/lib/ldap/*
  4. Use supplied script to restore from backup (script expects the file to be in /data/backup)

    • For not encrypted:

      /sbin/slapd-restore-data 20210204T090615-data.gz
    • For encrypted backed use gz.e file extension:

      /sbin/slapd-restore-data 20210204T090611-config.gz.e

Mounted files and volumes

  • Mandatory

    • Volume containing LDAP admin passwords.

      • Those passwords are used to secure cn=admin,{{ LDAP_BASE_DN }}, cn=admin,cn=config and (optional) cn={{ LDAP_READONLY_USER_USERNAME }},{{ LDAP_BASE_DN }} users.

      • Without this volume mounted, OpenLDAP will not initialize.

        Example
        volumes:
          - type: bind
            source: ./secrets/pwfiles
            target: /container/environment/90-adminpw
            read_only: true
  • Optional

    • Directory which will hold LDAP configuration.

      • There are your persistent data in this directory.

      • Without this directory mounted, you can run the container. But you will lose LDAP configuration (=data) on container rm…​

        Example
        volumes:
          - type: bind
            source: ./config
            target: /etc/ldap/slapd.d
            read_only: false
    • Directory which will hold LDAP database.

      • There are your persistent data in this directory.

      • Without this directory mounted, you can run the container. But you will lose your data on container rm…​

        Example
        volumes:
          - type: bind
            source: ./data
            target: /var/lib/ldap
            read_only: false
    • Directory which will hold LDAP backups.

      • There are your backups in the directory.

      • Without this directory mounted, container will not store your database backups persistently.

        Example
        volumes:
          - type: bind
            source: ./backup
            target: /data/backup
            read_only: false
    • Directory which will hold SSL certificates.

      • SSL-related stuff is stored here. If you do not use SSL, you do not need to mount this directory.

      • Directory must be mounted in read-write mode because container will generate a DH-param file and store it there.

        Example
        volumes:
          - type: bind
            source: ./secrets/certs
            target: /container/service/slapd/assets/certs/
            read_only: false
    • Directory which will hold encryption keys.

      • Encryption key for openldap database backup and restore

      • Directory must be mounted in read-write mode because container will generate backup files.

        Example
        volumes:
          - type: bind
            source: ./secrets/enc
            target: /run/secrets/enc
            read_only: true