Files
aza/AzA march 2026 - Kopie (8)/deploy/authorized_test.ps1
2026-04-16 13:32:32 +02:00

238 lines
7.6 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
AZA Step 12: Authorized Smoke-Test (PowerShell)
What it does:
- Loads MEDWORK_API_TOKENS (preferred) or MEDWORK_API_TOKEN (legacy) from deploy/.env
- Picks the first token (NEW) from a comma-separated list
- Calls GET /license/status with header: X-API-Token: <token>
- Optionally sends X-Device-Id (stable per run unless you override)
Run:
powershell -ExecutionPolicy Bypass -File .\deploy\authorized_test.ps1
Optional:
powershell -ExecutionPolicy Bypass -File .\deploy\authorized_test.ps1 -BaseUrl http://127.0.0.1:8000
powershell -ExecutionPolicy Bypass -File .\deploy\authorized_test.ps1 -DeviceId "test-device-123"
Expected:
200 + JSON: {"valid": true/false, "valid_until": 1774553596 or null}
#>
[CmdletBinding()]
param(
[string]$BaseUrl = "http://127.0.0.1:8000",
# default: .env next to this script (deploy\.env)
[string]$EnvFile = "",
[string]$DeviceId = ""
)
function Get-ScriptDir {
# Prefer PSScriptRoot when available, otherwise fall back to MyInvocation (works in Windows PowerShell).
if ($PSScriptRoot -and $PSScriptRoot.Trim().Length -gt 0) { return $PSScriptRoot }
$p = $MyInvocation.MyCommand.Path
if (-not $p) { throw "Cannot determine script directory (PSScriptRoot/MyInvocation empty)." }
return (Split-Path -Parent $p)
}
function Load-DotEnv([string]$Path) {
if (-not (Test-Path -LiteralPath $Path)) {
throw "Missing .env file at: $Path"
}
$map = @{}
Get-Content -LiteralPath $Path | ForEach-Object {
$line = $_.Trim()
if ($line.Length -eq 0) { return }
if ($line.StartsWith("#")) { return }
$idx = $line.IndexOf("=")
if ($idx -lt 1) { return }
$k = $line.Substring(0, $idx).Trim()
$v = $line.Substring($idx + 1).Trim()
# strip optional wrapping quotes
if (($v.StartsWith('"') -and $v.EndsWith('"')) -or ($v.StartsWith("'") -and $v.EndsWith("'"))) {
$v = $v.Substring(1, $v.Length - 2)
}
$map[$k] = $v
}
return $map
}
function First-TokenFromValue([string]$value) {
if (-not $value) { return "" }
# supports "NEW,OLD" and multi-line/space separated variants
$value = $value.Trim()
$parts = $value -split "[,\r\n]+" | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }
if ($parts.Count -ge 1) { return $parts[0] }
return ""
}
function All-TokensFromValue([string]$value) {
if (-not $value) { return @() }
$value = $value.Trim()
return ($value -split "[,\r\n]+" | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" })
}
try {
if (-not $EnvFile -or $EnvFile.Trim().Length -eq 0) {
$scriptDir = Get-ScriptDir
$EnvFile = Join-Path $scriptDir ".env"
}
$envMap = Load-DotEnv -Path $EnvFile
} catch {
Write-Host "$($_.Exception.Message)"
exit 1
}
$tokenValue = ""
$tokenSource = ""
if ($envMap.ContainsKey("MEDWORK_API_TOKENS")) { $tokenValue = $envMap["MEDWORK_API_TOKENS"] }
elseif ($envMap.ContainsKey("MEDWORK_API_TOKEN")) { $tokenValue = $envMap["MEDWORK_API_TOKEN"] }
$tokens = @()
if ($envMap.ContainsKey("MEDWORK_API_TOKENS")) {
$tokenSource = "MEDWORK_API_TOKENS"
$tokens = All-TokensFromValue -value $envMap["MEDWORK_API_TOKENS"]
} elseif ($envMap.ContainsKey("MEDWORK_API_TOKEN")) {
$tokenSource = "MEDWORK_API_TOKEN"
$tokens = All-TokensFromValue -value $envMap["MEDWORK_API_TOKEN"]
}
if (-not $tokens -or $tokens.Count -lt 1) {
Write-Host "❌ No token found in $EnvFile (expected MEDWORK_API_TOKENS or MEDWORK_API_TOKEN)."
exit 1
}
if (-not $DeviceId) {
# deterministic-ish per machine/user; override via -DeviceId when needed
$DeviceId = "ps-" + $env:COMPUTERNAME + "-" + $env:USERNAME
}
$base = $BaseUrl.TrimEnd("/")
$url = "$base/license/status"
Write-Host "[AZA] Authorized Smoke-Test"
Write-Host " BaseUrl: $base"
Write-Host " Endpoint: /license/status"
Write-Host " TokenSrc: $tokenSource"
Write-Host " Tokens: $($tokens.Count) (will try in order)"
Write-Host " TokenLen: $($tokens[0].Length) (first token length only)"
Write-Host " DeviceId: $DeviceId"
Write-Host ""
function Invoke-GetJson([string]$u, [hashtable]$h) {
try {
$resp = Invoke-RestMethod -Method GET -Uri $u -Headers $h -TimeoutSec 15
return @{ ok=$true; status=200; body=$resp }
} catch {
$e = $_.Exception
$status = $null
$body = ""
if ($e.Response -and $e.Response.StatusCode) {
$status = [int]$e.Response.StatusCode
try {
$stream = $e.Response.GetResponseStream()
if ($stream) {
$reader = New-Object System.IO.StreamReader($stream)
$body = $reader.ReadToEnd()
}
} catch { }
}
return @{ ok=$false; status=$status; body=$body; message=$e.Message }
}
}
$base = $BaseUrl.TrimEnd("/")
function Invoke-GetJsonNoAuth([string]$u) {
try {
$resp = Invoke-RestMethod -Method GET -Uri $u -TimeoutSec 15
return @{ ok=$true; status=200; body=$resp }
} catch {
$e = $_.Exception
$status = $null
if ($e.Response -and $e.Response.StatusCode) { $status = [int]$e.Response.StatusCode }
return @{ ok=$false; status=$status; message=$e.Message }
}
}
function Discover-LicenseStatusPath([string]$baseUrl) {
$openapiUrl = "$baseUrl/openapi.json"
$r = Invoke-GetJsonNoAuth $openapiUrl
if (-not $r.ok) { return @{ ok=$false; reason="openapi_unavailable"; path=$null } }
try {
$paths = $r.body.paths.PSObject.Properties.Name
$hits = @()
foreach ($p in $paths) {
$pl = $p.ToLowerInvariant()
if ($pl -like "*license*" -and $pl -like "*status*") { $hits += $p }
}
if ($hits.Count -ge 1) {
return @{ ok=$true; reason="openapi_match"; path=$hits[0]; all=$hits }
}
return @{ ok=$false; reason="openapi_no_match"; path=$null }
} catch {
return @{ ok=$false; reason="openapi_parse_failed"; path=$null }
}
}
$lastStatus = $null
# First: sanity check health so we know we're talking to the correct server
$health = Invoke-GetJsonNoAuth "$base/health"
if ($health.ok) {
Write-Host "Health: OK (GET /health)"
} else {
Write-Host "Health: not OK (GET /health) status=$($health.status)"
}
Write-Host ""
# Discover correct license/status path via OpenAPI if available
$disc = Discover-LicenseStatusPath $base
$pathsToTry = @()
if ($disc.ok -and $disc.path) {
$pathsToTry += $disc.path
if ($disc.all -and $disc.all.Count -gt 1) {
foreach ($p in $disc.all) { if ($p -ne $disc.path) { $pathsToTry += $p } }
}
Write-Host "Discovered path(s) via /openapi.json:"
$pathsToTry | ForEach-Object { Write-Host " - $_" }
} else {
# Fallback candidates (do not change server behavior, just try likely paths)
$pathsToTry = @("/license/status", "/api/license/status", "/v1/license/status", "/license/status/")
Write-Host "OpenAPI discovery not usable ($($disc.reason)). Trying common candidates:"
$pathsToTry | ForEach-Object { Write-Host " - $_" }
}
Write-Host ""
foreach ($path in $pathsToTry) {
$testUrl = "$base$path"
foreach ($t in $tokens) {
$headers = @{
"X-API-Token" = $t
"X-Device-Id" = $DeviceId
"Accept" = "application/json"
}
$res = Invoke-GetJson -u $testUrl -h $headers
if ($res.ok) {
Write-Host "OK HTTP 200 ($path)"
$json = $res.body | ConvertTo-Json -Depth 10 -Compress
Write-Host $json
exit 0
}
$lastStatus = $res.status
if ($res.status -eq 404) {
# try next path
break
}
if ($res.status -eq 401 -or $res.status -eq 403) {
# try next token
continue
}
Write-Host "FAIL HTTP $($res.status) ($path)"
if ($res.body) { Write-Host $res.body } else { Write-Host $res.message }
exit 1
}
}
Write-Host "FAIL (no matching license/status endpoint found, or all tokens unauthorized)"
Write-Host "LastStatus: $lastStatus"
exit 1