126 lines
4.3 KiB
Bash
Executable File
126 lines
4.3 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
is_local_database_host() {
|
|
database_host_value=$1
|
|
case $database_host_value in
|
|
'' | postgres | localhost | 127.*) return 0 ;;
|
|
esac
|
|
|
|
if [ "$(printf '%s' "$database_host_value" | tr -d '0:')" = 1 ]; then
|
|
return 0
|
|
fi
|
|
|
|
database_ipv6_prefix=${database_host_value%:*}
|
|
database_ipv6_tail=${database_host_value##*:}
|
|
database_ipv6_marker=$(printf '%s' "$database_ipv6_prefix" | tr -d '0:')
|
|
case $database_ipv6_tail in
|
|
0.0.0.1) [ -z "$database_ipv6_marker" ] && return 0 ;;
|
|
127.*) [ "$database_ipv6_marker" = ffff ] && return 0 ;;
|
|
esac
|
|
|
|
database_ipv6_high=${database_ipv6_prefix##*:}
|
|
database_ipv6_prefix=${database_ipv6_prefix%:*}
|
|
database_ipv6_marker=$(printf '%s' "$database_ipv6_prefix" | tr -d '0:')
|
|
case $database_ipv6_high in
|
|
7f[0-9a-f][0-9a-f]) [ "$database_ipv6_marker" = ffff ] && return 0 ;;
|
|
esac
|
|
return 1
|
|
}
|
|
|
|
validate_production_database_dsn() {
|
|
database_dsn=$1
|
|
database_dsn_label=${2:-production database DSN}
|
|
database_dsn_uses_certificate_files=0
|
|
if [ -z "$database_dsn" ]; then
|
|
echo "$database_dsn_label is required" >&2
|
|
return 1
|
|
fi
|
|
|
|
database_authority=${database_dsn#*://}
|
|
database_authority=${database_authority%%/*}
|
|
database_hostport=${database_authority##*@}
|
|
case $database_hostport in
|
|
\[* ) database_host=${database_hostport#\[}; database_host=${database_host%%\]*} ;;
|
|
* ) database_host=${database_hostport%%:*} ;;
|
|
esac
|
|
database_host=$(printf '%s' "$database_host" | tr '[:upper:]' '[:lower:]')
|
|
database_host=${database_host%.}
|
|
database_host=${database_host%%%*}
|
|
if is_local_database_host "$database_host"; then
|
|
echo "$database_dsn_label must use an external PostgreSQL host" >&2
|
|
return 1
|
|
fi
|
|
|
|
database_query=
|
|
case $database_dsn in
|
|
*\?*) database_query=${database_dsn#*\?}; database_query=${database_query%%#*} ;;
|
|
esac
|
|
|
|
sslmode_count=0
|
|
sslmode=
|
|
sslrootcert_count=0
|
|
sslcert_count=0
|
|
sslkey_count=0
|
|
database_parameters=$database_query
|
|
while [ -n "$database_parameters" ]; do
|
|
case $database_parameters in
|
|
*'&'*) database_parameter=${database_parameters%%&*}; database_parameters=${database_parameters#*&} ;;
|
|
*) database_parameter=$database_parameters; database_parameters= ;;
|
|
esac
|
|
database_key=${database_parameter%%=*}
|
|
database_value=${database_parameter#*=}
|
|
case $database_key in
|
|
sslmode) sslmode_count=$((sslmode_count + 1)); sslmode=$database_value ;;
|
|
sslrootcert)
|
|
sslrootcert_count=$((sslrootcert_count + 1))
|
|
[ "$database_value" = /run/secrets/external-db-ca.crt ] || { echo "$database_dsn_label sslrootcert must use /run/secrets/external-db-ca.crt" >&2; return 1; }
|
|
;;
|
|
sslcert)
|
|
sslcert_count=$((sslcert_count + 1))
|
|
[ "$database_value" = /run/secrets/external-db-client.crt ] || { echo "$database_dsn_label sslcert must use /run/secrets/external-db-client.crt" >&2; return 1; }
|
|
;;
|
|
sslkey)
|
|
sslkey_count=$((sslkey_count + 1))
|
|
[ "$database_value" = /run/secrets/external-db-client.key ] || { echo "$database_dsn_label sslkey must use /run/secrets/external-db-client.key" >&2; return 1; }
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ "$sslmode_count" -ne 1 ]; then
|
|
echo "$database_dsn_label must contain exactly one sslmode" >&2
|
|
return 1
|
|
fi
|
|
if [ "$sslmode" != disable ] && [ "$sslmode" != verify-ca ] && [ "$sslmode" != verify-full ]; then
|
|
echo "$database_dsn_label sslmode must be disable, verify-ca or verify-full" >&2
|
|
return 1
|
|
fi
|
|
|
|
tls_count=$((sslrootcert_count + sslcert_count + sslkey_count))
|
|
if [ "$tls_count" -ne 0 ]; then
|
|
database_dsn_uses_certificate_files=1
|
|
if [ "$sslrootcert_count" -ne 1 ] || [ "$sslcert_count" -ne 1 ] || [ "$sslkey_count" -ne 1 ]; then
|
|
echo "$database_dsn_label must contain each fixed TLS certificate parameter exactly once" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
dsn=${GOCHAT_DATABASE_DSN:-${DATA_SOURCE_NAME:-}}
|
|
validate_production_database_dsn "$dsn"
|
|
|
|
if [ "${1:-}" = --preflight ]; then
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$database_dsn_uses_certificate_files" -eq 1 ]; then
|
|
for file in /run/secrets/external-db-ca.crt /run/secrets/external-db-client.crt /run/secrets/external-db-client.key; do
|
|
[ -f "$file" ] && [ -r "$file" ] || { echo "database TLS file is missing or unreadable: $file" >&2; exit 1; }
|
|
done
|
|
fi
|
|
|
|
if [ "${1:-}" = --check ]; then
|
|
exit 0
|
|
fi
|
|
exec "$@"
|