Repair a web.config that an earlier build made unusable
Some checks failed
CI / backend (push) Failing after 8s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 8s
CI / migrations-mysql (push) Failing after 7s

Stage 4 deliberately leaves an existing web.config alone, because operators put
real changes in it: extra MIME maps, a /installers location, bindings, a
proxy-specific rule. Overwriting reverts those silently.

That rule had no exception, and earlier builds of this installer wrote an
<allowedServerVariables> block which is fatal on its own: the section is Deny
by default, so IIS rejects the entire file with 500.52 before
httpPlatformHandler runs. Any server already installed would therefore keep the
broken file forever, with re-running the fixed installer powerless to help,
since the first thing stage 4 does is decline to touch it.

Strip just that element, keeping every other edit, and only when it contains
nothing besides the variable this installer adds. A block holding anything else
is somebody's deliberate change and is left alone with a warning. The previous
file is copied to web.config.before-xff-fix first.

Exercised against four inputs: the file earlier builds wrote, which is repaired
and still parses as XML with the rewrite rule intact; a block with an
operator-added variable, which is left unchanged; an empty block, which is the
$null.Count trap under Set-StrictMode 2.0 and is why the filter is wrapped in
@(); and an already-correct file, which is a no-op.
This commit is contained in:
cproudlock
2026-08-04 20:06:47 -04:00
parent 95b0b77c13
commit aeee210cf6

View File

@@ -1699,6 +1699,40 @@ has to come from the bundle either way.
if (Test-Path $dstCfg) { if (Test-Path $dstCfg) {
Write-Log 'web.config already exists; leaving it alone' 'OK' Write-Log 'web.config already exists; leaving it alone' 'OK'
$existing = Get-Content $dstCfg -Raw $existing = Get-Content $dstCfg -Raw
# ONE EXCEPTION to leaving it alone. An <allowedServerVariables> block is
# fatal by itself: that section is Deny by default, so IIS rejects the
# whole file with 500.52 (0x80070021) before httpPlatformHandler runs.
# The app never starts and its stdout log stays empty, which reads as a
# broken application and is not one.
#
# Earlier builds of THIS installer wrote exactly that block, so honouring
# "leave it alone" without qualification would leave every server already
# installed permanently unable to start, with re-running powerless to fix
# it. Strip just that element and keep every other edit - and only when it
# contains nothing but the variable this installer puts there, because
# anything else is somebody's deliberate change.
if ($existing -match '(?s)<allowedServerVariables>(.*?)</allowedServerVariables>') {
$inner = $Matches[1]
$names = [regex]::Matches($inner, 'name\s*=\s*"([^"]+)"') |
ForEach-Object { $_.Groups[1].Value }
# @() around the pipeline: a zero-match filter returns $null, and
# $null.Count is a terminating error under Set-StrictMode 2.0.
$foreign = @($names | Where-Object { $_ -ne 'HTTP_X_FORWARDED_FOR' }).Count
if ($foreign -gt 0) {
Write-Log 'web.config declares <allowedServerVariables> holding variables this installer did not add' 'WARN'
Write-Log ' IIS returns 500.52 unless that section is unlocked server-wide; left unchanged' 'WARN'
} elseif (-not $WhatIfOnly) {
$backup = "$dstCfg.before-xff-fix"
Copy-Item $dstCfg $backup -Force
$fixed = $existing -replace '(?s)[ \t]*<allowedServerVariables>.*?</allowedServerVariables>\r?\n?', ''
Set-Content -Path $dstCfg -Value $fixed -Encoding UTF8
Write-Log 'removed <allowedServerVariables> from web.config; it made IIS return 500.52' 'OK'
Write-Log " the previous file is kept at $backup"
$existing = $fixed
}
}
$hasRule = $existing -match '<rewrite>' -and $existing -notmatch 'SHOPDB-CLIENTIP-BEGIN' $hasRule = $existing -match '<rewrite>' -and $existing -notmatch 'SHOPDB-CLIENTIP-BEGIN'
if ($ClientIpSource -eq 'direct' -and -not $hasRule) { if ($ClientIpSource -eq 'direct' -and -not $hasRule) {
Write-Log 'this web.config does NOT set X-Forwarded-For; client IPs will read as 127.0.0.1' 'WARN' Write-Log 'this web.config does NOT set X-Forwarded-For; client IPs will read as 127.0.0.1' 'WARN'