From 2f61e39f31d0cf088c6f9772e7f2c90ea12d7ae7 Mon Sep 17 00:00:00 2001
From: Ioannis Igoumenos <ioigoume@gmail.com>
Date: Thu, 11 Jul 2024 13:42:43 +0300
Subject: [PATCH 1/2] Add structure and main files.

---
 .gitignore                                    |    1 +
 Dockerfile                                    |   52 +
 common.bash                                   |    3 +
 jenkins/build.sh                              |   33 +
 jenkins/cleanup.sh                            |   35 +
 slashRoot/etc/crontab                         |    3 +
 slashRoot/etc/ldap/ldap.conf                  |    1 +
 slashRoot/srv/comanage-registry/local/crontab |   14 +
 .../local/bin/docker-comanage-cron-entrypoint |   24 +
 slashRoot/usr/local/lib/comanage_utils.sh     | 1482 +++++++++++++++++
 10 files changed, 1648 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Dockerfile
 create mode 100644 common.bash
 create mode 100755 jenkins/build.sh
 create mode 100755 jenkins/cleanup.sh
 create mode 100644 slashRoot/etc/crontab
 create mode 100644 slashRoot/etc/ldap/ldap.conf
 create mode 100644 slashRoot/srv/comanage-registry/local/crontab
 create mode 100755 slashRoot/usr/local/bin/docker-comanage-cron-entrypoint
 create mode 100644 slashRoot/usr/local/lib/comanage_utils.sh

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d19812c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea/**
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..b081c95
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,52 @@
+# COMANAGE #
+
+ARG COMANAGE_REGISTRY_VERSION
+ENV COMANAGE_REGISTRY_VERSION ${COMANAGE_REGISTRY_VERSION:-develop}
+
+ARG COMANAGE_REGISTRY_SRC_URL
+ENV COMANAGE_REGISTRY_SRC_URL=https://github.com/Internet2/comanage-registry/archive/${COMANAGE_REGISTRY_VERSION}.tar.gz
+
+LABEL comanage_registry_version=${COMANAGE_REGISTRY_VERSION}
+LABEL comanage_registry_src_url=${COMANAGE_REGISTRY_SRC_URL}
+
+ARG COMANAGE_REGISTRY_DIR
+ENV COMANAGE_REGISTRY_DIR ${COMANAGE_REGISTRY_DIR:-/srv/comanage-registry}
+
+FROM i2incommon/comanage-base:latest
+
+RUN yum -y update && yum -y install \
+        busybox \
+        && yum clean -y all
+
+WORKDIR "$COMANAGE_REGISTRY_DIR"
+
+RUN mkdir -p "${COMANAGE_REGISTRY_DIR}" \
+        && wget -O comanage.tar.gz ${COMANAGE_REGISTRY_SRC_URL} \
+        && tar -zxf comanage.tar.gz -C ${COMANAGE_REGISTRY_DIR} --strip-components=1 \
+        && rm -f comanage.tar.gz \
+        && rm -rf ${COMANAGE_REGISTRY_DIR}/app/tmp \
+        && cp -r ${COMANAGE_REGISTRY_DIR}/app/tmp.dist ${COMANAGE_REGISTRY_DIR}/app/tmp \
+        && chown -R apache:apache ${COMANAGE_REGISTRY_DIR}/app/tmp \
+        && cd ${COMANAGE_REGISTRY_DIR}/local \
+        && ln -s ${COMANAGE_REGISTRY_DIR}/app/tmp tmp \
+        && chown -h apache:apache ${COMANAGE_REGISTRY_DIR}/local/tmp \
+        && cd /var/www/html \
+        && ln -s ${COMANAGE_REGISTRY_DIR}/app/webroot registry
+
+COPY --chown=root:root slashRoot/etc/crontab /etc/crontab
+COPY --chown=root:root slashRoot/srv/comanage-registry/local/crontab /srv/comanage-registry/local/crontab
+COPY --chown=root:root slashRoot/etc/ldap/ldap.conf /etc/ldap/ldap.conf
+COPY slashRoot/usr/local/lib/comanage_utils.sh /usr/local/lib/
+
+RUN chmod +x /usr/local/lib/comanage_utils.sh
+
+RUN /usr/bin/crontab -u apache /srv/comanage-registry/local/crontab \
+      && /usr/sbin/usermod --shell /bin/bash apache \
+      && touch /etc/default/locale
+
+COPY slashRoot/usr/local/bin/docker-comanage-cron-entrypoint /usr/local/bin/
+
+ENTRYPOINT ["docker-comanage-cron-entrypoint"]
+
+CMD ["/usr/sbin/crond", "-n"]
+
diff --git a/common.bash b/common.bash
new file mode 100644
index 0000000..45fb114
--- /dev/null
+++ b/common.bash
@@ -0,0 +1,3 @@
+maintainer="i2incommon"
+imagename="comanage-registry-cron"
+comanage_version="4.3.4"
diff --git a/jenkins/build.sh b/jenkins/build.sh
new file mode 100755
index 0000000..5dba735
--- /dev/null
+++ b/jenkins/build.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+IMAGENAME=$1
+TAG=$2
+COMANAGE_REGISTRY_VERSION=$3
+DOCKERHUBPW=$4
+SUB=multiarch
+
+echo "image name: ${IMAGENAME}"
+echo "tag name: ${TAG}"
+echo "comanage registry version: ${COMANAGE_REGISTRY_VERSION}"
+
+docker login -u tieradmin -p $DOCKERHUBPW
+# NOTE: docker buildx ls when ran using backticks, returns the
+#       output of a plain ls run. If we do the flow below we get
+#       the expected output
+docker buildx ls |  awk '{if (NR>1) {print $1}}' > farm.txt
+# Preview the farm.txt file
+echo `cat farm.txt`
+# Parse the farm.txt file
+DOCKER_FARMS=`cat farm.txt`
+# Now remove the temporary file
+rm -f farm.txt
+
+if [[ "$DOCKER_FARMS" == *"$SUB"* ]]; then
+  echo "Farm multiarch exists"
+else
+  docker buildx create --use --name multiarch --append
+fi
+
+docker buildx inspect --bootstrap
+docker buildx build --no-cache --platform linux/amd64 -t ${IMAGENAME}_${TAG} --build-arg COMANAGE_REGISTRY_VERSION=${comanage_version} --load .
+docker buildx build --no-cache --platform linux/arm64 -t ${IMAGENAME}_${TAG}:arm64 --build-arg COMANAGE_REGISTRY_VERSION=${comanage_version} --load .
\ No newline at end of file
diff --git a/jenkins/cleanup.sh b/jenkins/cleanup.sh
new file mode 100755
index 0000000..62cfd51
--- /dev/null
+++ b/jenkins/cleanup.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+IMAGENAME=$1
+TAG=$2
+SUB=multiarch
+
+docker buildx ls |  awk '{if (NR>1) {print $1}}' > farm.txt
+# Preview the farm.txt file
+echo `cat farm.txt`
+# Parse the farm.txt file
+DOCKER_FARMS=`cat farm.txt`
+# Now remove the temporary file
+rm -f farm.txt
+
+if [[ "$DOCKER_FARMS" == *"$SUB"* ]]; then
+  echo "Farm multiarch exists"
+else
+  docker buildx create --use --name multiarch --append
+fi
+
+echo 'list docker processes'
+docker ps --all
+echo 'list all the docker images'
+docker image ls
+echo 'remove the amd64 docker image'
+docker rmi ${IMAGENAME}_${TAG} --force
+echo 'remove the arm64 docker image'
+docker rmi ${IMAGENAME}_${TAG}:arm64 --force
+
+echo "Remove all dangling images"
+docker image prune -a --force
+echo "Clear the build cache"
+docker buildx prune --force
+echo 'list all the docker images'
+docker image ls
\ No newline at end of file
diff --git a/slashRoot/etc/crontab b/slashRoot/etc/crontab
new file mode 100644
index 0000000..93dbebb
--- /dev/null
+++ b/slashRoot/etc/crontab
@@ -0,0 +1,3 @@
+SHELL=/bin/sh
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+MAILTO=""
diff --git a/slashRoot/etc/ldap/ldap.conf b/slashRoot/etc/ldap/ldap.conf
new file mode 100644
index 0000000..f58fc0e
--- /dev/null
+++ b/slashRoot/etc/ldap/ldap.conf
@@ -0,0 +1 @@
+TLS_CACERT /etc/ssl/certs/ca-certificates.crt
diff --git a/slashRoot/srv/comanage-registry/local/crontab b/slashRoot/srv/comanage-registry/local/crontab
new file mode 100644
index 0000000..fc3898d
--- /dev/null
+++ b/slashRoot/srv/comanage-registry/local/crontab
@@ -0,0 +1,14 @@
+SHELL=/bin/bash
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+MAILTO=""
+# Run Expiration Policies for CO 1 once a day at 1:00 AM
+0 1 * * * cd /srv/comanage-registry/app && ./Console/cake job CoreJob.Expire -s --coid 1
+
+# Run Synchronize Org Identity Sources for CO 1 once a day at 1:00 AM
+0 1 * * * cd /srv/comanage-registry/app && ./Console/cake job CoreJob.Sync -s --coid 1
+
+# Run Validate Group Member for CO 1 once a day at 1:00 AM
+0 1 * * * cd /srv/comanage-registry/app && ./Console/cake job CoreJob.ValidateGroupMember -s --coid 1
+
+# Run queued jobs for CO 1 every 5 minutes
+0-59/5 * * * * cd /srv/comanage-registry/app && ./Console/cake job -q -r -c 1
diff --git a/slashRoot/usr/local/bin/docker-comanage-cron-entrypoint b/slashRoot/usr/local/bin/docker-comanage-cron-entrypoint
new file mode 100755
index 0000000..3fb7594
--- /dev/null
+++ b/slashRoot/usr/local/bin/docker-comanage-cron-entrypoint
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# COmanage Registry Dockerfile entrypoint
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source /usr/local/lib/comanage_utils.sh
+
+comanage_utils::exec_cron "$@"
diff --git a/slashRoot/usr/local/lib/comanage_utils.sh b/slashRoot/usr/local/lib/comanage_utils.sh
new file mode 100644
index 0000000..7faea04
--- /dev/null
+++ b/slashRoot/usr/local/lib/comanage_utils.sh
@@ -0,0 +1,1482 @@
+#!/bin/bash
+
+# COmanage Registry bash shell utilities
+#
+# Portions licensed to the University Corporation for Advanced Internet
+# Development, Inc. ("UCAID") under one or more contributor license agreements.
+# See the NOTICE file distributed with this work for additional information
+# regarding copyright ownership.
+#
+# UCAID licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [ -n "$COMANAGE_DEBUG" ]
+then
+    OUTPUT=/dev/stdout
+else
+    OUTPUT=/dev/null
+fi
+
+##########################################
+# Configure CakePHP cache disable
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::configure_cache_disable() {
+    sed -i -e '/Cache.disable/ s+/++g' "$COMANAGE_REGISTRY_DIR/app/Config/core.php"
+}
+
+##########################################
+# Configure CakePHP debug level
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::configure_cakephp_debug() {
+    sed -i -e '/Configure::write(.debug/ s/0/2/' "$COMANAGE_REGISTRY_DIR/app/Config/core.php"
+}
+
+##########################################
+# Configure console (stdout) logging
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::configure_console_logging() {
+    sed -i -e '/FileLog/ s/FileLog/ConsoleLog/' "$COMANAGE_REGISTRY_DIR/app/Config/bootstrap.php"
+}
+
+##########################################
+# Configure CakePHP DebugKit
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::configure_cakephp_debugkit() {
+    sed -i -e '/\$components = array/ s/$/'"'"'DebugKit.Toolbar'"'"',/' "$COMANAGE_REGISTRY_DIR/app/Controller/AppController.php"
+}
+
+##########################################
+# Configure TIER logging
+# Globals:
+#   ENV
+#   USERTOKEN
+#   OUTPUT
+# Arguments:
+#   NONE
+# Returns:
+#   None
+##########################################
+function comanage_utils::configure_tier_logging() {
+
+    comanage_utils::manage_tier_environment
+
+    # Create pipes to use for COmanage Registry instead of standard log files.
+    rm -f "$COMANAGE_REGISTRY_DIR/app/tmp/logs/error.log" > "$OUTPUT" 2>&1
+    rm -f "$COMANAGE_REGISTRY_DIR/app/tmp/logs/debug.log" > "$OUTPUT" 2>&1
+    mkfifo -m 666 "$COMANAGE_REGISTRY_DIR/app/tmp/logs/error.log" > "$OUTPUT" 2>&1
+    mkfifo -m 666 "$COMANAGE_REGISTRY_DIR/app/tmp/logs/debug.log" > "$OUTPUT" 2>&1
+
+    # Format any output from COmanange Registry into standard TIER form.
+    (cat <> "$COMANAGE_REGISTRY_DIR/app/tmp/logs/error.log" | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "comanage_registry;error.log;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe)&
+    (cat <> "$COMANAGE_REGISTRY_DIR/app/tmp/logs/debug.log" | awk -v ENV="$ENV" -v UT="$USERTOKEN" '{printf "comanage_registry;debug.log;%s;%s;%s\n", ENV, UT, $0; fflush()}' 1>/tmp/logpipe)&
+}
+
+##########################################
+# Consume injected environment variables
+# Globals:
+#   See function
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::consume_injected_environment() {
+
+    echo "Examining environment variables..." > "$OUTPUT"
+
+    # Configuration details that may be injected through environment
+    # variables or the contents of files.
+    local injectable_config_vars
+
+    injectable_config_vars=(
+        COMANAGE_REGISTRY_ADMIN_GIVEN_NAME
+        COMANAGE_REGISTRY_ADMIN_FAMILY_NAME
+        COMANAGE_REGISTRY_ADMIN_USERNAME
+        COMANAGE_REGISTRY_CRON_USER
+        COMANAGE_REGISTRY_CRONTAB
+        COMANAGE_REGISTRY_DATASOURCE
+        COMANAGE_REGISTRY_DATABASE
+        COMANAGE_REGISTRY_DATABASE_HOST
+        COMANAGE_REGISTRY_DATABASE_PORT
+        COMANAGE_REGISTRY_DATABASE_POSTGRES_SSLMODE
+        COMANAGE_REGISTRY_DATABASE_USER
+        COMANAGE_REGISTRY_DATABASE_USER_PASSWORD
+        COMANAGE_REGISTRY_EMAIL_FROM
+        COMANAGE_REGISTRY_EMAIL_TRANSPORT
+        COMANAGE_REGISTRY_EMAIL_TLS
+        COMANAGE_REGISTRY_EMAIL_HOST
+        COMANAGE_REGISTRY_EMAIL_PORT
+        COMANAGE_REGISTRY_EMAIL_ACCOUNT
+        COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD
+        COMANAGE_REGISTRY_HTTP_LISTEN_PORT
+        COMANAGE_REGISTRY_HTTP_NO
+        COMANAGE_REGISTRY_HTTPS_LISTEN_PORT
+        COMANAGE_REGISTRY_HTTPS_NO
+        COMANAGE_REGISTRY_OIDC_AUTH_REQUEST_PARAMS
+        COMANAGE_REGISTRY_OIDC_CLIENT_ID
+        COMANAGE_REGISTRY_OIDC_CLIENT_SECRET
+        COMANAGE_REGISTRY_OIDC_CRYPTO_PASSPHRASE
+        COMANAGE_REGISTRY_OIDC_FORWARD_HEADERS
+        COMANAGE_REGISTRY_OIDC_PROVIDER_METADATA_URL
+        COMANAGE_REGISTRY_OIDC_REMOTE_USER_CLAIM
+        COMANAGE_REGISTRY_OIDC_SCOPES
+        COMANAGE_REGISTRY_OIDC_SESSION_INACTIVITY_TIMEOUT
+        COMANAGE_REGISTRY_OIDC_SESSION_MAX_DURATION
+        COMANAGE_REGISTRY_NO_DATABASE_CONFIG
+        COMANAGE_REGISTRY_NO_EMAIL_CONFIG
+        COMANAGE_REGISTRY_REMOTE_IP
+        COMANAGE_REGISTRY_REMOTE_IP_HEADER
+        COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY
+        COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY_LIST
+        COMANAGE_REGISTRY_REMOTE_IP_PROXIES_HEADER
+        COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL
+        COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL_EXCEPTIONS
+        COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY
+        COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY_LIST
+        COMANAGE_REGISTRY_SECURITY_SALT
+        COMANAGE_REGISTRY_SECURITY_SEED
+        COMANAGE_REGISTRY_PHP_SESSION_REDIS_URL
+        COMANAGE_REGISTRY_SKIP_SETUP
+        COMANAGE_REGISTRY_SKIP_UPGRADE
+        COMANAGE_REGISTRY_SLASH_ROOT_DIRECTORY
+        COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN
+        COMANAGE_REGISTRY_VIRTUAL_HOST_REDIRECT_HTTP_NO
+        COMANAGE_REGISTRY_VIRTUAL_HOST_SCHEME
+        COMANAGE_REGISTRY_VIRTUAL_HOST_PORT
+        HTTPS_CERT_FILE
+        HTTPS_PRIVKEY_FILE
+        SERVER_NAME
+    )
+
+    # If the file associated with a configuration variable is present then
+    # read the value from it into the appropriate variable. So for example
+    # if the variable COMANAGE_REGISTRY_DATASOURCE_FILE exists and its
+    # value points to a file on the file system then read the contents
+    # of that file into the variable COMANAGE_REGISTRY_DATASOURCE.
+
+    local config_var
+    for config_var in "${injectable_config_vars[@]}"
+    do
+        local file_name
+        eval file_name=\$"${config_var}_FILE";
+
+        if [[ -e "$file_name" ]]; then
+            declare -g "${config_var}"=`cat $file_name`
+            echo "Set ${config_var} to be contents of ${file_name}" > "$OUTPUT"
+        fi
+    done
+
+    echo "Done examining environment variables" > "$OUTPUT"
+}
+
+##########################################
+# Deploy crontab file
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+#   COMANAGE_REGISTRY_CRON_USER
+#   COMANAGE_REGISTRY_CRONTAB
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::deploy_crontab() {
+
+    local crontab
+    local cronuser
+
+    if [[ -n "${COMANAGE_REGISTRY_CRONTAB}" ]]; then
+        crontab="${COMANAGE_REGISTRY_CRONTAB}"
+    else
+        crontab="${COMANAGE_REGISTRY_DIR}/local/crontab"
+    fi
+
+    if [[ -n "${COMANAGE_REGISTRY_CRON_USER}" ]]; then
+        cronuser="${COMANAGE_REGISTRY_CRON_USER}"
+
+        echo "Removing image default crontab for user www-data ..." > "${OUTPUT}" 2>&1
+        /usr/bin/crontab -u www-data -r > "${OUTPUT}" 2>&1
+    else
+        cronuser="www-data"
+    fi
+
+    if [[ -f "${crontab}" ]]; then
+        echo "Deploying crontab ${crontab} for user ${cronuser} ..." > "${OUTPUT}" 2>&1
+        /usr/bin/crontab -u "${cronuser}" "${crontab}" > "${OUTPUT}" 2>&1
+    fi
+}
+
+##########################################
+# Enable the Apache HTTP Server virtual host
+# Globals:
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::enable_virtual_host() {
+
+    local a2site
+
+    a2site="000-comanage"
+
+    /usr/sbin/a2ensite "${a2site}" > "${OUTPUT}" 2>&1
+}
+
+##########################################
+# Enable non-core plugins
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+#   COMANAGE_REGISTRY_ENABLE_PLUGIN
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::enable_plugins() {
+
+    # Enable any supported non-core plugins if requested.
+    if [[ -n "${COMANAGE_REGISTRY_ENABLE_PLUGIN}" ]]; then
+        # Clear the caches.
+        comanage_utils::registry_clear_cache
+
+        local plugins
+        local plugin
+        plugins=(`echo "$COMANAGE_REGISTRY_ENABLE_PLUGIN" | sed -e 's@,@ @g'`) > "$OUTPUT" 2>&1
+        pushd "$COMANAGE_REGISTRY_DIR/local/Plugin" > "$OUTPUT" 2>&1
+        for plugin in "${plugins[@]}";
+        do
+            echo "Enabling available plugin $plugin..." > "$OUTPUT" 2>&1
+            ln -s "../../app/AvailablePlugin/$plugin" "$plugin" > "$OUTPUT" 2>&1
+        done
+
+        popd > "$OUTPUT" 2>&1
+
+        if [[ -z "${COMANAGE_REGISTRY_SKIP_SETUP}" ]]; then
+            pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+            ./Console/cake database > "$OUTPUT" 2>&1
+            popd > "$OUTPUT" 2>&1
+        fi
+
+        # Clear the caches again.
+        comanage_utils::registry_clear_cache
+    fi
+}
+
+##########################################
+# Exec to start and become Apache HTTP Server
+# Globals:
+#   COMANAGE_REGISTRY_NO_DATABASE_CONFIG
+#   COMANAGE_REGISTRY_NO_EMAIL_CONFIG
+# Arguments:
+#   Command and arguments to exec
+# Returns:
+#   Does not return
+##########################################
+function comanage_utils::exec_apache_http_server() {
+
+    comanage_utils::consume_injected_environment
+
+    comanage_utils::configure_console_logging
+
+    comanage_utils::process_slash_root
+
+    comanage_utils::prepare_local_directory
+
+    if [[ -z ${COMANAGE_REGISTRY_NO_DATABASE_CONFIG} ]]; then
+        comanage_utils::prepare_database_config
+    fi
+
+    if [[ -z ${COMANAGE_REGISTRY_NO_EMAIL_CONFIG} ]]; then
+        comanage_utils::prepare_email_config
+    fi
+
+    comanage_utils::prepare_https_cert_key
+
+    comanage_utils::prepare_server_name
+
+    comanage_utils::prepare_mod_remoteip
+
+    comanage_utils::prepare_virtual_host
+
+    comanage_utils::enable_virtual_host
+
+    comanage_utils::prepare_php_session
+
+    comanage_utils::wait_database_connectivity
+
+    comanage_utils::registry_setup
+
+    comanage_utils::registry_upgrade
+
+    comanage_utils::enable_plugins
+
+    comanage_utils::registry_clear_cache
+
+    comanage_utils::tmp_ownership
+
+    # first arg is `-f` or `--some-option`
+    if [ "${1#-}" != "$1" ]; then
+        set -- apache2-foreground "$@"
+    fi
+
+    exec "$@"
+}
+
+##########################################
+# Exec to start and become cron
+# Globals:
+#   None
+# Arguments:
+#   Command and arguments to exec
+# Returns:
+#   Does not return
+##########################################
+function comanage_utils::exec_cron() {
+
+    comanage_utils::consume_injected_environment
+
+    comanage_utils::configure_console_logging
+
+    comanage_utils::process_slash_root
+
+    comanage_utils::prepare_local_directory
+
+    if [[ -z ${COMANAGE_REGISTRY_NO_DATABASE_CONFIG} ]]; then
+        comanage_utils::prepare_database_config
+    fi
+
+    if [[ -z ${COMANAGE_REGISTRY_NO_EMAIL_CONFIG} ]]; then
+        comanage_utils::prepare_email_config
+    fi
+
+    comanage_utils::wait_database_connectivity
+
+    comanage_utils::enable_plugins
+
+    comanage_utils::registry_clear_cache
+
+    comanage_utils::configure_cache_disable
+
+    comanage_utils::tmp_ownership
+
+    comanage_utils::deploy_crontab
+
+    comanage_utils::start_syslogd
+
+    exec "$@"
+}
+
+##########################################
+# Manage TIER environment variables
+# Globals:
+#   None
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::manage_tier_environment() {
+
+    # If ENV or USERTOKEN as injected by the deployer contain a semi-colon remove it.
+    if [[ ${ENV} =~ .*";".* ]]; then
+        ENV=`echo ${ENV} | tr -d ';'`
+        export ENV
+    fi
+
+    if [[ ${USERTOKEN} =~ .*";".* ]]; then
+        USERTOKEN=`echo ${USERTOKEN} | tr -d ';'`
+        export USERTOKEN
+    fi
+
+    # If ENV or USERTOKEN as injected by the deployer contain a space remove it.
+    if [[ ${ENV} =~ [[:space:]] ]]; then
+        ENV=`echo ${ENV} | tr -d [:space:]`
+        export ENV
+    fi
+
+    if [[ ${USERTOKEN} =~ [[:space:]] ]]; then
+        USERTOKEN=`echo ${USERTOKEN} | tr -d [:space:]`
+        export USERTOKEN
+    fi
+}
+
+##########################################
+# Prepare database configuration
+# Globals:
+#   COMANAGE_REGISTRY_DATABASE
+#   COMANAGE_REGISTRY_DATABASE_HOST
+#   COMANAGE_REGISTRY_DATABASE_PORT
+#   COMANAGE_REGISTRY_DATABASE_USER
+#   COMANAGE_REGISTRY_DATABASE_USER_PASSWORD
+#   COMANAGE_REGISTRY_DATASOURCE
+#   COMANAGE_REGISTRY_DIR
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_database_config() {
+
+    # If the COmanage Registry database configuration file does not exist
+    # then try to create it from injected information with reasonable defaults
+    # that aid simple evaluation deployments.
+    local database_config
+    database_config="$COMANAGE_REGISTRY_DIR/local/Config/database.php"
+
+    # File already exists so return.
+    if [[ -e "$database_config" ]]; then
+        return
+    fi
+
+    # File does not exist so create it.
+    local php_string
+
+    read -r -d '' php_string <<'EOF'
+<?php
+
+class DATABASE_CONFIG {
+
+  public $default = array(
+    'persistent' => false,
+    'prefix' => 'cm_',
+EOF
+
+    php_string+=$'\n    '
+    php_string+="'datasource' => '${COMANAGE_REGISTRY_DATASOURCE:-Database/Postgres}',"
+
+    php_string+=$'\n    '
+    php_string+="'host' => '${COMANAGE_REGISTRY_DATABASE_HOST:-comanage-registry-database}',"
+
+    php_string+=$'\n    '
+    php_string+="'login' => '${COMANAGE_REGISTRY_DATABASE_USER:-registry_user}',"
+
+    php_string+=$'\n    '
+    php_string+="'password' => '${COMANAGE_REGISTRY_DATABASE_USER_PASSWORD:-password}',"
+
+    php_string+=$'\n    '
+    php_string+="'database' => '${COMANAGE_REGISTRY_DATABASE:-registry}',"
+
+    # The value of port is an integer.
+    if [[ -n "${COMANAGE_REGISTRY_DATABASE_PORT}" ]]; then
+        php_string+=$'\n    '
+        php_string+="'port' => ${COMANAGE_REGISTRY_DATABASE_PORT},"
+    fi
+
+    if [[ "${COMANAGE_REGISTRY_DATABASE_POSTGRES_SSLMODE}"  =~ ^(disable|allow|prefer|require|verify-ca|verify-full)$ ]]; then
+        php_string+=$'\n    '
+        php_string+="'sslmode' => '${COMANAGE_REGISTRY_DATABASE_POSTGRES_SSLMODE}',"
+    fi
+
+    php_string+=$'\n    );\n}\n';
+
+    printf "%s" "$php_string" > $database_config
+
+    echo "Wrote new database configuration file ${database_config}" > "$OUTPUT"
+}
+
+##########################################
+# Prepare email configuration
+# Globals:
+#   COMANAGE_REGISTRY_EMAIL_ACCOUNT
+#   COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD
+#   COMANAGE_REGISTRY_EMAIL_FROM
+#   COMANAGE_REGISTRY_EMAIL_HOST
+#   COMANAGE_REGISTRY_EMAIL_PORT
+#   COMANAGE_REGISTRY_EMAIL_TLS
+#   COMANAGE_REGISTRY_EMAIL_TRANSPORT
+#   COMANAGE_REGISTRY_DIR
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_email_config() {
+
+    # If the COmanage Registry email configuration file does not exist
+    # then try to create it from injected information with reasonable defaults
+    # that aid simple evaluation deployments.
+    local email_config
+    email_config="$COMANAGE_REGISTRY_DIR/local/Config/email.php"
+
+    # File already exists so return.
+    if [[ -e "$email_config" ]]; then
+        return
+    fi
+
+    # File does not exist so create it.
+    local php_string
+
+    read -r -d '' php_string <<'EOF'
+<?php
+
+class EmailConfig {
+
+  public $default = array(
+EOF
+
+    php_string+=$'\n\t\t'
+
+    # Prefer the array of sender email and name if available, but
+    # if not then prefer the sender email over the older default
+    # and if neither is set use a default since the 'from'
+    # configuration key is always required.
+    if [[ -n "${COMANAGE_REGISTRY_EMAIL_FROM_EMAIL}" && -n "${COMANAGE_REGISTRY_EMAIL_FROM_NAME}" ]]; then
+        php_string+="'from' => array('${COMANAGE_REGISTRY_EMAIL_FROM_EMAIL}' => '${COMANAGE_REGISTRY_EMAIL_FROM_NAME}'),"
+    elif [[ -n "${COMANAGE_REGISTRY_EMAIL_FROM_EMAIL}" && -z "${COMANAGE_REGISTRY_EMAIL_FROM_NAME}" ]]; then
+        php_string+="'from' => '${COMANAGE_REGISTRY_EMAIL_FROM_EMAIL}',"
+    elif [[ -n "${COMANAGE_REGISTRY_EMAIL_FROM}" && -z "${COMANAGE_REGISTRY_EMAIL_FROM_EMAIL}" ]]; then
+        php_string+="'from' => '${COMANAGE_REGISTRY_EMAIL_FROM}',"
+    elif [[ -z "${COMANAGE_REGISTRY_EMAIL_FROM}" ]]; then
+        php_string+="'from' => 'you@localhost',"
+    fi
+
+    if [[ -n "${COMANAGE_REGISTRY_EMAIL_HOST}" ]]; then
+        php_string+=$'\n\t\t'
+        php_string+="'host' => '${COMANAGE_REGISTRY_EMAIL_HOST}',"
+
+        if [[ "${COMANAGE_REGISTRY_EMAIL_HOST}" =~ ^tls:// && -z "${COMANAGE_REGISTRY_EMAIL_TRANSPORT}" ]]; then
+            COMANAGE_REGISTRY_EMAIL_TRANSPORT="Smtp"
+            export COMANAGE_REGISTRY_EMAIL_TRANSPORT
+        fi
+    fi
+
+    if [[ -n "${COMANAGE_REGISTRY_EMAIL_TRANSPORT}" ]]; then
+        php_string+=$'\n\t\t'
+        php_string+="'transport' => '${COMANAGE_REGISTRY_EMAIL_TRANSPORT}',"
+    fi
+
+    # The value of port is an integer.
+    if [[ -n "${COMANAGE_REGISTRY_EMAIL_PORT}" ]]; then
+        php_string+=$'\n\t\t'
+        php_string+="'port' => ${COMANAGE_REGISTRY_EMAIL_PORT},"
+    fi
+
+    # set tls if provided
+    if [[ -n "${COMANAGE_REGISTRY_EMAIL_TLS}" ]]; then
+        php_string+=$'\n\t\t'
+        php_string+="'tls' => ${COMANAGE_REGISTRY_EMAIL_TLS},"
+    fi
+
+    if [[ -n "${COMANAGE_REGISTRY_EMAIL_ACCOUNT}" ]]; then
+        php_string+=$'\n\t\t'
+        php_string+="'username' => '${COMANAGE_REGISTRY_EMAIL_ACCOUNT}',"
+    fi
+
+    if [[ -n "${COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD}" ]]; then
+        php_string+=$'\n\t\t'
+        php_string+="'password' => '${COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD}',"
+    fi
+
+    php_string+=$'\n\t\t);\n\n}\n';
+
+    printf "%s" "$php_string" > $email_config
+}
+
+##########################################
+# Prepare cert and key for HTTPS
+# Globals:
+#   HTTPS_CERT_FILE
+#   HTTPS_PRIVKEY_FILE
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_https_cert_key() {
+
+    local cert_path
+    local privkey_path
+    local web_user
+
+    if [[ -e '/etc/debian_version' ]]; then
+        cert_path='/etc/apache2/cert.pem'
+        privkey_path='/etc/apache2/privkey.pem'
+        web_user='www-data'
+    elif [[ -e '/etc/centos-release' ]]; then
+        cert_path='/etc/httpd/cert.pem'
+        privkey_path='/etc/httpd/privkey.pem'
+        web_user='apache'
+    elif [[ -e '/etc/rocky-release' ]]; then
+        cert_path='/etc/httpd/cert.pem'
+        privkey_path='/etc/httpd/privkey.pem'
+        web_user='apache'
+    fi
+
+    # If defined use configured location of Apache HTTP Server
+    # HTTPS certificate and key files. The certificate file may also
+    # include intermediate CA certificates, sorted from leaf to root.
+    if [[ -n "${HTTPS_CERT_FILE}" ]]; then
+        rm -f "${cert_path}"
+        cp "${HTTPS_CERT_FILE}" "${cert_path}"
+        chown "${web_user}" "${cert_path}"
+        chmod 0644 "${cert_path}"
+        echo "Copied HTTPS certificate file ${HTTPS_CERT_FILE} to ${cert_path}" > "$OUTPUT"
+        echo "Set ownership of ${cert_path} to ${web_user}" > "$OUTPUT"
+    fi
+
+    if [[ -n "${HTTPS_PRIVKEY_FILE}" ]]; then
+        rm -f "${privkey_path}"
+        cp "${HTTPS_PRIVKEY_FILE}" "${privkey_path}"
+        chown "${web_user}" "${privkey_path}"
+        chmod 0600 "${privkey_path}"
+        echo "Copied HTTPS private key file ${HTTPS_PRIVKEY_FILE} to ${privkey_path}" > "$OUTPUT"
+        echo "Set ownership of ${privkey_path} to ${web_user}" > "$OUTPUT"
+    fi
+}
+
+##########################################
+# Prepare local directory structure
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_local_directory() {
+
+    # Make sure the directory structure we need is available
+    # in the data volume for $COMANAGE_REGISTRY_DIR/local
+    local directories
+
+    declare -a directories=("Config"
+                            "Plugin"
+                            "View/Pages/public"
+                            "webroot/img"
+                            )
+
+    local dir
+    local full_path
+    for dir in "${directories[@]}"
+    do
+        full_path="${COMANAGE_REGISTRY_DIR}/local/${dir}"
+        if [[ ! -d "${full_path}" ]]; then
+            mkdir -p "${full_path}" > "$OUTPUT" 2>&1
+            echo "Created directory ${full_path}"
+        fi
+    done
+}
+
+##########################################
+# Prepare mod_remoteip
+# Globals:
+#   COMANAGE_REGISTRY_REMOTE_IP
+#   COMANAGE_REGISTRY_REMOTE_IP_HEADER
+#   COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY
+#   COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY_LIST
+#   COMANAGE_REGISTRY_REMOTE_IP_PROXIES_HEADER
+#   COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL
+#   COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL_EXCEPTIONS
+#   COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY
+#   COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY_LIST
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_mod_remoteip() {
+
+    local remoteip_config
+    remoteip_config="/etc/apache2/mods-available/remoteip.conf"
+
+    if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP}" ]]; then
+        echo "RemoteIPHeader ${COMANAGE_REGISTRY_REMOTE_IP_HEADER:-X-Forwarded-For}" >> $remoteip_config
+
+        if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY}" ]]; then
+            echo "RemoteIPInternalProxy ${COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY}" >> $remoteip_config
+        fi
+
+        if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY_LIST}" ]]; then
+            echo "RemoteIPInternalProxyList ${COMANAGE_REGISTRY_REMOTE_IP_INTERNAL_PROXY_LIST}" >> $remoteip_config
+        fi
+
+        if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP_PROXIES_HEADER}" ]]; then
+            echo "RemoteIPProxiesHeader ${COMANAGE_REGISTRY_REMOTE_IP_PROXIES_HEADER}" >> $remoteip_config
+        fi
+
+        if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL}" ]]; then
+            echo "RemoteIPProxyProtocol ${COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL}" >> $remoteip_config
+        fi
+
+        if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL_EXCEPTIONS}" ]]; then
+            echo "RemoteIPProxyProcotolException ${COMANAGE_REGISTRY_REMOTE_IP_PROXY_PROTOCOL_EXCEPTIONS}" >> $remoteip_config
+        fi
+
+        if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY}" ]]; then
+            echo "RemoteIPTrustedProxy ${COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY}" >> $remoteip_config
+        fi
+
+        if [[ -n "${COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY_LIST}" ]]; then
+            echo "RemoteIPTrustedProxyList ${COMANAGE_REGISTRY_REMOTE_IP_TRUSTED_PROXY_LIST}" >> $remoteip_config
+        fi
+
+        /usr/sbin/a2enmod remoteip > "$OUTPUT" 2>&1
+    fi
+}
+
+##########################################
+# Prepare PHP session storage
+# Globals:
+#   COMANAGE_REGISTRY_PHP_SESSION_REDIS_URL
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_php_session() {
+
+    local php_ini
+    php_ini="/usr/local/etc/php"
+
+    # Configure Redis for sessions if so configured.
+    if [[ -n "${COMANAGE_REGISTRY_PHP_SESSION_REDIS_URL}" ]]; then
+        sed -i -e '/session.save_handler/ s+files+redis+' $php_ini > ${OUTPUT} 2>&1
+        sed -i -e "/session.save_handler/a session.save_path = ${COMANAGE_REGISTRY_PHP_SESSION_REDIS_URL}" $phi_ini > ${OUTPUT} 2>&1
+    fi
+}
+
+##########################################
+# Prepare web server name
+# Globals:
+#   SERVER_NAME
+#   COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_server_name() {
+
+    # SERVER_NAME is deprecated in favor of COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN
+    # and will not be supported in a future version.
+    if [[ -n "$SERVER_NAME" ]]; then
+        echo "SERVER_NAME is deprecated and will not be supported in a future version"
+        echo "Use COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN instead of SERVER_NAME"
+        if [[ -z "$COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN" ]]; then
+            COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN="${SERVER_NAME}"
+            echo "SERVER_NAME=${SERVER_NAME} has been injected" > "$OUTPUT"
+            echo "Setting COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN=${COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN}"
+        fi
+    fi
+
+    # If COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN has not been injected try to determine
+    # it from the HTTPS_CERT_FILE.
+    if [[ -z "$COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN" ]]; then
+        COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN=$(openssl x509 -in /etc/apache2/cert.pem -text -noout |
+                      sed -n '/X509v3 Subject Alternative Name:/ {n;p}' |
+                      sed -E 's/.*DNS:(.*)\s*$/\1/')
+        if [[ -n "$COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN" ]]; then
+            echo "Set COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN=${COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN} using Subject Alternative Name from x509 certificate" > "$OUTPUT"
+        else
+            COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN=$(openssl x509 -in /etc/apache2/cert.pem -subject -noout |
+                          sed -E 's/subject=.*CN=(.*)\s*/\1/')
+            if [[ -n "$COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN" ]]; then
+                echo "Set COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN=${COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN} using CN from x509 certificate" > "$OUTPUT"
+            fi
+        fi
+    fi
+
+    # Configure Apache HTTP Server with the server name.
+    # This configures the server name for the default Debian
+    # Apache HTTP Server configuration but not the server name used
+    # by any virtual hosts.
+    if [[ -e '/etc/debian_version' ]]; then
+        cat > /etc/apache2/conf-available/server-name.conf <<EOF
+ServerName ${COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN:-unknown}
+EOF
+        a2enconf server-name.conf > "$OUTPUT" 2>&1
+    fi
+
+    # Export the server name so that it may be used by
+    # Apache HTTP Server virtual host configurations.
+    export COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN
+}
+
+##########################################
+# Prepare web server virtual host configuration
+# Globals:
+#   COMANAGE_REGISTRY_HTTP_LISTEN_PORT
+#   COMANAGE_REGISTRY_HTTP_NO
+#   COMANAGE_REGISTRY_HTTPS_LISTEN_PORT
+#   COMANAGE_REGISTRY_HTTPS_NO
+#   COMANAGE_REGISTRY_VIRTUAL_HOST_REDIRECT_HTTP_NO
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::prepare_virtual_host() {
+
+    local ports_config
+    local virtual_host_config
+
+    ports_config="/etc/apache2/ports.conf"
+    virtual_host_config="/etc/apache2/sites-available/000-comanage.conf"
+
+    # Configure the listening ports.
+    /bin/rm -f $ports_config > "${OUTPUT}" 2>&1
+
+    if [[ -z "${COMANAGE_REGISTRY_HTTP_NO}" ]]; then
+        echo "Listen ${COMANAGE_REGISTRY_HTTP_LISTEN_PORT:-80}" >> $ports_config
+    fi
+
+    if [[ -z "${COMANAGE_REGISTRY_HTTPS_NO}" ]]; then
+        echo "Listen ${COMANAGE_REGISTRY_HTTPS_LISTEN_PORT:-443}" >> $ports_config
+    fi
+
+    # Do not overwrite an existing virtual host configuration.
+    if [[ -e $virtual_host_config ]]; then
+        return 0
+    fi
+
+    if [[ -z "${COMANAGE_REGISTRY_HTTP_NO}" ]]; then
+        # Write configuration for HTTP virtual host.
+        comanage_utils::virtual_host_http_opening $virtual_host_config
+
+        if [[ -z "${COMANAGE_REGISTRY_VIRTUAL_HOST_REDIRECT_HTTP_NO}" ]]; then
+            # Write configuration for redirecting HTTP to HTTPS.
+            comanage_utils::virtual_host_http_redirect $virtual_host_config
+        else
+            # Write full configuration for HTTP including authentication.
+            comanage_utils::virtual_host_general_config $virtual_host_config
+            comanage_utils::virtual_host_authentication $virtual_host_config
+        fi
+
+        # Write close for virtual host.
+        comanage_utils::virtual_host_close $virtual_host_config
+
+    fi
+
+    if [[ -z "${COMANAGE_REGISTRY_HTTPS_NO}" ]]; then
+        # Write configuration for HTTPS.
+        comanage_utils::virtual_host_https_opening $virtual_host_config
+        comanage_utils::virtual_host_general_config $virtual_host_config
+        comanage_utils::virtual_host_authentication $virtual_host_config
+        comanage_utils::virtual_host_close $virtual_host_config
+    fi
+}
+
+##########################################
+# Process slash root directory if exists
+# Globals:
+#   COMANAGE_REGISTRY_SLASH_ROOT_DIRECTORY
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::process_slash_root() {
+
+    local slash_root
+
+    slash_root="${COMANAGE_REGISTRY_SLASH_ROOT_DIRECTORY:-/opt/registry/slashRoot}"
+
+    # Exit if directory does not exist.
+    if [[ ! -d "${slash_root}" ]]; then
+        return 0
+    fi
+
+    echo "Processing slash root directory ${slash_root}..."
+
+    pushd "${slash_root}"
+
+    # Copy all files and symlinks and preserve all details but exclude any files
+    # for the Shibboleth SP if they exist to allow the Shib SP
+    # entrypoint script to process that path and prevent a race
+    # condition.
+    find . -type f,l -not -path "./etc/shibboleth/*" | xargs -I{} cp --preserve=all --parents --no-dereference {} / > ${OUTPUT} 2>&1
+
+    popd
+
+    echo "Done processing slash root directory ${slash_root}"
+}
+
+##########################################
+# Clear CakePHP cache files
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::registry_clear_cache() {
+
+    local cache_dir
+    cache_dir="$COMANAGE_REGISTRY_DIR/app/tmp/cache"
+
+    if [[ -d $cache_dir ]]; then
+        find $cache_dir -type f -exec rm -f {} \;
+        echo "Cleared COmanage Registry CakePHP cache files in ${cache_dir}" > "$OUTPUT"
+    fi
+
+}
+
+##########################################
+# Run COmanage Registry setup shell command
+# Globals:
+#   COMANAGE_REGISTRY_ADMIN_GIVEN_NAME
+#   COMANAGE_REGISTRY_ADMIN_FAMILY_NAME
+#   COMANAGE_REGISTRY_ADMIN_USERNAME
+#   COMANAGE_REGISTRY_DIR
+#   COMANAGE_REGISTRY_ENABLE_POOLING
+#   COMANAGE_REGISTRY_SECURITY_SALT
+#   COMANAGE_REGISTRY_SECURITY_SEED
+#   COMANAGE_REGISTRY_SKIP_SETUP
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::registry_setup() {
+
+    local setup_already_script
+
+    if [[ -n "${COMANAGE_REGISTRY_SKIP_SETUP}" ]]; then
+        echo "Skipping database setup step" > "$OUTPUT" 2>&1
+        return 0
+    fi
+
+    # We only want to run the setup script once since it creates
+    # state in the database. Until COmanage Registry has a better
+    # mechanism for telling us if setup has already been run
+    # we create an ephemeral CakePHP script to tell us.
+    setup_already_script="$COMANAGE_REGISTRY_DIR/app/Console/Command/SetupAlreadyShell.php"
+
+    cat > $setup_already_script <<"EOF"
+<?php
+
+class SetupAlreadyShell extends AppShell {
+  var $uses = array('Co');
+
+  function main() {
+    $args = array();
+    $args['conditions']['Co.name'] = 'COmanage';
+    $args['contain'] = false;
+
+    try {
+      $co = $this->Co->find('first', $args);
+    } catch (CakeException $e) {
+      $this->out('Not setup already');
+    }
+
+    if(empty($co)) {
+      $this->out('Not setup already');
+    } else {
+      $this->error('Setup already');
+    }
+  }
+}
+EOF
+
+    local setup_already
+    pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+    echo "Testing if COmanage Registry setup has been done previously..." > "$OUTPUT"
+    ./Console/cake setupAlready > "$OUTPUT" 2>&1
+    setup_already=$?
+
+    rm -f "$setup_already_script"
+
+    local auto_generated_security
+
+    if [ $setup_already -eq 0 ]; then
+        echo "COmanage Registry setup has not been done previously" > "$OUTPUT"
+        rm -f "$COMANAGE_REGISTRY_DIR/local/Config/security.salt" > "$OUTPUT" 2>&1
+        rm -f "$COMANAGE_REGISTRY_DIR/local/Config/security.seed" > "$OUTPUT" 2>&1
+        echo "Running ./Console/cake database..." > "$OUTPUT"
+        ./Console/cake database > "$OUTPUT" 2>&1
+        echo "Running ./Console/cake setup..." > "$OUTPUT"
+        ./Console/cake setup --admin-given-name "${COMANAGE_REGISTRY_ADMIN_GIVEN_NAME}" \
+                             --admin-family-name "${COMANAGE_REGISTRY_ADMIN_FAMILY_NAME}" \
+                             --admin-username "${COMANAGE_REGISTRY_ADMIN_USERNAME}" \
+                             --enable-pooling "${COMANAGE_REGISTRY_ENABLE_POOLING}" > "$OUTPUT" 2>&1
+        echo "Set admin given name ${COMANAGE_REGISTRY_ADMIN_GIVEN_NAME}" > "$OUTPUT"
+        echo "Set admin family name ${COMANAGE_REGISTRY_ADMIN_FAMILY_NAME}" > "$OUTPUT"
+        echo "Set admin username ${COMANAGE_REGISTRY_ADMIN_USERNAME}" > "$OUTPUT"
+        echo "Set enable pooling to ${COMANAGE_REGISTRY_ENABLE_POOLING}" > "$OUTPUT"
+        auto_generated_security=1
+    fi
+
+    popd > "$OUTPUT" 2>&1
+
+    # If COmanage Registry CakePHP security salt and seed have been
+    # injected and the files do not otherwise exist create them.
+    if [[ -n "$COMANAGE_REGISTRY_SECURITY_SALT" && ( -n "$auto_generated_security" || ! -e "$COMANAGE_REGISTRY_DIR/local/Config/security.salt" ) ]]; then
+        echo "$COMANAGE_REGISTRY_SECURITY_SALT" > "$COMANAGE_REGISTRY_DIR/local/Config/security.salt"
+    fi
+
+    if [[ -n "$COMANAGE_REGISTRY_SECURITY_SEED" && ( -n "$auto_generated_security" || ! -e "$COMANAGE_REGISTRY_DIR/local/Config/security.seed" ) ]]; then
+        echo "$COMANAGE_REGISTRY_SECURITY_SEED" > "$COMANAGE_REGISTRY_DIR/local/Config/security.seed"
+    fi
+}
+
+##########################################
+# Run COmanage Registry upgradeVersion shell command
+# Globals:
+#   COMANAGE_REGISTRY_DATABASE_SCHEMA_FORCE
+#   COMANAGE_REGISTRY_DATABASE_SKIP_UPGRADE
+#   COMANAGE_REGISTRY_DIR
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::registry_upgrade() {
+
+    if [[ -n "${COMANAGE_REGISTRY_SKIP_UPGRADE}" ]]; then
+        echo "Skipping upgrade step" > "$OUTPUT" 2>&1
+        return 0
+    fi
+
+    # We always run upgradeVersion since it will not make any changes
+    # if the current and target versions are the same or if
+    # an upgrade from the current to the target version is not allowed.
+
+    # First clear the caches.
+    comanage_utils::registry_clear_cache
+
+    pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+    echo "Running ./Console/cake upgradeVersion..." > "$OUTPUT"
+    ./Console/cake upgradeVersion > "$OUTPUT" 2>&1
+    echo "Done running ./Console/cake upgradeVersion" > "$OUTPUT"
+    echo "You may ignore errors reported above if the Current and Target versions are the same" > "$OUTPUT"
+    popd > "$OUTPUT" 2>&1
+
+    # Force a datbase update if requested. This is helpful when deploying
+    # a new version of the code that does not result in a change in the
+    # version number and so upgradeVersion does not fire. An example
+    # of this scenario is when new code is introduced in the develop
+    # branch but before a release happens.
+    if [ -n "$COMANAGE_REGISTRY_DATABASE_SCHEMA_FORCE" ]; then
+        echo "Forcing a database schema update..." > "$OUTPUT"
+        pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+        ./Console/cake database > "$OUTPUT" 2>&1
+        echo "Done forcing database schema update" > "$OUTPUT"
+        popd > "$OUTPUT" 2>&1
+    fi
+
+    # Clear the caches again.
+    comanage_utils::registry_clear_cache
+}
+
+##########################################
+# Start syslogd from busybox for use with cron
+# Globals:
+#   None
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::start_syslogd() {
+
+    /sbin/syslogd -O /proc/1/fd/1 -S
+
+}
+
+##########################################
+# Set tmp directory file ownership
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::tmp_ownership() {
+
+    # Ensure that the web server user owns the tmp directory
+    # and all children.
+    local tmp_dir
+    local ownership
+
+    if [[ -e '/etc/debian_version' ]]; then
+        ownership='www-data:www-data'
+    elif [[ -e '/etc/centos-release' ]]; then
+        ownership='apache:apache'
+    elif [[ -e '/etc/rocky-release' ]]; then
+        ownership='apache:apache'
+    fi
+
+    tmp_dir="${COMANAGE_REGISTRY_DIR}/app/tmp"
+
+    chown -R "${ownership}" "${tmp_dir}"
+
+    echo "Recursively set ownership of ${tmp_dir} to ${ownership}" > "$OUTPUT"
+
+}
+
+##########################################
+# Write virtual host authentication stanza
+# Globals:
+#  COMANAGE_REGISTRY_OIDC_AUTH_REQUEST_PARAMS
+#  COMANAGE_REGISTRY_OIDC_CLIENT_ID
+#  COMANAGE_REGISTRY_OIDC_CLIENT_SECRET
+#  COMANAGE_REGISTRY_OIDC_CRYPTO_PASSPHRASE
+#  COMANAGE_REGISTRY_OIDC_FORWARD_HEADERS
+#  COMANAGE_REGISTRY_OIDC_PROVIDER_METADATA_URL
+#  COMANAGE_REGISTRY_OIDC_REMOTE_USER_CLAIM
+#  COMANAGE_REGISTRY_OIDC_SCOPES
+#  COMANAGE_REGISTRY_OIDC_SESSION_INACTIVITY_TIMEOUT
+#  COMANAGE_REGISTRY_OIDC_SESSION_MAX_DURATION
+#  COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN
+# Arguments:
+#   Path to file
+# Returns:
+#   None
+##########################################
+function comanage_utils::virtual_host_authentication() {
+        local a2query_out
+        local mod_auth_openidc
+        local shib
+        local virtual_host_config
+
+        virtual_host_config="$1"
+
+        mod_auth_openidc=0
+        shib=0
+
+        # Test for mod_auth_openidc module.
+        (a2query -m auth_openidc) > /dev/null 2>&1
+        a2query_out=$?
+        if [[ $a2query_out -eq 0 ]]; then
+            mod_auth_openidc=1
+        fi
+
+        # Test for shib2 module.
+        (a2query -m shib2) > /dev/null 2>&1
+        a2query_out=$?
+        if [[ $a2query_out -eq 0 ]]; then
+            shib=1
+        fi
+
+        # Write mod_auth_openidc if module enabled.
+        if [[ $mod_auth_openidc -eq 1 ]]; then
+            cat >> $virtual_host_config <<EOF
+
+OIDCProviderMetadataURL ${COMANAGE_REGISTRY_OIDC_PROVIDER_METADATA_URL}
+OIDCRemoteUserClaim ${COMANAGE_REGISTRY_OIDC_REMOTE_USER_CLAIM:-sub}
+
+OIDCClientID ${COMANAGE_REGISTRY_OIDC_CLIENT_ID}
+OIDCClientSecret ${COMANAGE_REGISTRY_OIDC_CLIENT_SECRET}
+
+OIDCScope "${COMANAGE_REGISTRY_OIDC_SCOPES:-openid}"
+OIDCCryptoPassphrase ${COMANAGE_REGISTRY_OIDC_CRYPTO_PASSPHRASE}
+
+OIDCRedirectURI https://${COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN}/secure/redirect
+
+OIDCSessionInactivityTimeout ${COMANAGE_REGISTRY_OIDC_SESSION_INACTIVITY_TIMEOUT:-3600}
+OIDCSessionMaxDuration ${COMANAGE_REGISTRY_OIDC_SESSION_MAX_DURATION:-3600}
+EOF
+
+            if [[ -n "${COMANAGE_REGISTRY_OIDC_FORWARD_HEADERS}" ]]; then
+                cat >> $virtual_host_config <<EOF
+OIDCXForwardedHeaders X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto
+EOF
+            fi
+
+            if [[ -n "${COMANAGE_REGISTRY_OIDC_AUTH_REQUEST_PARAMS}" ]]; then
+                cat >> $virtual_host_config <<EOF
+OIDCAuthRequestParams ${COMANAGE_REGISTRY_OIDC_AUTH_REQUEST_PARAMS}
+EOF
+            fi
+
+            cat >> $virtual_host_config <<EOF
+
+<Location /secure/redirect>
+  AuthType openid-connect
+  Require valid-user
+</Location>
+
+<Directory /var/www/html/registry>
+Options -Indexes +FollowSymLinks
+DirectoryIndex index.php
+AllowOverride All
+AuthType openid-connect
+OIDCUnAuthAction pass
+Require valid-user
+</Directory>
+
+<Directory /var/www/html/registry/auth/login>
+AuthType openid-connect
+OIDCUnAuthAction auth
+Require valid-user
+</Directory>
+
+RewriteEngine On
+RewriteCond %{QUERY_STRING} !after_redirect
+RewriteRule ^/registry/auth/logout.* https://%{HTTP_HOST}/secure/redirect?logout=https://%{HTTP_HOST}/registry/auth/logout/?after_redirect [L,R]
+EOF
+
+        # Write shib if module enabled.
+        elif [[ $shib -eq 1 ]]; then
+            cat >> $virtual_host_config <<EOF
+
+<Location "/Shibboleth.sso">
+SetHandler shib
+</Location>
+
+<Directory /var/www/html/registry/auth/login>
+AuthType shibboleth
+ShibRequestSetting requireSession 1
+Require valid-user
+</Directory>
+
+<Location />
+AuthType shibboleth
+Require shibboleth
+</Location>
+
+RewriteEngine On
+RewriteCond %{QUERY_STRING} !after_redirect
+RewriteRule ^/registry/auth/logout.* https://%{HTTP_HOST}/Shibboleth.sso/Logout?return=https://%{HTTP_HOST}/registry/auth/logout/?after_redirect [L,R]
+EOF
+
+        # Else assume basic authentication.
+        else
+            cat >> $virtual_host_config <<EOF
+
+<Directory /var/www/html/registry/auth/login>
+AuthType Basic
+AuthName "COmanage Registry Login"
+AuthBasicProvider file
+AuthUserFile "/etc/apache2/basic-auth"
+Require valid-user
+</Directory>
+EOF
+        fi
+}
+
+##########################################
+# Write virtual host closing stanza
+# Globals:
+# Arguments:
+#   Path to file
+# Returns:
+#   None
+##########################################
+function comanage_utils::virtual_host_close() {
+        local virtual_host_config
+
+        virtual_host_config="$1"
+
+        cat >> $virtual_host_config <<EOF
+
+</VirtualHost>
+EOF
+}
+
+##########################################
+# Write virtual host general configuration
+# Globals:
+# Arguments:
+#   Path to file
+# Returns:
+#   None
+##########################################
+function comanage_utils::virtual_host_general_config() {
+
+        local virtual_host_config
+        virtual_host_config="$1"
+
+        cat >> $virtual_host_config <<"EOF"
+DocumentRoot /var/www/html
+
+RedirectMatch ^/$ /registry/
+
+LogFormat "%a %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogLevel warn
+ErrorLog ${APACHE_LOG_DIR}/error.log
+CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+<Directory /var/www/html/registry>
+Options -Indexes +FollowSymLinks
+DirectoryIndex index.php
+AllowOverride All
+Require all granted
+</Directory>
+EOF
+
+}
+
+##########################################
+# Write virtual host HTTP opening stanza
+# Globals:
+#  COMANAGE_REGISTRY_HTTP_LISTEN_PORT
+#  COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN
+#  COMANAGE_REGISTRY_VIRTUAL_HOST_PORT
+#  COMANAGE_REGISTRY_VIRTUAL_HOST_SCHEME
+# Arguments:
+#   Path to file
+# Returns:
+#   None
+##########################################
+function comanage_utils::virtual_host_http_opening() {
+
+        local virtual_host_config
+        virtual_host_config="$1"
+
+        cat >> $virtual_host_config <<EOF
+<VirtualHost *:${COMANAGE_REGISTRY_HTTP_LISTEN_PORT:-80}>
+ServerName ${COMANAGE_REGISTRY_VIRTUAL_HOST_SCHEME:-http}://${COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN}:${COMANAGE_REGISTRY_VIRTUAL_HOST_PORT:-80}
+UseCanonicalName On
+UseCanonicalPhysicalPort On
+
+Header set Content-Security-Policy "frame-ancestors 'self';"
+
+EOF
+}
+
+##########################################
+# Write virtual host HTTPS opening stanza
+# Globals:
+#  COMANAGE_REGISTRY_VIRTUAL_HOST_SCHEME
+#  COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN
+#  COMANAGE_REGISTRY_VIRTUAL_HOST_PORT
+#  COMANAGE_REGISTRY_HTTPS_LISTEN_PORT
+# Arguments:
+#   Path to file
+# Returns:
+#   None
+##########################################
+function comanage_utils::virtual_host_https_opening() {
+
+        local virtual_host_config
+        virtual_host_config="$1"
+
+        cat >> $virtual_host_config <<EOF
+<VirtualHost *:${COMANAGE_REGISTRY_HTTPS_LISTEN_PORT:-443}>
+ServerName ${COMANAGE_REGISTRY_VIRTUAL_HOST_SCHEME:-https}://${COMANAGE_REGISTRY_VIRTUAL_HOST_FQDN}:${COMANAGE_REGISTRY_VIRTUAL_HOST_PORT:-443}
+UseCanonicalName On
+UseCanonicalPhysicalPort On
+
+Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
+Header always set Content-Security-Policy "frame-ancestors 'self';"
+
+SSLEngine on
+SSLProtocol all -SSLv2 -SSLv3
+SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
+SSLHonorCipherOrder on
+
+SSLCertificateFile /etc/apache2/cert.pem
+SSLCertificateKeyFile /etc/apache2/privkey.pem
+EOF
+
+}
+
+##########################################
+# Write virtual host HTTP redirect stanza
+# Globals:
+# Arguments:
+#   Path to file
+# Returns:
+#   None
+##########################################
+function comanage_utils::virtual_host_http_redirect() {
+
+        local virtual_host_config
+        virtual_host_config="$1"
+
+        cat >> $virtual_host_config <<"EOF"
+RewriteEngine On
+RewriteCond %{HTTPS} off
+RewriteRule ^ https://%{HTTP_HOST}:443%{REQUEST_URI} [R=302,L,QSA]
+EOF
+
+}
+
+
+##########################################
+# Wait until able to connect to database
+# Globals:
+#   COMANAGE_REGISTRY_DIR
+#   OUTPUT
+# Arguments:
+#   None
+# Returns:
+#   None
+##########################################
+function comanage_utils::wait_database_connectivity() {
+
+    # Create a CakePHP shell to test database connectivity.
+    local database_test_script
+    database_test_script="$COMANAGE_REGISTRY_DIR/app/Console/Command/DatabaseTestShell.php"
+
+    cat > $database_test_script <<"EOF"
+<?php
+
+App::import('Model', 'ConnectionManager');
+
+class DatabaseTestShell extends AppShell {
+  function main() {
+    try {
+      $db = ConnectionManager::getDataSource('default');
+    } catch (Exception $e) {
+      $this->error("Unable to connect to datasource");
+    }
+    $this->out("Connected to datasource");
+  }
+}
+EOF
+
+    pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
+
+    # Loop until we are able to open a connection to the database.
+    echo "Testing database availability..." > "$OUTPUT"
+    until ./Console/cake databaseTest > "$OUTPUT" 2>&1; do
+        >&2 echo "Database is unavailable - sleeping"
+        sleep 1
+    done
+
+    rm -f "$database_test_script"
+
+    echo "Database is available" > "$OUTPUT"
+
+    popd > "$OUTPUT" 2>&1
+}

From ddc196193a0d46678e8a5ec1c120374edf53385c Mon Sep 17 00:00:00 2001
From: Ioannis Igoumenos <ioigoume@gmail.com>
Date: Thu, 11 Jul 2024 13:44:24 +0300
Subject: [PATCH 2/2] Mark develop

---
 common.bash | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common.bash b/common.bash
index 45fb114..4ff9d3c 100644
--- a/common.bash
+++ b/common.bash
@@ -1,3 +1,3 @@
 maintainer="i2incommon"
-imagename="comanage-registry-cron"
+imagename="comanage-registry-cron-dev"
 comanage_version="4.3.4"