fix: validate commands, improve remove container logic, standardize logs in gitops router

This commit is contained in:
Pallav Vasa 2025-05-17 11:37:06 +00:00
parent 6e11d19510
commit 9629c3253e

View File

@ -64,10 +64,10 @@ update() {
[[ -f "$out" ]] && chmod 700 "$out" [[ -f "$out" ]] && chmod 700 "$out"
if curl -fsSL "$url" -o "$out"; then if curl -fsSL "$url" -o "$out"; then
log info "Downloaded $url$out" log INFO "Downloaded $url$out"
chmod "$mode" "$out" chmod "$mode" "$out"
else else
log error "Failed to download $url" log ERROR "Failed to download $url"
return 1 return 1
fi fi
} }
@ -78,36 +78,145 @@ clean_images() {
local dangling local dangling
dangling="$(podman images -f dangling=true -q)" dangling="$(podman images -f dangling=true -q)"
if [[ -z "$dangling" ]]; then if [[ -z "$dangling" ]]; then
log info "No dangling images to remove." log INFO "No dangling images to remove."
else else
log warn "Removing dangling images..." log WARN "Removing dangling images..."
echo "$dangling" | xargs podman rmi echo "$dangling" | xargs podman rmi
log info "Dangling images removed." log INFO "Dangling images removed."
fi
}
# ─────────────────────────────────────────────
# Remove host podman containers
remove_containers() {
local tokens=("$@")
local flags=() patterns=() containers=()
local valid='^[A-Za-z0-9._-]+$'
# allow unmatched globs to disappear
shopt -s nullglob
# separate flags (-f, etc.) from name patterns
for tok in "${tokens[@]}"; do
if [[ "$tok" == -* ]]; then
flags+=("$tok")
else
patterns+=("$tok")
fi
done
# validate & expand each pattern
for pat in "${patterns[@]}"; do
if [[ ! "$pat" =~ $valid ]]; then
log ERROR "Invalid container name: '$pat'"
shopt -u nullglob
return 1
fi
containers+=("$pat")
done
shopt -u nullglob
if ((${#containers[@]} == 0)); then
log WARN "No containers matched: ${patterns[*]}"
return 0
fi
# pass flags *then* containers to podman rm
podman rm "${flags[@]}" "${containers[@]}"
}
# ─────────────────────────────────────────────
# validate_command <cmd> [<tok1> <tok2> …]
validate_command() {
local cmd="$1"
shift
local tokens=("$@")
local yaml="$HOME/access.yml"
# 1) Is command allowed at all?
if [[ "$(yq e ".\"$PERSON\".commands | has(\"$cmd\")" "$yaml")" != "true" ]]; then
log ERROR "Unauthorized command: '$cmd'"
exit 1
fi
# 2) Load allowed args for this cmd (may be empty array)
mapfile -t allowed < <(yq e ".\"$PERSON\".commands.${cmd}[]" "$yaml")
if [[ "${#allowed[@]}" -eq 0 ]]; then
log ERROR "No allowed arguments for command '$cmd' in $yaml"
exit 1
fi
# 3) Extract just the non-flag tokens
local args=()
for tok in "${tokens[@]}"; do
[[ "$tok" == -* ]] && continue
args+=("$tok")
done
if [[ "$cmd" == "remove" ]]; then
# ─ remove: must have at least one arg
if ((${#args[@]} == 0)); then
log ERROR "Command '$cmd' requires at least one argument: ${allowed[*]}"
exit 1
fi
# Validate each against allowed[]
for a in "${args[@]}"; do
local ok=false
for want in "${allowed[@]}"; do
[[ "$a" == "$want" ]] && ok=true && break
done
if ! $ok; then
log ERROR "Invalid argument '$a' for '$cmd'; allowed: ${allowed[*]}"
exit 1
fi
done
else
# ─ all other cmds: must have exactly one arg
if ((${#args[@]} != 1)); then
log ERROR "Command '$cmd' requires exactly one argument: ${allowed[*]}"
exit 1
fi
# And that single arg must be allowed
local a="${args[0]}"
local ok=false
for want in "${allowed[@]}"; do
[[ "$a" == "$want" ]] && ok=true && break
done
if ! $ok; then
log ERROR "Invalid argument '$a' for '$cmd'; allowed: ${allowed[*]}"
exit 1
fi
fi fi
} }
# ───────────────────────────────────────────── # ─────────────────────────────────────────────
# Entry & command parsing # Entry & command parsing
if [[ -z "${SSH_ORIGINAL_COMMAND:-}" ]]; then if [[ -z "${SSH_ORIGINAL_COMMAND:-}" ]]; then
log error "No SSH_ORIGINAL_COMMAND provided." log ERROR "No SSH_ORIGINAL_COMMAND provided."
exit 1 exit 1
fi fi
log info "SSH_ORIGINAL_COMMAND: $SSH_ORIGINAL_COMMAND" log INFO "SSH_ORIGINAL_COMMAND: $SSH_ORIGINAL_COMMAND"
read -r cmd arg <<<"$SSH_ORIGINAL_COMMAND" read -ra parts <<<"$SSH_ORIGINAL_COMMAND"
cmd="${parts[0]}"
args=("${parts[@]:1}")
validate_command "$cmd" "${args[@]}"
# ───────────────────────────────────────────── # ─────────────────────────────────────────────
# Dispatch # Dispatch
case "$cmd" in case "$cmd" in
build) build)
case "$arg" in case "${args[0]}" in
base) run build-base.sh ;; base) run build-base.sh ;;
workspace) run build-workspace.sh ;; workspace) run build-workspace.sh ;;
*) log error "build: invalid arg '$arg'" ;; *) log ERROR "build: invalid arg '${args[0]}'" ;;
esac esac
;; ;;
update) update)
case "$arg" in case "${args[0]}" in
base) update build-base.sh .local/bin 500 ;; base) update build-base.sh .local/bin 500 ;;
workspace) update build-workspace.sh .local/bin 500 ;; workspace) update build-workspace.sh .local/bin 500 ;;
access) update access.yml . 400 ;; access) update access.yml . 400 ;;
@ -115,14 +224,14 @@ update)
gitops_router) update gitops_router.sh .local/bin 500 ;; gitops_router) update gitops_router.sh .local/bin 500 ;;
home_tar) update home.tar.gz . 500 media ;; home_tar) update home.tar.gz . 500 media ;;
gitconfig) update gitconfig.template . 500 ;; gitconfig) update gitconfig.template . 500 ;;
*) log error "update: invalid arg '$arg'" ;; *) log ERROR "update: invalid arg '${args[0]}'" ;;
esac esac
;; ;;
clean) clean_images ;; clean) clean_images ;;
status) podman images ;; status) podman images ;;
remove) podman rm "$arg" ;; remove) remove_containers "${args[@]}" ;;
*) *)
log error "Unknown command: '$cmd'" log ERROR "Unknown command: '$cmd'"
exit 127 exit 127
;; ;;
esac esac