mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
fix(install): trust Docker bridge for dashboard metadata
## Summary Closes #2909. The `persistent-docker` installer now discovers Docker's default bridge gateway and passes the exact `/32` gateway CIDR to the proxy's dashboard metadata allowlist when no explicit `HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS` value is configured. This keeps the existing metadata gate intact while allowing the first-party loopback-published container to see its own Recent Requests and Per-Project Savings data. Explicit user configuration continues to take precedence. Both native wrappers (POSIX and PowerShell) use the same behavior, and installer integration coverage verifies the generated Docker command. ## Validation - `python -m pytest tests/test_install/test_native_installers.py -q -k bash` (1 skipped on Windows because Bash is unavailable) - PowerShell wrapper smoke test with the repository fake Docker shim: verified `docker network inspect bridge` is called and `HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS=172.17.0.1/32` is passed to `docker run` - Explicit allowlist smoke test: verified an existing `HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS` is preserved without adding a discovered default - `git diff --check` ## Real behavior proof Setup tested: Windows 11 host, PowerShell wrapper, repository fake Docker shim (Docker CLI is not installed in this environment). Exact command: `headroom.ps1 install apply --profile smoke --port 18999 --image fake/headroom:test`. Observed result: the generated Docker invocation included `docker network inspect bridge --format ...` and `--env HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS=172.17.0.1/32`, and the installer completed successfully. Not tested: a live Docker daemon/dashboard request on this host. --------- Co-authored-by: Tejas Chopra <tejas@Tejass-MacBook-Pro.local>
This commit is contained in:
parent
c85abf7a87
commit
e044139001
3 changed files with 170 additions and 3 deletions
|
|
@ -346,6 +346,29 @@ function Get-PersistentDockerArgs {
|
|||
return ,$args.ToArray()
|
||||
}
|
||||
|
||||
function Add-DashboardGatewayEnv {
|
||||
param([System.Collections.Generic.List[string]]$ArgsList)
|
||||
|
||||
# This default is safe only because the published dashboard port is bound
|
||||
# to the host loopback interface below. A host request published through
|
||||
# Docker's default bridge reaches the
|
||||
# container from the bridge gateway (for example, 172.17.0.1), not from
|
||||
# 127.0.0.1. Trust only that exact gateway by default so the dashboard's
|
||||
# metadata gate works for the first-party persistent Docker preset while
|
||||
# preserving an explicitly configured allowlist.
|
||||
if (Test-Path Env:HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS) {
|
||||
return
|
||||
}
|
||||
|
||||
$gateway = (& docker network inspect bridge --format '{{(index .IPAM.Config 0).Gateway}}' 2>$null | Out-String).Trim()
|
||||
if ($LASTEXITCODE -eq 0 -and $gateway) {
|
||||
$ArgsList.Add('--env')
|
||||
$ArgsList.Add("HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS=$gateway/32")
|
||||
} else {
|
||||
Write-Warning 'Could not determine Docker bridge gateway; dashboard metadata remains restricted'
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ManifestProxyArgs {
|
||||
param(
|
||||
[int]$Port,
|
||||
|
|
@ -492,8 +515,9 @@ function Start-PersistentDockerInstall {
|
|||
docker rm -f $containerName | Out-Null 2>$null
|
||||
|
||||
$dockerArgs = New-Object System.Collections.Generic.List[string]
|
||||
$dockerArgs.AddRange([string[]]@('run','-d','--restart','unless-stopped','--name',$containerName,'-p',"$Port`:$Port"))
|
||||
$dockerArgs.AddRange([string[]]@('run','-d','--restart','unless-stopped','--name',$containerName,'-p',"127.0.0.1`:$Port`:$Port"))
|
||||
$dockerArgs.AddRange((Get-PersistentDockerArgs))
|
||||
Add-DashboardGatewayEnv -ArgsList $dockerArgs
|
||||
$dockerArgs.AddRange([string[]]@(
|
||||
'--env',"HEADROOM_DEPLOYMENT_PROFILE=$Profile",
|
||||
'--env','HEADROOM_DEPLOYMENT_PRESET=persistent-docker',
|
||||
|
|
|
|||
|
|
@ -292,6 +292,29 @@ append_persistent_container_args() {
|
|||
append_passthrough_envs "$1"
|
||||
}
|
||||
|
||||
append_dashboard_gateway_env() {
|
||||
local -n ref=$1
|
||||
|
||||
# This default is safe only because the published dashboard port is bound
|
||||
# to the host loopback interface below. A host request published through
|
||||
# Docker's default bridge reaches the
|
||||
# container from the bridge gateway (for example, 172.17.0.1), not from
|
||||
# 127.0.0.1. Trust only that exact gateway by default so the dashboard's
|
||||
# metadata gate works for the first-party persistent Docker preset while
|
||||
# preserving an explicitly configured allowlist.
|
||||
if [[ -n "${HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS+x}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local gateway
|
||||
gateway="$(docker network inspect bridge --format '{{(index .IPAM.Config 0).Gateway}}' 2>/dev/null || true)"
|
||||
if [[ -n "${gateway}" ]]; then
|
||||
ref+=(--env "HEADROOM_PROXY_TRUSTED_DASHBOARD_CLIENT_CIDRS=${gateway}/32")
|
||||
else
|
||||
warn "Could not determine Docker bridge gateway; dashboard metadata remains restricted"
|
||||
fi
|
||||
}
|
||||
|
||||
build_manifest_proxy_args() {
|
||||
local -n out_args=$1
|
||||
local port="$2"
|
||||
|
|
@ -466,8 +489,9 @@ start_persistent_docker_install() {
|
|||
|
||||
docker rm -f "${container_name}" >/dev/null 2>&1 || true
|
||||
|
||||
args=(docker run -d --restart unless-stopped --name "${container_name}" -p "${port}:${port}")
|
||||
args=(docker run -d --restart unless-stopped --name "${container_name}" -p "127.0.0.1:${port}:${port}")
|
||||
append_persistent_container_args args
|
||||
append_dashboard_gateway_env args
|
||||
args+=(
|
||||
--env "HEADROOM_DEPLOYMENT_PROFILE=${profile}"
|
||||
--env "HEADROOM_DEPLOYMENT_PRESET=persistent-docker"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue