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:
@@ -12,7 +12,7 @@ if (($#)); then
|
||||
compose_args=(--env-file "$env_file" "${compose_args[@]}")
|
||||
fi
|
||||
|
||||
required=(GOCHAT_IMAGE_REF SHANGWUTONG_IMAGE_REF GOCHAT_SERVER_CORS_ALLOWED_ORIGINS POSTGRES_PASSWORD REDIS_PASSWORD MEILI_MASTER_KEY GOCHAT_JWT_SECRET GOCHAT_BACKUP_OFFSITE_DIR GOCHAT_BACKUP_OFFSITE_SOURCE GOCHAT_BACKUP_OFFSITE_FSTYPE)
|
||||
required=(GOCHAT_IMAGE_REF SHANGWUTONG_IMAGE_REF GOCHAT_SERVER_CORS_ALLOWED_ORIGINS GOCHAT_DATABASE_DSN GOCHAT_REDIS_DSN MEILI_MASTER_KEY GOCHAT_JWT_SECRET GOCHAT_BACKUP_OFFSITE_DIR GOCHAT_BACKUP_OFFSITE_SOURCE GOCHAT_BACKUP_OFFSITE_FSTYPE)
|
||||
for name in "${required[@]}"; do
|
||||
value=${!name:-}
|
||||
if [[ -z $value || ${value^^} == *CHANGE_ME* ]]; then
|
||||
@@ -67,10 +67,45 @@ if ((${#MEILI_MASTER_KEY} < 16)); then
|
||||
echo "MEILI_MASTER_KEY must be at least 16 bytes" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n ${GOCHAT_DATABASE_DSN:-} && ! $GOCHAT_DATABASE_DSN =~ (^|[?&])sslmode=(require|verify-ca|verify-full)(&|$) ]]; then
|
||||
echo "GOCHAT_DATABASE_DSN must explicitly require TLS for an external database" >&2
|
||||
alertmanager_webhook_file=${ALERTMANAGER_WEBHOOK_URL_FILE:-../../.secrets/alertmanager-webhook-url}
|
||||
if [[ $alertmanager_webhook_file != /* ]]; then
|
||||
alertmanager_webhook_file=$script_dir/$alertmanager_webhook_file
|
||||
fi
|
||||
if [[ ! -r $alertmanager_webhook_file ]] || ! IFS= read -r alertmanager_webhook_url <"$alertmanager_webhook_file" || [[ ! $alertmanager_webhook_url =~ ^https://[^[:space:]]+$ ]]; then
|
||||
echo "ALERTMANAGER_WEBHOOK_URL_FILE must contain one HTTPS URL" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n ${GOCHAT_DATABASE_DSN:-} ]]; then
|
||||
"$script_dir/database_client_entrypoint.sh" --preflight
|
||||
if [[ $GOCHAT_DATABASE_DSN == *sslrootcert=* ]]; then
|
||||
tls_gid=${GOCHAT_DATABASE_TLS_GID:-}
|
||||
if [[ ! $tls_gid =~ ^[1-9][0-9]*$ ]]; then
|
||||
echo "GOCHAT_DATABASE_TLS_GID must be set to a positive numeric group ID" >&2
|
||||
exit 1
|
||||
fi
|
||||
for name in GOCHAT_DATABASE_TLS_CA_FILE GOCHAT_DATABASE_TLS_CLIENT_CERT_FILE GOCHAT_DATABASE_TLS_CLIENT_KEY_FILE; do
|
||||
host_file=${!name:-}
|
||||
if [[ -z $host_file ]]; then
|
||||
echo "$name must be set when the database DSN uses certificate files" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ $host_file != /* ]]; then
|
||||
host_file=$script_dir/$host_file
|
||||
fi
|
||||
if [[ ! -f $host_file ]]; then
|
||||
echo "$name must point to an existing regular file" >&2
|
||||
exit 1
|
||||
fi
|
||||
file_gid=$(stat -c %g -- "$host_file")
|
||||
file_mode=$(stat -c %a -- "$host_file")
|
||||
group_digit=${file_mode: -2:1}
|
||||
if [[ $file_gid != "$tls_gid" ]] || (((8#$group_digit & 4) == 0)); then
|
||||
echo "$name must be readable by GOCHAT_DATABASE_TLS_GID" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
images=$(docker compose "${compose_args[@]}" config --images)
|
||||
while IFS= read -r image; do
|
||||
|
||||
Reference in New Issue
Block a user