From 3ba3021b68238e4d924d7fc0d13a1b544b5d07ef Mon Sep 17 00:00:00 2001 From: murphy83 Date: Mon, 6 May 2024 17:13:13 +0200 Subject: [PATCH] =?UTF-8?q?Added=20possibility=20to=20use=20an=20existing?= =?UTF-8?q?=20config=20file=20for=20recursor=20or=20auth=E2=80=A6=20(#135)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added possibility to use an existing config file for recursor or authorative mysql-powerdns-server, in case the configuration file is handed in from a volume or bind mount (in which it should be mounted as read only!). * ammended changes to PostgreSQL init to provide the same features as the MySQL one. * do not forget to init superslaves if needed. * typos and really do install config file by environment. --------- Co-authored-by: Kai Schlachter --- pdns-mysql/docker-entrypoint.sh | 158 ++++++++++++++++++++--------- pdns-pgsql/docker-entrypoint.sh | 144 +++++++++++++++++--------- pdns-recursor/docker-entrypoint.sh | 27 +++-- 3 files changed, 225 insertions(+), 104 deletions(-) diff --git a/pdns-mysql/docker-entrypoint.sh b/pdns-mysql/docker-entrypoint.sh index 0865131..41014bb 100755 --- a/pdns-mysql/docker-entrypoint.sh +++ b/pdns-mysql/docker-entrypoint.sh @@ -2,65 +2,90 @@ set -eu -# Configure mysql env vars -: "${PDNS_gmysql_host:=${MYSQL_ENV_MYSQL_HOST:-mysql}}" -: "${PDNS_gmysql_port:=${MYSQL_ENV_MYSQL_PORT:-3306}}" -: "${PDNS_gmysql_user:=${MYSQL_ENV_MYSQL_USER:-root}}" -if [ "${PDNS_gmysql_user}" = 'root' ]; then - : "${PDNS_gmysql_password:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" -fi -: "${PDNS_gmysql_password:=${MYSQL_ENV_MYSQL_PASSWORD:-powerdns}}" -: "${PDNS_gmysql_dbname:=${MYSQL_ENV_MYSQL_DATABASE:-powerdns}}" - -# Use first part of node name as database name suffix -if [ "${NODE_NAME:-}" ]; then - NODE_NAME=$(echo "${NODE_NAME}" | sed -e 's/\..*//' -e 's/-//') - PDNS_gmysql_dbname="${PDNS_gmysql_dbname}${NODE_NAME}" -fi - -export PDNS_gmysql_host PDNS_gmysql_port PDNS_gmysql_user PDNS_gmysql_password PDNS_gmysql_dbname +##### Function definitions #### -EXTRA='' +function deriveMySQLSettingsFromExistingConfigFile { + if [ ! -f /etc/pdns/pdns.conf ]; then + echo "Use of existing file /etc/pdns/pdns.conf requested but file does not exist!" + exit 1 + fi + PDNS_gmysql_host=`sed -n 's/^gmysql-host=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gmysql_port=`sed -n 's/^gmysql-port=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gmysql_user=`sed -n 's/^gmysql-user=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gmysql_password=`sed -n 's/^gmysql-password=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gmysql_dbname=`sed -n 's/^gmysql-dbname=\(.*\)/\1/p' < /etc/pdns/pdns.conf` +} -# Password Auth -if [ "${PDNS_gmysql_password}" ]; then - EXTRA="${EXTRA} -p${PDNS_gmysql_password}" -fi +function deriveMySQLSettingsFromEnvironment { + # Configure mysql env vars + : "${PDNS_gmysql_host:=${MYSQL_ENV_MYSQL_HOST:-mysql}}" + : "${PDNS_gmysql_port:=${MYSQL_ENV_MYSQL_PORT:-3306}}" + : "${PDNS_gmysql_user:=${MYSQL_ENV_MYSQL_USER:-root}}" + if [ "${PDNS_gmysql_user}" = 'root' ]; then + : "${PDNS_gmysql_password:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" + fi + : "${PDNS_gmysql_password:=${MYSQL_ENV_MYSQL_PASSWORD:-powerdns}}" + : "${PDNS_gmysql_dbname:=${MYSQL_ENV_MYSQL_DATABASE:-powerdns}}" + + # Use first part of node name as database name suffix + if [ "${NODE_NAME:-}" ]; then + NODE_NAME=$(echo "${NODE_NAME}" | sed -e 's/\..*//' -e 's/-//') + PDNS_gmysql_dbname="${PDNS_gmysql_dbname}${NODE_NAME}" + fi + + export PDNS_gmysql_host PDNS_gmysql_port PDNS_gmysql_user PDNS_gmysql_password PDNS_gmysql_dbname +} -# Allow socket connections -if [ "${PDNS_gmysql_socket:-}" ]; then - export PDNS_gmysql_host='localhost' - EXTRA="${EXTRA} --socket=${PDNS_gmysql_socket}" -fi +function generateMySQLCommand { + EXTRA='' + + # Password Auth + if [ "${PDNS_gmysql_password}" ]; then + EXTRA="${EXTRA} -p${PDNS_gmysql_password}" + fi + + # Allow socket connections + if [ "${PDNS_gmysql_socket:-}" ]; then + export PDNS_gmysql_host='localhost' + EXTRA="${EXTRA} --socket=${PDNS_gmysql_socket}" + fi + + MYSQL_COMMAND="mysql -h ${PDNS_gmysql_host} -P ${PDNS_gmysql_port} -u ${PDNS_gmysql_user}${EXTRA}" +} -MYSQL_COMMAND="mysql -h ${PDNS_gmysql_host} -P ${PDNS_gmysql_port} -u ${PDNS_gmysql_user}${EXTRA}" -# Wait for MySQL to respond -until $MYSQL_COMMAND -e ';' ; do - >&2 echo 'MySQL is unavailable - sleeping' - sleep 3 -done +function createDatabaseIfRequested { + # Initialize DB if needed + if [ "${SKIP_DB_CREATE:-false}" != 'true' ]; then + $MYSQL_COMMAND -e "CREATE DATABASE IF NOT EXISTS ${PDNS_gmysql_dbname}" + fi +} -# Initialize DB if needed -if [ "${SKIP_DB_CREATE:-false}" != 'true' ]; then - $MYSQL_COMMAND -e "CREATE DATABASE IF NOT EXISTS ${PDNS_gmysql_dbname}" -fi +function initDatabase { + if [ "${SKIP_DB_INIT:-false}" != 'true' ]; then + MYSQL_CHECK_IF_HAS_TABLE="SELECT COUNT(DISTINCT table_name) FROM information_schema.columns WHERE table_schema = '${PDNS_gmysql_dbname}';" + MYSQL_NUM_TABLE=$($MYSQL_COMMAND --batch --skip-column-names -e "$MYSQL_CHECK_IF_HAS_TABLE") + if [ "$MYSQL_NUM_TABLE" -eq 0 ]; then + echo "Database exists and has no tables yet, doing init"; + $MYSQL_COMMAND -D "$PDNS_gmysql_dbname" < /usr/share/doc/pdns/schema.mysql.sql + else + echo "Database exists but already has tables, will not try to init"; + fi + fi +} -MYSQL_CHECK_IF_HAS_TABLE="SELECT COUNT(DISTINCT table_name) FROM information_schema.columns WHERE table_schema = '${PDNS_gmysql_dbname}';" -MYSQL_NUM_TABLE=$($MYSQL_COMMAND --batch --skip-column-names -e "$MYSQL_CHECK_IF_HAS_TABLE") -if [ "$MYSQL_NUM_TABLE" -eq 0 ]; then - $MYSQL_COMMAND -D "$PDNS_gmysql_dbname" < /usr/share/doc/pdns/schema.mysql.sql -fi - -# SQL migration to version 4.7 -MYSQL_CHECK_IF_47="SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = '${PDNS_gmysql_dbname}' AND table_name = 'domains' AND column_name = 'options';" -MYSQL_NUM_TABLE=$($MYSQL_COMMAND --batch --skip-column-names -e "$MYSQL_CHECK_IF_47") -if [ "$MYSQL_NUM_TABLE" -eq 0 ]; then +function migrateDatabaseTo47 { + # SQL migration to version 4.7 + MYSQL_CHECK_IF_47="SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = '${PDNS_gmysql_dbname}' AND table_name = 'domains' AND column_name = 'options';" + MYSQL_NUM_TABLE=$($MYSQL_COMMAND --batch --skip-column-names -e "$MYSQL_CHECK_IF_47") + if [ "$MYSQL_NUM_TABLE" -eq 0 ]; then echo 'Migrating MySQL schema to version 4.7...' $MYSQL_COMMAND -D "$PDNS_gmysql_dbname" < /usr/share/doc/pdns/4.3.0_to_4.7.0_schema.mysql.sql -fi + fi +} +function initSuperslave { if [ "${PDNS_superslave:-no}" = 'yes' ]; then # Configure supermasters if needed if [ "${SUPERMASTER_IPS:-}" ]; then @@ -83,8 +108,41 @@ if [ "${PDNS_superslave:-no}" = 'yes' ]; then $MYSQL_COMMAND -D "$PDNS_gmysql_dbname" -e "$MYSQL_INSERT_SUPERMASTERS" fi fi +} -# Create config file from template -subvars --prefix 'PDNS_' < '/pdns.conf.tpl' > '/etc/pdns/pdns.conf' +function generateAndInstallConfigFileFromEnvironment { + # Create config file from template + subvars --prefix 'PDNS_' < '/pdns.conf.tpl' > '/etc/pdns/pdns.conf' +} + + +#### End of function definitions, let's get to work ... + +if [ ${USE_EXISTING_CONFIG_FILE:-false} = 'true' ]; then + deriveMySQLSettingsFromExistingConfigFile +else + deriveMySQLSettingsFromEnvironment +fi + +generateMySQLCommand + +# Wait for MySQL to respond +until $MYSQL_COMMAND -e ';' ; do + >&2 echo 'MySQL is unavailable - sleeping' + sleep 3 +done + + +createDatabaseIfRequested +initDatabase +migrateDatabaseTo47 +initSuperslave + +if [ ${USE_EXISTING_CONFIG_FILE:-false} = 'false' ]; then + echo "(re-)generating config file from environment variables" + generateAndInstallConfigFileFromEnvironment +fi exec "$@" + + diff --git a/pdns-pgsql/docker-entrypoint.sh b/pdns-pgsql/docker-entrypoint.sh index 68f7b95..7db548a 100755 --- a/pdns-pgsql/docker-entrypoint.sh +++ b/pdns-pgsql/docker-entrypoint.sh @@ -2,25 +2,102 @@ set -eu -# Configure gpgsql env vars -: "${PDNS_gpgsql_host:=pgsql}" -: "${PDNS_gpgsql_port:=5432}" -: "${PDNS_gpgsql_user:=${PGSQL_ENV_POSTGRES_USER:-postgres}}" -: "${PDNS_gpgsql_password:=${PGSQL_ENV_POSTGRES_PASSWORD:-powerdns}}" -: "${PDNS_gpgsql_dbname:=${PGSQL_ENV_POSTGRES_DB:-powerdns}}" +function derivePostgreSQLSettingsFromExistingConfigFile { + if [ ! -f /etc/pdns/pdns.conf ]; then + echo "Use of existing file /etc/pdns/pdns.conf requested but file does not exist!" + exit 1 + fi + PDNS_gpgsql_host=`sed -n 's/^gpgsql-host=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gpgsql_port=`sed -n 's/^gpgsql-port=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gpgsql_user=`sed -n 's/^gpgsql-user=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gpgsql_password=`sed -n 's/^gpgsql-password=\(.*\)/\1/p' < /etc/pdns/pdns.conf` + PDNS_gpgsql_dbname=`sed -n 's/^gpgsql-dbname=\(.*\)/\1/p' < /etc/pdns/pdns.conf` +} -# Use first part of node name as database name suffix -if [ "${NODE_NAME:-}" ]; then - NODE_NAME=$(echo "${NODE_NAME}" | sed -e 's/\..*//' -e 's/-//') - PDNS_gpgsql_dbname="${PDNS_gpgsql_dbname}${NODE_NAME}" +function derivePostgreSQLSettingsFromEnvironment { + # Configure gpgsql env vars + : "${PDNS_gpgsql_host:=pgsql}" + : "${PDNS_gpgsql_port:=5432}" + : "${PDNS_gpgsql_user:=${PGSQL_ENV_POSTGRES_USER:-postgres}}" + : "${PDNS_gpgsql_password:=${PGSQL_ENV_POSTGRES_PASSWORD:-powerdns}}" + : "${PDNS_gpgsql_dbname:=${PGSQL_ENV_POSTGRES_DB:-powerdns}}" + + # Use first part of node name as database name suffix + if [ "${NODE_NAME:-}" ]; then + NODE_NAME=$(echo "${NODE_NAME}" | sed -e 's/\..*//' -e 's/-//') + PDNS_gpgsql_dbname="${PDNS_gpgsql_dbname}${NODE_NAME}" + fi + + export PDNS_gpgsql_host PDNS_gpgsql_port PDNS_gpgsql_user PDNS_gpgsql_password PDNS_gpgsql_dbname +} + + + +function generatePostgreSQLCommand { + PGSQL_COMMAND="psql -h ${PDNS_gpgsql_host} -p ${PDNS_gpgsql_port} -U ${PDNS_gpgsql_user}" +} + +function createDatabaseIfRequested { + # Initialize DB if needed + if [ "${SKIP_DB_CREATE:-false}" != 'true' ]; then + echo "SELECT 'CREATE DATABASE ${PDNS_gpgsql_dbname}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${PDNS_gpgsql_dbname}')\gexec" | $PGSQL_COMMAND + fi +} + +function initDatabase { + if [ "${SKIP_DB_INIT:-false}" != 'true' ]; then + PGSQL_CHECK_IF_HAS_TABLE="SELECT COUNT(DISTINCT table_name) FROM information_schema.columns WHERE table_catalog = '${PDNS_gpgsql_dbname}' AND table_schema = 'public';" + PGSQL_NUM_TABLE=$($PGSQL_COMMAND -At -d "$PDNS_gpgsql_dbname" -c "$PGSQL_CHECK_IF_HAS_TABLE") + if [ "$PGSQL_NUM_TABLE" -eq 0 ]; then + echo "Database exists and has no tables yet, doing init"; + $PGSQL_COMMAND -d "$PDNS_gpgsql_dbname" < /usr/share/doc/pdns/schema.pgsql.sql + else + echo "Database exists but already has tables, will not try to init"; + fi + fi +} + +function initSuperslave { + if [ "${PDNS_superslave:-no}" = 'yes' ]; then + # Configure supermasters if needed + if [ "${SUPERMASTER_IPS:-}" ]; then + $PGSQL_COMMAND -d "$PDNS_gpgsql_dbname" -c 'TRUNCATE supermasters;' + PGSQL_INSERT_SUPERMASTERS='' + if [ "${SUPERMASTER_COUNT:-0}" -eq 0 ]; then + SUPERMASTER_COUNT=10 + fi + i=1; while [ $i -le "${SUPERMASTER_COUNT}" ]; do + SUPERMASTER_HOST=$(echo "${SUPERMASTER_HOSTS:-}" | awk -v col="$i" '{ print $col }') + SUPERMASTER_IP=$(echo "${SUPERMASTER_IPS}" | awk -v col="$i" '{ print $col }') + if [ -z "${SUPERMASTER_HOST:-}" ]; then + SUPERMASTER_HOST=$(hostname -f) + fi + if [ "${SUPERMASTER_IP:-}" ]; then + PGSQL_INSERT_SUPERMASTERS="${PGSQL_INSERT_SUPERMASTERS} INSERT INTO supermasters VALUES('${SUPERMASTER_IP}', '${SUPERMASTER_HOST}', 'admin');" + fi + i=$(( i + 1 )) + done + $PGSQL_COMMAND -d "$PDNS_gpgsql_dbname" -c "$PGSQL_INSERT_SUPERMASTERS" + fi + fi +} + +function generateAndInstallConfigFileFromEnvironment { + # Create config file from template + subvars --prefix 'PDNS_' < '/pdns.conf.tpl' > '/etc/pdns/pdns.conf' +} +###End of function definitions + +if [ ${USE_EXISTING_CONFIG_FILE:-false} = 'true' ]; then + derivePostgreSQLSettingsFromExistingConfigFile +else + derivePostgreSQLSettingsFromEnvironment fi -export PDNS_gpgsql_host PDNS_gpgsql_port PDNS_gpgsql_user PDNS_gpgsql_password PDNS_gpgsql_dbname - +generatePostgreSQLCommand PGPASSWORD="${PDNS_gpgsql_password}" export PGPASSWORD -PGSQL_COMMAND="psql -h ${PDNS_gpgsql_host} -p ${PDNS_gpgsql_port} -U ${PDNS_gpgsql_user}" # Wait for pgsql to respond until $PGSQL_COMMAND -c ';' ; do @@ -28,43 +105,16 @@ until $PGSQL_COMMAND -c ';' ; do sleep 3 done -# Initialize DB if needed -if [ "${SKIP_DB_CREATE:-false}" != 'true' ]; then - echo "SELECT 'CREATE DATABASE ${PDNS_gpgsql_dbname}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${PDNS_gpgsql_dbname}')\gexec" | $PGSQL_COMMAND +createDatabaseIfRequested +initDatabase +initSuperslave + +if [ ${USE_EXISTING_CONFIG_FILE:-false} = 'false' ]; then + echo "(re-)generating config file from environment variables" + generateAndInstallConfigFileFromEnvironment fi -PGSQL_CHECK_IF_HAS_TABLE="SELECT COUNT(DISTINCT table_name) FROM information_schema.columns WHERE table_catalog = '${PDNS_gpgsql_dbname}' AND table_schema = 'public';" -PGSQL_NUM_TABLE=$($PGSQL_COMMAND -At -d "$PDNS_gpgsql_dbname" -c "$PGSQL_CHECK_IF_HAS_TABLE") -if [ "$PGSQL_NUM_TABLE" -eq 0 ]; then - $PGSQL_COMMAND -d "$PDNS_gpgsql_dbname" < /usr/share/doc/pdns/schema.pgsql.sql -fi - -if [ "${PDNS_superslave:-no}" = 'yes' ]; then - # Configure supermasters if needed - if [ "${SUPERMASTER_IPS:-}" ]; then - $PGSQL_COMMAND -d "$PDNS_gpgsql_dbname" -c 'TRUNCATE supermasters;' - PGSQL_INSERT_SUPERMASTERS='' - if [ "${SUPERMASTER_COUNT:-0}" -eq 0 ]; then - SUPERMASTER_COUNT=10 - fi - i=1; while [ $i -le "${SUPERMASTER_COUNT}" ]; do - SUPERMASTER_HOST=$(echo "${SUPERMASTER_HOSTS:-}" | awk -v col="$i" '{ print $col }') - SUPERMASTER_IP=$(echo "${SUPERMASTER_IPS}" | awk -v col="$i" '{ print $col }') - if [ -z "${SUPERMASTER_HOST:-}" ]; then - SUPERMASTER_HOST=$(hostname -f) - fi - if [ "${SUPERMASTER_IP:-}" ]; then - PGSQL_INSERT_SUPERMASTERS="${PGSQL_INSERT_SUPERMASTERS} INSERT INTO supermasters VALUES('${SUPERMASTER_IP}', '${SUPERMASTER_HOST}', 'admin');" - fi - i=$(( i + 1 )) - done - $PGSQL_COMMAND -d "$PDNS_gpgsql_dbname" -c "$PGSQL_INSERT_SUPERMASTERS" - fi -fi unset PGPASSWORD -# Create config file from template -subvars --prefix 'PDNS_' < '/pdns.conf.tpl' > '/etc/pdns/pdns.conf' - exec "$@" diff --git a/pdns-recursor/docker-entrypoint.sh b/pdns-recursor/docker-entrypoint.sh index a7caca3..7d9f63e 100755 --- a/pdns-recursor/docker-entrypoint.sh +++ b/pdns-recursor/docker-entrypoint.sh @@ -2,12 +2,17 @@ set -eu -# Configure base vars -: "${PDNS_local_port:=53}" -: "${PDNS_local_address:=0.0.0.0}" -: "${PDNS_allow_from:=0.0.0.0/0}" +#### Function definitions +function deriveConfigValuesFromEnvrionement { + # Configure base vars + : "${PDNS_local_port:=53}" + : "${PDNS_local_address:=0.0.0.0}" + : "${PDNS_allow_from:=0.0.0.0/0}" + + export PDNS_local_port PDNS_local_address PDNS_allow_from +} -export PDNS_local_port PDNS_local_address PDNS_allow_from +### end of function definitions if [ -f /etc/fedora-release ]; then config_file=/etc/pdns-recursor/recursor.conf @@ -17,10 +22,18 @@ elif [ -f /etc/alpine-release ]; then pdns_user=recursor fi +if [ ${USE_EXISTING_CONFIG_FILE:-false} = 'false' ]; then + deriveConfigValuesFromEnvrionement + echo "generating config file from environment" + subvars --prefix 'PDNS_' < '/recursor.conf.tpl' > "${config_file}" + chown "${pdns_user}:" "${config_file}" + else + echo "using existing config file ${config_file}" +fi + # Create config file from template -subvars --prefix 'PDNS_' < '/recursor.conf.tpl' > "${config_file}" # Fix config file ownership -chown "${pdns_user}:" "${config_file}" + exec "$@"