Ctrl K
ComunidadGuías…

gen-cert.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/bin/bash
# Generate a self-signed TLS certificate for local/LAN HTTPS.
# Required for camera access (getUserMedia) on iOS Safari.
#
# Usage: bash gen-cert.sh [domain]
#   domain  Optional domain name to include in the certificate (e.g. myhost.duckdns.org)
#           Can also be set via CERT_DOMAIN environment variable.
#
# The certificate is valid for 365 days and covers localhost + LAN IPs + optional domain.
# Compatible with both OpenSSL and LibreSSL (macOS).

set -e

CERT_DIR="certs"
mkdir -p "$CERT_DIR"
# S-12: openssl writes the key with the caller's umask, which on a normal host
# means 0644 — the server's TLS private key readable by every local account.
# Restrict the directory up front and the key itself after generation.
chmod 700 "$CERT_DIR"

# Domain from first argument or CERT_DOMAIN env var.
# Validate against a strict whitelist before interpolating
# into the OpenSSL config heredoc — newlines or `=` characters in DOMAIN
# would otherwise let a hostile env file inject extra cert extensions.
DOMAIN="${1:-${CERT_DOMAIN:-}}"
if [ -n "$DOMAIN" ] && ! [[ "$DOMAIN" =~ ^[A-Za-z0-9.-]+$ ]]; then
  echo "ERROR: DOMAIN must contain only A-Za-z0-9.-" >&2
  exit 1
fi

# Detect LAN IP (Linux then macOS fallback)
LAN_IP=""
if command -v hostname &>/dev/null && hostname -I &>/dev/null; then
  LAN_IP=$(hostname -I | awk '{print $1}')
fi
if [ -z "$LAN_IP" ] && command -v ipconfig &>/dev/null; then
  LAN_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || true)
fi
if [ -z "$LAN_IP" ]; then
  LAN_IP="192.168.1.100"
fi

echo "Generating self-signed certificate..."
echo "  LAN IP: $LAN_IP"
if [ -n "$DOMAIN" ]; then
  echo "  Domain: $DOMAIN"
fi

# Build SAN list: domain first (if provided), then localhost + LAN IP
SAN="DNS:localhost,IP:127.0.0.1,IP:$LAN_IP"
if [ -n "$DOMAIN" ]; then
  SAN="DNS:$DOMAIN,$SAN"
fi

# Use a config file for SAN (works with both OpenSSL and LibreSSL)
TMPCONF=$(mktemp)
cat > "$TMPCONF" <<CONF
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
x509_extensions = v3_ext

[dn]
CN = Meistertracker

[v3_ext]
subjectAltName = $SAN
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
CONF

openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout "$CERT_DIR/server.key" \
  -out "$CERT_DIR/server.crt" \
  -days 365 \
  -config "$TMPCONF"

rm -f "$TMPCONF"

chmod 600 "$CERT_DIR/server.key"
chmod 644 "$CERT_DIR/server.crt"

echo ""
echo "Certificate generated in $CERT_DIR/"
echo "  $CERT_DIR/server.key"
echo "  $CERT_DIR/server.crt"
if [ -n "$DOMAIN" ]; then
  echo "  SAN: $SAN"
fi
echo ""
echo "On iOS Safari, open https://$LAN_IP:3000 and accept the certificate warning."
if [ -n "$DOMAIN" ]; then
  echo "Or use https://$DOMAIN:3000 (certificate covers this domain)."
fi
echo "Restart the server for HTTPS to take effect."