# ============================================================= # cynfo Toolbox - Bootstrap (24h-Token) # # Aufruf vom Client: # irm 'https://toolbox.cynfo.com/cynfotoolbox' | iex # # Der Bootstrap fragt einmal nach dem 24h-Token, den der Techniker # unter http://10.172.100.131/token aus dem internen Netz abruft. # Der Token bleibt fuer die laufende PowerShell-Session aktiv # ($global:ToolboxToken), ein Wiederaufruf von irm prompted nicht # erneut. # # EDR-Workaround: Wenn der .NET-HTTP-Stack durch Defender Network # Protection / CrowdStrike / SentinelOne blockiert ist, statt diesem # Pfad toolbox.cmd benutzen (Variante 1 auf /install) - der Wrapper # laedt diese Datei via curl.exe und fragt dort nach dem Token. # ============================================================= $ErrorActionPreference = 'Stop' # TLS 1.2 erzwingen [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 $ToolboxUrl = 'https://toolbox.cynfo.com/cynfotoolbox.ps1' $TokenStatusUrl = 'https://toolbox.cynfo.com/api/token/status' $TokenUrl = 'http://10.172.100.131/token' $LocalPath = Join-Path $env:TEMP 'cynfotoolbox.ps1' $AuthBridge = Join-Path $env:TEMP 'toolbox_basic.txt' $TokenUser = 'toolbox' function _AskToken { Write-Host '' Write-Host 'Der Toolbox-Server erfordert einen 24h-Token.' -ForegroundColor Yellow Write-Host ('Token aus dem internen Netz abrufen: {0}' -f $TokenUrl) -ForegroundColor Gray Write-Host '' $t = Read-Host -Prompt '24h-Token' if ($null -eq $t) { return $null } return $t.Trim() } function _GetTokenState { # Fragt /api/token/status (public, kein Auth). Liefert 'active' / 'disabled' / # 'expired' / 'none' bei Erfolg, '' bei Netzwerkfehler (dann faellt der # Aufrufer auf das alte Verhalten zurueck und prompted trotzdem). try { $curl = Get-Command curl.exe -ErrorAction SilentlyContinue $body = $null if ($curl) { $body = & $curl.Source -ksSf --max-time 5 $TokenStatusUrl 2>$null if ($LASTEXITCODE -ne 0) { $body = $null } } if (-not $body) { $body = (Invoke-WebRequest -Uri $TokenStatusUrl -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop).Content } if (-not $body) { return '' } $data = $body | ConvertFrom-Json if ($data.state) { return [string]$data.state } } catch { } return '' } function _AuthString($token) { if (-not $token) { return $null } return "$($TokenUser):$token" } function _Fetch($Url, $OutFile, $Auth) { # curl.exe bevorzugt (umgeht .NET-HTTP-Hooks), Fallback Invoke-WebRequest. $curl = Get-Command curl.exe -ErrorAction SilentlyContinue if ($curl) { $a = @('-ksS','-o',$OutFile,'-w','%{http_code}') if ($Auth) { $a += @('-u',$Auth) } $a += $Url $code = & $curl.Source @a 2>$null $exit = $LASTEXITCODE $status = 0 if ("$code".Trim() -match '\d{3}$') { $status = [int]$Matches[0] } if ($exit -eq 0 -and $status -eq 200 -and (Test-Path $OutFile) -and (Get-Item $OutFile).Length -gt 0) { return @{ Ok = $true; Status = 200 } } if ($status -eq 401) { return @{ Ok = $false; Status = 401 } } # andere Fehler -> IWR-Fallback } try { $headers = @{} if ($Auth) { $headers['Authorization'] = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($Auth)) } Invoke-WebRequest -Uri $Url -UseBasicParsing -Headers $headers -OutFile $OutFile -MaximumRedirection 10 -ErrorAction Stop return @{ Ok = $true; Status = 200 } } catch { $st = 0 if ($_.Exception.Response) { $st = [int]$_.Exception.Response.StatusCode } return @{ Ok = $false; Status = $st } } } Write-Host 'Lade cynfo Toolbox...' -ForegroundColor Cyan # Vor dem Prompt: Status pruefen. Wenn der Admin den Token-Zugang deaktiviert # hat, laeuft die Toolbox im offenen Modus - kein Prompt, kein Auth-Header, # Download direkt unauthentifiziert. Reaktivierung erfolgt durch den Admin # (Tab Kunden -> Panel Zugangs-Token -> "Token reaktivieren"). $state = _GetTokenState $token = $null $auth = $null if ($state -eq 'disabled') { Write-Host 'Token-Auth ist deaktiviert - Toolbox laeuft im offenen Modus.' -ForegroundColor Cyan } else { # Token aus vorherigem Aufruf wiederverwenden, falls vorhanden. # Damit prompted ein zweites `irm | iex` in derselben PS-Session nicht erneut. $g = Get-Variable -Name ToolboxToken -Scope Global -ErrorAction SilentlyContinue if ($g -and $g.Value) { $token = [string]$g.Value } if (-not $token) { $token = _AskToken } if (-not $token) { Write-Warning 'Kein Token eingegeben - Abbruch.' return } $auth = _AuthString $token } $r = _Fetch $ToolboxUrl $LocalPath $auth # Bei 401 (Token-Modus + falscher Token) genau einmal erneut fragen. if (-not $r.Ok -and $r.Status -eq 401) { Write-Warning 'Token wurde vom Server abgelehnt - bitte erneut eingeben.' $token = _AskToken if ($token) { $auth = _AuthString $token $r = _Fetch $ToolboxUrl $LocalPath $auth } } if (-not $r.Ok) { Write-Warning ("Toolbox konnte nicht geladen werden (HTTP {0}) von {1}" -f $r.Status, $ToolboxUrl) return } # Token in der Session merken (Wiederaufruf ohne erneutes Tippen) if ($token) { $global:ToolboxToken = $token } # Bridge-Datei fuer den Orchestrator (auch ueber UAC-Elevation hinweg). # cynfotoolbox.ps1 liest sie beim Start und loescht sie sofort wieder. # Im offenen Modus (kein Auth) Bridge-Datei wegraeumen, damit der Orchestrator # nicht zufaellig einen alten Token mitschleift. if ($auth) { $utf8 = New-Object System.Text.UTF8Encoding $false [IO.File]::WriteAllText($AuthBridge, $auth, $utf8) } elseif (Test-Path $AuthBridge) { Remove-Item -LiteralPath $AuthBridge -Force -ErrorAction SilentlyContinue } $isAdmin = ([Security.Principal.WindowsPrincipal] ` [Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if ($isAdmin) { Write-Host 'Starte cynfo Toolbox...' -ForegroundColor Cyan & $LocalPath } else { Write-Host 'Starte cynfo Toolbox als Administrator (UAC bestaetigen)...' -ForegroundColor Yellow Start-Process powershell.exe -ArgumentList '-NoProfile','-NoExit','-ExecutionPolicy','Bypass','-File',$LocalPath -Verb RunAs }