#!/bin/sh
set -eu

if [ "$(id -u)" -ne 0 ]; then
  echo "Run this installer as root." >&2
  exit 1
fi

hub_endpoint="${VIMIFY_VPN_HUB_ENDPOINT:-}"
hub_public_key="${VIMIFY_VPN_HUB_PUBLIC_KEY:-}"
tunnel_address="${VIMIFY_VPN_TUNNEL_ADDRESS:-}"
allowed_ips="${VIMIFY_VPN_ALLOWED_IPS:-10.77.0.0/24}"
interface_name="wg-vimify"

case "$hub_endpoint" in *:*) ;; *) echo "VIMIFY_VPN_HUB_ENDPOINT must be host:port." >&2; exit 1 ;; esac
sanitized_endpoint="$(printf '%s' "$hub_endpoint" | tr -cd 'a-zA-Z0-9._:[]-')"
if [ "$sanitized_endpoint" != "$hub_endpoint" ]; then
  echo "VIMIFY_VPN_HUB_ENDPOINT contains unsupported characters." >&2
  exit 1
fi
case "$hub_public_key" in *[!a-zA-Z0-9+/=]*|'') echo "VIMIFY_VPN_HUB_PUBLIC_KEY is invalid." >&2; exit 1 ;; esac
case "$tunnel_address" in *[!0-9./]*|'') echo "VIMIFY_VPN_TUNNEL_ADDRESS is invalid." >&2; exit 1 ;; esac
case "$tunnel_address" in *.*.*.*'/32') ;; *) echo "VIMIFY_VPN_TUNNEL_ADDRESS must be a unique IPv4 /32 address." >&2; exit 1 ;; esac
case "$allowed_ips" in *[!0-9.,/]*|'') echo "VIMIFY_VPN_ALLOWED_IPS must contain IPv4 CIDRs." >&2; exit 1 ;; esac

environment_file="/etc/vimify-edge.env"
if [ ! -f "$environment_file" ]; then
  echo "$environment_file does not exist. Install Vimify Edge first." >&2
  exit 1
fi

if ! command -v wg >/dev/null 2>&1; then
  if ! command -v apt-get >/dev/null 2>&1; then
    echo "Install wireguard-tools, then run this installer again." >&2
    exit 1
  fi
  apt-get update
  DEBIAN_FRONTEND=noninteractive apt-get install -y wireguard-tools
fi

install -d -m 0700 /etc/wireguard
private_key_file="/etc/wireguard/$interface_name.key"
if [ ! -f "$private_key_file" ]; then
  umask 077
  wg genkey > "$private_key_file"
fi
chmod 0600 "$private_key_file"
private_key="$(sed -n '1p' "$private_key_file")"
public_key="$(printf '%s' "$private_key" | wg pubkey)"

configuration_file="/etc/wireguard/$interface_name.conf"
temporary_file="$(mktemp /etc/wireguard/.wg-vimify.XXXXXX)"
{
  printf '[Interface]\n'
  printf 'PrivateKey = %s\n' "$private_key"
  printf 'Address = %s\n\n' "$tunnel_address"
  printf '[Peer]\n'
  printf 'PublicKey = %s\n' "$hub_public_key"
  printf 'Endpoint = %s\n' "$hub_endpoint"
  printf 'AllowedIPs = %s\n' "$allowed_ips"
  printf 'PersistentKeepalive = 25\n'
} > "$temporary_file"
chmod 0600 "$temporary_file"
mv -f "$temporary_file" "$configuration_file"

update_environment() {
  key="$1"
  value="$2"
  temporary_environment="$(mktemp /etc/.vimify-edge.XXXXXX)"
  awk -F= -v key="$key" '$1 != key { print }' "$environment_file" > "$temporary_environment"
  printf '%s=%s\n' "$key" "$value" >> "$temporary_environment"
  chmod 0600 "$temporary_environment"
  mv -f "$temporary_environment" "$environment_file"
}

update_environment VIMIFY_VPN_ENABLED true
update_environment VIMIFY_VPN_INTERFACE "$interface_name"
update_environment VIMIFY_VPN_TUNNEL_IP "$tunnel_address"
update_environment VIMIFY_VPN_HUB_ENDPOINT "$hub_endpoint"

systemctl enable "wg-quick@$interface_name"
systemctl restart "wg-quick@$interface_name"
systemctl restart vimify-vpn-status.timer
systemctl restart vimify-edge

printf 'Vimify site VPN is active.\n'
printf 'Register this site public key on the hub:\n%s\n' "$public_key"
