#!/bin/bash # Enroll TOTP for an identity (2FA must NOT be enforced yet — run # cloudron-oidc-login.sh first, or admin totp_disable for seed-lost users). # usage: cloudron-totp-enroll.sh [vault-item] # Captures the seed into the vault item and verifies end-to-end. set -euo pipefail U="${1:?usage: cloudron-totp-enroll.sh [vault-item]}" ITEM="${2:-$U Cloudron}" BASE="https://my.knownelement.com" BEARER_FILE="/tmp/.oidc-bearer-$U" [ -f "$BEARER_FILE" ] || { echo "FAIL: run cloudron-oidc-login.sh $U first" >&2; exit 1; } ACCESS=$(cat "$BEARER_FILE") MYUID=$(curl -sk "$BASE/api/v1/profile" -H "Authorization: Bearer $ACCESS" | sed -n 's/.*"id":"\(uid-[^"]*\)".*/\1/p') [ -n "$MYUID" ] || { echo "FAIL: bearer rejected" >&2; exit 2; } SECRET=$(curl -sk "$BASE/api/v1/users/$MYUID/totp_setup" -H "Authorization: Bearer $ACCESS" | sed -n 's/.*"secret":"\([^"]*\)".*/\1/p') if [ -z "$SECRET" ]; then SECRET=$(curl -sk -X POST "$BASE/api/v1/users/$MYUID/totp_setup" -H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' -d '{}' | sed -n 's/.*"secret":"\([^"]*\)".*/\1/p') fi [ -n "$SECRET" ] || { echo "FAIL: no totp secret returned" >&2; exit 3; } CODE=$(bash "$(dirname "$0")/totp.sh" "$SECRET") ENAB=$(curl -sk -X POST "$BASE/api/v1/users/$MYUID/totp_setup" -H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' -d "{\"totpSecret\":\"$SECRET\",\"totpToken\":\"$CODE\"}") case "$ENAB" in *Invalid*|*404*|*"No such route"*) echo "PARTIAL: enable said: $(printf '%s' "$ENAB" | head -c 100)";; esac SM() { if [ "$(id -un)" = "TSGCOO" ]; then /data2/TSGCOO/.local/bin/sm "$@" /dev/null # end-to-end verify: fresh login with the stored seed bash "$(dirname "$0")/cloudron-oidc-login.sh" "$U" "$ITEM" >/dev/null 2>&1 if [ -s "$BEARER_FILE" ]; then WHO=$(curl -sk "$BASE/api/v1/profile" -H "Authorization: Bearer $(cat "$BEARER_FILE")" | sed -n 's/.*"username":"\([^"]*\)".*/\1/p') [ "$WHO" = "$U" ] && echo "OK: $U 2FA enrolled, seed in vault ($ITEM), TOTP login verified as $WHO" \ && exit 0 fi echo "PARTIAL: verify failed — check state for $U"