I'm using Windows Server 2019, Posh5.1, WebAdministrationDsc 4.1.0, and WebConfigPropertyCollection. I see I have to use 2 passes for the resource to do this way for multiple properties, so I populate an array in my psd1 data file then iterate over the collection like below, where I've seen comments in the issues github that this is the way. https://github.com/dsccommunity/WebAdministrationDsc/issues/534
("HttpCustomHeaderSts","IIS:\Sites\Default Web Site","system.applicationHost/sites","site","hsts","enabled","true","includeSubDomains","true","Present"),
("HttpCustomHeaderSts2","IIS:\Sites\Default Web Site","system.applicationHost/sites/site","site","hsts","enabled","true","redirectHttpToHttps","true","Present"),
$ConfigurationData.NonNodeData.Roles.([String]($Node.Role -eq "WEB")).ConfigColls.foreach({
WebConfigPropertyCollection $_[0]
{
WebsitePath = $_[1]
Filter = $_[2]
CollectionName = $_[3]
ItemName = $_[4]
ItemKeyName = $_[5]
ItemKeyValue = $_[6]
ItemPropertyName = $_[7]
ItemPropertyValue = $_[8]
Ensure = $_[9]
}
})
But I get:
Exception calling GetAddElementSchema with 1 argument(s): Invalid index.
Never mind. Rookie mistake on my end, where I didn't include the full error. This code 0x80070585 maps to The element specified by bstrElementName cannot be found. I stepped through the resource to hit that dead-end. I'll submit an edit, but I'm writing my own resource to do this that I'll provide. If you want to use though you'd need to append it to a library you don't use or create your own generic collection. I have one called xUtilityDsc I throw stuff like this into.
This seems to do the trick. First it's your schema.mof then the code.
[ClassVersion("1.0.0.0"), FriendlyName("xIisHsts")]
class xIisHsts : OMI_BaseResource
{
[Key] String Site;
[Write] Boolean Enabled;
[Write] Boolean RedirectHttpToHttps;
[Write] Boolean IncludeSubDomains;
[Write] Boolean Preload;
[Write] UInt32 Maxage;
[Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
};
Now Psm1 content:
<#
.SYNOPSIS
Returns HSTS settings for a passed in site name.
.PARAMETER Site
Site's hsts status.
#>
#Get-TargetResource "Default Web Site"
function Get-TargetResource
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param
(
# Name of the Firewall Rule
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Site
)
$siteElement = Get-IISConfigCollectionElement -ConfigCollection $sitesCollection -ConfigAttribute @{"name"=$Site}
return $hstsElement = Get-IISConfigElement -ConfigElement $siteElement -ChildElementName "hsts"
}
#Set-TargetResource -Site "Default Web Site" -Enabled $true -maxage 31536000 -redirectHttpToHttps $true -includeSubDomains $true -Ensure "Present" -preload $true
function Set-TargetResource
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[Boolean]
$Enabled,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Site,
[System.UInt32]
$maxage,
[Boolean]
$redirectHttpToHttps,
[Boolean]
$includeSubDomains,
[Boolean]
$preload,
[Parameter(Mandatory = $true)]
[ValidateSet("Present","Absent")]
[System.String]
$Ensure
)
Import-Module WebAdministration
If ($Ensure -eq "Absent")
{
Try{
Start-IISCommitDelay
$sitesCollection = Get-IISConfigSection -SectionPath "system.applicationHost/sites" | Get-IISConfigCollection
$siteElement = Get-IISConfigCollectionElement -ConfigCollection $sitesCollection -ConfigAttribute @{"name"=$Site}
$hstsElement = Get-IISConfigElement -ConfigElement $siteElement -ChildElementName "hsts" | Remove-IISConfigElement -Confirm:$false
Stop-IISCommitDelay
}
catch{
}
finally{
Write-Verbose "HSTS Failed"
}
}
else
{
Try{
Start-IISCommitDelay
$sitesCollection = Get-IISConfigSection -SectionPath "system.applicationHost/sites" | Get-IISConfigCollection
$siteElement = Get-IISConfigCollectionElement -ConfigCollection $sitesCollection -ConfigAttribute @{"name"=$Site}
$hstsElement = Get-IISConfigElement -ConfigElement $siteElement -ChildElementName "hsts"
Set-IISConfigAttributeValue -ConfigElement $hstsElement -AttributeName "max-age" -AttributeValue $maxage
Set-IISConfigAttributeValue -ConfigElement $hstsElement -AttributeName "includeSubDomains" -AttributeValue $includeSubDomains
Set-IISConfigAttributeValue -ConfigElement $hstsElement -AttributeName "preload" -AttributeValue $preload
Set-IISConfigAttributeValue -ConfigElement $hstsElement -AttributeName "redirectHttpToHttps" -AttributeValue $redirectHttpToHttps
Set-IISConfigAttributeValue -ConfigElement $hstsElement -AttributeName "enabled" -AttributeValue $Enabled
Stop-IISCommitDelay
}
catch{
}
finally{
Write-Verbose "HSTS Failed"
}
}
}
#Test-TargetResource -Site "Default Web Site" -Enabled $true -maxage 31536000 -redirectHttpToHttps $true -includeSubDomains $true -Ensure "Present" -preload $true
<#
.SYNOPSIS
Tests HSTS settings for a passed in site name.
.PARAMETER Site
Site's hsts status.
#>
function Test-TargetResource
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[Boolean]
$Enabled,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$Site,
[System.UInt32]
$maxage,
[Boolean]
$redirectHttpToHttps,
[Boolean]
$includeSubDomains,
[Boolean]
$preload,
[Parameter(Mandatory = $true)]
[ValidateSet("Present","Absent")]
[System.String]
$Ensure
)
Import-Module WebAdministration
[bool]$valid = $true
$butes = Get-IISConfigElement -ConfigElement (Get-IISConfigCollectionElement -ConfigCollection (Get-IISConfigSection -SectionPath "system.applicationHost/sites" | Get-IISConfigCollection) -ConfigAttribute @{"name"=$Site}) -ChildElementName "hsts"
if ($Ensure -eq "Absent" -and (![string]::IsNullOrWhiteSpace($butes.ElementTagName)))
{
$valid= $false
}
$butes.Attributes.ForEach({
if ($valid)
{
#write-host "name:$($_.name) value:$($_.value)"
if ($_.name -eq 'enabled'-and $_.value -ne $Enabled){$valid=$false}
if ($_.name -eq "max-age" -and $_.value -ne $maxage){$valid=$false}
if ($_.name -eq "redirectHttpToHttps" -and $_.value -ne $redirectHttpToHttps){$valid=$false}
if ($_.name -eq "includeSubDomains" -and $_.value -ne $includeSubDomains){$valid=$false}
if ($_.name -eq "preload" -and $_.value -ne $preload){$valid=$false}
}
})
#write-host $valid
If ($valid)
{$true}
else
{$false}
}
Export-ModuleMember -Function *-TargetResource