WebAdministrationDsc icon indicating copy to clipboard operation
WebAdministrationDsc copied to clipboard

xWebConfigPropertyCollection: braces not accepted in ItemKeyValue

Open trolleyboy opened this issue 6 years ago • 3 comments

Details of the scenario you tried and the problem that is occurring

I'm trying to add a URL Rewrite condition that has the ItemKeyValue "{HTTPS}". When applying this via DSC, I get this error logged to the DSC Operational log:

MIResult: 1 Error Message: The PowerShell DSC resource '[xWebConfigPropertyCollection]HSTS_Condition' with SourceInfo '::688::9::xWebConfigPropertyCollection' threw one or more non-terminating errors while running the Test-TargetResource functionality. These errors are logged to the ETW channel called Microsoft-Windows-DSC/Operational. Refer to this channel for more details. Message ID: NonTerminatingErrorFromProvider Error Category: 7 Error Code: 1 Error Type: MI

Troubleshooting and trying to manually add this using the Add-WebConfigurationProperty cmdlet, the condition is not fully added. Example:

add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -Filter "system.webServer/rewrite/outboundRules/rule[@name='Add Strict-Transport-Security when HTTPS']/conditions" -name "." -value @{name='{HTTPS}'}

results in this being added to the applicationHost.config:

<conditions>
<add />
</conditions>

Running the same DSC resource and powershell cmdlet without the { } around the HTTPS results in the condition being added correctly - obviously missing the { } braces.

I'm not sure if this is an escaping issue to do with the braces that I'm missing, or if there is something in the background that is unable to handle them correctly. If it's a simple escaping issue, any help pointing me in the right direction is appreciated.

The DSC configuration that is used to reproduce the issue (as detailed as possible)

xWebConfigPropertyCollection HSTS_Condition {
            WebsitePath = 'MACHINE/WEBROOT/APPHOST'
            Filter      = "system.webServer/rewrite/outboundRules/rule[@name='Add Strict-Transport-Security when HTTPS']"
            CollectionName = 'conditions'
            ItemName = 'add'
            ItemKeyName = 'input'
            ItemKeyValue = "{HTTPS}"
            ItemPropertyName = 'pattern'
            ItemPropertyValue = 'on'
            Ensure = 'Present'
            DependsOn = '[xWebConfigPropertyCollection]OutboundRuleName_HSTS'
        }

The operating system the target node is running

OsName               : Microsoft Windows Server 2012 R2 Datacenter
OsOperatingSystemSKU : DatacenterServerEdition
OsArchitecture       : 64-bit
WindowsBuildLabEx    : 9600.19376.amd64fre.winblue_ltsb_escrow.190520-1700
OsLanguage           : en-US
OsMuiLanguages       : {en-US}

Version and build of PowerShell the target node is running

Name                           Value
----                           -----
PSVersion                      5.1.14409.1005
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14409.1005
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Version of the DSC module that was used ('dev' if using current dev branch)

PowerShell      WebApplicationHandler     xWebAdministration             2.6.0.0
PowerShell      xIisFeatureDelegation     xWebAdministration             2.6.0.0
PowerShell      xIisHandler               xWebAdministration             2.6.0.0
PowerShell      xIisLogging               xWebAdministration             2.6.0.0
PowerShell      xIisMimeTypeMapping       xWebAdministration             2.6.0.0
PowerShell      xIisModule                xWebAdministration             2.6.0.0
PowerShell      xSSLSettings              xWebAdministration             2.6.0.0
PowerShell      xWebApplication           xWebAdministration             2.6.0.0
PowerShell      xWebAppPool               xWebAdministration             2.6.0.0
PowerShell      xWebAppPoolDefaults       xWebAdministration             2.6.0.0
PowerShell      xWebConfigKeyValue        xWebAdministration             2.6.0.0
PowerShell      xWebConfigProperty        xWebAdministration             2.6.0.0
PowerShell      xWebConfigPropertyColl... xWebAdministration             2.6.0.0
PowerShell      xWebsite                  xWebAdministration             2.6.0.0
PowerShell      xWebSiteDefaults          xWebAdministration             2.6.0.0
PowerShell      xWebVirtualDirectory      xWebAdministration             2.6.0.0

trolleyboy avatar Jul 03 '19 04:07 trolleyboy

Nice timing. I actually ran into this issue recently as well.

I could not find a way to properly escape the key name for the XPath query. However, I was able to partially fix the issue on my local copy of the module by tweaking this in Get-ItemValues

From

    $filter = "$($Filter)/$($CollectionName)/$($ItemName)[@$($ItemKeyName)='$($ItemKeyValue)']"

    $item = Get-WebConfigurationProperty `
                -PSPath $WebsitePath `
                -Filter $filter `
                -Location $Location `
                -Name "." `
                -ErrorAction SilentlyContinue

To

    $filter = "$($Filter)/$($CollectionName)/$($ItemName)"

    $item = Get-WebConfigurationProperty `
                -PSPath $WebsitePath `
                -Filter $filter `
                -Location $Location `
                -Name "." `
                -ErrorAction SilentlyContinue |
                Where-Object -FilterScript {$_.$ItemKeyName -eq $ItemKeyValue}

That handles Get and Test. Set is already fine when an item with that key doesn't already exist. I still haven't quite figured out how to make Set work when the item does already exist with an incorrect property value. A similar approach doesn't seem to work since the item returned by Get-WebConfigurationProperty is read-only and and other specifiers on Set-WebConfigurationProperty (like -AtElement) just build a similar, broken XPath string.

psychonic avatar Jul 05 '19 15:07 psychonic

To escape the XPath Query you just have to double up the brackets, but doing this in one of the parameters would cause other lookup steps to fail. I managed to get it working by updating any of the filter values to replace any single '{' or '}' with '{{' or '}}'

$filter = "$($Filter)/$($CollectionName)/$($ItemName)[@$($ItemKeyName)='$($ItemKeyValue.Replace('{','{{').Replace('}','}}'))']"

No idea if this is best practice or not.

LeftCoastBC avatar Jan 20 '20 23:01 LeftCoastBC