From f0987e855af48f974c5c7272574b9f10a59c7a64 Mon Sep 17 00:00:00 2001 From: alexveley Date: Wed, 24 Jun 2026 02:12:21 -0400 Subject: [PATCH] Update pve RustDesk GA sync scripts --- blair-sync-rustdesk-via-ga.sh | 97 +++++++++++------------------------ 1 file changed, 31 insertions(+), 66 deletions(-) diff --git a/blair-sync-rustdesk-via-ga.sh b/blair-sync-rustdesk-via-ga.sh index ddb4dc3..7302efb 100644 --- a/blair-sync-rustdesk-via-ga.sh +++ b/blair-sync-rustdesk-via-ga.sh @@ -1,6 +1,5 @@ #!/bin/bash -# Poll RustDesk IDs via QEMU guest agent; update Proxmox VM notes + registry.json. -# Canonical Blair fleet sync — no per-VM scheduled tasks or share reports required. +# Reads RustDesk peer ID via GA exec (rustdesk --get-id). Modern RustDesk stores enc_id in TOML, not plain id. # Install: /usr/local/sbin/blair-sync-rustdesk-via-ga.sh Cron: every 2 minutes. # Usage: blair-sync-rustdesk-via-ga.sh [--dry-run] BLAIR_VERBOSE=1 for detail. set -euo pipefail @@ -30,50 +29,9 @@ DRY_RUN = os.environ.get('BLAIR_DRY_RUN', '') in ('1', 'true', 'yes') VERBOSE = os.environ.get('BLAIR_VERBOSE', '') in ('1', 'true', 'yes') VMIDS_ENV = os.environ.get('BLAIR_VMIDS', '').strip() -# RustDesk2.toml (LocalService) is the source of truth on Windows seats. -GUEST_READ_PATHS = [ - r'C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\config\RustDesk2.toml', - r'C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\config\RustDesk.toml', - r'C:\Windows\System32\config\systemprofile\AppData\Roaming\RustDesk\config\RustDesk2.toml', - r'C:\ProgramData\RustDesk\config\RustDesk2.toml', - r'C:\ProgramData\Blair\rustdesk-report.json', -] - -PS_READ_ID = r''' -$ProgressPreference = 'SilentlyContinue' -$ErrorActionPreference = 'SilentlyContinue' -$paths = @( - 'C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\config\RustDesk2.toml', - 'C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk\config\RustDesk.toml', - 'C:\Windows\System32\config\systemprofile\AppData\Roaming\RustDesk\config\RustDesk2.toml', - 'C:\ProgramData\RustDesk\config\RustDesk2.toml', - 'C:\ProgramData\Blair\rustdesk-report.json' -) -foreach ($p in $paths) { - if (-not (Test-Path -LiteralPath $p)) { continue } - $t = Get-Content -Raw -LiteralPath $p - if ($p -like '*.json') { - try { - $j = $t | ConvertFrom-Json - if ($j.rustdesk_id -match '^\d{6,12}$') { Write-Output $j.rustdesk_id; exit 0 } - } catch {} - } - if ($t -match '(?m)^\s*id\s*=\s*[''"]?(\d{6,12})') { Write-Output $Matches[1]; exit 0 } -} -foreach ($rp in @( - 'HKLM:\SOFTWARE\RustDesk\Host', - 'HKLM:\SOFTWARE\RustDesk', - 'HKLM:\SOFTWARE\WOW6432Node\RustDesk\Host', - 'HKLM:\SOFTWARE\WOW6432Node\RustDesk' -)) { - if (-not (Test-Path $rp)) { continue } - foreach ($n in @('id', 'Id', 'rustdesk_id', 'peer_id')) { - $v = (Get-ItemProperty -Path $rp -Name $n -ErrorAction SilentlyContinue).$n - if ($v -match '^\d{6,12}$') { Write-Output $v; exit 0 } - } -} -exit 1 -''' +# RustDesk >=1.2 stores enc_id in TOML, not plain id. Primary: rustdesk.exe --get-id via GA exec. +RUSTDESK_EXE = r'C:\Program Files\RustDesk\rustdesk.exe' +GUEST_REPORT = r'C:\ProgramData\Blair\rustdesk-report.json' def log(msg: str, *, force: bool = False) -> None: @@ -263,30 +221,37 @@ def guest_file_read(vmid: int, guest_path: str) -> tuple[str | None, str | None] return None, f'file-read failed for {guest_path}' -def read_rustdesk_id(vmid: int) -> tuple[str | None, str | None]: - for path in GUEST_READ_PATHS: - try: - text, err = guest_file_read(vmid, path) - if not text: - log(f'VM {vmid}: file-read miss {path}: {err}') - continue - rid = parse_id_from_content(text, path) - if rid: - log(f'VM {vmid}: ID {rid} from {path}') - return rid, None - log(f'VM {vmid}: no id in {path}') - except Exception as exc: # noqa: BLE001 - log(f'VM {vmid}: {path}: {exc}') - - enc = base64.b64encode(PS_READ_ID.strip().encode('utf-16-le')).decode('ascii') +def read_rustdesk_id_cli(vmid: int) -> tuple[str | None, str | None]: rid, err = guest_exec_text( vmid, - ['powershell.exe', '-NoProfile', '-NonInteractive', '-EncodedCommand', enc], - timeout=120, + ['cmd.exe', '/c', f'"{RUSTDESK_EXE}" --get-id'], + timeout=45, ) - if rid: - log(f'VM {vmid}: ID {rid} from guest exec') + if rid and re.fullmatch(r'\d{6,12}', rid): return rid, None + return None, err or 'rustdesk --get-id returned no id' + + +def read_rustdesk_id_report(vmid: int) -> tuple[str | None, str | None]: + text, err = guest_file_read(vmid, GUEST_REPORT) + if not text: + return None, err + rid = parse_id_from_content(text, GUEST_REPORT) + return (rid, None) if rid else (None, 'no rustdesk_id in report json') + + +def read_rustdesk_id(vmid: int) -> tuple[str | None, str | None]: + rid, err = read_rustdesk_id_cli(vmid) + if rid: + log(f'VM {vmid}: ID {rid} from rustdesk --get-id') + return rid, None + log(f'VM {vmid}: cli miss: {err}') + + rid, err = read_rustdesk_id_report(vmid) + if rid: + log(f'VM {vmid}: ID {rid} from {GUEST_REPORT}') + return rid, None + return None, err or 'no RustDesk ID found'