Permalink
Find file Copy path
9041b3c Aug 3, 2018
1 contributor

Users who have contributed to this file

executable file 351 lines (291 sloc) 12.2 KB
#!/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.
if [ -n "$COMANAGE_DEBUG" ]
then
OUTPUT=/dev/stdout
else
OUTPUT=/dev/null
fi
# Configuration details that may be injected through environment
# variables or the contents of files.
injectable_config_vars=(
COMANAGE_REGISTRY_DATASOURCE
COMANAGE_REGISTRY_DATABASE
COMANAGE_REGISTRY_DATABASE_HOST
COMANAGE_REGISTRY_DATABASE_USER
COMANAGE_REGISTRY_DATABASE_USER_PASSWORD
COMANAGE_REGISTRY_EMAIL_FROM
COMANAGE_REGISTRY_EMAIL_TRANSPORT
COMANAGE_REGISTRY_EMAIL_HOST
COMANAGE_REGISTRY_EMAIL_PORT
COMANAGE_REGISTRY_EMAIL_ACCOUNT
COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD
COMANAGE_REGISTRY_SECURITY_SALT
COMANAGE_REGISTRY_SECURITY_SEED
ENV
HTTPS_CERT_FILE
HTTPS_PRIVKEY_FILE
SERVER_NAME
USERTOKEN
)
# 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.
for config_var in "${injectable_config_vars[@]}"
do
eval file_name=\$"${config_var}_FILE";
if [ -e "$file_name" ]; then
declare "${config_var}"=`cat $file_name`
fi
done
# Make sure the directory structure we need is available
# in the data volume for $COMANAGE_REGISTRY_DIR/local
mkdir -p "$COMANAGE_REGISTRY_DIR/local/Config"
mkdir -p "$COMANAGE_REGISTRY_DIR/local/Plugin"
mkdir -p "$COMANAGE_REGISTRY_DIR/local/View/Pages/public"
mkdir -p "$COMANAGE_REGISTRY_DIR/local/webroot/img"
# 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.
if [ ! -e "$COMANAGE_REGISTRY_DIR/local/Config/database.php" ]; then
cat > "$COMANAGE_REGISTRY_DIR/local/Config/database.php" <<EOF
<?php
class DATABASE_CONFIG {
public \$default = array(
'datasource' => '${COMANAGE_REGISTRY_DATASOURCE:-Database/Mysql}',
'persistent' => false,
'host' => '${COMANAGE_REGISTRY_DATABASE_HOST:-comanage-registry-database}',
'login' => '${COMANAGE_REGISTRY_DATABASE_USER:-registry_user}',
'password' => '${COMANAGE_REGISTRY_DATABASE_USER_PASSWORD:-password}',
'database' => '${COMANAGE_REGISTRY_DATABASE:-registry}',
'prefix' => 'cm_',
);
}
EOF
fi
# 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.
email_config="$COMANAGE_REGISTRY_DIR/local/Config/email.php"
if [ ! -e "$email_config" ]; then
# If the deployer has injected an email for from then use it,
# otherwise set a default purely as a template that can edited
# easier later.
if [ -n "$COMANAGE_REGISTRY_EMAIL_FROM" ]; then
email_from="$COMANAGE_REGISTRY_EMAIL_FROM"
else
email_from="array('account@gmail.com' => 'Registry')"
fi
# If the injected email from does not include a single quote (')
# then add them to make it a PHP string.
if [[ ! $email_from =~ .*"'".* ]]; then
email_from="'$email_from'"
fi
cat > "$email_config" <<EOF
<?php
class EmailConfig {
public \$default = array(
'from' => $email_from,
'transport' => '${COMANAGE_REGISTRY_EMAIL_TRANSPORT:-Smtp}',
'host' => '${COMANAGE_REGISTRY_EMAIL_HOST:-tls://smtp.gmail.com}',
'port' => ${COMANAGE_REGISTRY_EMAIL_PORT:-465},
EOF
# If the deployer has injected a username then add it to the configuration.
if [ -n "$COMANAGE_REGISTRY_EMAIL_ACCOUNT" ]; then
cat >> "$email_config" <<EOF
'username' => '$COMANAGE_REGISTRY_EMAIL_ACCOUNT',
EOF
fi
# If the deployer has injected a password then add it to the configuration.
if [ -n "$COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD" ]; then
cat >> "$email_config" <<EOF
'password' => '$COMANAGE_REGISTRY_EMAIL_ACCOUNT_PASSWORD',
EOF
fi
# Complete the PHP array.
cat >> "$email_config" <<EOF
);
}
EOF
fi
# Loop until we are able to open a connection to the database.
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
until ./Console/cake databaseTest > "$OUTPUT" 2>&1; do
>&2 echo "Database is unavailable - sleeping"
sleep 1
done
rm -f "$DATABASE_TEST_SCRIPT"
popd > "$OUTPUT" 2>&1
# 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
pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
./Console/cake setupAlready > "$OUTPUT" 2>&1
setup_already=$?
rm -f "$SETUP_ALREADY_SCRIPT"
if [ $setup_already -eq 0 ]; then
rm -f "$COMANAGE_REGISTRY_DIR/local/Config/security.salt" > "$OUTPUT" 2>&1
rm -f "$COMANAGE_REGISTRY_DIR/local/Config/security.seed" > "$OUTPUT" 2>&1
# Run database twice until issue on develop branch is resolved. Since
# the command is idempotent normally it is not a problem to have it run
# more than once.
./Console/cake database > "$OUTPUT" 2>&1 && \
./Console/cake database > "$OUTPUT" 2>&1 && \
./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
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
# 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.
pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
./Console/cake upgradeVersion "${COMANAGE_REGISTRY_UPGRADE_VERSION_OPTS}" > "$OUTPUT" 2>&1
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" 2>&1
pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
./Console/cake database > "$OUTPUT" 2>&1
popd > "$OUTPUT" 2>&1
fi
# Enable any supported non-core plugins if requested.
if [ -n "$COMANAGE_REGISTRY_ENABLE_PLUGIN" ]; then
plugins=(`echo "$COMANAGE_REGISTRY_ENABLE_PLUGIN" | sed -e 's@,@ @'`) > "$OUTPUT" 2>&1
for plugin in "${plugins[@]}";
do
echo "Enabling available plugin $plugin..." > "$OUTPUT" 2>&1
pushd "$COMANAGE_REGISTRY_DIR/local/Plugin" > "$OUTPUT" 2>&1
ln -s "../../app/AvailablePlugin/$plugin" "$plugin" > "$OUTPUT" 2>&1
popd > "$OUTPUT" 2>&1
pushd "$COMANAGE_REGISTRY_DIR/app" > "$OUTPUT" 2>&1
./Console/cake database > "$OUTPUT" 2>&1
popd > "$OUTPUT" 2>&1
done
fi
# Remove any cache files generated thus far.
find "$COMANAGE_REGISTRY_DIR/app/tmp/cache" -type f -exec rm -f {} \;
# 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 /etc/httpd/cert.pem
cp "$HTTPS_CERT_FILE" /etc/httpd/cert.pem
chown apache /etc/httpd/cert.pem
chmod 0644 /etc/httpd/cert.pem
fi
if [ -n "$HTTPS_PRIVKEY_FILE" ]; then
rm -f /etc/httpd/privkey.pem
cp "$HTTPS_PRIVKEY_FILE" /etc/httpd/privkey.pem
chown apache /etc/httpd/privkey.pem
chmod 0600 /etc/httpd/privkey.pem
fi
# If SERVER_NAME has not been injected try to determine
# it from the HTTPS_CERT_FILE.
if [ -z "$SERVER_NAME" ]; then
SERVER_NAME=`openssl x509 -in /etc/httpd/cert.pem -text -noout | sed -n '/X509v3 Subject Alternative Name:/ {n;p}' | sed -E 's/.*DNS:(.*)\s*$/\1/'`
if [ -z "$SERVER_NAME" ]; then
SERVER_NAME=`openssl x509 -in /etc/httpd/cert.pem -subject -noout | sed -E 's/subject=.*CN=(.*)\s*/\1/'`
fi
fi
# Configure Apache HTTP Server with the server name.
sed -i -e s@%%SERVER_NAME%%@"${SERVER_NAME:-unknown}"@g /etc/httpd/conf.d/000-comanage.conf
# 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
# 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)&
# Start Apache HTTP Server
exec /usr/sbin/httpd -DFOREGROUND