DSCResources/MSFT_xIisLogging/MSFT_xIisLogging.psm1
$script:resourceModulePath = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent $script:modulesFolderPath = Join-Path -Path $script:resourceModulePath -ChildPath 'Modules' $script:localizationModulePath = Join-Path -Path $script:modulesFolderPath -ChildPath 'xWebAdministration.Common' Import-Module -Name (Join-Path -Path $script:localizationModulePath -ChildPath 'xWebAdministration.Common.psm1') # Import Localization Strings $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_xIisLogging' <# .SYNOPSIS This will return a hashtable of results about the given LogPath #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [String] $LogPath ) Assert-Module $currentLogSettings = Get-WebConfiguration ` -filter '/system.applicationHost/sites/siteDefaults/Logfile' Write-Verbose -Message ($script:localizedData.VerboseGetTargetResult) $cimLogCustomFields = @(ConvertTo-CimLogCustomFields -InputObject $currentLogSettings.logFile.customFields.Collection) $logFlagsArray = $null if ($currentLogSettings.LogExtFileFlags -is [System.String]) { $logFlagsArray = [System.String[]] $currentLogSettings.LogExtFileFlags.Split(',') } return @{ LogPath = $currentLogSettings.directory LogFlags = $logFlagsArray LogPeriod = $currentLogSettings.period LogTruncateSize = $currentLogSettings.truncateSize LoglocalTimeRollover = $currentLogSettings.localTimeRollover LogFormat = $currentLogSettings.logFormat LogTargetW3C = $currentLogSettings.logTargetW3C LogCustomFields = $cimLogCustomFields } } <# .SYNOPSIS This will set the desired state .PARAMETER LogPath Path to the logfile .PARAMETER LogFlags Specifies flags to check Limited to the set: ('Date','Time','ClientIP','UserName','SiteName','ComputerName','ServerIP','Method','UriStem','UriQuery','HttpStatus','Win32Status','BytesSent','BytesRecv','TimeTaken','ServerPort','UserAgent','Cookie','Referer','ProtocolVersion','Host','HttpSubStatus') .PARAMETER LogPeriod Specifies the log period. Limited to the set: ('Hourly','Daily','Weekly','Monthly','MaxSize') .PARAMETER LogTruncateSize Specifies log truncate size Limited to the range (1048576 - 4294967295) .PARAMETER LoglocalTimeRollover Sets log local time rollover .PARAMETER LogFormat Specifies log format Limited to the set: ('IIS','W3C','NCSA') .PARAMETER LogTargetW3C Specifies W3C log format Limited to the set: ('File','ETW','File,ETW') .PARAMETER LogCustomField A CimInstance collection of what state the LogCustomField should be. #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String] $LogPath, [Parameter()] [ValidateSet('Date','Time','ClientIP','UserName','SiteName','ComputerName','ServerIP','Method','UriStem','UriQuery','HttpStatus','Win32Status','BytesSent','BytesRecv','TimeTaken','ServerPort','UserAgent','Cookie','Referer','ProtocolVersion','Host','HttpSubStatus')] [String[]] $LogFlags, [Parameter()] [ValidateSet('Hourly','Daily','Weekly','Monthly','MaxSize')] [String] $LogPeriod, [Parameter()] [ValidateScript({ ([ValidateRange(1048576, 4294967295)] $valueAsUInt64 = [UInt64]::Parse($_)) })] [String] $LogTruncateSize, [Parameter()] [Boolean] $LoglocalTimeRollover, [Parameter()] [ValidateSet('IIS','W3C','NCSA')] [String] $LogFormat, [Parameter()] [ValidateSet('File','ETW','File,ETW')] [String] $LogTargetW3C, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $LogCustomFields ) Assert-Module $currentLogState = Get-TargetResource -LogPath $LogPath # Update LogFormat if needed if ($PSBoundParameters.ContainsKey('LogFormat') -and ` ($LogFormat -ne $currentLogState.LogFormat)) { Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLogFormat) Set-WebConfigurationProperty '/system.applicationHost/sites/siteDefaults/logfile' ` -Name logFormat ` -Value $LogFormat } # Update LogPath if needed if ($PSBoundParameters.ContainsKey('LogPath') -and ($LogPath -ne $currentLogState.LogPath)) { Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLogPath) Set-WebConfigurationProperty '/system.applicationHost/sites/siteDefaults/logfile' ` -Name directory ` -Value $LogPath } # Update Logflags if needed; also sets logformat to W3C if ($PSBoundParameters.ContainsKey('LogFlags') -and ` (-not (Compare-LogFlags -LogFlags $LogFlags))) { Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLogFlags) Set-WebConfigurationProperty '/system.Applicationhost/Sites/SiteDefaults/logfile' ` -Name logFormat ` -Value 'W3C' Set-WebConfigurationProperty '/system.Applicationhost/Sites/SiteDefaults/logfile' ` -Name logExtFileFlags ` -Value ($LogFlags -join ',') } # Update Log Period if needed if ($PSBoundParameters.ContainsKey('LogPeriod') -and ` ($LogPeriod -ne $currentLogState.LogPeriod)) { if ($PSBoundParameters.ContainsKey('LogTruncateSize')) { Write-Verbose -Message ($script:localizedData.WarningLogPeriod) } Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLogPeriod) Set-WebConfigurationProperty '/system.Applicationhost/Sites/SiteDefaults/logfile' ` -Name period ` -Value $LogPeriod } # Update LogTruncateSize if needed if ($PSBoundParameters.ContainsKey('LogTruncateSize') -and ` ($LogTruncateSize -ne $currentLogState.LogTruncateSize)) { Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLogTruncateSize) Set-WebConfigurationProperty '/system.Applicationhost/Sites/SiteDefaults/logfile' ` -Name truncateSize ` -Value $LogTruncateSize Set-WebConfigurationProperty '/system.Applicationhost/Sites/SiteDefaults/logfile' ` -Name period ` -Value 'MaxSize' } # Update LoglocalTimeRollover if needed if ($PSBoundParameters.ContainsKey('LoglocalTimeRollover') -and ` ($LoglocalTimeRollover -ne ` ([System.Convert]::ToBoolean($currentLogState.LoglocalTimeRollover)))) { Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLoglocalTimeRollover) Set-WebConfigurationProperty '/system.Applicationhost/Sites/SiteDefaults/logfile' ` -Name localTimeRollover ` -Value $LoglocalTimeRollover } # Update LogTargetW3C if needed if ($PSBoundParameters.ContainsKey('LogTargetW3C') -and ` ($LogTargetW3C -ne $currentLogState.LogTargetW3C)) { Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLogTargetW3C) Set-WebConfigurationProperty '/system.applicationHost/sites/siteDefaults/logfile' ` -Name logTargetW3C ` -Value $LogTargetW3C } # Update LogCustomFields if neeed if ($PSBoundParameters.ContainsKey('LogCustomFields') -and ` (-not (Test-LogCustomField -LogCustomField $LogCustomFields))) { Write-Verbose -Message ($script:localizedData.VerboseSetTargetUpdateLogCustomFields) Set-LogCustomField -LogCustomField $LogCustomFields } } <# .SYNOPSIS This tests the desired state. If the state is not correct it will return $false. If the state is correct it will return $true .PARAMETER LogPath Path to the logfile .PARAMETER LogFlags Specifies flags to check Limited to the set: ('Date','Time','ClientIP','UserName','SiteName','ComputerName','ServerIP','Method','UriStem','UriQuery','HttpStatus','Win32Status','BytesSent','BytesRecv','TimeTaken','ServerPort','UserAgent','Cookie','Referer','ProtocolVersion','Host','HttpSubStatus') .PARAMETER LogPeriod Specifies the log period. Limited to the set: ('Hourly','Daily','Weekly','Monthly','MaxSize') .PARAMETER LogTruncateSize Specifies log truncate size Limited to the range (1048576 - 4294967295) .PARAMETER LoglocalTimeRollover Sets log local time rollover .PARAMETER LogFormat Specifies log format Limited to the set: ('IIS','W3C','NCSA') .PARAMETER LogTargetW3C Specifies W3C log format Limited to the set: ('File','ETW','File,ETW') .PARAMETER LogCustomField A CimInstance collection of what state the LogCustomField should be. #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [String] $LogPath, [Parameter()] [ValidateSet('Date','Time','ClientIP','UserName','SiteName','ComputerName','ServerIP','Method','UriStem','UriQuery','HttpStatus','Win32Status','BytesSent','BytesRecv','TimeTaken','ServerPort','UserAgent','Cookie','Referer','ProtocolVersion','Host','HttpSubStatus')] [String[]] $LogFlags, [Parameter()] [ValidateSet('Hourly','Daily','Weekly','Monthly','MaxSize')] [String] $LogPeriod, [Parameter()] [ValidateScript({ ([ValidateRange(1048576, 4294967295)] $valueAsUInt64 = [UInt64]::Parse($_)) })] [String] $LogTruncateSize, [Parameter()] [Boolean] $LoglocalTimeRollover, [Parameter()] [ValidateSet('IIS','W3C','NCSA')] [String] $LogFormat, [Parameter()] [ValidateSet('File','ETW','File,ETW')] [String] $LogTargetW3C, [Parameter()] [Microsoft.Management.Infrastructure.CimInstance[]] $LogCustomFields ) Assert-Module $currentLogState = Get-TargetResource -LogPath $LogPath # Check LogFormat if ($PSBoundParameters.ContainsKey('LogFormat')) { # Warn if LogFlags are passed in and Current LogFormat is not W3C if ($PSBoundParameters.ContainsKey('LogFlags') -and ` $LogFormat -ne 'W3C') { Write-Verbose -Message ($script:localizedData.WarningIncorrectLogFormat) } # Warn if LogFlags are passed in and Desired LogFormat is not W3C if ($PSBoundParameters.ContainsKey('LogFlags') -and ` $currentLogState.LogFormat -ne 'W3C') { Write-Verbose -Message ($script:localizedData.WarningIncorrectLogFormat) } # Check LogFormat if ($LogFormat -ne $currentLogState.LogFormat) { Write-Verbose -Message ($script:localizedData.VerboseTestTargetFalseLogFormat) return $false } } # Check LogFlags if ($PSBoundParameters.ContainsKey('LogFlags') -and ` (-not (Compare-LogFlags -LogFlags $LogFlags))) { Write-Verbose -Message ($script:localizedData.VerboseTestTargetFalseLogFlags) return $false } # Check LogPath if ($PSBoundParameters.ContainsKey('LogPath') -and ` ($LogPath -ne $currentLogState.LogPath)) { Write-Verbose -Message ($script:localizedData.VerboseTestTargetFalseLogPath) return $false } # Check LogPeriod if ($PSBoundParameters.ContainsKey('LogPeriod') -and ` ($LogPeriod -ne $currentLogState.LogPeriod)) { if ($PSBoundParameters.ContainsKey('LogTruncateSize')) { Write-Verbose -Message ($script:localizedData.WarningLogPeriod) } Write-Verbose -Message ($script:localizedData.VerboseTestTargetFalseLogPeriod) return $false } # Check LogTruncateSize if ($PSBoundParameters.ContainsKey('LogTruncateSize') -and ` ($LogTruncateSize -ne $currentLogState.LogTruncateSize)) { Write-Verbose -Message ($script:localizedData.VerboseTestTargetFalseLogTruncateSize) return $false } # Check LoglocalTimeRollover if ($PSBoundParameters.ContainsKey('LoglocalTimeRollover') -and ` ($LoglocalTimeRollover -ne ` ([System.Convert]::ToBoolean($currentLogState.LoglocalTimeRollover)))) { Write-Verbose -Message ($script:localizedData.VerboseTestTargetFalseLoglocalTimeRollover) return $false } # Check LogTargetW3C if ($PSBoundParameters.ContainsKey('LogTargetW3C') -and ` ($LogTargetW3C -ne $currentLogState.LogTargetW3C)) { Write-Verbose -Message ($script:localizedData.VerboseTestTargetFalseLogTargetW3C) return $false } # Check LogCustomFields if neeed if ($PSBoundParameters.ContainsKey('LogCustomFields') -and ` (-not (Test-LogCustomField -LogCustomFields $LogCustomFields))) { Write-Verbose -Message ($script:localizedData.VerboseTestTargetUpdateLogCustomFields) return $false } return $true } #region Helper functions <# .SYNOPSIS Helper function used to validate the logflags status. Returns False if the loglfags do not match and true if they do .PARAMETER LogFlags Specifies flags to check #> function Compare-LogFlags { [CmdletBinding()] [OutputType([Boolean])] param ( [Parameter()] [ValidateSet('Date','Time','ClientIP','UserName','SiteName','ComputerName','ServerIP','Method','UriStem','UriQuery','HttpStatus','Win32Status','BytesSent','BytesRecv','TimeTaken','ServerPort','UserAgent','Cookie','Referer','ProtocolVersion','Host','HttpSubStatus')] [String[]] $LogFlags ) $currentLogFlags = (Get-WebConfigurationProperty ` -Filter '/system.Applicationhost/Sites/SiteDefaults/logfile' ` -Name LogExtFileFlags) -split ',' | ` Sort-Object $proposedLogFlags = $LogFlags -split ',' | Sort-Object if (Compare-Object -ReferenceObject $currentLogFlags ` -DifferenceObject $proposedLogFlags) { return $false } return $true } <# .SYNOPSIS Converts IIS custom log field collection to instances of the MSFT_xLogCustomField CIM class. .PARAMETER InputObject Specifies input object passed in #> function ConvertTo-CimLogCustomFields { [CmdletBinding()] [OutputType([Microsoft.Management.Infrastructure.CimInstance])] param ( [Parameter(Mandatory = $true)] [AllowEmptyCollection()] [AllowNull()] [Object[]] $InputObject ) $cimClassName = 'MSFT_xLogCustomField' $cimNamespace = 'root/microsoft/Windows/DesiredStateConfiguration' $cimCollection = New-Object -TypeName 'System.Collections.ObjectModel.Collection`1[Microsoft.Management.Infrastructure.CimInstance]' foreach ($customField in $InputObject) { $cimProperties = @{ LogFieldName = $customField.LogFieldName SourceName = $customField.SourceName SourceType = $customField.SourceType } $cimCollection += (New-CimInstance -ClassName $cimClassName ` -Namespace $cimNamespace ` -Property $cimProperties ` -ClientOnly) } return $cimCollection } <# .SYNOPSIS Helper function used to set the LogCustomField for a website. .PARAMETER LogCustomField A CimInstance collection of what the LogCustomField should be. #> function Set-LogCustomField { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Microsoft.Management.Infrastructure.CimInstance[]] $LogCustomField ) $setCustomFields = @() foreach ($customField in $LogCustomField) { $setCustomFields += @{ logFieldName = $customField.LogFieldName sourceName = $customField.SourceName sourceType = $customField.SourceType } } <# Set-WebConfigurationProperty updates logfile.customFields. #> Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter "system.applicationHost/Sites/SiteDefaults/logFile/customFields" -Name "." -Value $setCustomFields } <# .SYNOPSIS Helper function used to test the LogCustomField state for a website. .PARAMETER LogCustomField A CimInstance collection of what state the LogCustomField should be. #> function Test-LogCustomField { [CmdletBinding()] [OutputType([Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Microsoft.Management.Infrastructure.CimInstance[]] $LogCustomFields ) $inDesiredSate = $true foreach ($customField in $LogCustomFields) { $filterString = "/system.Applicationhost/Sites/SiteDefaults/logFile/customFields/add[@logFieldName='{0}']" -f $customField.LogFieldName $presentCustomField = Get-WebConfigurationProperty -Filter $filterString -Name "." if ($presentCustomField) { $sourceNameMatch = $customField.SourceName -eq $presentCustomField.sourceName $sourceTypeMatch = $customField.SourceType -eq $presentCustomField.sourceType if (-not ($sourceNameMatch -and $sourceTypeMatch)) { $inDesiredSate = $false } } else { $inDesiredSate = $false } } return $inDesiredSate } #endregion Export-ModuleMember -function *-TargetResource |