diff --git a/ab-openldap.params.template b/ab-openldap.params.template new file mode 100644 index 0000000..50fd1a4 --- /dev/null +++ b/ab-openldap.params.template @@ -0,0 +1,67 @@ +# +## openldap environment variables +# + +### Usage +# +# ***VERY IMPORTANT! DO NOT PUT QUOTES AROUND VALUES IN THIS FILE!!!*** +# incorrect: ORG_NAME="MyOrganization" +# correct: ORG_NAME=MyOrganization +# +# Instead of typing a myriad of "-e ...", you can fill them all out in this +# file and then use "--env-file ab-openldap.params" to tell docker to source +# it's variables from here. You can also combine both methods if you like. +# Most important, if you're using the convenience script, it draws all info from +# this file! +# +# You should probably protect this file via file permissions since it likely +# will contain things like passwords! Suggest restricting it to root only +# ex: chown root:root ab-openldap.parms && chmod 600 ab-openldap.parms +### + +### Your timezone (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) +TZ=Area/Location + +### First user account (will be added to Organization DIT 'manager' role) +USER=admin +USER_PASS=admin +USER_FIRSTNAME=admin +USER_LASTNAME=admin + +### Your Organization domain and name +# domain in standard (dotted) format -- not LDAP format +DOMAIN=mydomain.net +# Org name: suggest using [A-Z][a-z][0-9][-_] ONLY. Avoid spaces. +ORG_NAME=MyOrganization + +### Your 'directory browser' user +BROWSER_USER=ldapbind +BROWSER_PASS=ldapbind + +### Anonymous binding (enabled by default) +ANONYMOUS_BINDING=yes + +### Location of your TLS files +# Note: This section is only automated if using the script file to start the +# container. If you are starting it manually and using '--env-file', you still +# have to manually bind-mount these files using '-v source:/certs/dest.file:ro'. +# +# If you're bind-mounting symlinks, remember that you have to fully expand them +# or Docker will try to bind the link instead of the target! This is most +# common with Let's Encrypt. +# +# Example that does not work (binding directory instead of files): +# /etc/letsencrypt/live/mydomain.net:/certs:ro +# This will end up copying the symlinks themselves and, since the targets are +# not available to the container, it doesn't work! +# Example of the right way (bind actual files): +# /etc/letsencrypt/live/mydomain.net/privkey.pem:/certs/privkey.pem:ro +### +#TLS_CERT=/etc/letsencrypt/live/mydomain.net/fullchain.pem +#TLS_KEY=/etc/letsencrypt/live/mydomain.net/privkey.pem +#TLS_CHAIN=/etc/letsencrypt/live/mydomain.net/chain.pem + +# The container will generate Diffie-Hellman parameters automatically the first +# time it's launched with TLS certificates defined. + +#EOF \ No newline at end of file diff --git a/ab-openldap.sh b/ab-openldap.sh new file mode 100755 index 0000000..fc862ac --- /dev/null +++ b/ab-openldap.sh @@ -0,0 +1,215 @@ +#!/bin/sh + +# +### start openldap container using params file variables +# + + +# error code reference: +# 0: exited normally, no errors +# 1: unknown startup option passed to script +# 2: current user is unauthorized to operate docker +# 3: 'params' file not found in same directory as script +# 5: specified TLS-related files (cert, key or chain) not found + + +# text formatting presets +cyan=$(tput setaf 6) +err=$(tput bold)$(tput setaf 1) +magenta=$(tput setaf 5) +norm=$(tput sgr0) +red=$(tput setaf 1) +yellow=$(tput setaf 3) + + +### parameter defaults +clean=false +container_name="ab-openldap" +unset remove +shell=false + + +scriptHelp () { + printf "\n${magenta}%80s\n" | tr " " "-" + printf "${norm}This is a simple helper script so you can avoid lengthy typing when working\n" + printf "with the openLDAP container. The script reads the contents of 'ab-openldap.params'\n" + printf "and constructs various 'docker run' commands based on that file. The biggest\n" + printf "timesaver is working with certificates. If they are specified in the '.params',\n" + printf "the script will automatically bind-mount them so openLDAP starts in 'TLS\n" + printf "required' mode.\n\n" + printf "If you run the script with no parameters, it will execute the container\n" + printf "'normally': Run in detached mode with openLDAP automatically launched and\n" + printf "logging to stdout. If you specified certificates, openLDAP will require a TLS\n" + printf "connection. All modes of operation allow you to enter the container and\n" + printf "connect directly using UNIX sockets also.\n\n" + printf "${magenta}The script has the following parameters:\n" + printf "${cyan}(parameter in cyan) ${yellow}(default in yellow)${norm}\n\n" + printf "${cyan}-n|--name${norm}\n" + printf "Change the name of the container. This is cosmetic and does not affect\n" + printf "operation in any way.\n" + printf "${yellow}(ab-openldap)${norm}\n\n" + printf "${cyan}--rm|--remove${norm}\n" + printf "Automatically remove the container and volume (unless data is written) after it\n" + printf "is exited.\n" + printf "${yellow}(off: do not destroy container when stopped)${norm}\n\n" + printf "${cyan}-s|--shell${norm}\n" + printf "Enter the container using an interactive POSIX shell. This happens after\n" + printf "startup operations but *before* openLDAP (slapd) is actually started. This is\n" + printf "a great way to see configuration changes possibly stopping openLDAP from\n" + printf "starting. You can combine this with '--rm' for easy configuration checks.\n" + printf "${yellow}(off: run in detached mode)${norm}\n\n" + printf "${cyan}--clean${norm}\n" + printf "This option will stop ALL running openLDAP containers *AND DESTROY ALL\n" + printf "VOLUMES*. This is meant to give you a 'clean start' if you've made\n" + printf "configuration changes, etc.\n\n" + printf "${yellow}More information can be found at:\n" + printf "https://git.asifbacchus.app/ab-docker/openldap/wiki\n" + printf "${magenta}%80s\n\n" | tr " " "-" + exit 0 +} + +### pre-requisite checks + +# is user root or in the docker group? +if [ ! "$( id -u )" -eq 0 ]; then + if ! id -Gn | grep docker > /dev/null; then + printf "${err}\nYou must either be root or in the 'docker' group to run this script since you must be able to actually start the container! Exiting.\n${norm}" + exit 2 + fi +fi + +# does the params file exist? +if [ ! -f "./ab-openldap.params" ]; then + printf "${err}\nCannot find 'ab-openldap.params' file in the same directory as this script. Exiting.\n${norm}" + exit 3 +fi + +# read .params file +. ./ab-openldap.params + +# check for certs if using TLS +if [ "$TLS_CERT" ]; then + if [ ! -f "$TLS_CERT" ]; then + printf "${err}\nCannot find specified TLS certificate file. Exiting.${norm}\n" + exit 5 + fi + if [ ! -f "$TLS_KEY" ]; then + printf "${err}\nCannot find specified TLS private key file. Exiting.${norm}\n" + exit 5 + fi + if [ ! -f "$TLS_CHAIN" ]; then + printf "${err}\nCannot find specified TLS certificate chain file. Exiting.${norm}\n" + exit 5 + fi +fi + +# process startup parameters +while [ $# -gt 0 ]; do + case "$1" in + -h|-\?|--help) + # display help + scriptHelp + exit 0 + ;; + --rm|--remove) + # remove container on exit + remove="--rm" + ;; + -s|--shell) + # start shell instead of default CMD + shell=true + ;; + --clean) + # stop if necessary, delete volumes + clean=true + ;; + -n|--name) + # container name + if [ -z "$2" ]; then + printf "${err}\nNo container name specified. Exiting.\n${norm}" + exit 1 + fi + container_name="$2" + shift + ;; + *) + printf "${err}\nUnknown option: %s\n" "$1" + printf "Use '--help' for valid options.\n\n${norm}" + exit 1 + ;; + esac + shift +done + + +# cleanup and running containers and volumes +if [ $clean = true ]; then + # get all ab-openldap containers + containers=$(docker ps -a --no-trunc --filter "label=org.label-schema.name=ab-openldap" --format "{{ .Names }}") + # check for null value -- no containers to remove + if [ -z "$containers" ]; then + printf "${err}No openldap containers to remove. Exiting.${norm}\n\n" + exit 0 + fi + + # iterate containers, stop them and remove straggling volumes + set -- dummy $containers + shift + for container; do + printf "\n${cyan}Found %s -- processing:${norm}\n" ${container} + volume=$(docker inspect --format '{{ range .Mounts }}{{ if eq .Destination "/var/openldap/data" }}{{ .Name }}{{ end }}{{ end }}' ${container}) + printf "\t${red}Stopping container...${norm}\n" + docker stop ${container} > /dev/null 2>&1 + printf "\t${red}Removing container...${norm}\n" + docker rm ${container} > /dev/null 2>&1 + printf "\t${red}Removing volume...${norm}\n" + docker volume rm ${volume} > /dev/null 2>&1 + printf "${cyan}...done${norm}\n" + done +# run without TLS +elif [ -z "$TLS_CERT" ]; then + if [ $shell = true ]; then + # exec shell + printf "${cyan}\nRunning SHELL on %s...${norm}\n" "$container_name" + docker run ${remove} -it --name ${container_name} \ + --env-file ab-openldap.params \ + -p 389:389 -p 636:636 \ + docker.asifbacchus.app/ldap/ab-openldap:latest /bin/sh + else + # exec normally + printf "${cyan}\nRunning OPENLDAP on %s...${norm}\n" "$container_name" + docker run ${remove} -d --name ${container_name} \ + --env-file ab-openldap.params \ + -p 389:389 -p 636:636 \ + --restart unless-stopped \ + docker.asifbacchus.app/ldap/ab-openldap:latest + fi +# run with TLS +elif [ "$TLS_CERT" ] && [ "$TLS_KEY" ] && [ "$TLS_CHAIN" ]; then + if [ $shell = true ]; then + # exec shell + printf "${cyan}\nRunning SHELL on %s (TLS)...${norm}\n" "$container_name" + docker run ${remove} -it --name ${container_name} \ + --env-file ab-openldap.params \ + -v "$TLS_CERT":/certs/fullchain.pem:ro \ + -v "$TLS_KEY":/certs/privkey.pem:ro \ + -v "$TLS_CHAIN":/certs/chain.pem:ro \ + -p 389:389 -p 636:636 \ + docker.asifbacchus.app/ldap/ab-openldap:latest /bin/sh + else + # exec normally + printf "${cyan}\nRunning OPENLDAP on %s (TLS)...${norm}\n" "$container_name" + docker run ${remove} -d --name ${container_name} \ + --env-file ab-openldap.params \ + -v "$TLS_CERT":/certs/fullchain.pem:ro \ + -v "$TLS_KEY":/certs/privkey.pem:ro \ + -v "$TLS_CHAIN":/certs/chain.pem:ro \ + -p 389:389 -p 636:636 \ + --restart unless-stopped \ + docker.asifbacchus.app/ldap/ab-openldap:latest + fi +fi + + +### exit gracefully +exit 0