Files
inter-hub/deploy/railiance/recovery-drill.sh

86 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SECRET_FILE="${SECRET_FILE:-deploy/railiance/secrets/inter-hub.env.sops.yaml}"
SOPS_BIN="${SOPS_BIN:-sops}"
timestamp_utc="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
timestamp_local="$(date +"%Y-%m-%dT%H:%M:%S%z")"
echo "inter-hub recovery drill"
echo "timestamp_utc=${timestamp_utc}"
echo "timestamp_local=${timestamp_local}"
echo "secret_file=${SECRET_FILE}"
echo "sops_age_key_file=${SOPS_AGE_KEY_FILE:-<default>}"
if ! command -v "$SOPS_BIN" >/dev/null 2>&1; then
echo "result=FAIL"
echo "reason=sops-not-found"
echo "hint=Install sops or run with SOPS_BIN=/path/to/sops."
exit 127
fi
if [[ ! -f "$SECRET_FILE" ]]; then
echo "result=FAIL"
echo "reason=secret-file-not-found"
exit 1
fi
if ! python3 -c 'import yaml' >/dev/null 2>&1; then
echo "result=FAIL"
echo "reason=python-yaml-not-found"
echo "hint=Install PyYAML for python3 before running the recovery drill."
exit 127
fi
echo "sops_version=$("$SOPS_BIN" --version 2>/dev/null | sed -n '1p')"
if ! "$SOPS_BIN" filestatus "$SECRET_FILE" \
| python3 -c 'import json, sys; data = json.load(sys.stdin); assert data.get("encrypted") is True'
then
echo "result=FAIL"
echo "reason=sops-file-is-not-encrypted"
exit 1
fi
decrypt_err="$(mktemp)"
trap 'rm -f "$decrypt_err"' EXIT
if ! decrypted_secret="$("$SOPS_BIN" --decrypt "$SECRET_FILE" 2>"$decrypt_err")"; then
echo "result=FAIL"
echo "reason=decrypt-failed"
sed -n '1,6p' "$decrypt_err" | sed 's/^/sops_error=/'
exit 1
fi
if ! python3 -c '
import sys
import yaml
data = yaml.safe_load(sys.stdin)
required = {"DATABASE_URL", "IHP_SESSION_SECRET", "IHP_BASEURL", "PORT", "IHP_ENV"}
assert data["apiVersion"] == "v1"
assert data["kind"] == "Secret"
assert data["metadata"]["name"] == "inter-hub-env"
assert data["metadata"]["namespace"] == "inter-hub"
assert data["type"] == "Opaque"
string_data = data["stringData"]
missing = sorted(required - set(string_data))
if missing:
raise SystemExit(f"missing required keys: {missing}")
for key in sorted(required):
if not str(string_data[key]):
raise SystemExit(f"empty required key: {key}")
print("checked_metadata=inter-hub/inter-hub-env")
print("checked_keys=" + ",".join(sorted(required)))
' <<< "$decrypted_secret"
then
echo "result=FAIL"
echo "reason=shape-check-failed"
exit 1
fi
unset decrypted_secret
echo "result=PASS"
echo "note=decrypted in memory only; secret values were not printed"