Harden PMA gateway cert candidate resolution

main
Anthony 2026-02-26 20:47:00 +08:00
parent 7dd77c6ccd
commit a60bc1c2f5
1 changed files with 74 additions and 20 deletions

View File

@ -37,14 +37,37 @@ if [[ "$CONTACT_EMAIL" == *'${'* ]]; then
CONTACT_EMAIL=""
fi
# Prefer explicit cert domain and fallback to Jelastic environment domain.
if [[ -z "$CERT_DOMAIN" ]]; then
if [[ -n "${JELASTIC_ENV_DOMAIN:-}" ]]; then
CERT_DOMAIN="$JELASTIC_ENV_DOMAIN"
else
CERT_DOMAIN=$(hostname -f)
CERT_DOMAIN=${CERT_DOMAIN#node*-} # strip nodeXXXX-
# Build domain candidates in priority order:
# 1) explicit --cert-domain
# 2) JELASTIC_ENV_DOMAIN
# 3) hostname-derived domain
HOSTNAME_DOMAIN=$(hostname -f)
HOSTNAME_DOMAIN=${HOSTNAME_DOMAIN#node*-}
DOMAIN_CANDIDATES=()
SEEN_DOMAINS="|"
for candidate in "$CERT_DOMAIN" "${JELASTIC_ENV_DOMAIN:-}" "$HOSTNAME_DOMAIN"; do
if [[ -n "$candidate" ]] && [[ "$SEEN_DOMAINS" != *"|$candidate|"* ]]; then
DOMAIN_CANDIDATES+=("$candidate")
SEEN_DOMAINS="${SEEN_DOMAINS}${candidate}|"
fi
done
# Never use legacy *.sites.mightybox.dev domains for PMA gateway certificates.
FILTERED_DOMAINS=()
for candidate in "${DOMAIN_CANDIDATES[@]}"; do
if [[ "$candidate" == *.sites.mightybox.dev ]]; then
echo "WARNING: Skipping legacy domain candidate '$candidate' for PMA gateway SSL." >&2
continue
fi
FILTERED_DOMAINS+=("$candidate")
done
DOMAIN_CANDIDATES=("${FILTERED_DOMAINS[@]}")
if [[ "${#DOMAIN_CANDIDATES[@]}" -eq 0 ]]; then
echo "FATAL: No valid non-legacy environment domain candidate found for PMA gateway certificate resolution." >&2
echo " Provide --cert-domain with the current default environment domain." >&2
exit 1
fi
# Fallback for email when not explicitly passed.
@ -52,7 +75,7 @@ if [[ -z "$CONTACT_EMAIL" ]] && [[ -n "${JELASTIC_USER_EMAIL:-}" ]]; then
CONTACT_EMAIL="$JELASTIC_USER_EMAIL"
fi
ENV_HOST="$CERT_DOMAIN"
ENV_HOST="${DOMAIN_CANDIDATES[0]}"
PMADB_DIR="/usr/share/phpMyAdmin"
GATEWAY_FILE="$PMADB_DIR/access-db-$SLUG.php"
@ -78,30 +101,42 @@ token="$base.$mac"
VHOST_CONFIG="/usr/share/phpMyAdmin/vhost.conf"
NEEDS_RESTART=0
# --- Let's Encrypt certificate resolution for ENV_HOST ---
# --- Let's Encrypt certificate resolution for domain candidates ---
LE_LIVE_DIR="/etc/letsencrypt/live"
LE_CERT_DIR=""
CERT_DOMAIN_USED=""
# Attempt exact match first.
if [[ -d "$LE_LIVE_DIR/$ENV_HOST" ]] && [[ -f "$LE_LIVE_DIR/$ENV_HOST/privkey.pem" ]] && [[ -f "$LE_LIVE_DIR/$ENV_HOST/fullchain.pem" ]]; then
LE_CERT_DIR="$LE_LIVE_DIR/$ENV_HOST"
echo "INFO: Found exact Let's Encrypt cert directory: $LE_CERT_DIR" >&2
# Find an existing certificate for the first matching candidate.
for candidate_host in "${DOMAIN_CANDIDATES[@]}"; do
if [[ -d "$LE_LIVE_DIR/$candidate_host" ]] && [[ -f "$LE_LIVE_DIR/$candidate_host/privkey.pem" ]] && [[ -f "$LE_LIVE_DIR/$candidate_host/fullchain.pem" ]]; then
LE_CERT_DIR="$LE_LIVE_DIR/$candidate_host"
CERT_DOMAIN_USED="$candidate_host"
echo "INFO: Found exact Let's Encrypt cert directory for '$candidate_host': $LE_CERT_DIR" >&2
break
fi
# Then try certbot-suffixed directories (e.g., domain-0001).
if [[ -z "$LE_CERT_DIR" ]]; then
for dir in "$LE_LIVE_DIR/$ENV_HOST"-*/; do
for dir in "$LE_LIVE_DIR/$candidate_host"-*/; do
if [[ -d "$dir" ]] && [[ -f "$dir/privkey.pem" ]] && [[ -f "$dir/fullchain.pem" ]]; then
LE_CERT_DIR="${dir%/}"
echo "INFO: Found suffixed Let's Encrypt cert directory: $LE_CERT_DIR" >&2
CERT_DOMAIN_USED="$candidate_host"
echo "INFO: Found suffixed Let's Encrypt cert directory for '$candidate_host': $LE_CERT_DIR" >&2
break
fi
done
if [[ -n "$LE_CERT_DIR" ]]; then
break
fi
done
if [[ -n "$CERT_DOMAIN_USED" ]]; then
ENV_HOST="$CERT_DOMAIN_USED"
fi
# If no cert exists yet, attempt one-time issuance for ENV_HOST.
# If no cert exists yet, attempt one-time issuance for highest-priority candidate.
if [[ -z "$LE_CERT_DIR" ]]; then
echo "WARNING: No Let's Encrypt certificate found for '$ENV_HOST'. Attempting to issue one now..." >&2
ENV_HOST="${DOMAIN_CANDIDATES[0]}"
echo "WARNING: No Let's Encrypt certificate found for domain candidates (${DOMAIN_CANDIDATES[*]}). Attempting to issue one for '$ENV_HOST' now..." >&2
CERTBOT_CMD=""
if command -v certbot >/dev/null 2>&1; then
@ -110,6 +145,24 @@ if [[ -z "$LE_CERT_DIR" ]]; then
CERTBOT_CMD="/opt/certbot/certbot-auto"
fi
if [[ -z "$CERTBOT_CMD" ]]; then
echo "WARNING: certbot is not available. Attempting to install certbot..." >&2
if command -v dnf >/dev/null 2>&1; then
sudo dnf install -y --setopt=install_weak_deps=False certbot >/dev/null 2>&1 || true
elif command -v yum >/dev/null 2>&1; then
sudo yum install -y certbot >/dev/null 2>&1 || true
elif command -v apt-get >/dev/null 2>&1; then
sudo apt-get update -qq >/dev/null 2>&1 || true
sudo apt-get install -y certbot >/dev/null 2>&1 || true
fi
if command -v certbot >/dev/null 2>&1; then
CERTBOT_CMD="certbot"
elif [[ -x "/opt/certbot/certbot-auto" ]]; then
CERTBOT_CMD="/opt/certbot/certbot-auto"
fi
fi
if [[ -z "$CERTBOT_CMD" ]]; then
echo "FATAL: certbot is not available and no existing Let's Encrypt certificate was found for '$ENV_HOST'." >&2
exit 1
@ -150,6 +203,7 @@ if [[ -n "$LE_CERT_DIR" ]]; then
LE_CERT_FILE="$LE_CERT_DIR/fullchain.pem"
else
echo "FATAL: Let's Encrypt certificate directory could not be found for ENV_HOST: $ENV_HOST" >&2
echo " Checked candidates: ${DOMAIN_CANDIDATES[*]}" >&2
echo " Checked specific path: $LE_LIVE_DIR/$ENV_HOST" >&2
echo " Checked suffixed paths: $LE_LIVE_DIR/${ENV_HOST}-*" >&2
exit 1