Files
computer-playbook/roles/user-backup/templates/ssh-wrapper.sh.j2
kevinveenbirkenbachandClaude Opus 5 508bc5adac test(lint): keep shell scripts out of jinja templates
A templated script is opaque to every tool that reads shell. shellcheck parses Jinja as syntax errors, the repository's own .sh guards skip the file because it is not a .sh, and nothing can execute it to test it: what runs on the host never exists in the repository, so a defect in the rendered half is found by deploying it.

The lint reports any *.sh.j2 under roles and points at the static slot sys-service already resolves, files/shell/script.sh, with the values passed as ExecStart arguments or Environment entries the way this repository's python scripts already take them.

None of the seven templates present meets the bar the marker is for, which is a script whose shape is generated rather than its values. Each is grandfathered with a marker naming what it interpolates, because converting a deployed script to argv changes what runs on the host. The guard exists to stop the next one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 20:36:04 +02:00

52 lines
1.7 KiB
Django/Jinja

#!/bin/sh
{# nocheck: shell-template grandfathered, values only: the backup directory and the repository list #}
# log command
if [ -n "$SSH_ORIGINAL_COMMAND" ]
then
echo "$(/bin/date): $SSH_ORIGINAL_COMMAND" | systemd-cat -t "ssh-wrapper.sh"
fi
get_hashed_machine_id="sha256sum /etc/machine-id";
hashed_machine_id="$($get_hashed_machine_id | head -c 64)"
get_backup_types="find {{ DIR_BACKUPS }}/$hashed_machine_id/ -maxdepth 1 -type d -execdir basename {} ;";
backup_types="{{ BACKUP_REPOSITORIES | join(' ') }}"
for backup_type in $backup_types; do
get_version_directories="ls -d {{ DIR_BACKUPS }}/$hashed_machine_id/$backup_type/*"
last_version_directory="$($get_version_directories 2>/dev/null | tail -1)"
case "$SSH_ORIGINAL_COMMAND" in
"$get_version_directories")
$get_version_directories
exit $?
;;
"sudo rsync --server --sender "*" . $last_version_directory/")
# Exception: rsync negotiates version-dependent server flags (3.4.x differs and adds --numeric-ids), so glob them instead of exact-matching a fixed string; allowlist-guard the chars so no shell metacharacter can be injected before running the client's path-constrained command.
if printf '%s' "$SSH_ORIGINAL_COMMAND" | grep -q '[^ A-Za-z0-9./_=+:-]'; then
echo "This command is not supported."
exit 1
fi
$SSH_ORIGINAL_COMMAND
exit $?
;;
esac
done
case "$SSH_ORIGINAL_COMMAND" in
"$get_hashed_machine_id")
$get_hashed_machine_id
;;
"$get_backup_types")
for backup_type in $backup_types; do
if [ -d "{{ DIR_BACKUPS }}/$hashed_machine_id/$backup_type" ]; then
echo "$backup_type"
fi
done
;;
*)
echo "This command is not supported."
exit 1
;;
esac