enroll: preserve every vault field in the recreate fallback

The fallback hardcoded username/password/uri/totp_seed and silently
destroyed live API-key fields on any enroll (bit vpentops 2026-09-09).
Rebuilds the full field set from the item JSON now.

https://projects.knownelement.com/issues/942#note-5514
This commit is contained in:
2026-09-09 22:00:33 -05:00
parent f7d54a30ae
commit 866b963773
@@ -25,15 +25,30 @@ printf '%s' "$ENABLED" | grep -q '|200$' || { echo "FAIL: totp_enable said: $(pr
SM() { if [ "$(id -un)" = "TSGCOO" ]; then /data2/TSGCOO/.local/bin/sm "$@" </dev/null; else sudo -u TSGCOO /data2/TSGCOO/.local/bin/sm "$@" </dev/null; fi; }
# store seed; smcli setfield 400s ("Data missing") on some ciphers, so verify
# the write and fall back to a full item recreate with the seed included
# the write and fall back to a full item recreate with the seed included.
# The recreate MUST carry EVERY existing field (username/password/uri whether
# stored as login or as type-1 fields, plus any app-key fields) — dropping
# fields here silently destroyed live API keys once (2026-09-09).
STORED=0
if SM setfield "$ITEM" totp_seed "$SECRET" >/dev/null 2>&1; then
STORED=1
else
VU=$(SM get "$ITEM" --field username); VP=$(SM get "$ITEM" --field password); VR=$(SM get "$ITEM" --field uri 2>/dev/null || true)
[ -n "$VR" ] || VR="$BASE"
JSON=$(SM get "$ITEM" 2>/dev/null)
ARGS=()
# rebuild every custom field, skipping an existing totp_seed
while IFS=$'\t' read -r fname fval; do
[ -n "$fname" ] || continue
[ "$fname" = "totp_seed" ] && continue
case "$fval" in *[[:space:]]*) continue ;; esac # multiline values can't ride argv; surface below
ARGS+=("$fname=$fval")
done < <(printf '%s' "$JSON" | jq -r '.fields[]? | "\(.name)\t\(.value)"' 2>/dev/null)
LU=$(printf '%s' "$JSON" | jq -r '.login.username // empty' 2>/dev/null)
LP=$(printf '%s' "$JSON" | jq -r '.login.password // empty' 2>/dev/null)
[ -n "$LU" ] && ARGS+=("username=$LU")
[ -n "$LP" ] && ARGS+=("password=$LP")
ARGS+=("totp_seed=$SECRET")
SM rm "$ITEM" >/dev/null 2>&1
SM set "$ITEM" "username=$VU" "password=$VP" "uri=$VR" "totp_seed=$SECRET" >/dev/null 2>&1 && STORED=1
SM set "$ITEM" "${ARGS[@]}" >/dev/null 2>&1 && STORED=1
fi
[ "$STORED" = 1 ] || { echo "FAIL: could not store seed in vault ($ITEM)" >&2; exit 5; }
[ "$(SM get "$ITEM" --field totp_seed)" = "$SECRET" ] || { echo "FAIL: seed readback mismatch ($ITEM)" >&2; exit 5; }