# Mariano's #23 Part A probe session on shif1021-vm (action Run Command). TEMPLATE: probe_orchestrator.py fills the # placeholders (version, package hash, expected test count, executions already done). No secret in this script: # the Oxylabs API user comes ONLY from Key Vault, read with the VM's managed identity. If that read fails the session # stops with the Key Vault error and sends nothing; there is no other route (v2.2.16). $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" $Version = "__VERSION__" $Expected = "__PKG_SHA__" $ExpectedTests = "__TESTS__" # not $Tests: PowerShell names are case-insensitive and $tests holds the pytest result $MaxRequests = __MAX_REQUESTS__ # this execution's share of the 15-job total (earlier jobs stay counted) $PriorRuns = __PRIOR_RUNS__ # Oxylabs executions the holder already counted; one more is authorized $Launcher = "__LAUNCHER_SHA__" # infra/run_probe.ps1 inside the reviewed package $Account = "https://shif1021sthfpzua5nrkvt2.blob.core.windows.net/" $Container = "scraper-test" $Vault = "https://shif1021-kv-hfpzua5n.vault.azure.net" $Stamp = (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmssZ") $Root = "C:\marianos\probe-$Version-$Stamp" # a new folder per session: earlier evidence on the VM is never removed $SessionLog = "C:\marianos\probe-session-$Stamp.log" function Say([string] $m) { $line = "$((Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')) $m"; Write-Output $line; Add-Content -LiteralPath $SessionLog $line } function Ev([int] $id, [string] $type, [string] $m) { try { Write-EventLog -LogName Application -Source ShifullahScraper -EventId $id -EntryType $type -Message $m } catch { Say "event not written: $($_.Exception.Message)" } } function Token([string] $res) { (Invoke-RestMethod -Headers @{ Metadata = "true" } -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$res").access_token } function PutBlob([string] $file, [string] $name) { Invoke-RestMethod -Method Put -Uri ($Account + "$Container/$name") -InFile $file -Headers @{ Authorization = "Bearer $(Token 'https://storage.azure.com/')"; "x-ms-version" = "2021-08-06"; "x-ms-blob-type" = "BlockBlob" } | Out-Null } New-Item -ItemType Directory -Force C:\marianos | Out-Null Say "session start on $env:COMPUTERNAME" $OxyUser = ""; $OxyPass = "" try { $kv = Token "https://vault.azure.net" $OxyUser = (Invoke-RestMethod -Headers @{ Authorization = "Bearer $kv" } -Uri "$Vault/secrets/oxylabs-username?api-version=7.4").value $OxyPass = (Invoke-RestMethod -Headers @{ Authorization = "Bearer $kv" } -Uri "$Vault/secrets/oxylabs-password?api-version=7.4").value } catch { $status = if ($_.Exception.Response) { "HTTP $([int]$_.Exception.Response.StatusCode)" } else { "no HTTP answer" } $msg = "STOP: Key Vault read failed (managed identity, $Vault, secrets oxylabs-username / oxylabs-password): $status; $($_.Exception.Message). Nothing sent; no other credential route exists." Say $msg; Ev 1202 Error $msg exit 5 } if (-not $OxyUser -or -not $OxyPass) { $msg = "STOP: Key Vault returned an empty oxylabs-username or oxylabs-password. Nothing sent." Say $msg; Ev 1202 Error $msg exit 5 } Say "Oxylabs API user read from Key Vault with the managed identity (in memory only)" $done = @(Get-ChildItem -Path "C:\marianos\probe-*\scraper\evidence" -Directory -Filter "oxylabs-probe-*" -ErrorAction SilentlyContinue) if ($done.Count -gt $PriorRuns) { Say "STOP: $($done.Count) Oxylabs probe folders already on this VM, $PriorRuns allowed before this one"; exit 3 } # 1. the reviewed package, from Blob, hash-checked on the VM $zip = "C:\marianos\marianos-scraper-$Version.zip" Invoke-WebRequest -UseBasicParsing -Uri ($Account + "$Container/deploy/marianos-scraper-$Version.zip") -Headers @{ Authorization = "Bearer $(Token 'https://storage.azure.com/')"; "x-ms-version" = "2021-08-06" } -OutFile $zip $h = (Get-FileHash $zip -Algorithm SHA256).Hash Say "package sha256 $h" if ($h -ne $Expected) { Say "STOP: package hash differs from the reviewed $Expected"; exit 3 } if (Test-Path $Root) { Say "STOP: $Root already exists; a session never reuses or removes a folder"; exit 3 } Expand-Archive $zip $Root Set-Location "$Root\scraper" $lh = (Get-FileHash .\infra\run_probe.ps1 -Algorithm SHA256).Hash Say "run_probe.ps1 sha256 $lh" if ($lh -ne $Launcher) { Say "STOP: launcher hash differs from the reviewed $Launcher"; exit 3 } # 2. isolated venv, pinned dependencies, offline tests (no probe if they fail) $py = "C:\Python313\python.exe" if (-not (Test-Path $py)) { $py = (Get-Command python -ErrorAction Stop).Source } & $py -m venv .venv & .\.venv\Scripts\python.exe -m pip install -q --disable-pip-version-check -r requirements-dev.txt *>> $SessionLog $env:PYTHONDONTWRITEBYTECODE = "1" $ver = & .\.venv\Scripts\python.exe -c "import sys; from marianos_scraper import __version__; from marianos_scraper.runner import code_fingerprint; print(sys.version.split()[0], __version__, code_fingerprint())" Say "venv python / version / fingerprint: $ver" $tests = (& .\.venv\Scripts\python.exe -m pytest -q tests -p no:cacheprovider 2>&1 | Select-Object -Last 1) -join "" Say "tests: $tests" if ($tests -notmatch "^=*\s*$ExpectedTests passed") { Say "STOP: tests did not all pass on the VM; probe not started"; exit 3 } # 3. the cumulative-usage ledger shared by every execution. The probe itself reads and writes the blob (lease, If-Match, # read-back) and stops before any request if it cannot; this script never keeps or uploads a copy of it. $LedgerUrl = $Account + "$Container/probe/cumulative-usage.json" function LedgerTotal { try { $l = Invoke-RestMethod -Uri $LedgerUrl -Headers @{ Authorization = "Bearer $(Token 'https://storage.azure.com/')"; "x-ms-version" = "2021-08-06" }; "$($l.total_jobs_counted) counted ($($l.total_jobs_submitted) before v2.2.16)" } catch { "not readable: $($_.Exception.Message)" } } Say "ledger (read only, before): $(LedgerTotal)" # 4. the single probe execution, through the reviewed launcher $out = "evidence\oxylabs-probe-$Stamp" Ev 1200 Information "Mariano's probe start (Part A, Oxylabs, Vernon Hills 53100502, 5 UPCs, max $MaxRequests jobs this run, 1200 s deadline). Evidence folder $out. Package sha256 $h." Say "probe start, evidence folder $out" $env:OXYLABS_USERNAME = $OxyUser $env:OXYLABS_PASSWORD = $OxyPass & powershell -NoProfile -ExecutionPolicy Bypass -File .\infra\run_probe.ps1 -Out $out ` -Upcs "0003940001880,0001600040803,0073820310311,0004157305440,0002100006058" ` -Roles "ppm-volume,ppm-digital,regular,unavailable,unavailable" -MaxRequests $MaxRequests -AzureImds -Ledger "blob:$LedgerUrl" *>> $SessionLog $code = $LASTEXITCODE Remove-Item Env:OXYLABS_USERNAME, Env:OXYLABS_PASSWORD -ErrorAction SilentlyContinue $OxyUser = $null; $OxyPass = $null Say "probe end, launcher exit $code" Ev 1201 Information "Mariano's probe end: launcher exit $code (0 accepted, 1 completed not accepted, 2 stopped, 4 site refused, 124 outer kill). Evidence folder $out." # 5. the ledger as the probe left it (read only; the probe's report.json says whether its final update was verified) Say "ledger (read only, after): $(LedgerTotal)" # 6. evidence to Blob, read back by SHA-256 against the manifest & powershell -NoProfile -ExecutionPolicy Bypass -File .\infra\upload_probe_evidence.ps1 -EvidenceDir $out -StorageAccountUrl $Account -Container $Container *>> $SessionLog Say "upload exit $LASTEXITCODE" Get-Content -LiteralPath "$out\upload_check.txt" -TotalCount 3 | ForEach-Object { Say "upload_check: $_" } $r = Get-Content -LiteralPath "$out\report.json" -Raw | ConvertFrom-Json Say "report: transport $($r.transport); acceptance $($r.acceptance.overall); requests sent $($r.requests.sent); stop $($r.stop_reason)" PutBlob $SessionLog ("probe/oxylabs-probe-$Stamp-session.log") Say "session log uploaded to probe/oxylabs-probe-$Stamp-session.log" exit $code