#!/bin/bash # FILE: admin/peer/del # DESCRIPTION: Delete a peer from the admin ui # USAGE: del $remote_ip $querystring # QUERYSTRING: ?t=$token&pubkey=$pubkey source /etc/wagon/config ip="${1}"; qs="$(<<<"${2}" tr '&' '\n' | sed 's/?//')" # Parse pubkey pubkey="$(<<<"${qs#}" grep 'pubkey=' | sed 's/pubkey=//')" printf '%s requested to delete %s\n' "${ip}" "${pubkey}" >&2 # Check token token_fail(){ printf 'Rejecting admin %s request to delete peer due to %s token\n' "${ip}" "${1}" >&2 printf 'Invalid token\n' | /usr/lib/wagon/http_res 403; exit } saved_token="$(grep "${ip}" /var/local/wagon/tokens | cut -f2)" [ "${saved_token}" == "" ] && token_fail 'missing' <<<"${qs}" grep -qx "t=${saved_token}" || token_fail 'mismatched' printf '%s token was valid\n' "${ip}" >&2 # Get peer IP list if ! wg_output="$(sudo /usr/bin/wg show "${TLD}" allowed-ips)"; then printf 'ERROR! Wireguard failed!\n' >&2 /usr/lib/wagon/http_res 500; exit fi # Filter out this user's user_peer="$(grep "${pubkey}" <<<"${wg_output}" 2>/dev/null)" if [ "${user_peer}" == "" ]; then printf 'ERROR! Could not find user for pubkey %s!\n' "${pubkey}" >&2 printf 'Peer not found' | /usr/lib/wagon/http_res 404; exit fi # Get peer domains if ! peer="$(/usr/lib/wagon/ips_to_peers tsv <<<"${user_peer}" | grep "${pubkey}")"; then printf 'ERROR! Failed to lookup domain for pubkey %s!\n' "${pubkey}" >&2 /usr/lib/wagon/http_res 500; exit fi domain="$(<<<"${peer}" cut -f1)" ipv4="$(<<<"${peer}" cut -f2)" ipv6="$(<<<"${peer}" cut -f3)" if ! printf 'Delete request was for %s %s %s\n' "${domain:?}" "${ipv4:?}" "${ipv6:?}" >&2; then printf 'ERROR! Failed to collect peer data: %s %s %s\n' "${domain}" "${ipv4}" "${ipv6}" >&2 /usr/lib/wagon/http_res 500; exit fi # Make sure admin isn't deleting their own peer if [ "${ip}" == "${ipv4}" ] || [ "${ip}" == "${ipv6}" ]; then printf 'Admin requested to delete peer from itself: %s.\n' "${ip}" >&2 printf 'You cannot delete a peer from itself!' | /usr/lib/wagon/http_res 400; exit fi hostname="$(<<<"${domain}" cut -d'.' -f1)" username="$(<<<"${domain}" cut -d'.' -f2)" # Wireguard # Run this function in parallel in the while loop below # https://stackoverflow.com/a/33058618 for_server_do() { [[ ${server_hostname:0:1} = \# ]] && return # Ignore comments server_hostname="${1}"; server_ipv4="${2}"; server_ipv6="${3}"; server_pubkey="${4}" server_endpoint="${5}"; server_url="${6}"; server_secret="${7}" if [ "${server_hostname}" == "${LOCAL_SERVER}" ]; then # Local server if /usr/lib/wagon/wg_peer_del "${pubkey}"; then printf 'Deleted %s from local wireguard server.\n' "${domain}" >&2 else printf 'ERROR! Failed to delete %s from local wireguard server!\n' "${domain}" >&2 # TODO: clear existing progress /usr/lib/wagon/http_res 500; exit fi else # Federated server if /usr/lib/wagon/fed_peer_del "${server_url}" "${server_secret}" "${pubkey}"; then printf 'Deleted %s from remote wireguard server %s.\n' "${domain}" "${server_hostname}" >&2 else printf 'ERROR! Failed to delete %s from remote wireguard server %s!\n' "${domain}" "${server_hostname}" >&2 /usr/lib/wagon/http_res 500; exit fi fi }; while IFS=$'\t' read -r server_hostname server_ipv4 server_ipv6 server_pubkey server_endpoint server_url server_secret do for_server_do "${server_hostname}" "${server_ipv4}" "${server_ipv6}" "${server_pubkey}" "${server_endpoint}" "${server_url}" "${server_secret}" & done &2 else printf 'ERROR! Failed to delete %s %s %s from DNS server!\n' "${domain}" "${ipv4}" "${ipv6}" >&2 fi & # Delete SSL cert if /usr/lib/wagon/ssl_peer_del "${hostname:?}" "${username:?}" then printf 'Successfully deleted SSL certs for %s\n' "${domain}" >&2 else printf 'ERROR! Failed to delete certs for %s!\n' "${domain}" >&2 fi # Respond to user # Do it before updating nameserver and certs because # if wireguard worked, there's no going back. The admin # can clean up missing records and certs after checking the logs printf 'Deleted %s.%s.%s' "${hostname}" "${username}" "${TLD}" | /usr/lib/wagon/http_res 202