Publish ITWorx Pulse source
Public source validation / validate (push) Failing after 3m8s

This commit is contained in:
ITWorx Pulse release export
2026-09-03 02:09:19 +02:00
commit bd774932d5
614 changed files with 77116 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
[CmdletBinding()]
param(
[Parameter()]
[ValidatePattern('^https://')]
[string]$BaseUrl = 'https://pulse.example.com',
[Parameter()]
[ValidatePattern('^http://')]
[string]$HttpUrl = 'http://pulse.example.com',
[Parameter()]
[ValidatePattern('^https://')]
[string]$ExpectedOIDCIssuer = 'https://auth.nuklearrabbit.com/application/o/itworx-pulse',
[Parameter()]
[ValidateRange(1, 30)]
[int]$TimeoutSeconds = 10
)
$ErrorActionPreference = 'Stop'
$base = [uri]$BaseUrl
$plain = [uri]$HttpUrl
$issuer = [uri]$ExpectedOIDCIssuer
if (-not [string]::IsNullOrEmpty($base.UserInfo) -or -not [string]::IsNullOrEmpty($plain.UserInfo) -or -not [string]::IsNullOrEmpty($issuer.UserInfo)) {
throw 'Production smoke URLs may not contain embedded credentials.'
}
function Invoke-NoRedirect([uri]$Uri) {
$handler = [System.Net.Http.HttpClientHandler]::new()
$handler.AllowAutoRedirect = $false
$client = [System.Net.Http.HttpClient]::new($handler)
$client.Timeout = [TimeSpan]::FromSeconds($TimeoutSeconds)
try {
$response = $client.GetAsync($Uri).GetAwaiter().GetResult()
$headers = @{}
foreach ($header in $response.Headers) {
$headers[$header.Key] = $header.Value -join ', '
}
foreach ($header in $response.Content.Headers) {
$headers[$header.Key] = $header.Value -join ', '
}
[pscustomobject]@{
StatusCode = [int]$response.StatusCode
Headers = $headers
Content = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult()
}
} finally {
$client.Dispose()
$handler.Dispose()
}
}
function Invoke-Probe([string]$Path) {
Invoke-NoRedirect ([uri]($BaseUrl.TrimEnd('/') + $Path))
}
function Assert-Status($Response, [int[]]$Expected, [string]$Label) {
if ($Expected -notcontains [int]$Response.StatusCode) {
throw "$Label returned HTTP $($Response.StatusCode); expected $($Expected -join '/')"
}
}
function Get-ResponseText($Response) {
if ($Response.Content -is [byte[]]) {
return [System.Text.Encoding]::UTF8.GetString([byte[]]$Response.Content)
}
return [string]$Response.Content
}
Write-Host '== HTTPS health and security headers ==' -ForegroundColor Cyan
$health = Invoke-Probe '/healthz'
Assert-Status $health @(200) 'HTTPS /healthz'
if ((Get-ResponseText $health).Trim() -ne 'ok' -or $health.Headers.'Content-Type' -notmatch '^text/plain') {
throw 'HTTPS /healthz must return exact text/plain ok content.'
}
foreach ($header in @('Strict-Transport-Security', 'Content-Security-Policy', 'X-Content-Type-Options', 'X-Frame-Options')) {
if ([string]::IsNullOrWhiteSpace([string]$health.Headers.$header)) { throw "HTTPS response is missing $header." }
}
if ([string]$health.Headers.'Strict-Transport-Security' -notmatch 'max-age=\d+') {
throw 'HSTS does not contain a max-age directive.'
}
$ready = Invoke-Probe '/readyz'
Assert-Status $ready @(200) 'HTTPS /readyz'
if ($ready.Headers.'Content-Type' -notmatch '^text/plain' -or (Get-ResponseText $ready) -match '<!doctype html') {
throw 'HTTPS /readyz is not genuine text/plain API readiness.'
}
Write-Host '== HTTP to HTTPS enforcement ==' -ForegroundColor Cyan
$redirect = Invoke-NoRedirect ([uri]($HttpUrl.TrimEnd('/') + '/healthz'))
Assert-Status $redirect @(301, 302, 307, 308) 'HTTP /healthz'
$location = [uri]::new($plain, [string]$redirect.Headers.Location)
if ($location.Scheme -ne 'https' -or $location.Host -ne $base.Host) {
throw "HTTP redirect escapes the production HTTPS host: $location"
}
Write-Host '== public exposure boundary ==' -ForegroundColor Cyan
foreach ($path in @('/metrics', '/debug/pprof/')) {
$response = Invoke-Probe $path
Assert-Status $response @(404) $path
if ((Get-ResponseText $response) -match '<!doctype html') { throw "$path fell through to the SPA." }
}
foreach ($path in @('/api/v1/system/status', '/api/v1/system/metrics', '/api/v1/system/diagnostics')) {
$response = Invoke-Probe $path
Assert-Status $response @(401) $path
}
Write-Host '== OIDC entrypoint ==' -ForegroundColor Cyan
$discovery = Invoke-NoRedirect ([uri]($ExpectedOIDCIssuer.TrimEnd('/') + '/.well-known/openid-configuration'))
Assert-Status $discovery @(200) 'OIDC discovery'
$provider = $discovery.Content | ConvertFrom-Json
if (([string]$provider.issuer).TrimEnd('/') -ne $ExpectedOIDCIssuer.TrimEnd('/')) {
throw "OIDC discovery returned an unexpected issuer: $($provider.issuer)"
}
$authorizationEndpoint = [uri][string]$provider.authorization_endpoint
if ($authorizationEndpoint.Scheme -ne 'https' -or $authorizationEndpoint.Host -ne $issuer.Host) {
throw "OIDC discovery returned an unsafe authorization endpoint: $authorizationEndpoint"
}
$login = Invoke-Probe '/auth/login'
Assert-Status $login @(302, 303, 307) '/auth/login'
$loginLocation = [uri]::new($base, [string]$login.Headers.Location)
if ($loginLocation.Scheme -ne $authorizationEndpoint.Scheme -or $loginLocation.Host -ne $authorizationEndpoint.Host -or $loginLocation.AbsolutePath -ne $authorizationEndpoint.AbsolutePath) {
throw "OIDC login redirect does not target the expected issuer: $loginLocation"
}
Write-Host "PRODUCTION PUBLIC SMOKE: PASS ($BaseUrl)" -ForegroundColor Green