#!/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 "$@"