Introduce webhook-backend-run and make sure scripts are user-agnostic

This commit is contained in:
southerntofu 2020-04-27 16:27:45 +02:00
parent fefc9643bc
commit 54ab642da2
5 changed files with 95 additions and 47 deletions

View File

@ -1,17 +1,42 @@
#! /bin/bash
# TODO: currently setup.sh assumes you're a sudoer, not root
DEST="/usr/local/bin"
# TODO: Make user configurable (see other todo notes)
# Should be autodetected in case of existing setup
owner="webhook"
sudo cp webhook /usr/local/bin
sudo chown "$owner:$owner" /usr/local/bin/webhook
# TODO: Detect if user has UID > 1000 so if it's a real user we refuse to setup
# and try to escalate to generate a dedicated account. Maybe also check for ownership
# of $DEST/webhook so if there's already a setup we escalate privileges to this user
# for setup?
sudo cp webhook-backend /usr/local/bin
sudo chown "$owner:$owner" /usr/local/bin/webhook-backend
# Please don't run me as root!
if [[ $EUID = 0 ]]; then
# TODO: Setup prompt to ask for new user to create and destination folder
echo "FATAL ERROR: please create a dedicated user to setup forgehook"
exit 1
fi
sudo cp webhook-run /usr/local/bin
sudo chown "$owner:$owner" /usr/local/bin/webhook-run
sudo chmod 744 /usr/local/bin/webhook-run
# Everyone can execute (user-facing wrapper)
sudo cp webhook $DEST
sudo chown "$owner:$owner" $DEST/webhook
# Only $owner can execute
sudo cp webhook-backend $DEST
sudo chown "$owner:$owner" $DEST/webhook-backend
sudo chmod 744 $DEST/webhook-backend
# Only root should execute
sudo cp webhook-run $DEST
sudo chown "$owner:$owner" $DEST/webhook-run
sudo chmod 744 $DEST/webhook-run
# Everyone can execute (wrapper script for build manager such as git-build)
sudo cp webhook-run-backend $DEST
sudo chown "$owner:$owner" $DEST/webhook-run-backend
sudo chmod 755 $DEST/webhook-run-backend
echo "Successfully installed webhook as user $owner to $DEST"

11
webhook
View File

@ -1,3 +1,12 @@
#! /bin/bash
sudo -u webhook webhook-backend $@
# Auto-detect owner of webhook-backend on current system
# stat has different syntax on various system so we use find
# TODO: if we don't find webhook-backend, we should error
bin="$(which webhook-backend)"
owner=$(find $bin -maxdepth 0 -printf '%u')
# Start the backend escalating privileges to its owner
# TODO: introduce timeout on a dummy sudo to check sudo rules
# are setup properly
sudo -u "$owner" webhook-backend $@

View File

@ -1,7 +1,6 @@
#! /bin/bash
db_owner="webhook"
db="/home/$db_owner/webhooks"
db="$HOME/webhooks"
# Make sure we don't fallback to a simple "*.foo" when no files matched the glob pattern
shopt -s nullglob

View File

@ -2,60 +2,38 @@
if [[ $EUID != 0 ]]; then
# We're not root... yet!
# Let's not forget to define the db while we have forgehook $USER
db=$HOME/webhooks
sudo webhook-run $@
exit $?
fi
if [[ $# = 0 ]]; then
echo "BUG? How did you call me without argument?"
# If the $db is empty/unset, we have a logic bug somewhere!
if [ -z $db ]; then
echo "FATAL ERROR: Could not find forgehook database (BUG)"
fi
# We only take one argument!
if [[ $# != 1 ]]; then
echo "FATAL ERROR: webhook-run can't deal with $# argument(s) (BUG)"
[[ $# != 0 ]] && echo "Found arguments: "$@""
exit 1
fi
# Ok now we're root
from_hex() {
echo -n "$@" | base64 -d
}
from_url() {
echo -n "$@" | base64
}
db=/home/webhook/webhooks
# We only take one argument!
r="$1"
rhex="$(from_url "$r")"
# hexencode URL
rhex="$(echo -n "$r" | base64)"
# Don't loop when nothing matches, plz?
shopt -s nullglob
# Iterate over the hex-encoded URL's subscriptions
for i in $db/"$rhex".*; do
# Strip $rhex prefix
user="$(basename "$i")"
user="${user#$rhex.}"
# Now find the user's git-build tasks subscribing to the repo
#r="$(from_hex "$rhex")"
gitbuild=/home/"$user"/.git-build
if [ ! -d "$gitbuild" ]; then
echo "$user has no ~/.git-build/ so we skip"
continue
fi
# Could use some grep-fu here, but maybe not intoduce another dependency?
FOUND=0
for f in $gitbuild/*.source; do
if [[ "$r" = "$(cat "$f")" ]]; then
FOUND=1
task="$(basename "$f" .source)"
echo "$task for $user"
bin="$(which git-build.sh)"
sudo -u "$user" bash "$bin" "$task"&
fi
done
if [[ $FOUND = 0 ]]; then
echo "User $user is subscribed to $r but no matching task was found"
fi
sudo -u "$user" webhook-run-backend "$1"
done

37
webhook-run-backend Normal file
View File

@ -0,0 +1,37 @@
#! /bin/bash
# We only take one argument!
if [[ $# != 1 ]]; then
echo "FATAL ERROR: webhook-run-backend can't deal with $# argument(s) (BUG)"
[[ $# != 0 ]] && echo "Found arguments: "$@""
exit 1
fi
# OK, now we're running as unprivileged user who wants to start their build scripts
# TODO: Maybe we should not care whether matching build tasks were found? Or maybe
# we do care and we want the webhook-endpoint to have nice info about which remotes
# failed to update and why?
# TODO: https://tildegit.org/southerntofu/git-build.sh/issues/14
# Logic should be moved to git-build so this becomes simpler
gitbuild=$HOME/.git-build
if [ ! -d "$gitbuild" ]; then
echo "$USER has no $gitbuild so we skip"
continue
fi
FOUND=0
for f in $gitbuild/*.source; do
if [[ "$r" = "$(cat "$f")" ]]; then
FOUND=1
task="$(basename "$f" .source)"
echo "$task for $USER"
bin="$(which git-build.sh)"
sudo -u "$USER" bash "$bin" "$task"&
fi
done
if [[ $FOUND = 0 ]]; then
echo "WARNING: $USER is subscribed to $r but no matching task was found"
fi