wagon/back/lib/admin/user/del

130 lines
5.4 KiB
Bash
Executable File

#!/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
CONFIG_FILE='/etc/wgapi/config'
SERVERS_FILE='/etc/wgapi/servers'
if ! [ ${#} -eq 2 ]; then
printf 'ERROR! Bad input: %s %s\n' "${0}" "${*}" >>"${LOGFILE}"
"${LIB_DIR}/http_res" 500; exit
fi & if ! [ -x '/usr/bin/wg' ]; then
printf 'ERROR! %s could not find /usr/bin/wg\n' "${0}" >>"${LOGFILE}"
"${LIB_DIR}/http_res" 500; exit
fi & if ! [ -f "${CONFIG_FILE}" ]; then
printf 'ERROR! %s could not find %s!\n' "${0}" "${CONFIG_FILE}" >>"${LOGFILE}"
"${LIB_DIR}/http_res" 500; exit
fi
source "${CONFIG_FILE}"
if ! [ -f "${SERVERS_FILE}" ]; then
printf 'ERROR! %s could not find %s!\n' "${0}" "${SERVERS_FILE}" >>"${LOGFILE}"
"${LIB_DIR}/http_res" 500; exit
fi & if ! [ -f "${TOKENS_FILE}" ]; then
printf 'ERROR! %s could not find %s!\n' "${0}" "${TOKENS_FILE}" >>"${LOGFILE}"
"${LIB_DIR}/http_res" 500; exit
fi
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}" >>"${LOGFILE}"
printf 'Invalid token\n' | "${LIB_DIR}/http_res" 403; exit
}
saved_token="$(grep "${ip}" "${TOKENS_FILE}" | cut -f2)"
[ "${saved_token}" == "" ] && token_fail 'missing' &
<<<"${qs}" grep -qx "t=${saved_token}" || token_fail 'mismatched'
printf '%s token was valid\n' "${ip}" >>"${LOGFILE}"
# 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 -a "${LOGFILE}" | "${LIB_DIR}/http_res" 400; exit
elif [[ "${usernumber}" == "" ]]; then
printf 'ERROR! Usernumber missing!\n' | tee -a "${LOGFILE}" |"${LIB_DIR}/http_res" 400; exit
else
printf 'Admin %s requested deletion of user "%s" with usernumber "%s"\n' "${ip}" "${username}" "${usernumber}" >>"${LOGFILE}"
fi
# Get all peer IPs
if ! wg_output="$(sudo /usr/bin/wg show "${TLD}" allowed-ips)"; then
printf 'ERROR! Wireguard failed!\n' >>"${LOGFILE}"
"${LIB_DIR}/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}." >>"${LOGFILE}"
"${LIB_DIR}/http_res" 500; exit
fi
# Get user peer domains
if ! peers="$("${LIB_DIR}/ips_to_peers" tsv <<<"${user_peers}")"; then
printf 'ERROR! Failed to retrieve domains for peers for %s!\n' "${IPV4_NET%.*.*}.${usernumber}" >>"${LOGFILE}"
"${LIB_DIR}/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_admin="${6}"; server_secret="${7}"
if [ "${server_hostname}" == "${LOCAL_SERVER}" ]; then
if "${LIB_DIR}/wg_peer_del" "${pubkey}"; then
printf 'Deleted %s from local wireguard server.\n' "${domain}" >>"${LOGFILE}"
else
printf 'ERROR! Failed to delete %s from local wireguard server!\n' "${domain}" >>"${LOGFILE}"
# TODO: clear existing progress
"${LIB_DIR}/http_res" 500; exit
fi
# TODO Delete federated peer
#else
# if "${LIB_DIR}/fed_peer_del" "${server_admin}" "${pubkey}" "${server_psk}" "${ipv4}/32,${ipv6}/128" "${server_secret}"; then
# printf 'Deleted %s from remote wireguard server %s.\n' "${domain}" "${server_hostname}" >>"${LOGFILE}"
# else
# printf 'ERROR! Failed to delete %s from remote wireguard server %s!\n' "${domain}" "${server_hostname}" >>"${LOGFILE}"
# # TODO: Send a 500 error
# # TODO: clear existing progress
# exit 16
# fi"${LIB_DIR}/fed_peer_del" "${server_admin}" "${pubkey}" "${server_secret}"
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}" >> "${LOGFILE}"
# Remove peer from wireguard
while IFS=$'\t' read -r server_hostname server_ipv4 server_ipv6 server_pubkey server_endpoint server_admin server_secret
do for_server_do "${server_hostname}" "${server_ipv4}" "${server_ipv6}" "${server_pubkey}" "${server_endpoint}" "${server_admin}" "${server_secret}" &
# Uncomment if SERVERS_FILE is very big
#[ $( jobs | wc -l ) -ge $( nproc ) ] && wait
done <"${SERVERS_FILE}" &
# Remove peer from nameserver
if "${LIB_DIR}/ns_update_del" "${domain:?}" "${ipv4:?}" "${ipv6:?}"
then printf 'Successfully deleted %s from DNS server.\n' "${domain}" >>"${LOGFILE}"
else printf 'ERROR! Failed to delete %s %s %s from DNS server!\n' "${domain}" "${ipv4}" "${ipv6}" >>"${LOGFILE}"
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}" >>"${LOGFILE}"
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}" | "${LIB_DIR}/http_res" 202