Repair a web.config that an earlier build made unusable
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:
@@ -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'
|
||||||
|
|||||||
Reference in New Issue
Block a user