#!/usr/bin/env bash
#
# RELAY-PHASE1 · E (TASK E) — PUBLIC-web TLS cert for the browser :443 endpoint (Let's Encrypt).
#
# STAGING TEMPLATE. This is the ONLY public-CA cert in the deployment: the browser hits
# https://<SUBDOMAIN>.<BASE_DOMAIN> (WSS same-origin), so it must chain to a public root. It is a
# DIFFERENT trust chain from the private agent-enrollment CA (deploy/scripts/gen-agent-ca.sh) — do
# NOT cross-wire them.
#
#   ICP-備案 ASSUMPTION (mainland Alibaba Cloud): BASE_DOMAIN is ALREADY ICP-filed and its A-record
#   <SUBDOMAIN>.<BASE_DOMAIN> -> 8.138.1.192 resolves. Serving :80/:443 on an unfiled domain in
#   mainland CN is blocked upstream; HTTP-01 will then fail. If unfiled, use DNS-01 (no inbound :80).
#
# Two challenge methods (pick with ACME_METHOD):
#   http-01  — a one-shot listener on :80 answers the challenge. REQUIRES inbound :80 open in the
#              Aliyun security group DURING issuance (you can close it again after; renewals reopen).
#   dns-01   — a TXT record under _acme-challenge.<SUBDOMAIN>.<BASE_DOMAIN>. No inbound :80. Needs the
#              acme.sh DNS-API creds for your provider (e.g. Ali_Key/Ali_Secret for the Aliyun DNS API).
#
# Installs to TLS_CERT_PATH (fullchain) + TLS_KEY_PATH, matching relay.env.
#
# Config via ENV only:
#     BASE_DOMAIN     REQUIRED  (e.g. term.example.com)
#     SUBDOMAIN       REQUIRED  (the tenant sub; FQDN = <SUBDOMAIN>.<BASE_DOMAIN>)
#     ACME_EMAIL      REQUIRED  account/registration email
#     ACME_METHOD     http-01 | dns-01                    (default http-01)
#     ACME_CLIENT     acme.sh | certbot                    (default acme.sh)
#     ACME_DNS_PROVIDER   acme.sh dnsapi id for dns-01 (e.g. dns_ali)   (dns-01 only)
#     TLS_CERT_PATH   install target for fullchain   (default /etc/relay/tls/fullchain.pem)
#     TLS_KEY_PATH    install target for privkey     (default /etc/relay/tls/privkey.pem)
#     ACME_STAGING    1 to use the LE staging CA (untrusted, avoids rate limits while testing)
#
# Verify (syntax): bash -n deploy/scripts/issue-tls-cert.sh
set -euo pipefail

: "${BASE_DOMAIN:?FATAL: BASE_DOMAIN is required (your ICP-filed domain)}"
: "${SUBDOMAIN:?FATAL: SUBDOMAIN is required}"
: "${ACME_EMAIL:?FATAL: ACME_EMAIL is required}"
ACME_METHOD="${ACME_METHOD:-http-01}"
ACME_CLIENT="${ACME_CLIENT:-acme.sh}"
TLS_CERT_PATH="${TLS_CERT_PATH:-/etc/relay/tls/fullchain.pem}"
TLS_KEY_PATH="${TLS_KEY_PATH:-/etc/relay/tls/privkey.pem}"

FQDN="${SUBDOMAIN}.${BASE_DOMAIN}"
echo "== Issuing Let's Encrypt cert for ${FQDN} via ${ACME_CLIENT} (${ACME_METHOD}) =="

mkdir -p "$(dirname "${TLS_CERT_PATH}")" "$(dirname "${TLS_KEY_PATH}")"

case "${ACME_CLIENT}" in
  acme.sh)
    command -v acme.sh >/dev/null 2>&1 || { echo "FATAL: acme.sh not installed. curl https://get.acme.sh | sh" >&2; exit 3; }
    acme.sh --register-account -m "${ACME_EMAIL}" >/dev/null 2>&1 || true
    STAGING_FLAG=""
    [[ "${ACME_STAGING:-0}" == "1" ]] && STAGING_FLAG="--staging"

    case "${ACME_METHOD}" in
      http-01)
        echo ">> Ensure inbound :80 is OPEN in the Aliyun security group for the duration of issuance."
        acme.sh --issue ${STAGING_FLAG} -d "${FQDN}" --standalone --httpport 80
        ;;
      dns-01)
        : "${ACME_DNS_PROVIDER:?FATAL: ACME_DNS_PROVIDER required for dns-01 (e.g. dns_ali); export the DNS-API creds too}"
        acme.sh --issue ${STAGING_FLAG} -d "${FQDN}" --dns "${ACME_DNS_PROVIDER}"
        ;;
      *)
        echo "FATAL: ACME_METHOD must be http-01 or dns-01" >&2; exit 2 ;;
    esac

    # --install-cert copies the current material AND registers the renew-reload hook.
    acme.sh --install-cert -d "${FQDN}" \
      --key-file       "${TLS_KEY_PATH}" \
      --fullchain-file "${TLS_CERT_PATH}" \
      --reloadcmd      "systemctl try-reload-or-restart relay-data-plane.service"
    ;;

  certbot)
    command -v certbot >/dev/null 2>&1 || { echo "FATAL: certbot not installed (apt-get install certbot)." >&2; exit 3; }
    STAGING_FLAG=""
    [[ "${ACME_STAGING:-0}" == "1" ]] && STAGING_FLAG="--staging"
    case "${ACME_METHOD}" in
      http-01)
        echo ">> Ensure inbound :80 is OPEN in the Aliyun security group for the duration of issuance."
        certbot certonly ${STAGING_FLAG} --standalone --non-interactive --agree-tos \
          -m "${ACME_EMAIL}" -d "${FQDN}"
        ;;
      dns-01)
        echo "FATAL: certbot dns-01 needs a provider plugin; prefer ACME_CLIENT=acme.sh for Aliyun DNS." >&2
        exit 2 ;;
      *)
        echo "FATAL: ACME_METHOD must be http-01 or dns-01" >&2; exit 2 ;;
    esac
    install -m 644 "/etc/letsencrypt/live/${FQDN}/fullchain.pem" "${TLS_CERT_PATH}"
    install -m 600 "/etc/letsencrypt/live/${FQDN}/privkey.pem"  "${TLS_KEY_PATH}"
    ;;

  *)
    echo "FATAL: ACME_CLIENT must be acme.sh or certbot" >&2; exit 2 ;;
esac

chmod 600 "${TLS_KEY_PATH}" || true
chmod 644 "${TLS_CERT_PATH}" || true

cat <<SUMMARY

Installed:
  TLS_CERT_PATH = ${TLS_CERT_PATH}
  TLS_KEY_PATH  = ${TLS_KEY_PATH}

RENEWAL (LE certs last ~90 days):
  - acme.sh installs its OWN cron on install ('acme.sh --cron'); --install-cert registered the
    reload hook above, so renewals auto-reload the data-plane. Verify: 'crontab -l | grep acme'.
  - certbot: add a cron/timer, e.g.
        0 3 * * *  certbot renew --quiet --deploy-hook 'systemctl try-reload-or-restart relay-data-plane.service'
  - http-01 renewals need :80 reachable at renew time; dns-01 does not.
SUMMARY
