#!/usr/bin/env bash
set -euo pipefail

API="https://bootstrap.pulsebridge.me"

if [ "$(id -u)" -ne 0 ]; then
  printf '%s\n' "Run this installer as root or with sudo." >&2
  exit 1
fi

if [ ! -r /etc/os-release ]; then
  printf '%s\n' "Unsupported operating system." >&2
  exit 1
fi

. /etc/os-release
if [ "${ID:-}" != "debian" ]; then
  printf '%s\n' "This installer currently supports Debian only." >&2
  exit 1
fi

apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl jq openssh-server

if systemctl list-unit-files cloudflared.service 2>/dev/null | grep -q '^cloudflared.service'; then
  printf '%s\n' "This machine already has a cloudflared service. Run 'sudo pulsebridge unenroll' before enrolling again." >&2
  exit 1
fi

printf 'Authorized email: '
read -r email </dev/tty
printf 'Device name [%s]: ' "$(hostname -s)"
read -r device_name </dev/tty
device_name="${device_name:-$(hostname -s)}"

challenge=$(curl -fsS -X POST "$API/api/challenges" --data-urlencode "email=$email" --data-urlencode "name=$device_name")
session_id=$(printf '%s' "$challenge" | jq -er '.sessionId')
client_token=$(printf '%s' "$challenge" | jq -er '.clientToken')

printf '%s\n' "A four-word enrollment phrase was sent to $email."
printf 'Enrollment phrase: '
read -rs phrase </dev/tty
printf '\n'

curl -fsS -X POST "$API/api/challenges/$session_id/verify" \
  -H "Authorization: Bearer $client_token" \
  --data-urlencode "phrase=$phrase" >/dev/null

printf '%s\n' "Identity verified. Provisioning Cloudflare Tunnel and Access..."
for _ in $(seq 1 120); do
  result=$(curl -fsS "$API/api/challenges/$session_id/result" -H "Authorization: Bearer $client_token")
  status=$(printf '%s' "$result" | jq -er '.status')
  if [ "$status" = "approved" ]; then
    break
  fi
  if [ "$status" = "failed" ] || [ "$status" = "expired" ]; then
    printf '%s\n' "Enrollment failed: $(printf '%s' "$result" | jq -r '.error // .status')" >&2
    exit 1
  fi
  sleep 2
done

if [ "${status:-}" != "approved" ]; then
  printf '%s\n' "Enrollment timed out." >&2
  exit 1
fi

hostname=$(printf '%s' "$result" | jq -er '.hostname')
username=$(printf '%s' "$result" | jq -er '.username')
tunnel_token=$(printf '%s' "$result" | jq -er '.tunnelToken')
management_token=$(printf '%s' "$result" | jq -er '.managementToken')
ca_public_key=$(printf '%s' "$result" | jq -er '.caPublicKey')

if ! getent passwd "$username" >/dev/null; then
  useradd --create-home --shell /bin/bash "$username"
  passwd --lock "$username" >/dev/null
fi

install -d -m 0700 /etc/pulsebridge
printf 'Authorization: Bearer %s\n' "$management_token" > /etc/pulsebridge/auth-header
chmod 0600 /etc/pulsebridge/auth-header
printf 'HOSTNAME=%q\n' "$hostname" > /etc/pulsebridge/device
chmod 0600 /etc/pulsebridge/device

cat > /usr/local/sbin/pulsebridge <<'CLI'
#!/usr/bin/env bash
set -euo pipefail
API="https://bootstrap.pulsebridge.me"
AUTH="/etc/pulsebridge/auth-header"
DEVICE="/etc/pulsebridge/device"

if [ "$(id -u)" -ne 0 ]; then
  printf '%s\n' "Run pulsebridge with sudo." >&2
  exit 1
fi

case "${1:-help}" in
  status)
    curl -fsS -H "@$AUTH" "$API/api/device/status" | jq
    ;;
  unenroll)
    if [ "${2:-}" != "--yes" ]; then
      printf 'Revoke Cloudflare access and remove this connector? [y/N] '
      read -r answer
      case "$answer" in y|Y|yes|YES) ;; *) exit 0 ;; esac
    fi
    curl -fsS -X POST -H "@$AUTH" "$API/api/device/unenroll" >/dev/null
    systemctl stop cloudflared.service 2>/dev/null || true
    cloudflared service uninstall 2>/dev/null || true
    rm -f /etc/ssh/sshd_config.d/90-cloudflare-access.conf /etc/ssh/cloudflare-access-ca.pub
    sshd -t
    systemctl reload ssh
    rm -rf /etc/pulsebridge
    printf '%s\n' "Enrollment removed. The Linux user and installed packages were preserved."
    ;;
  help|--help|-h)
    printf '%s\n' "Usage: sudo pulsebridge {status|unenroll|help}"
    ;;
  *)
    printf '%s\n' "Unknown command. Use: sudo pulsebridge help" >&2
    exit 2
    ;;
esac
CLI
chmod 0755 /usr/local/sbin/pulsebridge
trap 'pulsebridge unenroll --yes >/dev/null 2>&1 || true' ERR

install -d -m 0755 /etc/ssh/sshd_config.d
printf '%s\n' "$ca_public_key" > /etc/ssh/cloudflare-access-ca.pub
chmod 0600 /etc/ssh/cloudflare-access-ca.pub
printf '%s\n' "PubkeyAuthentication yes" "TrustedUserCAKeys /etc/ssh/cloudflare-access-ca.pub" > /etc/ssh/sshd_config.d/90-cloudflare-access.conf
sshd -t
systemctl enable --now ssh
systemctl reload ssh

install -d -m 0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg -o /usr/share/keyrings/cloudflare-main.gpg
printf '%s\n' 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' > /etc/apt/sources.list.d/cloudflared.list
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y cloudflared

cloudflared service install "$tunnel_token"
systemctl enable --now cloudflared
systemctl is-active --quiet cloudflared

curl -fsS -X POST "$API/api/challenges/$session_id/complete" -H "Authorization: Bearer $client_token" >/dev/null
trap - ERR
unset phrase tunnel_token management_token client_token result challenge ca_public_key
printf '%s\n' "Enrollment complete."
printf '%s\n' "Browser SSH: https://$hostname"
printf '%s\n' "Linux username: $username"
printf '%s\n' "Manage locally: sudo pulsebridge status | unenroll | help"
