geenforce client: make ApiToken optional for IP-allowlisted kiosks

Get-ShopdbConfig required both BaseUrl AND ApiToken, so a token-less kiosk
(authorized by the server's IP allowlist) got a null config and never ran.
Now BaseUrl alone is a valid config; X-API-Key is sent only when a token is
present (New-ShopdbAuthHeaders), so token-authorized sites are unchanged and
vaulted-network sites need no per-PC token.
This commit is contained in:
cproudlock
2026-07-27 14:17:51 -04:00
parent 0860aa85c5
commit 2d675720b7
2 changed files with 17 additions and 5 deletions

View File

@@ -85,7 +85,7 @@ try {
$config = Get-ShopdbConfig -BaseUrl $BaseUrl -ApiToken $ApiToken
if (-not $config) {
Write-Log 'No shopdb BaseUrl/ApiToken configured yet - retry next cycle.' 'WARN'
Write-Log 'No shopdb BaseUrl configured yet - retry next cycle.' 'WARN'
exit 0
}

View File

@@ -66,10 +66,22 @@ function Get-ShopdbConfig {
if (-not $BaseUrl -and $props.BaseUrl) { $BaseUrl = $props.BaseUrl }
if (-not $ApiToken -and $props.ApiToken) { $ApiToken = $props.ApiToken }
}
if (-not $BaseUrl -or -not $ApiToken) { return $null }
# ApiToken is OPTIONAL: on a vaulted network the server may authorize by
# source-IP allowlist, so a BaseUrl alone is a valid config. When a token
# is present it is still sent (and honored) for token-authorized sites.
if (-not $BaseUrl) { return $null }
return @{ BaseUrl = $BaseUrl.TrimEnd('/'); ApiToken = $ApiToken }
}
function New-ShopdbAuthHeaders {
# Only send X-API-Key when a token is configured; a token-less client
# relies on the server's IP allowlist.
param($Config)
if ($Config.ApiToken) { return @{ 'X-API-Key' = $Config.ApiToken } }
return @{}
}
function Sync-ShopdbManifest {
<#
Fetch the current published manifest for a scope into a local cache, using
@@ -87,7 +99,7 @@ function Sync-ShopdbManifest {
if (-not (Test-Path $CacheDir)) { New-Item -ItemType Directory -Path $CacheDir -Force | Out-Null }
$manifestPath = Join-Path $CacheDir "$Scope.json"
$etagPath = Join-Path $CacheDir "$Scope.etag"
$headers = @{ 'X-API-Key' = $Config.ApiToken }
$headers = New-ShopdbAuthHeaders $Config
if (Test-Path $etagPath) { $headers['If-None-Match'] = (Get-Content -LiteralPath $etagPath -Raw).Trim() }
$uri = "$($Config.BaseUrl)/api/geenforce/manifest?pctype=$([uri]::EscapeDataString($Scope))"
@@ -170,7 +182,7 @@ function Send-ShopdbReport {
try {
$body = ($Report | ConvertTo-Json -Depth 6)
Invoke-RestMethod -Uri "$($Config.BaseUrl)/api/geenforce/report" `
-Method Post -Headers @{ 'X-API-Key' = $Config.ApiToken } `
-Method Post -Headers (New-ShopdbAuthHeaders $Config) `
-ContentType 'application/json' -Body $body -TimeoutSec 30 -ErrorAction Stop | Out-Null
return $true
} catch {
@@ -250,7 +262,7 @@ function Get-ShopdbPayload {
$uri = "$($Config.BaseUrl)/api/geenforce/payload/$sha"
$tmp = "$dest.tmp"
try {
Invoke-WebRequest -Uri $uri -Headers @{ 'X-API-Key' = $Config.ApiToken } `
Invoke-WebRequest -Uri $uri -Headers (New-ShopdbAuthHeaders $Config) `
-UseBasicParsing -TimeoutSec 120 -OutFile $tmp -ErrorAction Stop
} catch {
if (Test-Path $tmp) { Remove-Item -LiteralPath $tmp -Force -ErrorAction SilentlyContinue }