fix: validate deployment rollback and server topology
This commit is contained in:
Executable
+72
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
# Prepare the nested targets required beneath the server profile's writable Pi-state parent bind.
|
||||
set -euo pipefail
|
||||
|
||||
fail() {
|
||||
printf 'prepare-server-pi-state: %s\n' "$*" >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
[[ $# -ge 1 && $# -le 3 ]] \
|
||||
|| fail "usage: $0 ABSOLUTE_PI_STATE_ROOT [NUMERIC_UID [NUMERIC_GID]]"
|
||||
|
||||
pi_state_root="$1"
|
||||
owner="${2:-$(id -u)}"
|
||||
group="${3:-$(id -g)}"
|
||||
[[ "$pi_state_root" == /* && "$pi_state_root" != / && "$pi_state_root" != */ \
|
||||
&& "$pi_state_root" != *//* && "$pi_state_root/" != */../* \
|
||||
&& "$pi_state_root/" != */./* ]] \
|
||||
|| fail "Pi-state root must be an absolute canonical non-root path"
|
||||
[[ "$owner" =~ ^[0-9]+$ && "$group" =~ ^[0-9]+$ ]] \
|
||||
|| fail "owner and group must be numeric"
|
||||
[[ ! -L "$pi_state_root" ]] || fail "Pi-state root must not be a symlink"
|
||||
|
||||
if [[ "$(id -u)" -ne 0 && ( "$owner" != "$(id -u)" || "$group" != "$(id -g)" ) ]]; then
|
||||
fail "non-root execution may prepare only its own UID/GID"
|
||||
fi
|
||||
|
||||
ensure_directory() {
|
||||
local path="$1" mode="$2"
|
||||
if [[ -e "$path" && ( ! -d "$path" || -L "$path" ) ]]; then
|
||||
fail "expected a real directory: $path"
|
||||
fi
|
||||
mkdir -p "$path"
|
||||
chmod "$mode" "$path"
|
||||
if [[ "$(id -u)" -eq 0 ]]; then
|
||||
chown "$owner:$group" "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_target() {
|
||||
local target="$1" temporary=""
|
||||
if [[ -e "$target" || -L "$target" ]]; then
|
||||
[[ -f "$target" && ! -L "$target" ]] || fail "expected a regular target file: $target"
|
||||
else
|
||||
temporary="$(mktemp "${target%/*}/.${target##*/}.XXXXXX")"
|
||||
trap '[[ -z "${temporary:-}" ]] || rm -f "$temporary"' RETURN
|
||||
chmod 0600 "$temporary"
|
||||
if [[ "$(id -u)" -eq 0 ]]; then
|
||||
chown "$owner:$group" "$temporary"
|
||||
fi
|
||||
if ! ln "$temporary" "$target" 2>/dev/null; then
|
||||
[[ -f "$target" && ! -L "$target" ]] \
|
||||
|| fail "could not atomically create target: $target"
|
||||
fi
|
||||
rm -f "$temporary"
|
||||
temporary=""
|
||||
trap - RETURN
|
||||
fi
|
||||
chmod 0600 "$target"
|
||||
if [[ "$(id -u)" -eq 0 ]]; then
|
||||
chown "$owner:$group" "$target"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_directory "$pi_state_root" 0750
|
||||
ensure_directory "$pi_state_root/agent" 0700
|
||||
for name in auth.json models.json settings.json; do
|
||||
ensure_target "$pi_state_root/agent/$name"
|
||||
done
|
||||
|
||||
printf 'Prepared server Pi-state targets under %s for %s:%s.\n' \
|
||||
"$pi_state_root" "$owner" "$group"
|
||||
Reference in New Issue
Block a user