#!/bin/bash -e

DESCRIPTION="Idempotent setup script for SSH access"

MBD_USERS="mini-buildd-uploader mini-buildd-admin mini-buildd-staff"

case "${1}" in
	"--purge")
		read -p"Really purge users ${MBD_USERS} (Ctrl-c to abort)? " DUMMY
		for user in ${MBD_USERS}; do
			killall -v -u "${user}" || true
			! getent passwd "${user}" || deluser --remove-home "${user}"
		done
		exit 0
		;;
	"--help"|"-h")
		cat <<EOF
Usage: $(basename "${0}") [[<ENDPOINT>]|[--purge]]  (as user root)

${DESCRIPTION}

Create and setup three UNIX users that are corresponding to mini-buildd users of the same name:

 * mini-buildd-uploader:  Allow uploads via SSH
 * mini-buildd-staff:     Allow API calls with 'staff' authorization via SSH
 * mini-buildd-admin:     Allow API calls with 'admin' authorization via SSH

Needed extra work on mini-buildd:

 * BEFORE running this:  Please create all the three mini-buildd users
 * AFTER running this:   Please check/configure/activate the Upload Profile for user mini-buildd-uploader

When this is up:

 * Grant someone access:  See the example line in created 'authorized_keys' files of the resp. users.
 * Run API calls:         'ssh mini-buildd-staff|admin@<yourhost> mini-buildd-api <mini_buildd_api_args>'
   Note that you will need the _complete_ arguments, including the correct user endpoint (like 'http://mini-buildd-staff@<yourhost>:8066')
 * Upload:                An extra '.dput.cf' will be generated in '/var/lib/mini-buildd/etc/dput.cf' (for dput_conf API call)
   Authorized users can now also upload with this new target.

Caveats:

Someone with access to 'mini-buildd-uploader' could potentially copy from or write to arbitrary locations (within the
mini-buildd-uploader user's permissions).
EOF
	exit 0
esac

[ $(id -u) -eq 0 ] || { printf "E: Needs to be run as root (try --help for usage).\n" >&2; exit 1; }

read -p"Really create && setup UNIX users ${MBD_USERS} (Check --help first, Ctrl-c to abort)? " DUMMY

MBD_ENDPOINT="${1:-http://$(hostname -f):8066}"
MBD_STATUS=$(mini-buildd-api --json status "${MBD_ENDPOINT}")
MBD_IDENTITY=$(jq --raw-output ".identity" <<<${MBD_STATUS})
MBD_URL=$(jq --raw-output ".url" <<<${MBD_STATUS})
[ -n "${MBD_IDENTITY}" ] || { printf "E: Can't get identity from ${MBD_ENDPOINT}\n" >&2; exit 1; }
printf "I: Using mini-buildd endpoint '%s' with identity '%s'\n" "${MBD_ENDPOINT}" "${MBD_IDENTITY}"

for user in ${MBD_USERS}; do
	getent passwd "${user}" || adduser --disabled-password --gecos "${user}" "${user}"
	su - "${user}" --command "mkdir -v -m700 .ssh" || true
done
su - "mini-buildd-uploader" --command "mkdir -v -m755 incoming" || true

DPUT_CF="/tmp/mbd_dput.cf"
MBD_DPUT_CF="/var/lib/mini-buildd/etc/dput.cf"

cat <<EOF | tee "${DPUT_CF}"

# Alternate local setup to upload via SSH
[mini-buildd-${MBD_IDENTITY}-ssh]
method   = scp
login    = mini-buildd-uploader
fqdn     = $(hostname -f)
incoming = /home/mini-buildd-uploader/incoming/
EOF

if [ -e "${MBD_DPUT_CF}" ]; then
	diff -u "${DPUT_CF}" "${MBD_DPUT_CF}" || printf "W: ${MBD_DPUT_CF} differs from generated\n" >&2
	printf "I: Not touching already existing ${MBD_DPUT_CF}\n"
else
	cp -v "${DPUT_CF}" "${MBD_DPUT_CF}"
	chown -v mini-buildd:mini-buildd "${MBD_DPUT_CF}"
fi

_install_authorized_key_example()
{
	local user=${1} command=${2}
	local example_path="/tmp/mbd_auth_keys_example_${user}"
	target_file=$(getent passwd ${user} | cut -d: -f6)/.ssh/authorized_keys
	cat <<EOF | tee "${example_path}"
# command="${command}",no-port-forwarding,no-X11-forwarding <public_key>
EOF
	if [ -e "${target_file}" ]; then
		printf "I: Not touching already existing ${target_file}\n"
	else
		cp -v "${example_path}" "${target_file}"
		chown -v "${user}:${user}" "${target_file}"
	fi
}

_install_authorized_key_example mini-buildd-uploader /usr/sbin/mini-buildd-ssh-uploader-command
_install_authorized_key_example mini-buildd-staff '/usr/bin/mini-buildd-api ${SSH_ORIGINAL_COMMAND#* }'
_install_authorized_key_example mini-buildd-admin '/usr/bin/mini-buildd-api ${SSH_ORIGINAL_COMMAND#* }'

UPLOADER_DPUT_CF=~mini-buildd-uploader/.dput.cf
if [ -e "${UPLOADER_DPUT_CF}" ]; then
	printf "I: Not touching already existing ${UPLOADER_DPUT_CF}\n"
else
	mini-buildd-api dput_conf "${MBD_ENDPOINT}" | tee "${UPLOADER_DPUT_CF}"
	chown -v mini-buildd-uploader:mini-buildd-uploader "${UPLOADER_DPUT_CF}"
fi

_setup_pk_plain()
{
	sudo apt-get install python3-keyrings.alt || true   # for the PlainTextKeyring (newer versions only)

	local home=${1}
	local user=$(stat --format "%U" ${home}) configDir
	# python-keyring 21.3.0 (bullseye+) fixes config file location to '~/.config/python_keyring'; we need to support the old path for some time still.
	for configDir in "${home}/.config/python_keyring" "${home}/.local/share/python_keyring"; do
		mkdir -p "${configDir}"
		local configFile="${configDir}/keyringrc.cfg"
		cat <<EOF >"${configFile}"
# suit		able for python3-keyring > 8
[backend]
default-keyring=keyrings.alt.file.PlaintextKeyring
EOF
		chown -v -R $(stat --format "%U:%G" ${home}) "${configDir}"
	done
	while true; do
		read -p "=> About to test/update stored password for user ${user} on ${MBD_URL} (please CREATE NOW if it does not exist yet && and save password when asked) (Ctrl-c to abort, RET to continue)" DUMMY
		! su - "${user}" --command "mini-buildd-api status ${MBD_URL/\/\//\/\/${user}@}" || break
	done
}
_setup_pk_plain ~mini-buildd-staff || true
_setup_pk_plain ~mini-buildd-admin || true

for user in mini-buildd-uploader; do
	if su - "mini-buildd-uploader" --command "gpg --batch --passphrase '' --quick-generate-key mini-buildd-uploader"; then
		UPLOADER_PUB_KEY=$(su - "mini-buildd-uploader" --command "gpg --export --armor mini-buildd-uploader")
		printf "%s\n" "${UPLOADER_PUB_KEY}"
		read -p "=> About to auto-upload above key to ${user} on ${MBD_URL} (please CREATE NOW if it does not exist yet && rather don't save password when asked) (Ctrl-c to abort, RET to continue)" DUMMY
		su - "mini-buildd-uploader" --command "mini-buildd-api --auto-confirm set_user_key ${MBD_URL/\/\//\/\/mini-buildd-uploader@} '${UPLOADER_PUB_KEY}'"
	fi
done
