From a26bbc9b5793a242ec67a732b92a5b04f9be9f6c Mon Sep 17 00:00:00 2001 From: sebthom Date: Sat, 24 Jul 2021 20:52:56 +0200 Subject: [PATCH] improve build config --- .dockerignore | 6 + .editorconfig | 18 +++ .gitattributes | 156 +++++++++++++++++----- .github/dependabot.yml | 16 +++ .github/stale.yml | 24 ++++ .github/workflows/build.yml | 25 +++- .gitignore | 2 + README.md | 3 +- build-debug-image.sh | 11 -- build-image.sh | 125 +++++------------ example/docker-compose/docker-compose.yml | 1 - example/docker/example.env | 1 - image/Dockerfile | 87 +++++------- image/run.sh | 138 ++++++------------- 14 files changed, 314 insertions(+), 299 deletions(-) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .github/dependabot.yml create mode 100644 .github/stale.yml delete mode 100644 build-debug-image.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..faa03b7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +*.md +*.txt +.github/ +.shared/.* +.shared/*.md +.shared/*.txt diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6423822 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 3 + +[*.{bat,cmd}] +end_of_line = crlf + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes index 3e4e359..7bf405f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,43 +1,131 @@ -# from https://github.com/alexkaratarakis/gitattributes/blob/master/Java.gitattributes +# inspired by +# - https://github.com/alexkaratarakis/gitattributes/blob/master/Java.gitattributes +# - https://github.com/alexkaratarakis/gitattributes/blob/master/Common.gitattributes # Handle line endings automatically for files detected as text # and leave all files detected as binary untouched. * text=auto # -# The above will handle all files NOT found below +# The above will handle all files with names NOT matching patterns defined below # -# These files are text and should be normalized (Convert crlf => lf) -*.css text -*.df text -*.htm text -*.html text -*.java text -*.js text -*.json text -*.jsp text -*.jspf text -*.jspx text -*.properties text -*.sh text -*.tld text -*.txt text -*.tag text -*.tagx text -*.xml text -*.yml text -# These files are binary and should be left untouched -# (binary is a macro for -text -diff) -*.class binary -*.dll binary -*.ear binary -*.gif binary -*.ico binary -*.jar binary -*.jpg binary -*.jpeg binary -*.png binary -*.so binary -*.war binary +# Git files +.gitattributes text eol=lf +**/.gitattributes text eol=lf +.gitignore text eol=lf +**/.gitignore text eol=lf + +# Documents +*.doc binary diff=astextplain +*.docx binary diff=astextplain +*.dot binary diff=astextplain +*.pdf binary diff=astextplain +*.ppt binary diff=astextplain +*.pptx binary diff=astextplain +*.rtf binary diff=astextplain +*.vsd binary diff=astextplain +*.vsdx binary diff=astextplain +*.odt binary diff=odf +*.ods binary diff=odf +*.odp binary diff=odf +*.adoc text +*.csv text +*.md text diff=markdown +*.txt text + + +# Config/Serialisation +.editorconfig text +**/.editorconfig text +*.ini text +*.properties text +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text + + +# Scripts +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf +*.bash text eol=lf +*.fish text eol=lf +*.sh text eol=lf +*.zsh text eol=lf +*.lua text +*.php text +*.python text +*.sql text + + +# Archives +*.7z binary +*.gz binary +*.tar binary +*.tar.gz binary +*.tgz binary +*.xz binary +*.zip binary + + +# Native binaries +*.dll binary +*.dylib binary +*.exe binary +*.so binary + + +# Images +*.eps binary +*.gif binary +*.ico binary +*.jpg binary +*.jpeg binary +*.png binary +*.svg text +*.svgz binary +*.tif binary +*.tiff binary + + +# Fonts +*.eot binary +*.otf binary +*.ttf binary +*.woff binary + + +# Java +*.gradle text diff=java +*.gradle.kts text diff=java +*.java text diff=java +*.class binary +*.ear binary +*.jceks binary +*.jks binary +*.jar binary +*.pak binary +*.war binary +*.jsp text +*.jspf text +*.jspx text +*.tld text +*.tag text +*.tagx text + + +# Web +*.css text diff=css +*.htm text diff=html +*.html text diff=html +*.js text + + +# https://git-scm.com/docs/gitattributes#_export_ignore +.gitattributes export-ignore +.gitignore export-ignore +.gitkeep export-ignore diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..7135646 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: monday + time: "09:00" + commit-message: + prefix: fix + prefix-development: chore + include: scope + labels: + - gha + - dependencies diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000..e7df9f1 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,24 @@ +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 + +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security + +# Label to use when marking an issue as stale +staleLabel: wontfix + +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed in 7 days if no further activity occurs. + Thank you for your contributions. + +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d917ab6..bea4470 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,8 +1,19 @@ +# Copyright 2019-2021 by Vegard IT GmbH, Germany, https://vegardit.com +# SPDX-License-Identifier: Apache-2.0 +# +# Author: Sebastian Thomschke, Vegard IT GmbH +# +# https://github.com/vegardit/docker-openldap +# # https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions name: Build on: push: + branches: + - '**' + tags-ignore: + - '**' paths-ignore: - '**/*.md' schedule: @@ -12,8 +23,6 @@ on: # https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/ env: - DOCKER_IMAGE_REPO: vegardit/openldap - DOCKER_IMAGE_TAG: latest TRIVY_CACHE_DIR: ~/.trivy/cache jobs: @@ -33,17 +42,19 @@ jobs: ${{ runner.os }}-trivy- - name: Install dos2unix - run: sudo apt-get install --no-install-recommends -y dos2unix + # using '-o Acquire::Retries=3' to workaround sporadic connectivity issues "Could not connect to azure.archive.ubuntu.com:80" + # see https://github.com/actions/virtual-environments/issues/675 + run: sudo apt-get install -o Acquire::Retries=3 --no-install-recommends -y dos2unix - - name: Build ${{ env.DOCKER_IMAGE_REPO }}:${{ env.DOCKER_IMAGE_TAG }} + - name: Build docker image shell: bash env: - DOCKER_PUSH: 1 DOCKER_REGISTRY: docker.io DOCKER_REGISTRY_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} DOCKER_REGISTRY_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }} - MICROBADGER_TOKEN: ${{ secrets.MICROBADGER_TOKEN }} run: | + if [ "$GITHUB_REF" == "refs/heads/main" ]; then + export DOCKER_PUSH=1 + fi echo "$DOCKER_REGISTRY_TOKEN" | docker login -u="$DOCKER_REGISTRY_USERNAME" "$DOCKER_REGISTRY" --password-stdin bash build-image.sh - curl -X POST https://hooks.microbadger.com/images/$DOCKER_REPO/$MICROBADGER_TOKEN || true; diff --git a/.gitignore b/.gitignore index 710c216..ef47666 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Local work folder that is not checked in _LOCAL/ +.shared + # Eclipse .apt_generated/ .checkstyle diff --git a/README.md b/README.md index 8df6a33..a0a760c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ # vegardit/openldap What is it? -Opinionated docker image based on the [Debian](https://www.debian.org/) docker image [`debian:buster-slim`](https://hub.docker.com/_/debian?tab=tags&name=buster-slim) to run an [OpenLDAP 2.4](https://www.openldap.org/doc/admin24/) server. +Opinionated docker image based on the [Debian](https://www.debian.org/) docker image [`debian:stable-slim`](https://hub.docker.com/_/debian?tab=tags&name=stable-slim) to run an [OpenLDAP 2.4](https://www.openldap.org/doc/admin24/) server. It is automatically built **daily** to include the latest OS security fixes. diff --git a/build-debug-image.sh b/build-debug-image.sh deleted file mode 100644 index 982cff1..0000000 --- a/build-debug-image.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2019-2020 by Vegard IT GmbH, Germany, https://vegardit.com -# SPDX-License-Identifier: Apache-2.0 -# -# Author: Sebastian Thomschke, Vegard IT GmbH -# -# https://github.com/vegardit/docker-openldap -# - -bash "$(dirname "$0")/build-image.sh" --build-arg DEBUG_BUILD=1 diff --git a/build-image.sh b/build-image.sh index da49130..ddaaa57 100644 --- a/build-image.sh +++ b/build-image.sh @@ -1,23 +1,15 @@ #!/usr/bin/env bash # -# Copyright 2019-2020 by Vegard IT GmbH, Germany, https://vegardit.com +# Copyright 2019-2021 by Vegard IT GmbH, Germany, https://vegardit.com # SPDX-License-Identifier: Apache-2.0 # # Author: Sebastian Thomschke, Vegard IT GmbH # # https://github.com/vegardit/docker-openldap -# -set -eu - -################################################# -# execute script with bash if loaded with other shell interpreter -################################################# -if [ -z "${BASH_VERSINFO:-}" ]; then /usr/bin/env bash "$0" "$@"; exit; fi - -set -o pipefail - -trap 'echo >&2 "$(date +%H:%M:%S) Error - exited with status $? at line $LINENO:"; pr -tn $0 | tail -n+$((LINENO - 3)) | head -n7' ERR +shared_lib="$(dirname $0)/.shared" +[ -e "$shared_lib" ] || curl -sSf https://raw.githubusercontent.com/vegardit/docker-shared/v1/download.sh?_=$(date +%s) | bash -s v1 "$shared_lib" || exit 1 +source "$shared_lib/lib/build-image-init.sh" ################################################# @@ -25,29 +17,9 @@ trap 'echo >&2 "$(date +%H:%M:%S) Error - exited with status $? at line $LINENO: ################################################# docker_registry=${DOCKER_REGISTRY:-docker.io} image_repo=${DOCKER_IMAGE_REPO:-vegardit/openldap} -base_image_name=${DOCKER_BASE_IMAGE:-debian:buster-slim} +base_image_name=${DOCKER_BASE_IMAGE:-debian:stable-slim} base_image_tag=${base_image_name#*:} -image_name=$image_repo:${DOCKER_IMAGE_TAG:-latest} - - -################################################# -# determine directory of current script -################################################# -project_root=$(readlink -e $(dirname "${BASH_SOURCE[0]}")) - - -################################################# -# ensure Linux new line chars -################################################# -# env -i PATH="$PATH" -> workaround for "find: The environment is too large for exec()" -env -i PATH="$PATH" find "$project_root/image" -type f -exec dos2unix {} \; - - -################################################# -# calculate BASE_LAYER_CACHE_KEY -################################################# -# using the current date, i.e. the base layer cache (that holds system packages with security updates) will be invalidate once per day -base_layer_cache_key=$(date +%Y%m%d) +image_name=$image_repo:latest ################################################# @@ -58,8 +30,11 @@ if [[ $OSTYPE == "cygwin" || $OSTYPE == "msys" ]]; then project_root=$(cygpath -w "$project_root") fi -docker build "$project_root/image" \ - --pull \ +docker pull $base_image_name +DOCKER_BUILDKIT=1 docker build "$project_root" \ + --file "image/Dockerfile" \ + --progress=plain \ + --build-arg INSTALL_SUPPORT_TOOLS=${INSTALL_SUPPORT_TOOLS:-0} \ `# using the current date as value for BASE_LAYER_CACHE_KEY, i.e. the base layer cache (that holds system packages with security updates) will be invalidate once per day` \ --build-arg BASE_LAYER_CACHE_KEY=$base_layer_cache_key \ --build-arg BASE_IMAGE=$base_image_name \ @@ -73,64 +48,38 @@ docker build "$project_root/image" \ ################################################# -# perform security audit using https://github.com/aquasecurity/trivy -################################################# -if [[ $OSTYPE != cygwin ]] && [[ $OSTYPE != msys ]]; then - trivy_cache_dir="${TRIVY_CACHE_DIR:-$HOME/.trivy/cache}" - trivy_cache_dir="${trivy_cache_dir/#\~/$HOME}" - mkdir -p "$trivy_cache_dir" - docker run --rm \ - -v /var/run/docker.sock:/var/run/docker.sock:ro \ - -v "$trivy_cache_dir:/root/.cache/" \ - aquasec/trivy --no-progress --exit-code 0 --severity HIGH,CRITICAL $image_name - docker run --rm \ - -v /var/run/docker.sock:/var/run/docker.sock:ro \ - -v "$trivy_cache_dir:/root/.cache/" \ - aquasec/trivy --no-progress --ignore-unfixed --exit-code 1 --severity HIGH,CRITICAL $image_name - sudo chown -R $USER:$(id -gn) "$trivy_cache_dir" || true -fi - - -################################################# -# determine effective LDAP version and apply tags +# determine effective OpenLDAP version ################################################# # LC_ALL=en_US.utf8 -> workaround for "grep: -P supports only unibyte and UTF-8 locales" -ldap_version=$(docker run --rm $image_name "dpkg -s slapd | grep 'Version:' | LC_ALL=en_US.utf8 grep -oP 'Version: \K\d+\.\d+\.\d+'") -docker image tag $image_name $image_repo:${ldap_version%.*}.x #2.4.x -docker image tag $image_name $image_repo:${ldap_version%%.*}.x #2.x +ldap_version=$(docker run --rm $image_name dpkg -s slapd | LC_ALL=en_US.utf8 grep -oP 'Version: \K\d+\.\d+\.\d+') +echo "ldap_version=$ldap_version" + + +################################################# +# apply tags +################################################# +declare -a tags=() +tags+=($image_name) # :latest +tags+=($image_repo:${ldap_version}) # :2.4.47 +tags+=($image_repo:${ldap_version%.*}.x) # :2.4.x +tags+=($image_repo:${ldap_version%%.*}.x) # :2.x + +for tag in ${tags[@]}; do + docker image tag $image_name $tag +done + + +################################################# +# perform security audit +################################################# +bash "$shared_lib/cmd/audit-image.sh" $image_name ################################################# # push image with tags to remote docker image registry ################################################# if [[ "${DOCKER_PUSH:-0}" == "1" ]]; then - docker image tag $image_name $docker_registry/$image_name - docker image tag $image_name $docker_registry/$image_repo:${ldap_version} #2.4.47 - docker image tag $image_name $docker_registry/$image_repo:${ldap_version%.*}.x #2.4.x - docker image tag $image_name $docker_registry/$image_repo:${ldap_version%%.*}.x #2.x - - docker push $docker_registry/$image_name - docker push $docker_registry/$image_repo:${ldap_version} #2.4.47 - docker push $docker_registry/$image_repo:${ldap_version%.*}.x #2.4.x - docker push $docker_registry/$image_repo:${ldap_version%%.*}.x #2.x + for tag in ${tags[@]}; do + docker push $docker_registry/$tag + done fi - - -################################################# -# remove untagged images -################################################# -# http://www.projectatomic.io/blog/2015/07/what-are-docker-none-none-images/ -untagged_images=$(docker images -f "dangling=true" -q --no-trunc) -[[ -n $untagged_images ]] && docker rmi $untagged_images || true - - -################################################# -# display some image information -################################################# -echo "" -echo "IMAGE NAME" -echo "$image_name" -echo "" -docker images "$image_repo" -echo "" -docker history "$image_name" diff --git a/example/docker-compose/docker-compose.yml b/example/docker-compose/docker-compose.yml index e6a63b6..2f96b07 100644 --- a/example/docker-compose/docker-compose.yml +++ b/example/docker-compose/docker-compose.yml @@ -12,7 +12,6 @@ services: # https://github.com/vegardit/docker-openldap image: vegardit/openldap:latest # https://hub.docker.com/r/vegardit/openldap environment: - #DEBUG_RUN_SH: 1 LDAP_INIT_ORG_DN: o=example.com LDAP_INIT_ORG_NAME: Example Inc. LDAP_INIT_ROOT_USER_DN: uid=admin,o=example.com diff --git a/example/docker/example.env b/example/docker/example.env index 6bcca4d..8e0c319 100644 --- a/example/docker/example.env +++ b/example/docker/example.env @@ -1,6 +1,5 @@ #See https://docs.docker.com/compose/env-file/ -#DEBUG_RUN_SH=0 #INIT_SH_FILE= LDAP_INIT_ORG_DN=o=yourorg diff --git a/image/Dockerfile b/image/Dockerfile index 15d15e0..766cf27 100644 --- a/image/Dockerfile +++ b/image/Dockerfile @@ -1,4 +1,5 @@ -# Copyright 2019-2020 by Vegard IT GmbH, Germany, https://vegardit.com +#syntax=docker/dockerfile:1.2 +# Copyright 2019-2021 by Vegard IT GmbH, Germany, https://vegardit.com # SPDX-License-Identifier: Apache-2.0 # # Author: Sebastian Thomschke, Vegard IT GmbH @@ -6,8 +7,8 @@ # https://github.com/vegardit/docker-openldap # -# https://hub.docker.com/_/debian?tab=tags&name=buster-slim -ARG BASE_IMAGE=debian:buster-slim +# https://hub.docker.com/_/debian?tab=tags&name=stable-slim +ARG BASE_IMAGE=debian:stable-slim FROM ${BASE_IMAGE} @@ -17,47 +18,32 @@ USER root SHELL ["/bin/bash", "-c"] -# if set to 1 debug tools are added to the image (htop,less,mc,vim) -ARG DEBUG_BUILD=0 - -ARG PQCHECKER_URL=https://www.meddeb.net/pub/pqchecker/deb/8/pqchecker_2.0.0_amd64.deb -ARG PQCHECKER_MD5=c005ce596e97d13e39485e711dcbc7e1 - ARG DEBIAN_FRONTEND=noninteractive ARG LC_ALL=C ARG BASE_LAYER_CACHE_KEY +ARG INSTALL_SUPPORT_TOOLS=0 -RUN \ +ARG PQCHECKER_URL=https://www.meddeb.net/pub/pqchecker/deb/8/pqchecker_2.0.0_amd64.deb +ARG PQCHECKER_MD5=c005ce596e97d13e39485e711dcbc7e1 + +RUN --mount=type=bind,source=.shared,target=/mnt/shared \ set -eu && \ - echo "#################################################" && \ - echo "Installing OS updates..." && \ - echo "#################################################" && \ - apt-get update -y && \ - # https://github.com/phusion/baseimage-docker/issues/319 - apt-get install --no-install-recommends -y apt-utils 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 ) && \ - apt-get upgrade -y && \ + /mnt/shared/cmd/debian-install-os-updates.sh && \ + /mnt/shared/cmd/debian-install-support-tools.sh && \ + # + echo "#################################################" && \ + echo "Installing tini..." && \ + echo "#################################################" && \ + apt-get install --no-install-recommends -y tini && \ # - if [ "${DEBUG_BUILD}" = "1" ]; then \ - echo "#################################################" && \ - echo "Installing debugging tools..." && \ - echo "#################################################" && \ - apt-get install --no-install-recommends -y libcomerr2 mc && \ - apt-get install --no-install-recommends -y htop less procps vim && \ - echo -e 'set ignorecase\n\ -set showmatch\n\ -set novisualbell\n\ -set noerrorbells\n\ -syntax enable\n\ -set mouse-=a' > ~/.vimrc; \ - fi && \ echo "#################################################" && \ echo "Installing slapd..." && \ echo "#################################################" && \ echo 'slapd slapd/root_password password whatever' | debconf-set-selections && \ echo 'slapd slapd/root_password_again password whatever' | debconf-set-selections && \ apt-get install --no-install-recommends -y slapd ldap-utils && \ - echo "OpenLDAP $(apt-cache show slapd | grep Version)" >> /opt/build_info && \ + echo "OpenLDAP $(apt-cache show slapd | grep Version)" >> /opt/build_info && \ # workaround for 'service slapd stop' not working, see https://stackoverflow.com/a/58792698/5116073 sed -i 's/--exec $SLAPD 2/--name slapd 2/' /etc/init.d/slapd && \ # @@ -80,20 +66,7 @@ set mouse-=a' > ~/.vimrc; \ mv /var/lib/ldap /var/lib/ldap_orig && \ mkdir /var/lib/ldap && \ # - echo "#################################################" && \ - echo "apt-get clean up..." && \ - echo "#################################################" && \ - apt-get remove apt-utils -y && \ - apt-get clean autoclean && \ - apt-get autoremove --purge -y && \ - # - echo "#################################################" && \ - echo "Removing logs, caches and temp files..." && \ - echo "#################################################" && \ - rm -rf /var/cache/{apt,debconf} \ - /var/lib/apt/lists/* \ - /var/log/{apt,alternatives.log,bootstrap.log,dpkg.log} \ - /tmp/* /var/tmp/* + /mnt/shared/cmd/debian-cleanup.sh ARG BUILD_DATE ARG GIT_BRANCH @@ -109,8 +82,8 @@ LABEL \ # Default configuration: can be overridden at the docker command line ENV \ - DEBUG_RUN_SH=0 \ INIT_SH_FILE='' \ + # LDAP_INIT_ORG_DN='o=example.com' \ LDAP_INIT_ORG_NAME='Example Corporation' \ LDAP_INIT_ADMIN_GROUP_DN='cn=ldapadmins,ou=Groups,${LDAP_INIT_ORG_DN}' \ @@ -130,21 +103,23 @@ ENV \ LDAP_OPENLDAP_UID='' \ LDAP_OPENLDAP_GID='' -COPY ldifs /opt/ldifs -COPY run.sh /opt/run.sh - RUN \ - echo "GIT_REPO: $GIT_REPO_URL" > /opt/build_info && \ - echo "GIT_BRANCH: $GIT_BRANCH" >> /opt/build_info && \ - echo "GIT_COMMIT: $GIT_COMMIT_HASH @ $GIT_COMMIT_DATE" >> /opt/build_info && \ - echo "IMAGE_BUILD: $BUILD_DATE" >> /opt/build_info && \ + set -eu && \ + echo -e "\ +GIT_REPO: $GIT_REPO_URL\n\ +GIT_BRANCH: $GIT_BRANCH\n\ +GIT_COMMIT: $GIT_COMMIT_HASH @ $GIT_COMMIT_DATE\n\ +IMAGE_BUILD: $BUILD_DATE\n" >/opt/build_info && \ cat /opt/build_info +COPY image/ldifs /opt/ldifs +COPY image/run.sh /opt/run.sh +COPY .shared/lib/bash-init.sh /opt/bash-init.sh + VOLUME ["/etc/ldap/slapd.d", "/var/lib/ldap"] EXPOSE 389 -ENTRYPOINT ["/bin/sh", "-c"] +ENTRYPOINT ["/usr/bin/tini", "--"] -# exec is required for propagating SIGTERM from docker to child process -CMD ["exec /bin/bash /opt/run.sh"] +CMD ["/bin/bash", "/opt/run.sh"] diff --git a/image/run.sh b/image/run.sh index d72bf59..b597497 100644 --- a/image/run.sh +++ b/image/run.sh @@ -8,52 +8,38 @@ # https://github.com/vegardit/docker-openldap # -set -e -u - -############################## -# execute script with bash if loaded with other shell interpreter -############################## -if [ -z "${BASH_VERSINFO:-}" ]; then /usr/bin/env bash "$0" "$@"; exit; fi - -set -o pipefail - -trap 'echo >&2 "$(date +%H:%M:%S) Error - exited with status $? at line $LINENO:"; pr -tn $0 | tail -n+$((LINENO - 3)) | head -n7' ERR - -if [ "${DEBUG_RUN_SH:-}" == "1" ]; then - set -x -fi +source /opt/bash-init.sh +################################################# +# print header +################################################# cat <<'EOF' - _ __ __ __________ -| | / /__ ____ _____ __________/ / / _/_ __/ -| | / / _ \/ __ `/ __ `/ ___/ __ / / / / / -| |/ / __/ /_/ / /_/ / / / /_/ / _/ / / / -|___/\___/\__, /\__,_/_/ \__,_/ /___/ /_/ - /____/ + ___ _ ____ _ ____ + / _ \ _ __ ___ _ __ | | | _ \ / \ | _ \ + | | | | '_ \ / _ \ '_ \| | | | | |/ _ \ | |_) | + | |_| | |_) | __/ | | | |___| |_| / ___ \| __/ + \___/| .__/ \___|_| |_|_____|____/_/ \_\_| + |_| EOF cat /opt/build_info echo -if [ -f "$INIT_SH_FILE" ]; then +log INFO "Timezone is $(date +"%Z %z")" + + +################################################# +# load custom init script if specified +################################################# +if [[ -f $INIT_SH_FILE ]]; then + log INFO "Loading [$INIT_SH_FILE]..." source "$INIT_SH_FILE" fi -function log() { - if [ -p /dev/stdin ]; then - while read line; do - echo "[$(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}:${BASH_LINENO}] $line" - done - else - echo "[$(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}:${BASH_LINENO}] ${@}" - fi -} - - # display slapd build info -slapd -VVV 2>&1 | log || true +slapd -VVV 2>&1 | log INFO || true # Limit maximum number of open file descriptors otherwise slapd consumes two @@ -67,14 +53,14 @@ ulimit -n $LDAP_NOFILE_LIMIT if [ -n "${LDAP_OPENLDAP_UID:-}" ]; then effective_uid=$(id -u openldap) if [ "$LDAP_OPENLDAP_UID" != "$effective_uid" ]; then - log "Changing UID of openldap user from $effective_uid to $LDAP_OPENLDAP_UID..." + log INFO "Changing UID of openldap user from $effective_uid to $LDAP_OPENLDAP_UID..." usermod -o -u "$LDAP_OPENLDAP_UID" openldap fi fi if [ -n "${LDAP_OPENLDAP_GID:-}" ]; then effective_gid=$(id -g openldap) if [ "$LDAP_OPENLDAP_GID" != "$effective_gid" ]; then - log "Changing GID of openldap user from $effective_gid to $LDAP_OPENLDAP_GID..." + log INFO "Changing GID of openldap user from $effective_gid to $LDAP_OPENLDAP_GID..." usermod -o -u "$LDAP_OPENLDAP_GID" openldap fi fi @@ -89,22 +75,6 @@ chown -R openldap:openldap /var/run/slapd ################################################################# if [ ! -e /etc/ldap/slapd.d/initialized ]; then - function interpolate_vars() { - # based on https://stackoverflow.com/a/40167919 - local line lineEscaped - while IFS= read -r line || [ -n "$line" ]; do # the `||` clause ensures that the last line is read even if it doesn't end with \n - # escape all chars that could trigger an expansion - IFS= read -r lineEscaped < <(echo "$line" | tr '`([$' '\1\2\3\4') - # selectively re-enable ${ references - lineEscaped=${lineEscaped//$'\4'{/\${} - # escape back slashes to preserve them - lineEscaped=${lineEscaped//\\/\\\\} - # escape embedded double quotes to preserve them - lineEscaped=${lineEscaped//\"/\\\"} - eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$' - done - } - function substr_before() { echo "${1%%$2*}" } @@ -115,17 +85,17 @@ if [ ! -e /etc/ldap/slapd.d/initialized ]; then } function ldif() { - log "--------------------------------------------" + log INFO "--------------------------------------------" local action=$1 && shift local file=${!#} - log "Loading [$file]..." - interpolate_vars < $file > /tmp/$(basename $file) + log INFO "Loading [$file]..." + interpolate < $file > /tmp/$(basename $file) ldap$action -H ldapi:/// "${@:1:${#}-1}" -f /tmp/$(basename $file) } # interpolate variable placeholders in env vars starting with "LDAP_INIT_" for name in ${!LDAP_INIT_*}; do - declare "${name}=$(echo "${!name}" | interpolate_vars)" + declare "${name}=$(echo "${!name}" | interpolate)" done # pre-populate folders in case they are empty @@ -134,7 +104,7 @@ if [ ! -e /etc/ldap/slapd.d/initialized ]; then continue fi if [ -z "$(ls $folder)" ]; then - log "Initializing [$folder]..." + log INFO "Initializing [$folder]..." cp -r --preserve=all ${folder}_orig/. $folder fi done @@ -144,7 +114,7 @@ if [ ! -e /etc/ldap/slapd.d/initialized ]; then sleep 3 if [ "${LDAP_INIT_RFC2307BIS_SCHEMA:-}" == "1" ]; then - log "Replacing NIS (RFC2307) schema with RFC2307bis schema..." + log INFO "Replacing NIS (RFC2307) schema with RFC2307bis schema..." ldapdelete -Y EXTERNAL cn={2}nis,cn=schema,cn=config ldif add -Y EXTERNAL /opt/ldifs/schema_rfc2307bis02.ldif fi @@ -166,12 +136,12 @@ if [ ! -e /etc/ldap/slapd.d/initialized ]; then ldif add -x -D "$LDAP_INIT_ROOT_USER_DN" -w "$LDAP_INIT_ROOT_USER_PW" /opt/ldifs/init_org_ppolicy.ldif ldif add -x -D "$LDAP_INIT_ROOT_USER_DN" -w "$LDAP_INIT_ROOT_USER_PW" /opt/ldifs/init_org_entries.ldif - log "--------------------------------------------" + log INFO "--------------------------------------------" echo "1" > /etc/ldap/slapd.d/initialized rm -f /tmp/*.ldif - log "Creating periodic LDAP backup at [$LDAP_BACKUP_FILE]..." + log INFO "Creating periodic LDAP backup at [$LDAP_BACKUP_FILE]..." slapcat -n 1 -l $LDAP_BACKUP_FILE || true /etc/init.d/slapd stop @@ -185,10 +155,10 @@ echo "$LDAP_PPOLICY_PQCHECKER_RULE" > /etc/ldap/pqchecker/pqparams.dat # Configure background task for LDAP backup ################################################################# if [ -n "${LDAP_BACKUP_TIME:-}" ]; then - log "--------------------------------------------" - log "Configuring LDAP backup task to run daily: time=[${LDAP_BACKUP_TIME}] file=[$LDAP_BACKUP_FILE]..." + log INFO "--------------------------------------------" + log INFO "Configuring LDAP backup task to run daily: time=[${LDAP_BACKUP_TIME}] file=[$LDAP_BACKUP_FILE]..." if [[ "$LDAP_BACKUP_TIME" != +([0-9][0-9]:[0-9][0-9]) ]]; then - log "The configured value [$LDAP_BACKUP_TIME] for LDAP_BACKUP_TIME is not in the expected 24-hour format [hh:mm]!" + log INFO "The configured value [$LDAP_BACKUP_TIME] for LDAP_BACKUP_TIME is not in the expected 24-hour format [hh:mm]!" exit 1 fi @@ -200,7 +170,7 @@ if [ -n "${LDAP_BACKUP_TIME:-}" ]; then while [ "$(date +%H:%M)" != "${LDAP_BACKUP_TIME}" ]; do sleep 10s done - log "Creating periodic LDAP backup at [$LDAP_BACKUP_FILE]..." + log INFO "Creating periodic LDAP backup at [$LDAP_BACKUP_FILE]..." slapcat -n 1 -l "$LDAP_BACKUP_FILE" || true sleep 23h done @@ -213,42 +183,12 @@ fi ################################################################# # Start LDAP service ################################################################# -log "--------------------------------------------" -log "Starting OpenLDAP: slapd..." +log INFO "--------------------------------------------" +log INFO "Starting OpenLDAP: slapd..." -#required for propagating SIGTERM from docker to service process -#https://unix.stackexchange.com/questions/146756/forward-sigterm-to-child-in-bash/444676#444676 -function trap_handler() { - local signal=$1 - if [ -n "${service_process_pid:-}" ]; then - log "Sending [$signal] to PID [$service_process_pid] ..." - kill -s $signal $service_process_pid 2>/dev/null - else - log "Received [$signal] before service started." - sig_received_before_service_started=$signal - fi -} - -trap 'trap_handler TERM' SIGTERM SIGINT SIGHUP # https://github.com/openldap/openldap/search?q=SIGTERM -trap 'trap_handler QUIT' SIGQUIT -trap 'trap_handler USR1' SIGUSR1 # https://github.com/openldap/openldap/search?q=SIGUSR1 -trap 'trap_handler USR2' SIGUSR2 # https://github.com/openldap/openldap/search?q=SIGUSR2 - -/usr/sbin/slapd \ +exec /usr/sbin/slapd \ $(for logLevel in ${LDAP_LOG_LEVELS:-}; do echo -n "-d $logLevel "; done) \ -h "ldap:/// ldapi:///" \ - -u openldap -g openldap \ - -F /etc/ldap/slapd.d 2>&1 | log & - -service_process_pid=$(jobs -p | tail -1) -log "OpenLDAP PID: $service_process_pid" - -if [ -n "${sig_received_before_service_started:-}" ]; then - kill -s $sig_received_before_service_started $service_process_pid 2>/dev/null -fi - -wait $service_process_pid -trap - TERM INT -wait $service_process_pid -exit_status=$? -exit $exit_status + -u openldap \ + -g openldap \ + -F /etc/ldap/slapd.d 2>&1 | log INFO