#!/usr/bin/env bash # # RELAY-PHASE1 · Native mTLS tunnel · V2 — Revoke a device/frp-client leaf, regenerate the CRL. # # STAGING TEMPLATE. Marks a previously-issued leaf revoked in the CA database and regenerates # /crl.pem, which nginx :8470 serves via `ssl_crl` (V4) — so the revoked device is rejected at # the TLS handshake fleet-wide the moment nginx reloads. This script does NOT touch the remote VPS: it # only prints the reload hint; run the reload yourself on the box after copying the CRL. # # Requires the `openssl ca` database created by deploy/scripts/gen-device-ca.sh (index.txt/serial/…). # # Usage: revoke-device.sh # revoke by the issued cert file # or revoke-device.sh --serial # revoke by serial (uses /newcerts/.pem) # # Config via ENV or flags (no secrets): # CA_DIR which CA to revoke against (default /etc/relay/device-ca) — or --ca-dir # # Verify (syntax): bash -n deploy/scripts/revoke-device.sh set -euo pipefail CA_DIR="${CA_DIR:-/etc/relay/device-ca}" LEAF="" SERIAL="" while [[ $# -gt 0 ]]; do case "$1" in --ca-dir) CA_DIR="${2:?--ca-dir needs a value}"; shift 2 ;; --serial) SERIAL="${2:?--serial needs a value}"; shift 2 ;; -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; -*) echo "FATAL: unknown flag '$1' (see --help)" >&2; exit 2 ;; *) if [[ -z "${LEAF}" ]]; then LEAF="$1"; else echo "FATAL: too many positional args at '$1'" >&2; exit 2; fi; shift ;; esac done command -v openssl >/dev/null 2>&1 || { echo "FATAL: openssl not found on PATH." >&2; exit 3; } [[ -f "${CA_DIR}/openssl.cnf" ]] || { echo "FATAL: no CA db in ${CA_DIR} (run gen-device-ca.sh first)." >&2; exit 3; } # ---- resolve the target leaf (by path or by serial) to an absolute path -------------------------- if [[ -n "${SERIAL}" ]]; then # Boundary-validate the serial (used to build a path); openssl stores newcerts/.pem. [[ "${SERIAL}" =~ ^[0-9A-Fa-f]+$ ]] || { echo "FATAL: --serial must be hex." >&2; exit 2; } LEAF="${CA_DIR}/newcerts/$(echo "${SERIAL}" | tr '[:lower:]' '[:upper:]').pem" fi [[ -n "${LEAF}" ]] || { echo "FATAL: pass a or --serial ." >&2; exit 2; } [[ -f "${LEAF}" ]] || { echo "FATAL: leaf cert not found: ${LEAF}" >&2; exit 3; } LEAF="$(cd "$(dirname "${LEAF}")" && pwd)/$(basename "${LEAF}")" REVOKED_SERIAL="$(openssl x509 -in "${LEAF}" -noout -serial | cut -d= -f2)" echo "== Revoking serial ${REVOKED_SERIAL} against CA ${CA_DIR} ==" # ---- revoke + regenerate the CRL (cd in so openssl.cnf's dir=. resolves to CA_DIR) ---------------- ( cd "${CA_DIR}" openssl ca -config openssl.cnf -revoke "${LEAF}" openssl ca -config openssl.cnf -gencrl -out crl.pem ) chmod 644 "${CA_DIR}/crl.pem" cat <