35 lines
1.4 KiB
Bash
35 lines
1.4 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# PreToolUse guard: never write infra/deploy/secrets/*.yaml directly.
|
||
|
|
#
|
||
|
|
# Every file matching that glob is SOPS-encrypted, and secrets-guard.yml fails the
|
||
|
|
# build if one is not. This is the same rule enforced one step earlier: a direct
|
||
|
|
# Write or Edit produces plaintext, and by the time CI catches it the secret has
|
||
|
|
# already been written to disk and probably committed.
|
||
|
|
#
|
||
|
|
# The supported path is `sops edit <file>`, which decrypts to a temp file, opens an
|
||
|
|
# editor and re-encrypts on save — the plaintext never touches the working tree.
|
||
|
|
#
|
||
|
|
# Denies rather than asks: there is no legitimate reason to hand-write one of these,
|
||
|
|
# so a prompt would only be an invitation to click through.
|
||
|
|
set -uo pipefail
|
||
|
|
|
||
|
|
payload=$(cat)
|
||
|
|
command -v jq >/dev/null 2>&1 || exit 0
|
||
|
|
|
||
|
|
path=$(printf '%s' "$payload" | jq -r '.tool_input.file_path // ""')
|
||
|
|
[ -n "$path" ] || exit 0
|
||
|
|
|
||
|
|
case "$path" in
|
||
|
|
*/infra/deploy/secrets/*.yaml)
|
||
|
|
jq -n --arg p "$path" '{
|
||
|
|
hookSpecificOutput: {
|
||
|
|
hookEventName: "PreToolUse",
|
||
|
|
permissionDecision: "deny",
|
||
|
|
permissionDecisionReason: ("Refusing to write \($p) directly — every file under infra/deploy/secrets/ is SOPS-encrypted and a direct write would land plaintext. Use `sops edit \($p)` instead, which re-encrypts on save. (secrets-guard.yml would fail the build on this anyway, but only after the secret was already on disk.)")
|
||
|
|
}
|
||
|
|
}'
|
||
|
|
exit 0
|
||
|
|
;;
|
||
|
|
*) exit 0 ;;
|
||
|
|
esac
|