#!/bin/bash # FILE: admin/user/del # DESCRIPTION: Delete a user from admin UI # USAGE: del $remote_ip $querystring # QUERYSTRING: ?t=$token&user=$username&un=$usernumber source /etc/wagon/config ip="${1}"; qs="$(<<<"${2}" tr '&' '\n' | sed 's/?//')" # Check token token_fail(){ printf 'Rejecting admin %s request for new 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 # Check username and usernumber username="$(<<<"${qs}" grep -oP 'user=(.*)' | sed 's/^user=//')" usernumber="$(<<<"${qs}" grep -oP 'un=(.*)' | sed 's/^un=//')" if [[ "${username}" == "" ]]; then printf 'ERROR! Username missing!\n' | tee >(cat 1>&2) | /usr/lib/wagon/http_res 400; exit elif [[ "${usernumber}" == "" ]]; then printf 'ERROR! Usernumber missing!\n' | tee >(cat 1>&2) |/usr/lib/wagon/http_res 400; exit else printf 'Admin %s requested deletion of user "%s" with usernumber "%s"\n' "${ip}" "${username}" "${usernumber}" >&2 fi # Get all peer IPs 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 the user's user_peers="$(grep "${IPV4_NET%.*.*}.${usernumber}." <<<"${wg_output}" 2>/dev/null)" if [ "${user_peers}" == "" ]; then printf "ERROR! Couldn't find any peers for %s!\n" "${IPV4_NET%.*.*}.${usernumber}." >&2 /usr/lib/wagon/http_res 500; exit fi # Get user peer domains if ! peers="$(/usr/lib/wagon/ips_to_peers tsv <<<"${user_peers}")"; then printf 'ERROR! Failed to retrieve domains for peers for %s!\n' "${IPV4_NET%.*.*}.${usernumber}" >&2 /usr/lib/wagon/http_res 500; exit fi # 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 } # Delete user peers (in parallel) delete_peer() { domain="${1}"; ipv4="${2}"; ipv6="${3}"; pubkey="${4}" username="$(<<<"${domain}" cut -d'.' -f2)" printf 'Deleting peer %s\n' "${domain}" >&2 # Remove peer from wireguard 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 } printf '%s\n' "${peers}" | while IFS=$'\t' read -r domain ipv4 ipv6 pubkey do delete_peer "${domain}" "${ipv4}" "${ipv6}" "${pubkey}" & [ "$(jobs | wc -l)" -ge "$(nproc)" ] && wait done # Delete SSL cert directory if ! sudo rm -rf "${SSL_CONFIG_DIR:?}/${username:?}/"; then printf 'Failed to delete user SSL directory %s/%s/:\n' "${SSL_CONFIG_DIR}" "${username}" >&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' "${username}" | /usr/lib/wagon/http_res 202