Files
soleprint/berth/ctrl/certs.sh
2026-09-14 03:57:00 -03:00

59 lines
1.9 KiB
Bash

#!/usr/bin/env bash
# The wildcard TLS cert for the gateway.
#
# Usage:
# ./certs.sh status # SANs issued vs SANs the services need
# ./certs.sh verify # inspect the cert served on :443
# ./certs.sh renew # refuses: issues a real cert
# ./certs.sh push # refuses: ships to a live gateway
set -euo pipefail
cd "$(dirname "$0")"
source ./lib/config.sh
source ./lib/estate.sh
load_config
status() {
local issued; issued=$(estate_get "certs.issued" | python3 -c 'import json,sys
try: print("\n".join(json.load(sys.stdin)))
except Exception: pass')
echo "issued SANs (estate/${ESTATE}.json: certs.issued):"
echo "$issued" | sed 's/^/ /'
echo
echo "SANs the services NEED (derived from services[]):"
estate_sans | sed 's/^/ /'
echo
local missing=0 s
while IFS= read -r s; do
[ -z "$s" ] && continue
grep -qxF "$s" <<< "$issued" || { echo "MISSING: $s"; missing=1; }
done < <(estate_sans)
[ "$missing" = 0 ] && echo "the issued cert covers every derived name."
echo
echo "certbot image: $(eval echo "\$$CERTBOT_IMAGE_VAR") provider: $DNS_PROVIDER"
}
verify() {
echo "would run:"
echo " echo | openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} 2>/dev/null \\"
echo " | openssl x509 -noout -dates -ext subjectAltName"
echo
echo "read-only against a live host — announce and approve first (§7)."
}
refuse() {
echo "REFUSING: '$1' acts on a live cert and a live gateway." >&2
echo " renew issues a real Let's Encrypt cert (rate-limited)." >&2
echo " push rsyncs to the gateway and reloads nginx." >&2
echo " Neither runs without explicit approval." >&2
exit 1
}
case "${1:-status}" in
status) status ;;
verify) verify ;;
renew|push) refuse "$1" ;;
*) echo "usage: $0 [status|verify|renew|push]" >&2; exit 1 ;;
esac