Repository navigation
Expand file tree
/
Copy pathpiclock-receive
More file actions
executable file
·54 lines (47 loc) · 2.04 KB
/
Copy pathpiclock-receive
File metadata and controls
executable file
·54 lines (47 loc) · 2.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/env bash
# Forced-command receiver for PiClock CI deploys.
#
# Pinned as the only thing the `piclock-deploy` account's key may run, via its
# authorized_keys:
#
# command="/usr/local/sbin/piclock-receive",restrict ssh-ed25519 AAAA... ci
#
# The CI job pipes a gzipped tar of the tagged source over stdin and requests
# `deploy <sha>`. We validate that, stage the payload, and hand off to the
# root-owned piclock-apply (the one command this account may sudo). This script
# runs as the unprivileged piclock-deploy user.
set -euo pipefail
STAGING="/var/lib/piclock-deploy/staging"
log() { logger -t piclock-receive -- "$*"; echo "piclock-receive: $*" >&2; }
# 1. Validate the requested command (defence in depth; the key is already pinned
# to this script, so SSH_ORIGINAL_COMMAND is the only attacker-influenced bit).
read -r verb sha extra <<<"${SSH_ORIGINAL_COMMAND:-}" || true
if [ -n "$extra" ] || [ "$verb" != "deploy" ] || ! [[ "$sha" =~ ^[0-9a-f]{7,40}$ ]]; then
log "rejecting request: '${SSH_ORIGINAL_COMMAND:-}'"
echo "expected: deploy <sha>" >&2
exit 64
fi
log "receiving deploy $sha"
# Hold staging stable through apply when two tags arrive together.
exec 9>/var/lib/piclock-deploy/receive.lock
flock -x 9
umask 022
# 2. Stream the tarball to a temp file so we can reject an empty/garbage payload
# before touching the staging tree.
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
cat >"$tmp"
test -s "$tmp" || { log "empty payload"; exit 65; }
mkdir -p "$STAGING"
find "$STAGING" -mindepth 1 -delete
tar -xzf "$tmp" -C "$STAGING" --no-same-owner --no-same-permissions
# The unprivileged clocker account performs the runtime copy.
chmod -R a+rX "$STAGING"
# 3. Sanity-check the payload looks like piclock before applying anything.
for required in main.py requirements.txt piclock/app.py; do
test -f "$STAGING/$required" || { log "payload missing $required"; exit 65; }
done
# 4. Hand off to the privileged, root-owned apply step (the only allowed sudo).
log "applying deploy $sha"
sudo /usr/local/sbin/piclock-apply
log "deploy $sha complete"