Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save tcartwright/2415882c40f6d71ff136eb0d5e8f7f89 to your computer and use it in GitHub Desktop.

Select an option

Save tcartwright/2415882c40f6d71ff136eb0d5e8f7f89 to your computer and use it in GitHub Desktop.
POWERSHELL: Enforce IIS standard logging fields
Clear-Host
#Requires -RunAsAdministrator
Import-Module WebAdministration -ErrorAction Stop
$apphost = "MACHINE/WEBROOT/APPHOST"
$standardFlags = "Date,Time,ClientIP,UserName,SiteName,ComputerName,ServerIP,Method,UriStem,UriQuery,HttpStatus,HttpSubStatus,Win32Status,BytesSent,BytesRecv,TimeTaken,ServerPort,UserAgent,Referer,ProtocolVersion,Host"
$customFields = @(
@{ name = "X-Forwarded-For"; src = "X-Forwarded-For"; type = "RequestHeader" }
@{ name = "Correlation-ID"; src = "X-Correlation-ID"; type = "RequestHeader" }
@{ name = "TLS-Protocol"; src = "CRYPT_PROTOCOL"; type = "ServerVariable" }
)
# 1) Baseline at server level
Set-WebConfigurationProperty -PSPath $apphost -Filter "system.applicationHost/sites/siteDefaults/logFile" -Name logExtFileFlags -Value $standardFlags
Clear-WebConfiguration -PSPath $apphost -Filter "system.applicationHost/sites/siteDefaults/logFile/customFields"
foreach ($f in $customFields) {
Add-WebConfigurationProperty -PSPath $apphost -Filter "system.applicationHost/sites/siteDefaults/logFile/customFields" `
-Name "." -Value @{ logFieldName = $f.name; sourceName = $f.src; sourceType = $f.type }
}
# 2) Normalize each site: same standard flags, and clear per-site customFields so they inherit
foreach ($site in Get-Website) {
$filter = "system.applicationHost/sites/site[@name='$($site.Name)']/logFile"
Set-WebConfigurationProperty -PSPath $apphost -Filter $filter -Name logExtFileFlags -Value $standardFlags
Clear-WebConfiguration -PSPath $apphost -Filter "$filter/customFields" -ErrorAction SilentlyContinue
}
# Expected state (must match what enforcement applied)
$expectedFlags = ($standardFlags -split ',' | ForEach-Object { $_.Trim() } | Sort-Object)
$expectedCustom = $customFields | ForEach-Object { "$($_.name)|$($_.type)|$($_.src)" } | Sort-Object
$results = foreach ($site in Get-Website) {
$filter = "system.applicationHost/sites/site[@name='$($site.Name)']/logFile"
# Effective standard flags (compare as a SET - IIS reorders them)
$actualFlags = (Get-WebConfigurationProperty -PSPath $apphost -Filter $filter -Name logExtFileFlags).ToString() `
-split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ } | Sort-Object
$flagsOk = -not (Compare-Object $expectedFlags $actualFlags)
# Effective custom fields (inherited from siteDefaults + any local)
$cf = Get-WebConfigurationProperty -PSPath $apphost -Filter "$filter/customFields" -Name Collection
$actualCustom = @($cf | ForEach-Object {
"$($_.logFieldName)|$($_.sourceType)|$($_.sourceName)"
} | Sort-Object)
$customOk = -not (Compare-Object $expectedCustom $actualCustom)
# Surface what's wrong, if anything
$missingFlags = (Compare-Object $expectedFlags $actualFlags |
Where-Object SideIndicator -eq '<=').InputObject -join ','
$extraFlags = (Compare-Object $expectedFlags $actualFlags |
Where-Object SideIndicator -eq '=>').InputObject -join ','
[pscustomobject]@{
Site = $site.Name
FlagsOK = $flagsOk
CustomOK = $customOk
Pass = ($flagsOk -and $customOk)
Missing = $missingFlags
Extra = $extraFlags
}
}
Write-Host "`n=== Verification ===" -ForegroundColor Cyan
$results | Format-Table Site, FlagsOK, CustomOK, Pass, Missing, Extra -AutoSize
$failed = $results | Where-Object { -not $_.Pass }
if ($failed) {
Write-Host "`n$($failed.Count) site(s) FAILED validation." -ForegroundColor Red
$failed | ForEach-Object {
Write-Host " [$($_.Site)] flags=$($_.FlagsOK) custom=$($_.CustomOK) missing='$($_.Missing)' extra='$($_.Extra)'" -ForegroundColor Red
}
# exit 1 # uncomment if running as a pipeline task so the step fails loudly
} else {
Write-Host "`nAll $($results.Count) site(s) PASSED - effective logging settings match the standard." -ForegroundColor Green
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment