Harden scratch setup bootstrap and authority admin scopes
This commit is contained in:
@@ -406,7 +406,7 @@ services:
|
|||||||
Platform__EnvironmentSettings__TokenEndpoint: "https://stella-ops.local/connect/token"
|
Platform__EnvironmentSettings__TokenEndpoint: "https://stella-ops.local/connect/token"
|
||||||
Platform__EnvironmentSettings__RedirectUri: "https://stella-ops.local/auth/callback"
|
Platform__EnvironmentSettings__RedirectUri: "https://stella-ops.local/auth/callback"
|
||||||
Platform__EnvironmentSettings__PostLogoutRedirectUri: "https://stella-ops.local/"
|
Platform__EnvironmentSettings__PostLogoutRedirectUri: "https://stella-ops.local/"
|
||||||
Platform__EnvironmentSettings__Scope: "openid profile email offline_access ui.read ui.admin ui.preferences.read ui.preferences.write authority:tenants.read authority:users.read authority:roles.read authority:clients.read authority:tokens.read authority:branding.read authority.audit.read graph:read sbom:read scanner:read policy:read policy:simulate policy:author policy:review policy:approve policy:run policy:activate policy:audit policy:edit policy:operate policy:publish airgap:seal airgap:status:read orch:read orch:quota analytics.read advisory:read advisory-ai:view advisory-ai:operate vex:read vexhub:read exceptions:read exceptions:approve aoc:verify findings:read release:read release:write release:publish scheduler:read scheduler:operate notify.viewer notify.operator notify.admin notify.escalate evidence:read export.viewer export.operator export.admin vuln:view vuln:investigate vuln:operate vuln:audit platform.context.read platform.context.write doctor:run doctor:admin ops.health integration:read integration:write integration:operate packs.read packs.write packs.run packs.approve registry.admin timeline:read timeline:write trust:read trust:write trust:admin signer:read signer:sign signer:rotate signer:admin"
|
Platform__EnvironmentSettings__Scope: "openid profile email offline_access ui.read ui.admin ui.preferences.read ui.preferences.write authority:tenants.read authority:tenants.write authority:users.read authority:users.write authority:roles.read authority:roles.write authority:clients.read authority:clients.write authority:tokens.read authority:tokens.revoke authority:branding.read authority:branding.write authority.audit.read graph:read sbom:read scanner:read policy:read policy:simulate policy:author policy:review policy:approve policy:run policy:activate policy:audit policy:edit policy:operate policy:publish airgap:seal airgap:status:read orch:read orch:quota analytics.read advisory:read advisory-ai:view advisory-ai:operate vex:read vexhub:read exceptions:read exceptions:approve aoc:verify findings:read release:read release:write release:publish scheduler:read scheduler:operate notify.viewer notify.operator notify.admin notify.escalate evidence:read export.viewer export.operator export.admin vuln:view vuln:investigate vuln:operate vuln:audit platform.context.read platform.context.write doctor:run doctor:admin ops.health integration:read integration:write integration:operate packs.read packs.write packs.run packs.approve registry.admin timeline:read timeline:write trust:read trust:write trust:admin signer:read signer:sign signer:rotate signer:admin"
|
||||||
STELLAOPS_ROUTER_URL: "http://router.stella-ops.local"
|
STELLAOPS_ROUTER_URL: "http://router.stella-ops.local"
|
||||||
STELLAOPS_PLATFORM_URL: "http://platform.stella-ops.local"
|
STELLAOPS_PLATFORM_URL: "http://platform.stella-ops.local"
|
||||||
STELLAOPS_AUTHORITY_URL: "http://authority.stella-ops.local"
|
STELLAOPS_AUTHORITY_URL: "http://authority.stella-ops.local"
|
||||||
@@ -509,7 +509,7 @@ services:
|
|||||||
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__ClientId: "stella-ops-ui"
|
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__ClientId: "stella-ops-ui"
|
||||||
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__DisplayName: "Stella Ops Console"
|
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__DisplayName: "Stella Ops Console"
|
||||||
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__AllowedGrantTypes: "authorization_code refresh_token"
|
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__AllowedGrantTypes: "authorization_code refresh_token"
|
||||||
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__AllowedScopes: "openid profile email offline_access ui.read ui.admin ui.preferences.read ui.preferences.write authority:tenants.read authority:users.read authority:roles.read authority:clients.read authority:tokens.read authority:branding.read authority.audit.read graph:read sbom:read scanner:read policy:read policy:simulate policy:author policy:review policy:approve policy:run policy:activate policy:audit policy:edit policy:operate policy:publish airgap:seal airgap:status:read orch:read orch:quota analytics.read advisory:read advisory-ai:view advisory-ai:operate vex:read vexhub:read exceptions:read exceptions:approve aoc:verify findings:read release:read release:write release:publish scheduler:read scheduler:operate notify.viewer notify.operator notify.admin notify.escalate evidence:read export.viewer export.operator export.admin vuln:view vuln:investigate vuln:operate vuln:audit platform.context.read platform.context.write doctor:run doctor:admin ops.health integration:read integration:write integration:operate packs.read packs.write packs.run packs.approve registry.admin timeline:read timeline:write trust:read trust:write trust:admin signer:read signer:sign signer:rotate signer:admin"
|
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__AllowedScopes: "openid profile email offline_access ui.read ui.admin ui.preferences.read ui.preferences.write authority:tenants.read authority:tenants.write authority:users.read authority:users.write authority:roles.read authority:roles.write authority:clients.read authority:clients.write authority:tokens.read authority:tokens.revoke authority:branding.read authority:branding.write authority.audit.read graph:read sbom:read scanner:read policy:read policy:simulate policy:author policy:review policy:approve policy:run policy:activate policy:audit policy:edit policy:operate policy:publish airgap:seal airgap:status:read orch:read orch:quota analytics.read advisory:read advisory-ai:view advisory-ai:operate vex:read vexhub:read exceptions:read exceptions:approve aoc:verify findings:read release:read release:write release:publish scheduler:read scheduler:operate notify.viewer notify.operator notify.admin notify.escalate evidence:read export.viewer export.operator export.admin vuln:view vuln:investigate vuln:operate vuln:audit platform.context.read platform.context.write doctor:run doctor:admin ops.health integration:read integration:write integration:operate packs.read packs.write packs.run packs.approve registry.admin timeline:read timeline:write trust:read trust:write trust:admin signer:read signer:sign signer:rotate signer:admin"
|
||||||
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__RedirectUris: "https://stella-ops.local/auth/callback https://stella-ops.local/auth/silent-refresh https://127.1.0.1/auth/callback https://127.1.0.1/auth/silent-refresh"
|
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__RedirectUris: "https://stella-ops.local/auth/callback https://stella-ops.local/auth/silent-refresh https://127.1.0.1/auth/callback https://127.1.0.1/auth/silent-refresh"
|
||||||
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__PostLogoutRedirectUris: "https://stella-ops.local/ https://127.1.0.1/"
|
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__PostLogoutRedirectUris: "https://stella-ops.local/ https://127.1.0.1/"
|
||||||
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__RequirePkce: "true"
|
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__BootstrapClients__0__RequirePkce: "true"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"tokenEndpoint": "https://stella-ops.local/connect/token",
|
"tokenEndpoint": "https://stella-ops.local/connect/token",
|
||||||
"redirectUri": "https://stella-ops.local/auth/callback",
|
"redirectUri": "https://stella-ops.local/auth/callback",
|
||||||
"postLogoutRedirectUri": "https://stella-ops.local/",
|
"postLogoutRedirectUri": "https://stella-ops.local/",
|
||||||
"scope": "openid profile email offline_access ui.read ui.admin ui.preferences.read ui.preferences.write authority:tenants.read authority:users.read authority:roles.read authority:clients.read authority:tokens.read authority:branding.read authority.audit.read graph:read sbom:read scanner:read policy:read policy:simulate policy:author policy:review policy:approve policy:run policy:activate policy:audit policy:edit policy:operate policy:publish airgap:seal airgap:status:read orch:read orch:quota analytics.read advisory:read advisory-ai:view advisory-ai:operate vex:read vexhub:read exceptions:read exceptions:approve aoc:verify findings:read release:read release:write release:publish scheduler:read scheduler:operate notify.viewer notify.operator notify.admin notify.escalate evidence:read export.viewer export.operator export.admin vuln:view vuln:investigate vuln:operate vuln:audit platform.context.read platform.context.write doctor:run doctor:admin ops.health integration:read integration:write integration:operate packs.read packs.write packs.run packs.approve registry.admin timeline:read timeline:write",
|
"scope": "openid profile email offline_access ui.read ui.admin ui.preferences.read ui.preferences.write authority:tenants.read authority:tenants.write authority:users.read authority:users.write authority:roles.read authority:roles.write authority:clients.read authority:clients.write authority:tokens.read authority:tokens.revoke authority:branding.read authority:branding.write authority.audit.read graph:read sbom:read scanner:read policy:read policy:simulate policy:author policy:review policy:approve policy:run policy:activate policy:audit policy:edit policy:operate policy:publish airgap:seal airgap:status:read orch:read orch:quota analytics.read advisory:read advisory-ai:view advisory-ai:operate vex:read vexhub:read exceptions:read exceptions:approve aoc:verify findings:read release:read release:write release:publish scheduler:read scheduler:operate notify.viewer notify.operator notify.admin notify.escalate evidence:read export.viewer export.operator export.admin vuln:view vuln:investigate vuln:operate vuln:audit platform.context.read platform.context.write doctor:run doctor:admin ops.health integration:read integration:write integration:operate packs.read packs.write packs.run packs.approve registry.admin timeline:read timeline:write",
|
||||||
"audience": "stella-ops-api",
|
"audience": "stella-ops-api",
|
||||||
"dpopAlgorithms": [
|
"dpopAlgorithms": [
|
||||||
"ES256"
|
"ES256"
|
||||||
|
|||||||
@@ -637,8 +637,12 @@ VALUES
|
|||||||
ARRAY['https://stella-ops.local/', 'https://127.1.0.1/'],
|
ARRAY['https://stella-ops.local/', 'https://127.1.0.1/'],
|
||||||
ARRAY['openid', 'profile', 'email', 'offline_access',
|
ARRAY['openid', 'profile', 'email', 'offline_access',
|
||||||
'ui.read', 'ui.admin', 'ui.preferences.read', 'ui.preferences.write',
|
'ui.read', 'ui.admin', 'ui.preferences.read', 'ui.preferences.write',
|
||||||
'authority:tenants.read', 'authority:users.read', 'authority:roles.read',
|
'authority:tenants.read', 'authority:tenants.write',
|
||||||
'authority:clients.read', 'authority:tokens.read', 'authority:branding.read',
|
'authority:users.read', 'authority:users.write',
|
||||||
|
'authority:roles.read', 'authority:roles.write',
|
||||||
|
'authority:clients.read', 'authority:clients.write',
|
||||||
|
'authority:tokens.read', 'authority:tokens.revoke',
|
||||||
|
'authority:branding.read', 'authority:branding.write',
|
||||||
'authority.audit.read',
|
'authority.audit.read',
|
||||||
'graph:read', 'sbom:read', 'scanner:read',
|
'graph:read', 'sbom:read', 'scanner:read',
|
||||||
'policy:read', 'policy:simulate', 'policy:author', 'policy:review', 'policy:approve',
|
'policy:read', 'policy:simulate', 'policy:author', 'policy:review', 'policy:approve',
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ The scripts will:
|
|||||||
4. Start infrastructure and wait for healthy containers
|
4. Start infrastructure and wait for healthy containers
|
||||||
5. Create or reuse the external frontdoor Docker network from `.env` (`FRONTDOOR_NETWORK`, default `stellaops_frontdoor`)
|
5. Create or reuse the external frontdoor Docker network from `.env` (`FRONTDOOR_NETWORK`, default `stellaops_frontdoor`)
|
||||||
6. Stop repo-local host-run Stella services that would lock build outputs, then build repo-owned .NET solutions and publish backend services locally into small Docker contexts before building hardened runtime images (vendored dependency trees such as `node_modules` are excluded)
|
6. Stop repo-local host-run Stella services that would lock build outputs, then build repo-owned .NET solutions and publish backend services locally into small Docker contexts before building hardened runtime images (vendored dependency trees such as `node_modules` are excluded)
|
||||||
7. Launch the full platform with health checks
|
7. Launch the full platform with health checks and wait for the first-user frontdoor bootstrap path (`/welcome`, `/envsettings.json`, OIDC discovery, `/connect/authorize`) before reporting success
|
||||||
|
|
||||||
Open **https://stella-ops.local** when setup completes.
|
Open **https://stella-ops.local** when setup completes.
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Setup scripts validate prerequisites, build solutions and Docker images, and lau
|
|||||||
./scripts/setup.sh --images-only # only build Docker images
|
./scripts/setup.sh --images-only # only build Docker images
|
||||||
```
|
```
|
||||||
|
|
||||||
The scripts will check for required tools (dotnet 10.x, node 20+, npm 10+, docker, git), warn about missing hosts file entries, copy `.env` from the example if needed, and stop repo-local host-run Stella services before the solution build so scratch bootstraps do not fail on locked `bin/Debug` outputs. See the manual steps below for details on each stage.
|
The scripts will check for required tools (dotnet 10.x, node 20+, npm 10+, docker, git), warn about missing hosts file entries, copy `.env` from the example if needed, and stop repo-local host-run Stella services before the solution build so scratch bootstraps do not fail on locked `bin/Debug` outputs. A full setup now waits for the first-user frontdoor bootstrap path as well: `/welcome`, `/envsettings.json`, OIDC discovery, and a PKCE-style `/connect/authorize` request must all be live before the script prints success. See the manual steps below for details on each stage.
|
||||||
|
|
||||||
On Windows and Linux, the backend image builder now publishes each selected .NET service locally and builds the hardened runtime image from a small temporary context. That avoids repeatedly streaming the whole monorepo into Docker during scratch setup.
|
On Windows and Linux, the backend image builder now publishes each selected .NET service locally and builds the hardened runtime image from a small temporary context. That avoids repeatedly streaming the whole monorepo into Docker during scratch setup.
|
||||||
|
|
||||||
|
|||||||
@@ -470,11 +470,21 @@ function Start-Platform {
|
|||||||
function Test-ExpectedHttpStatus([string]$url, [int[]]$allowedStatusCodes, [int]$timeoutSeconds = 5, [int]$attempts = 6, [int]$retryDelaySeconds = 2) {
|
function Test-ExpectedHttpStatus([string]$url, [int[]]$allowedStatusCodes, [int]$timeoutSeconds = 5, [int]$attempts = 6, [int]$retryDelaySeconds = 2) {
|
||||||
for ($attempt = 1; $attempt -le $attempts; $attempt++) {
|
for ($attempt = 1; $attempt -le $attempts; $attempt++) {
|
||||||
$statusCode = $null
|
$statusCode = $null
|
||||||
|
$previousCertificateCallback = $null
|
||||||
|
$hasCertificateCallbackOverride = $false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$request = [System.Net.WebRequest]::Create($url)
|
$request = [System.Net.WebRequest]::Create($url)
|
||||||
$request.Method = 'GET'
|
$request.Method = 'GET'
|
||||||
$request.Timeout = $timeoutSeconds * 1000
|
$request.Timeout = $timeoutSeconds * 1000
|
||||||
|
if ($request -is [System.Net.HttpWebRequest]) {
|
||||||
|
$request.AllowAutoRedirect = $false
|
||||||
|
}
|
||||||
|
if ($url.StartsWith('https://', [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||||
|
$previousCertificateCallback = [System.Net.ServicePointManager]::ServerCertificateValidationCallback
|
||||||
|
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
|
||||||
|
$hasCertificateCallbackOverride = $true
|
||||||
|
}
|
||||||
$response = [System.Net.HttpWebResponse]$request.GetResponse()
|
$response = [System.Net.HttpWebResponse]$request.GetResponse()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -492,6 +502,10 @@ function Test-ExpectedHttpStatus([string]$url, [int[]]$allowedStatusCodes, [int]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
} finally {
|
||||||
|
if ($hasCertificateCallbackOverride) {
|
||||||
|
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $previousCertificateCallback
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($null -ne $statusCode -and $allowedStatusCodes -contains $statusCode) {
|
if ($null -ne $statusCode -and $allowedStatusCodes -contains $statusCode) {
|
||||||
@@ -506,6 +520,52 @@ function Test-ExpectedHttpStatus([string]$url, [int[]]$allowedStatusCodes, [int]
|
|||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Test-FrontdoorBootstrap {
|
||||||
|
$baseUrl = 'https://stella-ops.local'
|
||||||
|
$probes = @(
|
||||||
|
@{
|
||||||
|
Name = 'Frontdoor readiness'
|
||||||
|
Url = "$baseUrl/health/ready"
|
||||||
|
AllowedStatusCodes = @(200)
|
||||||
|
},
|
||||||
|
@{
|
||||||
|
Name = 'Frontdoor welcome page'
|
||||||
|
Url = "$baseUrl/welcome"
|
||||||
|
AllowedStatusCodes = @(200)
|
||||||
|
},
|
||||||
|
@{
|
||||||
|
Name = 'Frontdoor environment settings'
|
||||||
|
Url = "$baseUrl/envsettings.json"
|
||||||
|
AllowedStatusCodes = @(200)
|
||||||
|
},
|
||||||
|
@{
|
||||||
|
Name = 'Authority discovery'
|
||||||
|
Url = "$baseUrl/.well-known/openid-configuration"
|
||||||
|
AllowedStatusCodes = @(200)
|
||||||
|
},
|
||||||
|
@{
|
||||||
|
Name = 'Authority authorize bootstrap'
|
||||||
|
Url = "$baseUrl/connect/authorize?client_id=stella-ops-ui&redirect_uri=https%3A%2F%2Fstella-ops.local%2Fauth%2Fcallback&response_type=code&scope=openid%20profile%20email&state=setup-smoke&nonce=setup-smoke&code_challenge=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&code_challenge_method=S256"
|
||||||
|
AllowedStatusCodes = @(200, 302, 303)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Step 'Waiting for frontdoor bootstrap readiness'
|
||||||
|
|
||||||
|
foreach ($probe in $probes) {
|
||||||
|
$statusCode = Test-ExpectedHttpStatus $probe.Url $probe.AllowedStatusCodes -timeoutSeconds 5 -attempts 24 -retryDelaySeconds 5
|
||||||
|
if ($null -ne $statusCode) {
|
||||||
|
Write-Ok "$($probe.Name) (HTTP $statusCode)"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Fail "$($probe.Name) did not reach an expected status ($($probe.AllowedStatusCodes -join '/'))"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
# ─── 8. Smoke test ─────────────────────────────────────────────────────────
|
# ─── 8. Smoke test ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function Test-Smoke {
|
function Test-Smoke {
|
||||||
@@ -559,6 +619,14 @@ function Test-Smoke {
|
|||||||
$hasBlockingFailures = $true
|
$hasBlockingFailures = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not $InfraOnly) {
|
||||||
|
if (Test-FrontdoorBootstrap) {
|
||||||
|
Write-Ok 'Frontdoor bootstrap path is ready for first-user sign-in'
|
||||||
|
} else {
|
||||||
|
$hasBlockingFailures = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Platform container health summary
|
# Platform container health summary
|
||||||
Write-Step 'Container health summary'
|
Write-Step 'Container health summary'
|
||||||
Push-Location $ComposeDir
|
Push-Location $ComposeDir
|
||||||
@@ -679,7 +747,8 @@ if ($InfraOnly) {
|
|||||||
Start-Infrastructure
|
Start-Infrastructure
|
||||||
$infraSmokeFailed = Test-Smoke
|
$infraSmokeFailed = Test-Smoke
|
||||||
if ($infraSmokeFailed) {
|
if ($infraSmokeFailed) {
|
||||||
Write-Warn 'Infrastructure started with blocking smoke failures. Review output and docker compose logs.'
|
Write-Fail 'Infrastructure setup did not pass blocking smoke tests. Review output and docker compose logs.'
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
Write-Host "`nDone (infra only). Infrastructure is running." -ForegroundColor Green
|
Write-Host "`nDone (infra only). Infrastructure is running." -ForegroundColor Green
|
||||||
exit 0
|
exit 0
|
||||||
@@ -696,7 +765,8 @@ if (-not $SkipImages) {
|
|||||||
Start-Platform
|
Start-Platform
|
||||||
$platformSmokeFailed = Test-Smoke
|
$platformSmokeFailed = Test-Smoke
|
||||||
if ($platformSmokeFailed) {
|
if ($platformSmokeFailed) {
|
||||||
Write-Warn 'Setup completed with blocking smoke failures. Review output and docker compose logs.'
|
Write-Fail 'Setup did not pass blocking smoke tests. Review output and docker compose logs.'
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "`n=============================================" -ForegroundColor Green
|
Write-Host "`n=============================================" -ForegroundColor Green
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ http_status() {
|
|||||||
local status=""
|
local status=""
|
||||||
|
|
||||||
for (( attempt=1; attempt<=attempts; attempt++ )); do
|
for (( attempt=1; attempt<=attempts; attempt++ )); do
|
||||||
status=$(curl -s -o /dev/null --connect-timeout 5 -w '%{http_code}' "$url" 2>/dev/null || true)
|
status=$(curl -sk -o /dev/null --connect-timeout 5 -w '%{http_code}' "$url" 2>/dev/null || true)
|
||||||
if [[ -n "$status" && "$status" != "000" ]]; then
|
if [[ -n "$status" && "$status" != "000" ]]; then
|
||||||
printf '%s' "$status"
|
printf '%s' "$status"
|
||||||
return 0
|
return 0
|
||||||
@@ -353,16 +353,54 @@ http_status() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frontdoor_bootstrap_ready() {
|
||||||
|
step 'Waiting for frontdoor bootstrap readiness'
|
||||||
|
|
||||||
|
local probes=(
|
||||||
|
"Frontdoor readiness|https://stella-ops.local/health/ready|200"
|
||||||
|
"Frontdoor welcome page|https://stella-ops.local/welcome|200"
|
||||||
|
"Frontdoor environment settings|https://stella-ops.local/envsettings.json|200"
|
||||||
|
"Authority discovery|https://stella-ops.local/.well-known/openid-configuration|200"
|
||||||
|
"Authority authorize bootstrap|https://stella-ops.local/connect/authorize?client_id=stella-ops-ui&redirect_uri=https%3A%2F%2Fstella-ops.local%2Fauth%2Fcallback&response_type=code&scope=openid%20profile%20email&state=setup-smoke&nonce=setup-smoke&code_challenge=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&code_challenge_method=S256|200,302,303"
|
||||||
|
)
|
||||||
|
|
||||||
|
local entry name url allowed status matched
|
||||||
|
for entry in "${probes[@]}"; do
|
||||||
|
IFS='|' read -r name url allowed <<<"$entry"
|
||||||
|
status="$(http_status "$url" 24 5)"
|
||||||
|
matched=false
|
||||||
|
IFS=',' read -ra allowed_codes <<<"$allowed"
|
||||||
|
for code in "${allowed_codes[@]}"; do
|
||||||
|
if [[ "$status" == "$code" ]]; then
|
||||||
|
matched=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$matched" == "true" ]]; then
|
||||||
|
ok "$name (HTTP $status)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
fail "$name did not reach an expected status ($allowed)"
|
||||||
|
return 1
|
||||||
|
done
|
||||||
|
|
||||||
|
ok 'Frontdoor bootstrap path is ready for first-user sign-in'
|
||||||
|
}
|
||||||
|
|
||||||
# ─── 8. Smoke test ─────────────────────────────────────────────────────────
|
# ─── 8. Smoke test ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
smoke_test() {
|
smoke_test() {
|
||||||
step 'Running smoke tests'
|
step 'Running smoke tests'
|
||||||
|
local has_blocking_failures=false
|
||||||
|
|
||||||
# Infrastructure checks
|
# Infrastructure checks
|
||||||
if docker exec stellaops-dev-postgres pg_isready -U stellaops &>/dev/null; then
|
if docker exec stellaops-dev-postgres pg_isready -U stellaops &>/dev/null; then
|
||||||
ok 'PostgreSQL'
|
ok 'PostgreSQL'
|
||||||
else
|
else
|
||||||
warn 'PostgreSQL not responding'
|
warn 'PostgreSQL not responding'
|
||||||
|
has_blocking_failures=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local pong; pong=$(docker exec stellaops-dev-valkey valkey-cli ping 2>/dev/null || true)
|
local pong; pong=$(docker exec stellaops-dev-valkey valkey-cli ping 2>/dev/null || true)
|
||||||
@@ -370,6 +408,7 @@ smoke_test() {
|
|||||||
ok 'Valkey'
|
ok 'Valkey'
|
||||||
else
|
else
|
||||||
warn 'Valkey not responding'
|
warn 'Valkey not responding'
|
||||||
|
has_blocking_failures=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local rustfs_url rustfs_status
|
local rustfs_url rustfs_status
|
||||||
@@ -379,6 +418,7 @@ smoke_test() {
|
|||||||
ok "RustFS S3 endpoint (HTTP $rustfs_status)"
|
ok "RustFS S3 endpoint (HTTP $rustfs_status)"
|
||||||
else
|
else
|
||||||
warn 'RustFS S3 endpoint did not respond with an expected status (wanted 200/403)'
|
warn 'RustFS S3 endpoint did not respond with an expected status (wanted 200/403)'
|
||||||
|
has_blocking_failures=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local registry_url registry_status
|
local registry_url registry_status
|
||||||
@@ -388,6 +428,13 @@ smoke_test() {
|
|||||||
ok "Zot registry endpoint (HTTP $registry_status)"
|
ok "Zot registry endpoint (HTTP $registry_status)"
|
||||||
else
|
else
|
||||||
warn 'Zot registry endpoint did not respond with an expected status (wanted 200/401)'
|
warn 'Zot registry endpoint did not respond with an expected status (wanted 200/401)'
|
||||||
|
has_blocking_failures=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$INFRA_ONLY" != "true" ]]; then
|
||||||
|
if ! frontdoor_bootstrap_ready; then
|
||||||
|
has_blocking_failures=true
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Platform container health summary
|
# Platform container health summary
|
||||||
@@ -429,9 +476,14 @@ smoke_test() {
|
|||||||
ok 'Platform listening on https://stella-ops.local (TLS handshake pending)'
|
ok 'Platform listening on https://stella-ops.local (TLS handshake pending)'
|
||||||
else
|
else
|
||||||
warn 'Platform not yet accessible at https://stella-ops.local (may still be starting)'
|
warn 'Platform not yet accessible at https://stella-ops.local (may still be starting)'
|
||||||
|
has_blocking_failures=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
|
|
||||||
|
if [[ "$has_blocking_failures" == "true" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ─── Main ───────────────────────────────────────────────────────────────────
|
# ─── Main ───────────────────────────────────────────────────────────────────
|
||||||
@@ -454,7 +506,10 @@ ensure_env
|
|||||||
start_infra
|
start_infra
|
||||||
|
|
||||||
if [[ "$INFRA_ONLY" == "true" ]]; then
|
if [[ "$INFRA_ONLY" == "true" ]]; then
|
||||||
smoke_test
|
if ! smoke_test; then
|
||||||
|
fail 'Infrastructure setup did not pass blocking smoke tests. Review output and docker compose logs.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
echo ''
|
echo ''
|
||||||
echo 'Done (infra only). Infrastructure is running.'
|
echo 'Done (infra only). Infrastructure is running.'
|
||||||
exit 0
|
exit 0
|
||||||
@@ -473,7 +528,10 @@ if [[ "$SKIP_IMAGES" != "true" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
start_platform
|
start_platform
|
||||||
smoke_test
|
if ! smoke_test; then
|
||||||
|
fail 'Setup did not pass blocking smoke tests. Review output and docker compose logs.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo ''
|
echo ''
|
||||||
echo '============================================='
|
echo '============================================='
|
||||||
|
|||||||
Reference in New Issue
Block a user