48 lines
1.6 KiB
Bash
48 lines
1.6 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# Meta credential store CLI (operator-only)
|
||
|
|
# Usage:
|
||
|
|
# meta-creds.sh add <type> <id> # interactive add (prompts for fields)
|
||
|
|
# meta-creds.sh get <type> <id> # output JSON to stdout (never log)
|
||
|
|
# meta-creds.sh list <type> # list IDs (no secrets)
|
||
|
|
# Types: muse, instagram, facebook
|
||
|
|
STORE_DIR="/etc/netvm/meta-credentials"
|
||
|
|
STORE="$STORE_DIR/store.age"
|
||
|
|
KEY="$STORE_DIR/.age-key"
|
||
|
|
if [ ! -f "$STORE" ] || [ ! -f "$KEY" ]; then
|
||
|
|
echo "error: store not initialized" >&2; exit 1
|
||
|
|
fi
|
||
|
|
decrypt() { sudo age -d -i "$KEY" "$STORE" 2>/dev/null; }
|
||
|
|
encrypt() {
|
||
|
|
PUBKEY=$(sudo grep "public key" "$KEY" | awk '{print $4}')
|
||
|
|
sudo age -r "$PUBKEY" -o "$STORE.tmp" 2>/dev/null && sudo mv "$STORE.tmp" "$STORE" && sudo chmod 600 "$STORE"
|
||
|
|
}
|
||
|
|
case "$1" in
|
||
|
|
list)
|
||
|
|
decrypt | jq -r ".$2 | keys[]" 2>/dev/null || echo "(empty)"
|
||
|
|
;;
|
||
|
|
get)
|
||
|
|
decrypt | jq ".$2[\"$3\"]" 2>/dev/null
|
||
|
|
;;
|
||
|
|
add)
|
||
|
|
TYPE="$2"; ID="$3"
|
||
|
|
echo "Adding $TYPE/$ID (fields as JSON, empty to skip):"
|
||
|
|
TMP=$(mktemp)
|
||
|
|
decrypt > "$TMP" 2>/dev/null
|
||
|
|
# Build entry via prompts
|
||
|
|
ENTRY=$(jq -n '{}')
|
||
|
|
for field in email phone username password notes age_verified instagram_linked verified_by; do
|
||
|
|
read -p "$field: " val
|
||
|
|
if [ -n "$val" ]; then
|
||
|
|
ENTRY=$(echo "$ENTRY" | jq --arg v "$val" ".$field=\$v")
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
ENTRY=$(echo "$ENTRY" | jq ".verified_at=\"$(date -u +%FT%TZ)\"")
|
||
|
|
jq --arg t "$TYPE" --arg id "$ID" --argjson e "$ENTRY" '.[$t][$id]=$e' "$TMP" | encrypt
|
||
|
|
rm -f "$TMP"
|
||
|
|
echo "added $TYPE/$ID"
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
echo "usage: meta-creds.sh {list|get|add} <type> [id]"
|
||
|
|
;;
|
||
|
|
esac
|