From 5645e18dea7ff2d6800fa71923cf015aa9844b2a Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Fri, 24 Apr 2015 11:34:41 -0500 Subject: [PATCH 1/2] Initial commit to merger PHO cWebsite to xWebsite --- DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 | 458 +++++++++++------- .../MSFT_xWebsite/MSFT_xWebsite.schema.mof | 37 +- 2 files changed, 295 insertions(+), 200 deletions(-) diff --git a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 index 1a372dfab..a454a5645 100644 --- a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 +++ b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 @@ -12,9 +12,11 @@ WebsiteUpdateFailureError=Failure to successfully update the properties for webs WebsiteBindingUpdateFailureError=Failure to successfully update the bindings for website "{0}". WebsiteBindingInputInvalidationError=Desired website bindings not valid for website "{0}". WebsiteCompareFailureError=Failure to successfully compare properties for website "{0}". -WebBindingCertifcateError=Failure to add certificate to web binding. Please make sure that the certificate thumbprint "{0}" is valid. +WebBindingCertifcateError=Failure to add certificate to web binding. WebsiteStateFailureError=Failure to successfully set the state of the website {0}. -WebsiteBindingConflictOnStartError = Website "{0}" could not be started due to binding conflict. Ensure that the binding information for this website does not conflict with any existing website's bindings before trying to start it. +WebsiteBindingMissingCertificateInformation=HTTPS binding on port {0} for website "{1}" must have CertificateThumbprint and CertificateStoreName properties. +WebsiteBindingCertificateNotInstalled=Certificate {0} was not found for HTTPS binding on port {1} for website "{2}". +WebsiteBindingCertificateMissingPrivateKey=No private key found for certificate {0}, for HTTPS binding on port {1} for website "{2}". '@ } @@ -27,8 +29,16 @@ function Get-TargetResource ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] - [string]$Name + [string]$Name, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$PhysicalPath ) + # The LCM requires Get-TargetResource to take all Key AND Required properties as parameters, even though + # the Required properties such as PhysicalPath are really part of Get-TargetResource's output, not its + # input. This is probably an LCM bug. + # We're not actually doing anything with whatever value was passed in to $PhysicalPath here. $getTargetResourceResult = $null; @@ -38,7 +48,7 @@ function Get-TargetResource Throw "Please ensure that WebAdministration module is installed." } - $Website = Get-Website -Name $Name + $Website = Get-Website | Where-Object {$_.Name -eq $name} if ($Website.count -eq 0) # No Website exists with this name. { @@ -54,11 +64,8 @@ function Get-TargetResource $CimBindings = foreach ($binding in $bindings) { $BindingObject = get-WebBindingObject -BindingInfo $binding - New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;IPAddress=$BindingObject.IPaddress;HostName=$BindingObject.Hostname;CertificateThumbprint=$BindingObject.CertificateThumbprint;CertificateStoreName=$BindingObject.CertificateStoreName} -ClientOnly + New-CimInstance -ClassName PSHOrg_cWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;IPAddress=$BindingObject.IPaddress;HostName=$BindingObject.Hostname;CertificateThumbprint=$BindingObject.CertificateThumbprint;CertificateStoreName=$BindingObject.CertificateStoreName} -ClientOnly } - - $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path "IIS:\sites\" $Name) |%{Write-Output $_.value}) - } else # Multiple websites with the same name exist. This is not supported and is an error { @@ -80,14 +87,14 @@ function Get-TargetResource ID = $Website.id; ApplicationPool = $Website.applicationPool; BindingInfo = $CimBindings; - DefaultPage = $allDefaultPage + webConfigProp = $CimWebConfigProp; } return $getTargetResourceResult; } -# The Set-TargetResource cmdlet is used to create, delete or configuure a website on the target machine. +# The Set-TargetResource cmdlet is used to create, delete or configure a website on the target machine. function Set-TargetResource { [CmdletBinding(SupportsShouldProcess=$true)] @@ -111,7 +118,7 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]]$BindingInfo, - [string[]]$DefaultPage + [Microsoft.Management.Infrastructure.CimInstance[]]$webConfigProp ) @@ -127,22 +134,21 @@ function Set-TargetResource #Remove bindings from parameters if they exist #Bindings will be added to site using separate cmdlet $Result = $psboundparameters.Remove("BindingInfo"); - - #Remove default pages from parameters if they exist - #Default Pages will be added to site using separate cmdlet - $Result = $psboundparameters.Remove("DefaultPage"); + + #Remove web configuration properties from parameters if they exist + #web configuration properties will be added to site using separate cmdlet + $Result = $psboundparameters.Remove("webConfigProp"); # Check if WebAdministration module is present for IIS cmdlets if(!(Get-Module -ListAvailable -Name WebAdministration)) { Throw "Please ensure that WebAdministration module is installed." } - $website = get-website $Name + $website = Get-Website | Where-Object {$_.Name -eq $name} if($website -ne $null) { #update parameters as required - $UpdateNotRequired = $true #Update Physical Path if required @@ -154,6 +160,82 @@ function Set-TargetResource Write-Verbose("Physical path for website $Name has been updated to $PhysicalPath"); } + #Update Web Configuration Properties if needed + if ($webConfigProp -ne $null) + { + foreach ($prop in $webConfigProp) + { + #if location has a value we need to combine it with pspath to do get-webconfigurationproperty + if($prop.CimInstanceProperties["Location"].Value) + { + $PSPath = $prop.CimInstanceProperties["PSPath"].Value + "/" + $prop.CimInstanceProperties["Location"].Value + } + else + { + $PSPath = $prop.CimInstanceProperties["PSPath"].Value + } + + Try + { + $propObject = Get-WebConfigurationProperty -Filter $prop.CimInstanceProperties["Filter"].Value -PSPath $PSPath -Name $prop.CimInstanceProperties["Name"].Value | Select Value + } + Catch [System.IO.FileNotFoundException] + { + Write-Warning("Exception: $($_.Exception.Message)") + } + + if($propObject -ne $null) + { + #get-webconfigurationproperty returns values differently depending on the property so we have to check if .Value is null or not and proceed accordingly + if($propObject[0].Value) + { + if($propObject[0].Value.toString() -ne $prop.CimInstanceProperties["Value"].Value.toString())#produces inconsistent results without toString + { + $UpdateNotRequired = $false + + #use the location parameter if it is specified + if($prop.CimInstanceProperties["Location"].Value) + { + Set-WebConfigurationProperty -filter $prop.CimInstanceProperties["Filter"].Value -pspath $prop.CimInstanceProperties["PSPath"].Value -location $prop.CimInstanceProperties["Location"].Value -name $prop.CimInstanceProperties["Name"].Value -value $prop.CimInstanceProperties["Value"].Value + } + else + { + Set-WebConfigurationProperty -filter $prop.CimInstanceProperties["Filter"].Value -pspath $prop.CimInstanceProperties["PSPath"].Value -name $prop.CimInstanceProperties["Name"].Value -value $prop.CimInstanceProperties["Value"].Value + } + + $propName = $prop.CimInstanceProperties["Name"].Value + Write-Verbose("$propName for website $Name have been updated.") + } + } + else + { + if($propObject[0].toString() -ne $prop.CimInstanceProperties["Value"].Value.toString())#produces inconsistent results without toString + { + $UpdateNotRequired = $false + + #use the location parameter if it is specified + if($prop.CimInstanceProperties["Location"].Value) + { + Set-WebConfigurationProperty -filter $prop.CimInstanceProperties["Filter"].Value -pspath $prop.CimInstanceProperties["PSPath"].Value -location $prop.CimInstanceProperties["Location"].Value -name $prop.CimInstanceProperties["Name"].Value -value $prop.CimInstanceProperties["Value"].Value + } + else + { + Set-WebConfigurationProperty -filter $prop.CimInstanceProperties["Filter"].Value -pspath $prop.CimInstanceProperties["PSPath"].Value -name $prop.CimInstanceProperties["Name"].Value -value $prop.CimInstanceProperties["Value"].Value + } + + $propName = $prop.CimInstanceProperties["Name"].Value + Write-Verbose("$propName for website $Name have been updated.") + } + } + } + else + { + Write-Warning("Could not find $PSPath " + $prop.CimInstanceProperties["Filter"].Value + " " + $prop.CimInstanceProperties["Name"].Value) + } + + } + } + #Update Bindings if required if ($BindingInfo -ne $null) { @@ -176,98 +258,41 @@ function Set-TargetResource Write-Verbose("Application Pool for website $Name has been updated to $ApplicationPool") } - #Update Default pages if required - if($DefaultPage -ne $null) - { - UpdateDefaultPages -Name $Name -DefaultPage $DefaultPage - } - #Update State if required if($website.state -ne $State -and $State -ne "") { - $UpdateNotRequired = $false - if($State -eq "Started") + try { - # Ensure that there are no other websites with binding information that will conflict with this site before starting - $existingSites = Get-Website | Where Name -ne $Name - - foreach($site in $existingSites) + $UpdateNotRequired = $false + if($State -eq "Started") { - $siteInfo = Get-TargetResource -Name $site.name - - foreach ($binding in $BindingInfo) - { - #Normalize empty IPAddress to "*" - if($binding.IPAddress -eq "" -or $binding.IPAddress -eq $null) - { - $NormalizedIPAddress = "*" - } - else - { - $NormalizedIPAddress = $binding.IPAddress - } - - if( !(EnsurePortIPHostUnique -Port $Binding.Port -IPAddress $NormalizedIPAddress -HostName $binding.HostName -BindingInfo $siteInfo.BindingInfo -UniqueInstances 1)) - { - #return error & Do not start Website - $errorId = "WebsiteBindingConflictOnStart"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult - $errorMessage = $($LocalizedData.WebsiteBindingConflictOnStartError) -f ${Name} - $exception = New-Object System.InvalidOperationException $errorMessage - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - - $PSCmdlet.ThrowTerminatingError($errorRecord); - } - } + + Start-Website -Name $Name + } - - try + else { + Stop-Website -Name $Name + } - Start-Website -Name $Name + Write-Verbose("State for website $Name has been updated to $State"); - } - catch - { - $errorId = "WebsiteStateFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f ${Name} ; - $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage ; - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - - $PSCmdlet.ThrowTerminatingError($errorRecord); - } - } - else + catch { - try - { + $errorId = "WebsiteStateFailure"; + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; + $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f ${Name} ; + $exception = New-Object System.InvalidOperationException $errorMessage ; + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - Stop-Website -Name $Name - - } - catch - { - $errorId = "WebsiteStateFailure"; - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f ${Name} ; - $errorMessage += $_.Exception.Message - $exception = New-Object System.InvalidOperationException $errorMessage ; - $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - - $PSCmdlet.ThrowTerminatingError($errorRecord) - } + $PSCmdlet.ThrowTerminatingError($errorRecord); } - - Write-Verbose("State for website $Name has been updated to $State"); - } if($UpdateNotRequired) { - Write-Verbose("Website $Name already exists and properties do not need to be udpated."); + Write-Verbose("Website $Name already exists and properties do not need to be updated."); } @@ -276,9 +301,18 @@ function Set-TargetResource { try { - $Website = New-Website @psboundparameters + $Websites = Get-Website + if ($Websites -eq $null) + { + # We do not have any sites this will cause a break in 2008R2 + $Website = New-Website @psboundparameters -ID 0 + } + else + { + $Website = New-Website @psboundparameters + } $Result = Stop-Website $Website.name -ErrorAction Stop - + #Clear default bindings if new bindings defined and are different if($BindingInfo -ne $null) { @@ -288,12 +322,24 @@ function Set-TargetResource } } - #Add Default pages for new created website - if($DefaultPage -ne $null) + #Update Web Configuration Properties if needed + if ($webConfigProp -ne $null) { - UpdateDefaultPages -Name $Name -DefaultPage $DefaultPage - } + foreach ($prop in $webConfigProp) + { + + #use the location parameter if it is specified + if($prop.CimInstanceProperties["Location"].Value) + { + Set-WebConfigurationProperty -filter $prop.CimInstanceProperties["Filter"].Value -pspath $prop.CimInstanceProperties["PSPath"].Value -location $prop.CimInstanceProperties["Location"].Value -name $prop.CimInstanceProperties["Name"].Value -value $prop.CimInstanceProperties["Value"].Value + } + else + { + Set-WebConfigurationProperty -filter $prop.CimInstanceProperties["Filter"].Value -pspath $prop.CimInstanceProperties["PSPath"].Value -name $prop.CimInstanceProperties["Name"].Value -value $prop.CimInstanceProperties["Value"].Value + } + } + } Write-Verbose("successfully created website $Name") #Start site if required @@ -306,17 +352,16 @@ function Set-TargetResource } Write-Verbose("successfully started website $Name") - } catch - { + { $errorId = "WebsiteCreationFailure"; $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebsiteCreationFailureError) -f ${Name} ; - $errorMessage += $_.Exception.Message + $errorMessage = $($LocalizedData.FeatureCreationFailureError) -f ${Name} ; $exception = New-Object System.InvalidOperationException $errorMessage ; $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null - $PSCmdlet.ThrowTerminatingError($errorRecord); + + $PSCmdlet.ThrowTerminatingError($errorRecord); } } } @@ -324,7 +369,7 @@ function Set-TargetResource { try { - $website = get-website $Name + $website = Get-Website | Where-Object {$_.Name -eq $name} if($website -ne $null) { Remove-website -name $Name @@ -341,7 +386,6 @@ function Set-TargetResource $errorId = "WebsiteRemovalFailure"; $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; $errorMessage = $($LocalizedData.WebsiteRemovalFailureError) -f ${Name} ; - $errorMessage += $_.Exception.Message $exception = New-Object System.InvalidOperationException $errorMessage ; $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null @@ -375,10 +419,10 @@ function Test-TargetResource [string]$ApplicationPool, [Microsoft.Management.Infrastructure.CimInstance[]]$BindingInfo, - - [string[]]$DefaultPage + + [Microsoft.Management.Infrastructure.CimInstance[]]$webConfigProp ) - + $DesiredConfigurationMatch = $true; # Check if WebAdministration module is present for IIS cmdlets @@ -387,10 +431,10 @@ function Test-TargetResource Throw "Please ensure that WebAdministration module is installed." } - $website = Get-Website -Name $Name + $website = Get-Website | Where-Object {$_.Name -eq $name} $Stop = $true - Do + Do { #Check Ensure if(($Ensure -eq "Present" -and $website -eq $null) -or ($Ensure -eq "Absent" -and $website -ne $null)) @@ -413,63 +457,90 @@ function Test-TargetResource #Check State if($website.state -ne $State -and $State -ne $null) - { - $DesiredConfigurationMatch = $false - Write-Verbose("The state of Website $Name does not match the desired state."); - break - } + { + $DesiredConfigurationMatch = $false + Write-Verbose("The state of Website $Name does not match the desired state."); + break + } #Check Application Pool property if(($ApplicationPool -ne "") -and ($website.applicationPool -ne $ApplicationPool)) - { - $DesiredConfigurationMatch = $false - Write-Verbose("Application Pool for Website $Name does not match the desired state."); - break - } - - #Check Binding properties - if($BindingInfo -ne $null) { - if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo) - { - $DesiredConfigurationMatch = $false - Write-Verbose("Bindings for website $Name do not mach the desired state."); - break - } - + $DesiredConfigurationMatch = $false + Write-Verbose("Application Pool for Website $Name does not match the desired state."); + break } - } - #Check Default Pages - if($DefaultPage -ne $null) + #Check Web Configuration Properties + foreach ($prop in $webConfigProp) { - $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path "IIS:\sites\" $Name) |%{Write-Output $_.value}) - - $allDefaultPagesPresent = $true - - foreach($page in $DefaultPage ) + #if location has a value we need to combine it with pspath to do get-webconfigurationproperty + + if($prop.CimInstanceProperties["Location"].Value) { - if(-not ($allDefaultPage -icontains $page)) - { - $DesiredConfigurationMatch = $false - Write-Verbose("Default Page for website $Name do not mach the desired state."); - $allDefaultPagesPresent = $false - break + $PSPath = $prop.CimInstanceProperties["PSPath"].Value + "/" + $prop.CimInstanceProperties["Location"].Value + } + else + { + $PSPath = $prop.CimInstanceProperties["PSPath"].Value + } + + Try + { + $propObject = Get-WebConfigurationProperty -Filter $prop.CimInstanceProperties["Filter"].Value -PSPath $PSPath -Name $prop.CimInstanceProperties["Name"].Value + } + Catch [System.IO.FileNotFoundException] + { + Write-Warning("Exception: $($_.Exception.Message)") + } + + if($propObject -ne $null) + { + #get-webconfigurationproperty returns values differently depending on the property so we have to check if .Value is null or not and proceed accordingly + if ($propObject[0].Value) + { + if($propObject[0].Value.toString() -ne $prop.CimInstanceProperties["Value"].Value.toString())#produces inconsistent results without toString + { + $DesiredConfigurationMatch = $false + $propName = $prop.CimInstanceProperties["Name"].Value + Write-Verbose("$propName for Website $Name does not match the desired state."); + break + } + } + else + { + if($propObject -ne $prop.CimInstanceProperties["Value"].Value.toString())#produces inconsistent results without toString + { + $DesiredConfigurationMatch = $false + $propName = $prop.CimInstanceProperties["Name"].Value + Write-Verbose("$propName for Website $Name does not match the desired state."); + break + } } } - - if($allDefaultPagesPresent -eq $false) + else { - # This is to break out from Test - break - } + Write-Warning("Could not find $PSPath " + $prop.CimInstanceProperties["Filter"].Value + " " + $prop.CimInstanceProperties["Name"].Value) + } } + + #Check Binding properties + if($BindingInfo -ne $null) + { + if(ValidateWebsiteBindings -Name $Name -BindingInfo $BindingInfo) + { + $DesiredConfigurationMatch = $false + Write-Verbose("Bindings for website $Name do not match the desired state."); + break + } - - $Stop = $false + } + + $Stop = $false + } } - While($Stop) - + While($Stop) + $DesiredConfigurationMatch; } @@ -541,7 +612,7 @@ function ValidateWebsiteBindings foreach($binding in $BindingInfo) { # First ensure that desired binding information is valid ie. No duplicate IPAddres, Port, Host name combinations. - + if (!(EnsurePortIPHostUnique -Port $binding.Port -IPAddress $binding.IPAddress -HostName $Binding.Hostname -BindingInfo $BindingInfo) ) { $errorId = "WebsiteBindingInputInvalidation"; @@ -552,6 +623,47 @@ function ValidateWebsiteBindings $PSCmdlet.ThrowTerminatingError($errorRecord); } + + # Ensure valid SSL certificate information for https bindings + + if ($binding.Protocol -eq 'https') + { + if (-not $binding.CertificateThumbprint -or -not $binding.CertificateStoreName) + { + $errorId = "WebsiteBindingInputInvalidation"; + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument + $errorMessage = $LocalizedData.WebsiteBindingMissingCertificateInformation -f $binding.Port, $Name + $exception = New-Object System.ArgumentException $errorMessage + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + + $PSCmdlet.ThrowTerminatingError($errorRecord) + } + + $certPath = Join-Path Cert:\LocalMachine "$($binding.CertificateStoreName)\$($binding.CertificateThumbprint)" + if (-not (Test-Path -LiteralPath $certPath)) + { + $errorId = "WebsiteBindingInputInvalidation"; + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument + $errorMessage = $LocalizedData.WebsiteBindingCertificateNotInstalled -f $certPath, $binding.Port, $Name + $exception = New-Object System.ArgumentException $errorMessage + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + + $PSCmdlet.ThrowTerminatingError($errorRecord) + } + + $cert = Get-Item -LiteralPath $certPath -ErrorAction Stop + + if (-not $cert.HasPrivateKey) + { + $errorId = "WebsiteBindingInputInvalidation"; + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidData + $errorMessage = $LocalizedData.WebsiteBindingCertificateMissingPrivateKey -f $certPath, $binding.Port, $Name + $exception = New-Object System.ArgumentException $errorMessage + $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null + + $PSCmdlet.ThrowTerminatingError($errorRecord) + } + } } return compareWebsiteBindings -Name $Name -BindingInfo $BindingInfo @@ -576,12 +688,11 @@ function EnsurePortIPHostUnique [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [Microsoft.Management.Infrastructure.CimInstance[]] - $BindingInfo, - - [parameter()] - $UniqueInstances = 0 + $BindingInfo ) + $UniqueInstances = 0 + foreach ($Binding in $BindingInfo) { if($binding.Port -eq $Port -and [string]$Binding.IPAddress -eq $IPAddress -and [string]$Binding.HostName -eq $HostName) @@ -621,7 +732,7 @@ function compareWebsiteBindings #check to see if actual settings have been passed in. If not get them from website if($ActualBindings -eq $null) { - $ActualBindings = Get-Website $Name | Get-WebBinding + $ActualBindings = Get-Website | Where-Object {$_.Name -eq $Name} | Get-WebBinding #Format Binding information: Split BindingInfo into individual Properties (IPAddress:Port:HostName) $ActualBindingObjects = @() @@ -701,7 +812,6 @@ function compareWebsiteBindings $errorId = "WebsiteCompareFailure"; $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult $errorMessage = $($LocalizedData.WebsiteCompareFailureError) -f ${Name} - $errorMessage += $_.Exception.Message $exception = New-Object System.InvalidOperationException $errorMessage $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null @@ -772,7 +882,6 @@ function UpdateBindings $errorId = "WebsiteBindingUpdateFailure"; $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult $errorMessage = $($LocalizedData.WebsiteUpdateFailureError) -f ${Name} - $errorMessage += $_.Exception.Message $exception = New-Object System.InvalidOperationException $errorMessage $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null @@ -791,8 +900,7 @@ function UpdateBindings { $errorId = "WebBindingCertifcateError"; $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation; - $errorMessage = $($LocalizedData.WebBindingCertifcateError) -f ${CertificateThumbprint} ; - $errorMessage += $_.Exception.Message + $errorMessage = $($LocalizedData.WebBindingCertifcateError) -f ${Name} ; $exception = New-Object System.InvalidOperationException $errorMessage ; $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null @@ -830,27 +938,5 @@ function get-WebBindingObject return $WebBindingObject } -# Helper function used to Update default pages of website -function UpdateDefaultPages -{ - param - ( - [string] $Name, - - [string[]] $DefaultPage - ) - - $allDefaultPage = @(Get-WebConfiguration //defaultDocument/files/* -PSPath (Join-Path "IIS:\sites\" $Name) |%{Write-Output $_.value}) - - foreach($page in $DefaultPage ) - { - if(-not ($allDefaultPage -icontains $page)) - { - Write-Verbose("Deafult page for website $Name has been updated to $page"); - Add-WebConfiguration //defaultDocument/files -PSPath (Join-Path "IIS:\sites\" $Name) -Value @{value = $page } - } - } -} - -#endregion +#endregion \ No newline at end of file diff --git a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof index 02e80023b..a9125240a 100644 --- a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof +++ b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof @@ -1,26 +1,35 @@ -[ClassVersion("1.0.0")] +[ClassVersion("1.0.1")] Class MSFT_xWebBindingInformation { - [write]UInt16 Port; - [Write,ValueMap{"http", "https"},Values{"http", "https"}] string Protocol; - [write]String IPAddress; - [write]String HostName; - [write]String CertificateThumbprint; - [write,ValueMap{"Personal", "WebHosting"},Values{"Personal", "WebHosting"}] string CertificateStoreName; + [write,Description("Port the website should listen on")]UInt16 Port; + [Write,Description("Is it http or https"), ValueMap{"http", "https"},Values{"http", "https"}] string Protocol; + [write,Description("What IP should the website listen on leave blank for any IP")]String IPAddress; + [write,Description("What hostname should the website respond to, leave blank for any name")]String HostName; + [write,Description("Thumbprint of the cert when using https")]String CertificateThumbprint; + [write,Description("Cert store, needed when giving Thumbprint normally the My option"),ValueMap{"My", "WebHosting"},Values{"My", "WebHosting"}] string CertificateStoreName; }; +[ClassVersion("1.0.0")] +Class MSFT_xWebConfigProp +{ + [write,Description("Specifies the IIS configuration section or an XPath query that returns a configuration element.")]String Filter; + [write,Description("Specifies the configuration path in the format machine/webroot/apphost")]String PSPath; + [write,Description("The name of the configuration property to change.")]String Name; + [write,Description("The value of the configuration setting to change.")]String Value; + [write,Description("The location of the configuration setting. e.g. name of website")]String Location; +}; -[ClassVersion("2.0.0"), FriendlyName("xWebsite")] +[ClassVersion("2.0.1"), FriendlyName("xWebsite")] class MSFT_xWebsite : OMI_BaseResource { - [Key] string Name; - [write] string PhysicalPath; - [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; - [write,ValueMap{"Started","Stopped"},Values{"Started", "Stopped"}] string State; + [Key, Description("Name of the website")] string Name; + [required, Description("Path on file system that the website should point to")] string PhysicalPath; + [write, Description("Should the website be present or absent"), ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure; + [write, Description("Should the website be started or stopped"), ValueMap{"Started","Stopped"},Values{"Started", "Stopped"}] string State; [write, EmbeddedInstance("MSFT_xWebBindingInformation"), Description("Hashtable containing binding information (Port, Protocol, IPAddress, HostName, CertificateThumbPrint, CertificateStore)")] string BindingInfo[]; - [write] string ApplicationPool; + [write, EmbeddedInstance("MSFT_xWebConfigProp"), Description("Hashtable containing Web Configuration Properties (Filter, PSPath, Name, Location, Value)")] string webConfigProp[]; + [write, Description("What app pool should the site use")] string ApplicationPool; [read] string Id; - [write, Description("The default pages for the website")] String DefaultPage[]; }; From 7584df5fad7f03e0c1355200e922133dee6c0a74 Mon Sep 17 00:00:00 2001 From: Aaron Zuehlke Date: Fri, 24 Apr 2015 13:44:22 -0500 Subject: [PATCH 2/2] Fix PSHOrg_cWebBindingInformation reference --- DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 index a454a5645..c0cac83d8 100644 --- a/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 +++ b/DSCResources/MSFT_xWebsite/MSFT_xWebsite.psm1 @@ -64,7 +64,7 @@ function Get-TargetResource $CimBindings = foreach ($binding in $bindings) { $BindingObject = get-WebBindingObject -BindingInfo $binding - New-CimInstance -ClassName PSHOrg_cWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;IPAddress=$BindingObject.IPaddress;HostName=$BindingObject.Hostname;CertificateThumbprint=$BindingObject.CertificateThumbprint;CertificateStoreName=$BindingObject.CertificateStoreName} -ClientOnly + New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{Port=[System.UInt16]$BindingObject.Port;Protocol=$BindingObject.Protocol;IPAddress=$BindingObject.IPaddress;HostName=$BindingObject.Hostname;CertificateThumbprint=$BindingObject.CertificateThumbprint;CertificateStoreName=$BindingObject.CertificateStoreName} -ClientOnly } } else # Multiple websites with the same name exist. This is not supported and is an error