Harden OMNL dotenv layering and local health

This commit is contained in:
defiQUG
2026-07-05 17:31:33 -07:00
parent abdd8881e2
commit 8ee8930b5b
6 changed files with 278 additions and 132 deletions

View File

@@ -11,18 +11,56 @@ CONFIG="$REPO_DIR/config/omnl-super-admins.v1.json"
[[ -f "$ENV_FILE" ]] || { echo "Missing $ENV_FILE" >&2; exit 1; }
set -a
set +u
# shellcheck disable=SC1090
source "$ENV_FILE"
set -u
set +a
if [[ -f "$REPO_DIR/scripts/lib/deployment/dotenv.sh" ]]; then
# shellcheck disable=SC1090
source "$REPO_DIR/scripts/lib/deployment/dotenv.sh"
ENV_FILE="$ENV_FILE" load_deployment_env --repo-root "$REPO_DIR"
else
set -a
set +u
# shellcheck disable=SC1090
source "$ENV_FILE"
set -u
set +a
fi
grep -E '^(OMNL_FINERACT_|OMNL_PUBLIC_MONEY_SUPPLY=|OMNL_REQUIRE_API_KEY=|OMNL_CUSTOMER_SECURITY_PRODUCTION=|OMNL_CUSTOMER_API_KEYS=|OFFICE24_OPENING_M1_USD=|OMNL_PORTAL_INTERNAL_SECRET=|JWT_SECRET=|DATABASE_URL=|RPC_URL_138=|CHAIN_138_RPC_URL=|SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=|SETTLEMENT_ALLOW_HYBX_PRODUCTION=|OMNL_ALLOW_CHAIN_MINT_EXECUTE=|OMNL_MINT_OPERATOR_PRIVATE_KEY=|TOKEN_AGGREGATION_URL=|SWIFT_LISTENER_URL=|HYBX_MIFOS_FINERACT_SIDECAR_URL=|INFURA_PROJECT_ID=|INFURA_PROJECT_SECRET=)' "$ENV_FILE" || true
emit_key() {
local key="$1"
local value="${!key:-}"
[[ -n "$value" ]] && printf '%s=%s\n' "$key" "$value"
}
for key in \
OMNL_FINERACT_BASE_URL \
OMNL_FINERACT_TENANT \
OMNL_FINERACT_USERNAME \
OMNL_FINERACT_USER \
OMNL_FINERACT_PASSWORD \
OMNL_PUBLIC_MONEY_SUPPLY \
OMNL_REQUIRE_API_KEY \
OMNL_CUSTOMER_SECURITY_PRODUCTION \
OMNL_CUSTOMER_API_KEYS \
OFFICE24_OPENING_M1_USD \
OMNL_PORTAL_INTERNAL_SECRET \
JWT_SECRET \
DATABASE_URL \
RPC_URL_138 \
CHAIN_138_RPC_URL \
SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE \
SETTLEMENT_ALLOW_HYBX_PRODUCTION \
OMNL_ALLOW_CHAIN_MINT_EXECUTE \
OMNL_MINT_OPERATOR_PRIVATE_KEY \
TOKEN_AGGREGATION_URL \
SWIFT_LISTENER_URL \
HYBX_MIFOS_FINERACT_SIDECAR_URL \
INFURA_PROJECT_ID \
INFURA_PROJECT_SECRET
do
emit_key "$key"
done
for key in OMNL_SUPER_ADMIN_OFFICE24_KEY OMNL_SUPER_ADMIN_EXCHANGE_KEY OMNL_SUPER_ADMIN_SECURE_KEY OMNL_SUPER_ADMIN_FOREX_KEY; do
val="${!key:-}"
[[ -n "$val" ]] && echo "${key}=${val}"
emit_key "$key"
done
ADMIN_ENV_KEY="$(node -e "

View File

@@ -6,21 +6,27 @@ REPO_DIR="${OMNL_BANK_ROOT:-$HOME/smom-dbis-138}"
BRANCH="${OMNL_BANK_BRANCH:-main}"
LOG_DIR="${OMNL_BANK_LOG_DIR:-$HOME/omnl-bank/logs}"
ENV_FILE="${OMNL_BANK_ENV:-$REPO_DIR/.env}"
SKIP_GIT_PULL="${OMNL_SKIP_GIT_PULL:-0}"
DEPLOY_DOTENV_LIB="${REPO_DIR}/scripts/lib/deployment/dotenv.sh"
log() { echo "[$(date -Iseconds)] $*"; }
mkdir -p "$LOG_DIR"
if [ ! -d "$REPO_DIR/.git" ]; then
if ! git -C "$REPO_DIR" rev-parse --git-dir >/dev/null 2>&1; then
log "Cloning smom-dbis-138..."
git clone "https://gitea.d-bis.org/d-bis/smom-dbis-138.git" "$REPO_DIR"
fi
cd "$REPO_DIR"
log "Pull latest ($BRANCH)..."
git fetch origin
git checkout "$BRANCH"
git pull --ff-only origin "$BRANCH"
if [[ "$SKIP_GIT_PULL" == "1" ]]; then
log "Skipping git fetch/checkout/pull (OMNL_SKIP_GIT_PULL=1); building current working tree."
else
log "Pull latest ($BRANCH)..."
git fetch origin
git checkout "$BRANCH"
git pull --ff-only origin "$BRANCH"
fi
log "Generate 128-chain registry..."
node scripts/generate-omnl-128-chains.mjs
@@ -30,12 +36,20 @@ export DBIS_EXCHANGE_CONFIG="${DBIS_EXCHANGE_CONFIG:-$REPO_DIR/config/dbis-excha
export OMNL_SUPPORTED_CHAINS_CONFIG="${OMNL_SUPPORTED_CHAINS_CONFIG:-$REPO_DIR/config/omnl-supported-chains.v1.json}"
export OMNL_M2_TOKEN_REGISTRY="${OMNL_M2_TOKEN_REGISTRY:-$REPO_DIR/config/omnl-m2-token-registry.v1.json}"
if [ -f "$ENV_FILE" ]; then
if grep -q $'\r' "$ENV_FILE" 2>/dev/null; then
log "Normalizing CRLF line endings in $ENV_FILE"
tr -d '\r' <"$ENV_FILE" >"${ENV_FILE}.lf" && mv "${ENV_FILE}.lf" "$ENV_FILE"
chmod 600 "$ENV_FILE"
fi
if [[ -f "$ENV_FILE" && "$(grep -c $'\r' "$ENV_FILE" 2>/dev/null || true)" -gt 0 ]]; then
log "Normalizing CRLF line endings in $ENV_FILE"
tr -d '\r' <"$ENV_FILE" >"${ENV_FILE}.lf" && mv "${ENV_FILE}.lf" "$ENV_FILE"
chmod 600 "$ENV_FILE"
fi
if [[ -f "$DEPLOY_DOTENV_LIB" ]]; then
# Reuse the shared loader so repo .env values are loaded first and smom-dbis-138/.env backfills only missing keys.
export ENV_FILE
export PROJECT_ROOT="$REPO_DIR"
# shellcheck disable=SC1090
source "$DEPLOY_DOTENV_LIB"
load_deployment_env --repo-root "$REPO_DIR"
elif [ -f "$ENV_FILE" ]; then
set -a
set +u
# shellcheck disable=SC1090

View File

@@ -1,33 +1,48 @@
#!/usr/bin/env bash
# Merge KEY=VALUE lines from a fragment file into target .env (replace existing keys).
# Merge KEY=VALUE lines from a fragment file into target .env.
# Default strategy replaces managed keys from the fragment and preserves all others.
set -euo pipefail
TARGET="${1:?target .env path}"
FRAGMENT="${2:?fragment file path}"
MERGE_STRATEGY="${OMNL_MERGE_STRATEGY:-overwrite}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROXMOX_MERGE_PY="${PROXMOX_MERGE_DOTENV_PY:-$(cd "$SCRIPT_DIR/../../.." && pwd)/scripts/lib/merge-dotenv.py}"
touch "$TARGET"
tmp="$(mktemp)"
if [[ -f "$TARGET" ]]; then
cp "$TARGET" "$tmp"
if [[ -f "$PROXMOX_MERGE_PY" ]]; then
python3 "$PROXMOX_MERGE_PY" --strategy "$MERGE_STRATEGY" "$TARGET" "$FRAGMENT" >/dev/null
else
: > "$tmp"
tmp="$(mktemp)"
trap 'rm -f "$tmp" "${tmp}.new"' EXIT
cp "$TARGET" "$tmp"
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line//$'\r'/}"
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
key="${line%%=*}"
[[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue
if [[ "$MERGE_STRATEGY" == "preserve" ]] && grep -q "^${key}=" "$tmp"; then
continue
fi
if [[ "$MERGE_STRATEGY" == "fill-empty" ]] && grep -q "^${key}=" "$tmp"; then
current="$(grep "^${key}=" "$tmp" | tail -n 1 | cut -d= -f2-)"
[[ -n "$current" ]] && continue
fi
grep -v "^${key}=" "$tmp" > "${tmp}.new" || true
mv "${tmp}.new" "$tmp"
printf '%s\n' "$line" >> "$tmp"
done < "$FRAGMENT"
mv "$tmp" "$TARGET"
trap - EXIT
fi
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line//$'\r'/}"
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
key="${line%%=*}"
[[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue
grep -v "^${key}=" "$tmp" > "${tmp}.new" || true
mv "${tmp}.new" "$tmp"
printf '%s\n' "$line" >> "$tmp"
done < "$FRAGMENT"
if grep -q '^OMNL_FINERACT_USER=' "$tmp" && ! grep -q '^OMNL_FINERACT_USERNAME=' "$tmp"; then
u="$(grep '^OMNL_FINERACT_USER=' "$tmp" | cut -d= -f2-)"
printf 'OMNL_FINERACT_USERNAME=%s\n' "$u" >> "$tmp"
if grep -q '^OMNL_FINERACT_USER=' "$TARGET" && ! grep -q '^OMNL_FINERACT_USERNAME=' "$TARGET"; then
u="$(grep '^OMNL_FINERACT_USER=' "$TARGET" | tail -n 1 | cut -d= -f2-)"
printf 'OMNL_FINERACT_USERNAME=%s\n' "$u" >> "$TARGET"
fi
mv "$tmp" "$TARGET"
tr -d '\r' <"$TARGET" >"${TARGET}.lf" && mv "${TARGET}.lf" "$TARGET"
chmod 600 "$TARGET"

View File

@@ -1,92 +1,130 @@
#!/usr/bin/env bash
# Start OMNL services from /srv/zardasht-portal inside PCT
set -euo pipefail
ROOT="${OMNL_PORTAL_ROOT:-/srv/zardasht-portal}"
LOG_DIR="${OMNL_BANK_LOG_DIR:-/var/log/omnl-bank}"
NGINX_TEMPLATE="${ROOT}/deploy/nginx/omnl-lxc-portal.conf"
ENV_FILE="${OMNL_BANK_ENV:-${ROOT}/.env}"
mkdir -p "$LOG_DIR"
if [[ -f "$ENV_FILE" ]]; then
set -a
set +u
# shellcheck disable=SC1090
source "$ENV_FILE"
set -u
set +a
fi
export SETTLEMENT_MIDDLEWARE_CONFIG="${ROOT}/config/settlement-middleware.production.v1.json"
export DBIS_EXCHANGE_CONFIG="${ROOT}/config/dbis-exchange.production.v1.json"
export OMNL_SUPPORTED_CHAINS_CONFIG="${ROOT}/config/omnl-supported-chains.v1.json"
export OMNL_M2_TOKEN_REGISTRY="${ROOT}/config/omnl-m2-token-registry.v1.json"
export OMNL_BANK_ROOT="$ROOT"
start() {
local name="$1" dir="$2" cmd="$3"
cd "${ROOT}/${dir}"
pkill -f "${ROOT}/${dir}" 2>/dev/null || true
nohup env \
SETTLEMENT_MIDDLEWARE_CONFIG="$SETTLEMENT_MIDDLEWARE_CONFIG" \
DBIS_EXCHANGE_CONFIG="$DBIS_EXCHANGE_CONFIG" \
OMNL_SUPPORTED_CHAINS_CONFIG="$OMNL_SUPPORTED_CHAINS_CONFIG" \
OMNL_M2_TOKEN_REGISTRY="$OMNL_M2_TOKEN_REGISTRY" \
OMNL_BANK_ROOT="$ROOT" \
OMNL_API_KEY="${OMNL_API_KEY:-}" \
OMNL_SUPER_ADMIN_OFFICE24_KEY="${OMNL_SUPER_ADMIN_OFFICE24_KEY:-}" \
OMNL_SUPER_ADMIN_EXCHANGE_KEY="${OMNL_SUPER_ADMIN_EXCHANGE_KEY:-}" \
OMNL_SUPER_ADMIN_SECURE_KEY="${OMNL_SUPER_ADMIN_SECURE_KEY:-}" \
OMNL_SUPER_ADMIN_FOREX_KEY="${OMNL_SUPER_ADMIN_FOREX_KEY:-}" \
OMNL_PORTAL_INTERNAL_SECRET="${OMNL_PORTAL_INTERNAL_SECRET:-}" \
OMNL_CUSTOMER_API_KEYS="${OMNL_CUSTOMER_API_KEYS:-}" \
OMNL_CUSTOMER_SECURITY_PRODUCTION="${OMNL_CUSTOMER_SECURITY_PRODUCTION:-1}" \
OMNL_FINERACT_BASE_URL="${OMNL_FINERACT_BASE_URL:-}" \
OMNL_FINERACT_TENANT="${OMNL_FINERACT_TENANT:-omnl}" \
OMNL_FINERACT_USERNAME="${OMNL_FINERACT_USERNAME:-}" \
#!/usr/bin/env bash
# Start OMNL banking portal services from a deployed portal root.
set -euo pipefail
ROOT="${OMNL_PORTAL_ROOT:-/srv/zardasht-portal}"
LOG_DIR="${OMNL_BANK_LOG_DIR:-/var/log/omnl-bank}"
NGINX_TEMPLATE="${ROOT}/deploy/nginx/omnl-lxc-portal.conf"
ENV_FILE="${OMNL_BANK_ENV:-${ROOT}/.env}"
FRONTEND_PORT="${OMNL_BANK_FRONTEND_PORT:-3002}"
DEPLOY_DOTENV_LIB="${ROOT}/scripts/lib/deployment/dotenv.sh"
mkdir -p "$LOG_DIR"
if [[ -f "$DEPLOY_DOTENV_LIB" ]]; then
# Reuse the shared loader so explicit ENV_FILE wins while repo-root and secure-secret defaults backfill safely.
export ENV_FILE
export PROJECT_ROOT="$ROOT"
# shellcheck disable=SC1090
source "$DEPLOY_DOTENV_LIB"
load_deployment_env --repo-root "$ROOT"
elif [[ -f "$ENV_FILE" ]]; then
set +u
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
set -u
fi
export SETTLEMENT_MIDDLEWARE_CONFIG="${ROOT}/config/settlement-middleware.production.v1.json"
export DBIS_EXCHANGE_CONFIG="${ROOT}/config/dbis-exchange.production.v1.json"
export OMNL_SUPPORTED_CHAINS_CONFIG="${ROOT}/config/omnl-supported-chains.v1.json"
export OMNL_M2_TOKEN_REGISTRY="${ROOT}/config/omnl-m2-token-registry.v1.json"
export OMNL_BANK_ROOT="$ROOT"
ROOT_ALIASES=("$ROOT")
if [[ "$ROOT" == "/srv/ali-portal" ]]; then
ROOT_ALIASES+=("/srv/zardasht-portal")
elif [[ "$ROOT" == "/srv/zardasht-portal" ]]; then
ROOT_ALIASES+=("/srv/ali-portal")
fi
start_service() {
local name="$1"
local dir="$2"
local cmd="$3"
local active_root=""
local alias_root
for alias_root in "${ROOT_ALIASES[@]}"; do
if [[ -z "$active_root" && -d "${alias_root}/${dir}" ]]; then
active_root="$alias_root"
fi
pkill -f "${alias_root}/${dir}" 2>/dev/null || true
done
[[ -n "$active_root" ]] || active_root="$ROOT"
cd "${active_root}/${dir}"
local -a env_args=(
"SETTLEMENT_MIDDLEWARE_CONFIG=$SETTLEMENT_MIDDLEWARE_CONFIG"
"DBIS_EXCHANGE_CONFIG=$DBIS_EXCHANGE_CONFIG"
"OMNL_SUPPORTED_CHAINS_CONFIG=$OMNL_SUPPORTED_CHAINS_CONFIG"
"OMNL_M2_TOKEN_REGISTRY=$OMNL_M2_TOKEN_REGISTRY"
"OMNL_BANK_ROOT=$ROOT"
"OMNL_API_KEY=${OMNL_API_KEY:-}"
"OMNL_SUPER_ADMIN_OFFICE24_KEY=${OMNL_SUPER_ADMIN_OFFICE24_KEY:-}"
"OMNL_SUPER_ADMIN_EXCHANGE_KEY=${OMNL_SUPER_ADMIN_EXCHANGE_KEY:-}"
"OMNL_SUPER_ADMIN_SECURE_KEY=${OMNL_SUPER_ADMIN_SECURE_KEY:-}"
"OMNL_SUPER_ADMIN_FOREX_KEY=${OMNL_SUPER_ADMIN_FOREX_KEY:-}"
"OMNL_PORTAL_INTERNAL_SECRET=${OMNL_PORTAL_INTERNAL_SECRET:-}"
"OMNL_CUSTOMER_API_KEYS=${OMNL_CUSTOMER_API_KEYS:-}"
"OMNL_CUSTOMER_SECURITY_PRODUCTION=${OMNL_CUSTOMER_SECURITY_PRODUCTION:-1}"
"OMNL_FINERACT_BASE_URL=${OMNL_FINERACT_BASE_URL:-}"
"OMNL_FINERACT_TENANT=${OMNL_FINERACT_TENANT:-omnl}"
"OMNL_FINERACT_USERNAME=${OMNL_FINERACT_USERNAME:-}"
"OMNL_FINERACT_USER=${OMNL_FINERACT_USER:-}"
"OMNL_FINERACT_PASSWORD=${OMNL_FINERACT_PASSWORD:-}"
"OMNL_PUBLIC_MONEY_SUPPLY=${OMNL_PUBLIC_MONEY_SUPPLY:-1}"
"DATABASE_URL=${DATABASE_URL:-}"
"SETTLEMENT_ALLOW_HYBX_PRODUCTION=${SETTLEMENT_ALLOW_HYBX_PRODUCTION:-1}"
"SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=${SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE:-1}"
"OMNL_ALLOW_CHAIN_MINT_EXECUTE=${OMNL_ALLOW_CHAIN_MINT_EXECUTE:-1}"
"TOKEN_AGGREGATION_URL=${TOKEN_AGGREGATION_URL:-http://127.0.0.1:3000}"
"HYBX_MIFOS_FINERACT_SIDECAR_URL=${HYBX_MIFOS_FINERACT_SIDECAR_URL:-}"
"SWIFT_LISTENER_URL=${SWIFT_LISTENER_URL:-}"
"RPC_URL_138=${RPC_URL_138:-${CHAIN_138_RPC_URL:-}}"
"CHAIN_138_RPC_URL=${CHAIN_138_RPC_URL:-${RPC_URL_138:-}}"
"OMNL_MINT_OPERATOR_PRIVATE_KEY=${OMNL_MINT_OPERATOR_PRIVATE_KEY:-}"
"INFURA_PROJECT_ID=${INFURA_PROJECT_ID:-}"
"INFURA_PROJECT_SECRET=${INFURA_PROJECT_SECRET:-}"
)
nohup env "${env_args[@]}" bash -lc "$cmd" >"${LOG_DIR}/${name}.log" 2>&1 &
echo $! >"${LOG_DIR}/${name}.pid"
}
start_service token-aggregation services/token-aggregation "npm run start"
sleep 2
start_service settlement-middleware services/settlement-middleware "npm run start"
sleep 2
start_service dbis-exchange services/dbis-exchange "npm run start"
sleep 2
pkill -f "serve -s.*${FRONTEND_PORT}" 2>/dev/null || true
pkill -f "vite.*preview.*${FRONTEND_PORT}" 2>/dev/null || true
if [[ -f "${LOG_DIR}/nginx.pid" ]]; then
nginx -s quit -g "pid ${LOG_DIR}/nginx.pid;" 2>/dev/null || true
fi
fuser -k "${FRONTEND_PORT}/tcp" 2>/dev/null || true
sleep 1
if command -v nginx >/dev/null 2>&1 && [[ -f "$NGINX_TEMPLATE" ]]; then
sed "s|/srv/zardasht-portal|${ROOT}|g; s|/srv/ali-portal|${ROOT}|g" "$NGINX_TEMPLATE" >"${LOG_DIR}/nginx.conf"
nginx -t -c "${LOG_DIR}/nginx.conf"
nohup nginx -c "${LOG_DIR}/nginx.conf" >"${LOG_DIR}/frontend.log" 2>&1 &
echo $! >"${LOG_DIR}/frontend.pid"
echo "OMNL banking portal started under ${ROOT} (nginx :${FRONTEND_PORT})"
else
cd "${ROOT}/frontend-dapp"
if [[ -x "./node_modules/vite/bin/vite.js" || -f "./node_modules/vite/bin/vite.js" ]]; then
nohup node ./node_modules/vite/bin/vite.js preview --host 0.0.0.0 --port "$FRONTEND_PORT" \
>"${LOG_DIR}/frontend.log" 2>&1 &
echo "OMNL banking portal started under ${ROOT} (vite preview :${FRONTEND_PORT})"
else
nohup npx --yes serve -s dist -l "$FRONTEND_PORT" >"${LOG_DIR}/frontend.log" 2>&1 &
echo "OMNL banking portal started under ${ROOT} (serve :${FRONTEND_PORT})"
fi
echo $! >"${LOG_DIR}/frontend.pid"
fi

View File

@@ -27,6 +27,34 @@ _dep_dotenv_source() {
(( had_nounset )) && set -u
}
_dep_dotenv_defaults() {
local f="$1"
[[ -f "$f" ]] || return 0
local had_nounset=0 line key value
if [[ $- == *u* ]]; then
had_nounset=1
set +u
fi
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line//$'\r'/}"
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
[[ "$line" == export\ * ]] && line="${line#export }"
[[ "$line" == *=* ]] || continue
key="${line%%=*}"
value="${line#*=}"
[[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue
[[ -n "${!key:-}" ]] && continue
value="${value%$'\n'}"
if [[ "$value" =~ ^\".*\"$ ]]; then
value="${value:1:${#value}-2}"
elif [[ "$value" =~ ^\'.*\'$ ]]; then
value="${value:1:${#value}-2}"
fi
export "$key=$value"
done < "$f"
(( had_nounset )) && set -u
}
_dep_export_from_private_key() {
[[ -n "${DEPLOYER_ADDRESS:-}" || -z "${PRIVATE_KEY:-}" ]] && return 0
command -v cast >/dev/null 2>&1 || return 0
@@ -97,7 +125,7 @@ load_deployment_env() {
[[ -n "${ENV_FILE:-}" && -f "${ENV_FILE}" ]] && dotenv="${ENV_FILE}"
_dep_dotenv_source "$dotenv"
if [[ -z "${ENV_FILE:-}" ]]; then
_dep_dotenv_source "${root}/smom-dbis-138/.env"
_dep_dotenv_defaults "${root}/smom-dbis-138/.env"
fi
local secure_secrets_file="${SECURE_SECRETS_FILE:-$HOME/.secure-secrets/private-keys.env}"
if [[ -f "$secure_secrets_file" ]]; then