1
0
Fork 0
nixfiles/pkgs/clerie-sops/clerie-sops-edit.sh

94 lines
1.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Edit a single attribute of a sops json file
# Helps working with multiline strings in json
set -euo pipefail
print_help() {
cat << EOF
clerie-sops-edit <secrets_file> <action> <key>
This script allows editing single secrets in a secrets file by key.
<secrets_file> is a sops secrets file
<action> is one of "edit", "read", "set" and "append"
<key> is the key of the secret in the secrets file to modify
EOF
}
if [[ $# != 3 ]]; then
print_help
exit 1
fi
SECRETS_FILE="$1"
if [[ ! -f "${SECRETS_FILE}" ]]; then
echo "File \"${SECRETS_FILE}\" does not exist"
echo
print_help
exit 1
fi
ACTION="$2"
if ! echo "edit read set append" | grep -wq "${ACTION}"; then
echo "Action \"${ACTION}\" not supported"
echo
print_help
exit 1
fi
KEY="$3"
KEY_SELECTOR="$(jq -Rsc '[.]' <(echo -n "${KEY}"))"
if [[ -n $EDITOR ]]; then
EDITOR=vim
fi
TMP_FILE="$(mktemp)"
DECRYPT_ERROR_FILE="$(mktemp)"
if ! clerie-sops --decrypt --extract "${KEY_SELECTOR}" "${SECRETS_FILE}" > "${TMP_FILE}" 2> "${DECRYPT_ERROR_FILE}"; then
# Ignore that the key does not exist, but fail for all other errors
if ! grep -q "component .* not found" "${DECRYPT_ERROR_FILE}"; then
cat "${DECRYPT_ERROR_FILE}"
exit 1
fi
fi
TMP_FILE_HASH_BEFORE="$(sha256sum "${TMP_FILE}")"
case "${ACTION}" in
edit)
"${EDITOR}" "${TMP_FILE}"
;;
read)
cat "${TMP_FILE}"
;;
set)
cat > "${TMP_FILE}"
;;
append)
cat >> "${TMP_FILE}"
;;
*)
echo "Unsupported action"
exit 1
;;
esac
TMP_FILE_HASH_AFTER="$(sha256sum "${TMP_FILE}")"
# Don't write value back when it hasn't changed
if [[ "${TMP_FILE_HASH_BEFORE}" == "${TMP_FILE_HASH_AFTER}" ]]; then
exit 0
fi
JSON_QUOTED_SECRET="$(jq -Rsc '.' "${TMP_FILE}")"
rm "${TMP_FILE}"
clerie-sops --set "${KEY_SELECTOR} ${JSON_QUOTED_SECRET}" "${SECRETS_FILE}"