PrintToVeraeTimeStamp/platform/windows/scripts/user-token.ps1

76 lines
4.1 KiB
PowerShell

# Verae signing key handling for the installer (runs elevated, acts for the LOGGED-IN user).
# -Mode status : detect target user + existing key → INI [token]
# -Mode validate : check key in -TokenFile against Verae (free) → INI [validate]
# -Mode save : validate-format + write <profile>\.verae\xverae-token with user-only ACL → INI [save]
# The key is never printed; only a masked form (xVerae-...abcd) is logged.
param(
[ValidateSet("status","validate","save")][string]$Mode = "status",
[string]$TokenFile,
[Parameter(Mandatory=$true)][string]$IniOut
)
$ErrorActionPreference = "Continue"
. (Join-Path $PSScriptRoot "common.ps1")
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ValidateUrl = "https://zap.verae.ai/v1/status" # documented as free; 401 = bad key
function Test-VeraeKey([string]$tok) {
if ($tok -notmatch '^(xVerae-|key-)\S{8,}$') { return @{ result = "badformat"; detail = "must start with xVerae- (or legacy key-)" } }
try {
$r = Invoke-WebRequest -UseBasicParsing -TimeoutSec 10 -Uri $ValidateUrl -Headers @{ "x-api-key" = $tok }
return @{ result = "valid"; detail = "HTTP $($r.StatusCode)" }
} catch {
$code = $null
if ($_.Exception.Response) { $code = [int]$_.Exception.Response.StatusCode }
if ($code -eq 401 -or $code -eq 403) { return @{ result = "invalid"; detail = "HTTP $code from Verae" } }
if ($code) { return @{ result = "unknown"; detail = "HTTP $code from Verae" } }
return @{ result = "unreachable"; detail = $_.Exception.Message }
}
}
$u = Get-VeraeTargetUser
$tokPath = Join-Path $u.Profile ".verae\xverae-token"
Write-Host "user-token.ps1 mode=$Mode target=$($u.Account) sid=$($u.Sid) profile=$($u.Profile) via=$($u.Source) runningAs=$([Security.Principal.WindowsIdentity]::GetCurrent().Name)"
switch ($Mode) {
"status" {
$existing = $null
if (Test-Path $tokPath) { $existing = (Get-Content $tokPath -Raw -ErrorAction SilentlyContinue) }
if ($existing) { $existing = $existing.Trim() }
$v = @{ result = "none"; detail = "" }
if ($existing) { $v = Test-VeraeKey $existing }
Write-Host "existing key: $([bool]$existing) $(Get-MaskedToken $existing) check=$($v.result) $($v.detail)"
Write-VeraeIni $IniOut "token" ([ordered]@{
account = $u.Account; sid = $u.Sid; profile = $u.Profile; source = $u.Source; path = $tokPath
present = $(if ($existing) { 1 } else { 0 }); masked = (Get-MaskedToken $existing)
check = $v.result; detail = $v.detail })
}
"validate" {
$tok = (Get-Content $TokenFile -Raw).Trim()
$v = Test-VeraeKey $tok
Write-Host "validate $(Get-MaskedToken $tok): $($v.result) $($v.detail)"
Write-VeraeIni $IniOut "validate" ([ordered]@{ result = $v.result; detail = $v.detail; masked = (Get-MaskedToken $tok) })
}
"save" {
$tok = (Get-Content $TokenFile -Raw).Trim()
$ok = $false; $err = ""
try {
if ($tok -notmatch '^(xVerae-|key-)\S{8,}$') { throw "bad token format" }
$dir = Split-Path $tokPath -Parent
New-Item -ItemType Directory -Force -Path $dir | Out-Null
# same format as internal/auth.SaveXVeraeToken: token + "\n", no BOM
[IO.File]::WriteAllText($tokPath, $tok + "`n", (New-Object Text.UTF8Encoding($false)))
# ACL: the logged-in user owns it; only user, SYSTEM, Administrators have access
icacls $dir /grant "*$($u.Sid):(OI)(CI)F" /C | Out-Host
icacls $dir /setowner "*$($u.Sid)" /C | Out-Host
icacls $tokPath /inheritance:r /grant:r "*$($u.Sid):F" "*S-1-5-18:F" "*S-1-5-32-544:F" /C | Out-Host
icacls $tokPath /setowner "*$($u.Sid)" /C | Out-Host
$back = (Get-Content $tokPath -Raw).Trim()
$ok = ($back -eq $tok)
if (-not $ok) { $err = "read-back mismatch" }
icacls $tokPath | Out-Host
} catch { $err = $_.Exception.Message }
Write-Host "save $(Get-MaskedToken $tok) -> $tokPath : $(if ($ok) {'OK'} else {"FAIL $err"})"
Write-VeraeIni $IniOut "save" ([ordered]@{ result = $(if ($ok) { "OK" } else { "FAIL" }); detail = $err; path = $tokPath; masked = (Get-MaskedToken $tok); account = $u.Account })
}
}
exit 0