HH-445: deploy production observability and runbooks (#96)
* HH-445: deploy production observability and runbooks * fix(ops): share production database DSN * fix(HH-445): enforce database TLS gate * fix(HH-445): preserve production serve command * fix(prod): require external database dependencies * fix(prod): unify database host rejection gates * test(prod): enforce exact database TLS runbook contract --------- Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
Executable
+125
@@ -0,0 +1,125 @@
|
||||
#!/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" != verify-ca ] && [ "$sslmode" != verify-full ]; then
|
||||
echo "$database_dsn_label sslmode must be 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 "$@"
|
||||
Reference in New Issue
Block a user