我如何在 powershell 中验证 IIS web.config
how do i validate an IIS web.config in powershell
不幸的是,在 IIS 中,如果您在 wwwroot\web.config 和 wwwroot\myapp\web.config 中定义相同的设置,某些类型的设置将相互冲突,从而导致 500.19 错误。
例如允许的动词:
<security>
<requestFiltering>
<verbs allowUnlisted="false">
<add verb="HEAD" allowed="true" />
<add verb="POST" allowed="true" />
<add verb="GET" allowed="true" />
</verbs>
</requestFiltering>
</security>
此外,不幸的是,PowerShell Set-WebConfiguration 在进行更改之前不会对此进行验证,一旦损坏,您将无法删除错误的配置。
我需要一种方法来验证配置 before/after 更改,以便我可以回滚它或采取行动。
我找到了这个解决方案:https://serverfault.com/questions/708079/is-there-a-cmd-tool-to-check-a-web-config-file-for-validity 但是它只验证 SYNTAX 失败或仅验证非常重要的配置问题。
它不检测其他过滤器路径的冲突:
例如无法添加唯一键属性 'verb' 设置为 'HEAD'
类型 'add' 的重复集合条目
我发现解决这个问题的方法是创建一个读取 web.config 的函数,通过解析 xml 编译过滤器列表,然后为每个过滤器执行 get-webconfiguration,过滤器将 return 一些东西,什么都没有(如果没有要读取的设置)或异常(我们关心的)
代码:
function Test-IISWebAppConfigIsValid
{
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineBYPropertyName=$true)]
[string]$AppName,
[string]$SiteName='Default Web Site'
)
process
{
$Result = @{
IsValid=$false;
SiteName=$SiteName
AppName=$AppName
}
try
{
$result.Add("FileInfo",(Get-WebConfigFile -PSPath "IIS:\Sites$SiteName$AppName"))
$Result.Add("FileExists",$result.FileInfo.Exists)
$result.Add("IsXML",$False)
#load the web.config
[xml]$ConfigXML = $result.FileInfo | Get-Content
$result.IsXML = $true
#find all the elements in the config file
$Elements = $ConfigXML.SelectNodes("//node()[name() != 'add' and name() != 'remove' and name() != 'clear']")
#extract the filters from the xpath by finding all the configured elements
$FilterList = @()
foreach ($el in $Elements)
{
$FilterStack = @()
$tempel = $el
while ($tempel.ParentNode -and $tempel -ne $ConfigXML.DocumentElement -and $tempel -ne $ConfigXML)
{
$name = $tempel.get_name()
if ($tempel.NodeType -eq 'Element')
{
$FilterSTack += $name
}
$tempel = $tempel.ParentNode
}
if ($FilterStack.Count -gt 0) {
[array]::Reverse($FilterStack)
$FilterList += "/"+[string]::Join("/",$FilterStack)
}
}
$Result.Add("FilterList", ($FilterList | Sort-Object -Unique))
#load the configuration for each xpath
if (($result.FilterList | Measure-Object).Count -gt 0) {
Get-WebConfiguration -PSPath "IIS:\Sites$SiteName$AppName" -Filter $result.FilterList | Out-Null
}
$result.IsValid=$true
}
catch [System.Exception]
{
$result.Add("Exception",$_.Exception)
}
finally
{
write-output ([PSCustomObject]$result)
}
}#process
}#function Test-IISWebAppConfigIsValid
'myapp1','myapp2' | Test-IISWebAppConfigIsValid |ft -Property AppName,FileExists,IsValid,Exception -AutoSize
输出:
AppName FileExists IsValid Exception
------- ---------- ------- ---------
myapp1 True False System.Runtime.InteropServices.COMException (0x800700B7): Filename: \?\C:\inetpub\wwwroot\myapp1\web.config...
myapp2 True True
不幸的是,在 IIS 中,如果您在 wwwroot\web.config 和 wwwroot\myapp\web.config 中定义相同的设置,某些类型的设置将相互冲突,从而导致 500.19 错误。
例如允许的动词:
<security>
<requestFiltering>
<verbs allowUnlisted="false">
<add verb="HEAD" allowed="true" />
<add verb="POST" allowed="true" />
<add verb="GET" allowed="true" />
</verbs>
</requestFiltering>
</security>
此外,不幸的是,PowerShell Set-WebConfiguration 在进行更改之前不会对此进行验证,一旦损坏,您将无法删除错误的配置。
我需要一种方法来验证配置 before/after 更改,以便我可以回滚它或采取行动。
我找到了这个解决方案:https://serverfault.com/questions/708079/is-there-a-cmd-tool-to-check-a-web-config-file-for-validity 但是它只验证 SYNTAX 失败或仅验证非常重要的配置问题。
它不检测其他过滤器路径的冲突: 例如无法添加唯一键属性 'verb' 设置为 'HEAD'
类型 'add' 的重复集合条目我发现解决这个问题的方法是创建一个读取 web.config 的函数,通过解析 xml 编译过滤器列表,然后为每个过滤器执行 get-webconfiguration,过滤器将 return 一些东西,什么都没有(如果没有要读取的设置)或异常(我们关心的)
代码:
function Test-IISWebAppConfigIsValid
{
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineBYPropertyName=$true)]
[string]$AppName,
[string]$SiteName='Default Web Site'
)
process
{
$Result = @{
IsValid=$false;
SiteName=$SiteName
AppName=$AppName
}
try
{
$result.Add("FileInfo",(Get-WebConfigFile -PSPath "IIS:\Sites$SiteName$AppName"))
$Result.Add("FileExists",$result.FileInfo.Exists)
$result.Add("IsXML",$False)
#load the web.config
[xml]$ConfigXML = $result.FileInfo | Get-Content
$result.IsXML = $true
#find all the elements in the config file
$Elements = $ConfigXML.SelectNodes("//node()[name() != 'add' and name() != 'remove' and name() != 'clear']")
#extract the filters from the xpath by finding all the configured elements
$FilterList = @()
foreach ($el in $Elements)
{
$FilterStack = @()
$tempel = $el
while ($tempel.ParentNode -and $tempel -ne $ConfigXML.DocumentElement -and $tempel -ne $ConfigXML)
{
$name = $tempel.get_name()
if ($tempel.NodeType -eq 'Element')
{
$FilterSTack += $name
}
$tempel = $tempel.ParentNode
}
if ($FilterStack.Count -gt 0) {
[array]::Reverse($FilterStack)
$FilterList += "/"+[string]::Join("/",$FilterStack)
}
}
$Result.Add("FilterList", ($FilterList | Sort-Object -Unique))
#load the configuration for each xpath
if (($result.FilterList | Measure-Object).Count -gt 0) {
Get-WebConfiguration -PSPath "IIS:\Sites$SiteName$AppName" -Filter $result.FilterList | Out-Null
}
$result.IsValid=$true
}
catch [System.Exception]
{
$result.Add("Exception",$_.Exception)
}
finally
{
write-output ([PSCustomObject]$result)
}
}#process
}#function Test-IISWebAppConfigIsValid
'myapp1','myapp2' | Test-IISWebAppConfigIsValid |ft -Property AppName,FileExists,IsValid,Exception -AutoSize
输出:
AppName FileExists IsValid Exception
------- ---------- ------- ---------
myapp1 True False System.Runtime.InteropServices.COMException (0x800700B7): Filename: \?\C:\inetpub\wwwroot\myapp1\web.config...
myapp2 True True