Skip to content

Instantly share code, notes, and snippets.

@timstew
Created March 16, 2026 19:04
Show Gist options
  • Select an option

  • Save timstew/dc255b57ebcb911c6d04a629df82dec6 to your computer and use it in GitHub Desktop.

Select an option

Save timstew/dc255b57ebcb911c6d04a629df82dec6 to your computer and use it in GitHub Desktop.
OpenClaw Mac Mini — Revoke Admin Access (security handoff)
#!/bin/bash
# ============================================================================
# OpenClaw Mac Mini — Revoke Admin Access
# ============================================================================
# This script automates the security handoff (Path A: Full Handoff).
# Run this on the Mac Mini when you're ready to hand full control to the client.
#
# What it does:
# 1. Generates new random passwords for Mac accounts
# 2. Removes all SSH authorized_keys entries
# 3. Re-enables password authentication for SSH
# 4. Rotates the OpenClaw gateway token
# 5. Writes new credentials to a file
# 6. Reminds you to change Tailscale and Gmail passwords manually
#
# IMPORTANT: This will lock you out of the Mac. Make sure the client
# can access the system before running this. There is no undo.
#
# Run as: sudo ./revoke-admin-access.command
# Or from the admin's machine: ssh admin@<ip> 'sudo bash -s' < revoke-admin-access.command
# ============================================================================
# No set -euo pipefail — handle errors per-step for safety
ERRORS=()
CREDENTIALS_FILE="/Users/openclaw/Desktop/client-credentials.txt"
# --- Helpers ----------------------------------------------------------------
log() {
echo "[OK] $1"
}
warn() {
echo "[!!] $1"
}
fail() {
echo "[ERR] $1"
ERRORS+=("$1")
}
generate_password() {
# Generate a 20-character base64 password (URL-safe, no ambiguous chars)
openssl rand -base64 15 | tr -d '/+=' | head -c 20
echo ""
}
# --- Pre-flight checks ------------------------------------------------------
echo ""
echo "=============================================="
echo " OpenClaw — Revoke Admin Access"
echo "=============================================="
echo ""
if [[ "$(uname)" != "Darwin" ]]; then
echo "This script only runs on macOS."
exit 1
fi
if [[ $EUID -ne 0 ]]; then
echo "This script requires root. Re-running with sudo..."
exec sudo "$0" "$@"
fi
CURRENT_USER="${SUDO_USER:-$(logname 2>/dev/null || echo $USER)}"
echo "WARNING: This script will:"
echo " - Change all Mac account passwords"
echo " - Remove all SSH keys"
echo " - Rotate the OpenClaw gateway token"
echo " - Lock you (the admin) out of this Mac"
echo ""
echo "There is NO UNDO. The new credentials will be written to:"
echo " $CREDENTIALS_FILE"
echo ""
read -p "Type YES to continue: " CONFIRM
if [[ "$CONFIRM" != "YES" ]]; then
echo "Aborted."
exit 0
fi
echo ""
# --- Detect accounts --------------------------------------------------------
# Find the admin user (the one who ran this script or the first admin)
ADMIN_USER="$CURRENT_USER"
OPENCLAW_USER="openclaw"
# Verify the openclaw user exists
if ! id "$OPENCLAW_USER" &>/dev/null; then
fail "User '$OPENCLAW_USER' does not exist. Cannot continue."
echo "Errors: ${ERRORS[*]}"
exit 1
fi
echo "Admin account: $ADMIN_USER"
echo "OpenClaw account: $OPENCLAW_USER"
echo ""
# --- Step 1: Generate new passwords ----------------------------------------
echo "--- Step 1: Generating new passwords ---"
NEW_ADMIN_PW=$(generate_password)
NEW_OPENCLAW_PW=$(generate_password)
if [[ -z "$NEW_ADMIN_PW" ]] || [[ -z "$NEW_OPENCLAW_PW" ]]; then
fail "Password generation failed"
exit 1
fi
# Change admin password
if sysadminctl -resetPasswordFor "$ADMIN_USER" -newPassword "$NEW_ADMIN_PW" 2>/dev/null; then
log "Admin account password changed"
else
fail "Could not change admin password"
fi
# Change openclaw password
if sysadminctl -resetPasswordFor "$OPENCLAW_USER" -newPassword "$NEW_OPENCLAW_PW" 2>/dev/null; then
log "OpenClaw account password changed"
else
fail "Could not change openclaw password"
fi
echo ""
# --- Step 2: Remove SSH authorized_keys ------------------------------------
echo "--- Step 2: Removing SSH authorized keys ---"
for USER_HOME in "/Users/$ADMIN_USER" "/Users/$OPENCLAW_USER"; do
AUTH_KEYS="$USER_HOME/.ssh/authorized_keys"
if [[ -f "$AUTH_KEYS" ]]; then
> "$AUTH_KEYS"
chmod 600 "$AUTH_KEYS"
log "Cleared $AUTH_KEYS"
else
log "No authorized_keys at $AUTH_KEYS (already clean)"
fi
done
echo ""
# --- Step 3: Re-enable password SSH auth -----------------------------------
echo "--- Step 3: Re-enabling password SSH authentication ---"
SSHD_CONFIG="/etc/ssh/sshd_config"
if [[ -f "$SSHD_CONFIG" ]]; then
# Re-enable password authentication
sed -i '' 's/^PasswordAuthentication no/PasswordAuthentication yes/' "$SSHD_CONFIG" 2>/dev/null
sed -i '' 's/^KbdInteractiveAuthentication no/KbdInteractiveAuthentication yes/' "$SSHD_CONFIG" 2>/dev/null
log "Password authentication re-enabled in sshd_config"
# Restart SSH
launchctl stop com.openssh.sshd 2>/dev/null
launchctl start com.openssh.sshd 2>/dev/null
log "SSH service restarted"
else
warn "sshd_config not found at expected path"
fi
echo ""
# --- Step 4: Rotate OpenClaw gateway token ---------------------------------
echo "--- Step 4: Rotating OpenClaw gateway token ---"
NEW_TOKEN=""
# Try to rotate the token as the openclaw user
if command -v openclaw &>/dev/null || [[ -x /opt/homebrew/bin/openclaw ]] || [[ -x /usr/local/bin/openclaw ]]; then
OPENCLAW_BIN=$(which openclaw 2>/dev/null || echo "/opt/homebrew/bin/openclaw")
if [[ ! -x "$OPENCLAW_BIN" ]]; then
OPENCLAW_BIN="/usr/local/bin/openclaw"
fi
if [[ -x "$OPENCLAW_BIN" ]]; then
TOKEN_OUTPUT=$(sudo -u "$OPENCLAW_USER" "$OPENCLAW_BIN" dashboard --regenerate-token --no-open 2>&1) || true
# Try to extract the token from the output
NEW_TOKEN=$(echo "$TOKEN_OUTPUT" | grep -oE 'token=[a-zA-Z0-9_-]+' | head -1 | sed 's/token=//')
if [[ -n "$NEW_TOKEN" ]]; then
log "OpenClaw gateway token rotated"
else
warn "Could not parse new token from output. You may need to rotate it manually."
warn "Output was: $TOKEN_OUTPUT"
fi
else
warn "OpenClaw binary not found — rotate the token manually"
fi
else
warn "OpenClaw not found in PATH — rotate the token manually"
fi
echo ""
# --- Step 5: Write credentials file ----------------------------------------
echo "--- Step 5: Writing credentials file ---"
# Ensure the Desktop directory exists
mkdir -p "/Users/$OPENCLAW_USER/Desktop" 2>/dev/null
{
echo "=============================================="
echo " CLIENT CREDENTIALS"
echo " Generated: $(date)"
echo "=============================================="
echo ""
echo "MAC ADMIN ACCOUNT"
echo " Username: $ADMIN_USER"
echo " Password: $NEW_ADMIN_PW"
echo ""
echo "OPENCLAW ACCOUNT"
echo " Username: $OPENCLAW_USER"
echo " Password: $NEW_OPENCLAW_PW"
echo ""
if [[ -n "$NEW_TOKEN" ]]; then
echo "OPENCLAW DASHBOARD TOKEN"
echo " Token: $NEW_TOKEN"
echo ""
else
echo "OPENCLAW DASHBOARD TOKEN"
echo " (Could not rotate automatically — rotate manually)"
echo ""
fi
echo "IMPORTANT: Change these additional passwords manually:"
echo " - Tailscale account password: https://login.tailscale.com/admin/settings"
echo " - Gmail account password: https://myaccount.google.com/security"
echo " - Remove the admin's device from Tailscale"
echo " - Add the client's device to Tailscale"
echo ""
echo "Send these credentials to the client securely (not plain email)."
echo "=============================================="
} > "$CREDENTIALS_FILE" 2>/dev/null
if [[ -f "$CREDENTIALS_FILE" ]]; then
# Set ownership to openclaw user
chown "$OPENCLAW_USER:staff" "$CREDENTIALS_FILE" 2>/dev/null
chmod 600 "$CREDENTIALS_FILE"
log "Credentials written to: $CREDENTIALS_FILE"
else
fail "Could not write credentials file"
echo ""
echo "--- CREDENTIALS (copy these manually) ---"
echo "Admin: $ADMIN_USER / $NEW_ADMIN_PW"
echo "OpenClaw: $OPENCLAW_USER / $NEW_OPENCLAW_PW"
if [[ -n "$NEW_TOKEN" ]]; then
echo "Token: $NEW_TOKEN"
fi
fi
echo ""
# --- Step 6: Verification --------------------------------------------------
echo "--- Step 6: Verification ---"
# Verify keys are removed
for USER_HOME in "/Users/$ADMIN_USER" "/Users/$OPENCLAW_USER"; do
AUTH_KEYS="$USER_HOME/.ssh/authorized_keys"
if [[ -f "$AUTH_KEYS" ]]; then
KEY_COUNT=$(grep -c "ssh-" "$AUTH_KEYS" 2>/dev/null || echo "0")
if [[ "$KEY_COUNT" -eq 0 ]]; then
echo " [PASS] No SSH keys in $AUTH_KEYS"
else
echo " [FAIL] $KEY_COUNT SSH key(s) still in $AUTH_KEYS"
fi
else
echo " [PASS] No authorized_keys file at $AUTH_KEYS"
fi
done
# Verify password auth is enabled
if grep -q "^PasswordAuthentication yes" /etc/ssh/sshd_config 2>/dev/null; then
echo " [PASS] Password SSH authentication is enabled"
elif grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config 2>/dev/null; then
echo " [FAIL] Password SSH authentication is still disabled"
else
echo " [PASS] Password SSH authentication is at default (enabled)"
fi
echo ""
# --- Summary ----------------------------------------------------------------
echo "=============================================="
echo " Revocation Complete"
echo "=============================================="
echo ""
if [[ ${#ERRORS[@]} -gt 0 ]]; then
echo " Completed with ${#ERRORS[@]} error(s):"
for item in "${ERRORS[@]}"; do
echo " [ERR] $item"
done
echo ""
fi
echo " Credentials saved to: $CREDENTIALS_FILE"
echo ""
echo " MANUAL STEPS REMAINING:"
echo " 1. Change the Tailscale account password"
echo " https://login.tailscale.com/admin/settings"
echo ""
echo " 2. Remove your device from the Tailscale network"
echo " https://login.tailscale.com/admin/machines"
echo ""
echo " 3. Change the Gmail account password"
echo " https://myaccount.google.com/security"
echo ""
echo " 4. Add the client's device to Tailscale"
echo ""
echo " 5. Send the credentials file to the client securely"
echo ""
echo " 6. Verify you can NO LONGER access this Mac:"
echo " ssh $OPENCLAW_USER@<tailscale-ip>"
echo " (this should fail after removing your Tailscale device)"
echo ""
echo "=============================================="
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment