diff --git a/CHANGELOG.md b/CHANGELOG.md index 61d74daa..146c5665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added the 'Source' parameter for Add-WindowsCapability as an optional parameter - Fixes [Issue #361](https://github.com/dsccommunity/ComputerManagementDsc/issues/361) +### Added + +- WindowsEventLog + - Added support to restrict guest access - Fixes [Issue #338](https://github.com/dsccommunity/ComputerManagementDsc/issues/338). + - Added support to create custom event sources and optionally register + resource files - Fixes [Issue #355](https://github.com/dsccommunity/ComputerManagementDsc/issues/355). + +### Changed + +- WindowsEventLog + - Reformatted code to better align with current DSCResources coding standards. + ### Fixed +- WindowsEventLog + - Fixed issue requiring IsEnabled to be declared and set to $true in order + to set the MaximumSizeInBytes property - Fixes [Issue #349](https://github.com/dsccommunity/ComputerManagementDsc/issues/349). + - Fixed issue where configuring log retention on a non-classic event log will + throw. - ScheduledTask - Fixed issue with disabling scheduled tasks that have "Run whether user is logged on or not" configured - Fixes [Issue #306](https://github.com/dsccommunity/ComputerManagementDsc/issues/306). diff --git a/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.psm1 b/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.psm1 index 813fd150..b61e0f66 100644 --- a/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.psm1 +++ b/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.psm1 @@ -12,10 +12,10 @@ $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' <# .SYNOPSIS - Gets the current state of the Windows Event Log. + Gets the current state of an event log. .PARAMETER LogName - Specifies the given name of a Windows Event Log. + Specifies the name of a valid event log. #> function Get-TargetResource { @@ -25,55 +25,73 @@ function Get-TargetResource ( [Parameter(Mandatory = $true)] [System.String] - $LogName, - - [Parameter()] - [System.Boolean] - $IsEnabled + $LogName ) + Write-Verbose -Message ($script:localizedData.GetTargetResource -f $LogName) + $log = Get-WindowsEventLog -LogName $LogName - $LogRetentionDays = (Get-EventLog -List | Where-Object -Property Log -eq $LogName).minimumRetentionDays + if ($log.IsClassicLog -eq $true) + { + $logRetentionDays = Get-WindowsEventLogRetentionDays -LogName $LogName + } + + $restrictGuestAccess = Get-WindowsEventLogRestrictGuestAccess -LogName $LogName $returnValue = @{ - LogName = [System.String] $LogName - LogFilePath = [system.String] $log.LogFilePath - MaximumSizeInBytes = [System.Int64] $log.MaximumSizeInBytes - IsEnabled = [System.Boolean] $log.IsEnabled - LogMode = [System.String] $log.LogMode - SecurityDescriptor = [System.String] $log.SecurityDescriptor - LogRetentionDays = [System.Int32] $logRetentionDays + LogName = $LogName + LogFilePath = $log.LogFilePath + MaximumSizeInBytes = [System.Int64] $log.MaximumSizeInBytes + IsEnabled = $log.IsEnabled + LogMode = $log.LogMode + SecurityDescriptor = $log.SecurityDescriptor + LogRetentionDays = $logRetentionDays + RestrictGuestAccess = $restrictGuestAccess } - Write-Verbose -Message ($script:localizedData.GettingEventlogName -f $LogName) return $returnValue } <# .SYNOPSIS - Sets the current state of the Windows Event Log. + Sets the desired state of an event log. .PARAMETER LogName - Specifies the given name of a Windows Event Log. + Specifies the name of a valid event log. .PARAMETER MaximumSizeInBytes - Specifies the given maximum size in bytes for a specified Windows Event Log. + Specifies the maximum size in bytes for the specified event log. .PARAMETER LogMode - Specifies the given LogMode for a specified Windows Event Log. + Specifies the log mode for the specified event log. .PARAMETER LogRetentionDays - Specifies the given LogRetentionDays for the Logmode 'AutoBackup'. + Specifies the number of days to retain events when the log mode is AutoBackup. .PARAMETER SecurityDescriptor - Specifies the given SecurityDescriptor for a specified Windows Event Log. + Specifies the SDDL for the specified event log. .PARAMETER IsEnabled - Specifies the given state of a Windows Event Log. + Specifies whether the specified event log should be enabled or disabled. .PARAMETER LogFilePath - Specifies the given LogFile path of a Windows Event Log. + Specifies the file name and path for the specified event log. + + .PARAMETER RegisteredSource + Specifies the name of an event source to register for the specified event log. + + .PARAMETER CategoryResourceFile + Specifies the category resource file for the event source. + + .PARAMETER MessageResourceFile + Specifies the message resource file for the event source. + + .PARAMETER ParameterResourceFile + Specifies the parameter resource file for the event source. + + .PARAMETER RestrictGuestAccess + Specifies whether to allow guests to have access to the specified event log. #> function Set-TargetResource { @@ -89,6 +107,7 @@ function Set-TargetResource $IsEnabled, [Parameter()] + [ValidateRange(64KB, 4GB)] [System.Int64] $MaximumSizeInBytes, @@ -99,6 +118,7 @@ function Set-TargetResource [Parameter()] [System.Int32] + [ValidateRange(0, 365)] $LogRetentionDays, [Parameter()] @@ -107,115 +127,220 @@ function Set-TargetResource [Parameter()] [System.String] - $LogFilePath + $LogFilePath, + + [Parameter()] + [System.String] + $RegisteredSource, + + [Parameter()] + [System.String] + $CategoryResourceFile, + + [Parameter()] + [System.String] + $MessageResourceFile, + + [Parameter()] + [System.String] + $ParameterResourceFile, + + [Parameter()] + [System.Boolean] + $RestrictGuestAccess ) + $shouldSaveLogFile = $false + $shouldRegisterSource = $false $log = Get-WindowsEventLog -LogName $LogName + $currentRestrictGuestAccess = Get-WindowsEventLogRestrictGuestAccess -LogName $LogName - if ($null -eq $log) + if ($PSBoundParameters.ContainsKey('IsEnabled') ` + -and $IsEnabled -ne $log.IsEnabled) { - return + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'IsEnabled', $log.IsEnabled, $isEnabled) + $log.IsEnabled = $IsEnabled + $shouldSaveLogFile = $true } - $shouldSaveLogFile = $false + if ($PSBoundParameters.ContainsKey('MaximumSizeInBytes') ` + -and $MaximumSizeInBytes -ne $log.MaximumSizeInBytes) + { + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'MaximumSizeInBytes', $log.MaximumSizeInBytes, $MaximumSizeInBytes) + $log.MaximumSizeInBytes = $MaximumSizeInBytes + $shouldSaveLogFile = $true + } - Write-Verbose -Message ($script:localizedData.GettingEventlogName -f $LogName) + if ($PSBoundParameters.ContainsKey('LogMode') ` + -and $LogMode -ne $log.LogMode) + { + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'LogMode', $log.LogMode, $LogMode) + $log.LogMode = $LogMode + $shouldSaveLogFile = $true + } - if ($IsEnabled -eq $true) + if ($PSBoundParameters.ContainsKey('SecurityDescriptor') ` + -and $SecurityDescriptor -ne $log.SecurityDescriptor) { - if ($PSBoundParameters.ContainsKey('IsEnabled') -and $IsEnabled -ne $log.IsEnabled) + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'SecurityDescriptor', $log.SecurityDescriptor, $SecurityDescriptor) + $log.SecurityDescriptor = $SecurityDescriptor + $shouldSaveLogFile = $true + } + + if ($PSBoundParameters.ContainsKey('LogFilePath') ` + -and $LogFilePath -ne $log.LogFilePath) { + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'LogFilePath', $log.LogFilePath, $LogFilePath) + $log.LogFilePath = $LogFilePath + $shouldSaveLogFile = $true + } + + if ($PSBoundParameters.ContainsKey('RestrictGuestAccess') ` + -and $RestrictGuestAccess -ne $currentRestrictGuestAccess) + { + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'RestrictGuestAccess', $currentRestrictGuestAccess, $RestrictGuestAccess) + + if ($PSBoundParameters.ContainsKey('SecurityDescriptor')) + { + Write-Warning -Message ($script:localizedData.ModifyUserProvidedSecurityDescriptor) + $log.SecurityDescriptor = Set-WindowsEventLogRestrictGuestAccess ` + -LogName $LogName -RestrictGuestAccess $RestrictGuestAccess -Sddl $SecurityDescriptor + } + else { - Write-Verbose -Message ($script:localizedData.SettingEventlogIsEnabled -f $LogName, $IsEnabled) - $log.IsEnabled = $IsEnabled - $shouldSaveLogFile = $true + Write-Verbose -Message ($script:localizedData.ModifySystemProvidedSecurityDescriptor) + $log.SecurityDescriptor = Set-WindowsEventLogRestrictGuestAccess ` + -LogName $LogName -RestrictGuestAccess $RestrictGuestAccess -Sddl $log.SecurityDescriptor + } + + $shouldSaveLogFile = $true + } + + if ($PSBoundParameters.ContainsKey('RegisteredSource')) + { + $sourceProperties = @{ + LogName = $LogName + SourceName = $RegisteredSource } - if ($PSBoundParameters.ContainsKey('MaximumSizeInBytes') -and $MaximumSizeInBytes -ne $log.MaximumSizeInBytes) + $currentRegisteredSource = Get-WindowsEventLogRegisteredSource ` + -LogName $LogName ` + -SourceName $RegisteredSource + + $currentCategoryResourceFile = Get-WindowsEventLogRegisteredSourceFile ` + -LogName $LogName ` + -SourceName $RegisteredSource ` + -ResourceFileType Category + + $currentMessageResourceFile = Get-WindowsEventLogRegisteredSourceFile ` + -LogName $LogName ` + -SourceName $RegisteredSource ` + -ResourceFileType Message + + $currentParameterResourceFile = Get-WindowsEventLogRegisteredSourceFile ` + -LogName $LogName ` + -SourceName $RegisteredSource ` + -ResourceFileType Parameter + + if ($RegisteredSource -ne $currentRegisteredSource) { - Write-Verbose -Message ($script:localizedData.SettingEventlogLogSize -f $LogName, $MaximumSizeInBytes) - $log.MaximumSizeInBytes = $MaximumSizeInBytes - $shouldSaveLogFile = $true + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'RegisteredSource', $currentRegisteredSource, $RegisteredSource) + $shouldRegisterSource = $true } - if ($PSBoundParameters.ContainsKey('LogMode') -and $LogMode -ne $log.LogMode) + if ($PSBoundParameters.ContainsKey('CategoryResourceFile') ` + -and $CategoryResourceFile -ne $currentCategoryResourceFile) { - Write-Verbose -Message ($script:localizedData.SettingEventlogLogMode -f $LogName, $LogMode) - $log.LogMode = $LogMode - $shouldSaveLogFile = $true + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'CategoryResourceFile', $currentCategoryResourceFile, $CategoryResourceFile) + $sourceProperties.CategoryResourceFile = $CategoryResourceFile + $shouldRegisterSource = $true } - if ($PSBoundParameters.ContainsKey('SecurityDescriptor') -and $SecurityDescriptor -ne $log.SecurityDescriptor) + if ($PSBoundParameters.ContainsKey('MessageResourceFile') ` + -and $MessageResourceFile -ne $currentMessageResourceFile) { - Write-Verbose -Message ($script:localizedData.SettingEventlogSecurityDescriptor -f $LogName, $SecurityDescriptor) - $log.SecurityDescriptor = $SecurityDescriptor - $shouldSaveLogFile = $true + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'MessageResourceFile', $currentMessageResourceFile, $MessageResourceFile) + $sourceProperties.MessageResourceFile = $MessageResourceFile + $shouldRegisterSource = $true } - if ($PSBoundParameters.ContainsKey('LogFilePath') -and $LogFilePath -ne $log.LogFilePath) + if ($PSBoundParameters.ContainsKey('ParameterResourceFile') ` + -and $ParameterResourceFile -ne $currentParameterResourceFile) { - Write-Verbose -Message ($script:localizedData.SettingEventlogLogFilePath -f $LogName, $LogFilePath) - $log.LogFilePath = $LogFilePath - $shouldSaveLogFile = $true + Write-Verbose -Message ($script:localizedData.SetTargetResourceProperty ` + -f $LogName, 'ParameterResourceFile', $currentParameterResourceFile, $ParameterResourceFile) + $sourceProperties.ParameterResourceFile = $ParameterResourceFile + $shouldRegisterSource = $true } } - else + + if ($shouldSaveLogFile) { - Write-Verbose -Message ($script:localizedData.SettingEventlogIsEnabled -f $LogName, $IsEnabled) - $log.IsEnabled = $IsEnabled - $shouldSaveLogFile = $true + Save-WindowsEventLog -Log $log } - if ($shouldSaveLogFile -eq $true) + if ($shouldRegisterSource) { - Save-LogFile -Log $log + Register-WindowsEventLogSource @sourceProperties } if ($PSBoundParameters.ContainsKey('LogRetentionDays')) { - if ($LogMode -eq 'AutoBackup' -and (Get-EventLog -List | Where-Object -FilterScript {$_.Log -like $LogName})) + if ($log.IsClassicLog -eq $true) { - $matchingEventLog = Get-EventLog -List | Where-Object -FilterScript { - $_.Log -eq $LogName - } - - $minimumRetentionDaysForLog = $matchingEventLog.minimumRetentionDays - - if ($LogRetentionDays -ne $minimumRetentionDaysForLog) - { - Set-LogRetentionDays -LogName $LogName -LogRetentionDays $LogRetentionDays - } + Set-WindowsEventLogRetentionDays -LogName $LogName -LogMode $LogMode -LogRetentionDays $LogRetentionDays } else { - Write-Verbose -Message ($script:localizedData.EventlogLogRetentionDaysWrongMode -f $LogName) + Write-Warning -Message ($script:localizedData.SetWindowsEventLogRetentionDaysNotClassic -f $LogName) } } } <# .SYNOPSIS - Tests if the the current state of the Windows Event Log is in the desired state. + Tests if the current state of an event log is the same as the desired state. .PARAMETER LogName - Specifies the given name of a Windows Event Log. + Specifies the name of a valid event log. .PARAMETER MaximumSizeInBytes - Specifies the given maximum size in bytes for a specified Windows Event Log. + Specifies the maximum size in bytes for the specified event log. .PARAMETER LogMode - Specifies the given LogMode for a specified evWindows Event Logentlog. + Specifies the log mode for the specified event log. .PARAMETER LogRetentionDays - Specifies the given LogRetentionDays for the Logmode 'AutoBackup'. + Specifies the number of days to retain events when the log mode is AutoBackup. .PARAMETER SecurityDescriptor - Specifies the given SecurityDescriptor for a specified Windows Event Log. + Specifies the SDDL for the specified event log. .PARAMETER IsEnabled - Specifies the given state of a Windows Event Log. + Specifies whether the specified event log should be enabled or disabled. .PARAMETER LogFilePath - Specifies the given LogFile path of a Windows Event Log. + Specifies the file name and path for the specified event log. + + .PARAMETER RegisteredSource + Specifies the name of an event source in the specified event log. + + .PARAMETER CategoryResourceFile + Specifies the category resource file for the event source. + + .PARAMETER MessageResourceFile + Specifies the message resource file for the event source. + + .PARAMETER ParameterResourceFile + Specifies the parameter resource file for the event source. #> function Test-TargetResource { @@ -232,7 +357,7 @@ function Test-TargetResource $IsEnabled, [Parameter()] - [ValidateRange(1028kb, 18014398509481983kb)] + [ValidateRange(64KB, 4GB)] [System.Int64] $MaximumSizeInBytes, @@ -242,7 +367,7 @@ function Test-TargetResource $LogMode, [Parameter()] - [ValidateRange(1, 365)] + [ValidateRange(0, 365)] [System.Int32] $LogRetentionDays, @@ -252,178 +377,570 @@ function Test-TargetResource [Parameter()] [System.String] - $LogFilePath + $LogFilePath, + + [Parameter()] + [System.String] + $RegisteredSource, + + [Parameter()] + [System.String] + $CategoryResourceFile, + + [Parameter()] + [System.String] + $MessageResourceFile, + + [Parameter()] + [System.String] + $ParameterResourceFile, + + [Parameter()] + [System.Boolean] + $RestrictGuestAccess ) + $inDesiredState = $true $log = Get-WindowsEventLog -LogName $LogName - if ($null -eq $log) + if ($log.IsClassicLog -eq $true) { - return + $currentLogRetentionDays = Get-WindowsEventLogRetentionDays -LogName $LogName } - $desiredState = $true + $currentRestrictGuestAccess = Get-WindowsEventLogRestrictGuestAccess -LogName $LogName - if ($IsEnabled -eq $true) + if ($PSBoundParameters.ContainsKey('IsEnabled') ` + -and $IsEnabled -ne $log.IsEnabled) { - if ($PSBoundParameters.ContainsKey('IsEnabled') -and $log.IsEnabled -ne $IsEnabled) - { - Write-Verbose -Message ($script:localizedData.TestingEventlogIsEnabled -f $LogName, $IsEnabled) - $desiredState = $false - } - else + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'IsEnabled', $log.IsEnabled, $IsEnabled) + $inDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('MaximumSizeInBytes') ` + -and $MaximumSizeInBytes -ne $log.MaximumSizeInBytes) + { + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'MaximumSizeInBytes', $log.MaximumSizeInBytes, $MaximumSizeInBytes) + $inDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('LogMode') ` + -and $LogMode -ne $log.LogMode) + { + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'LogMode', $log.LogMode, $LogMode) + $inDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('SecurityDescriptor') ` + -and $SecurityDescriptor -ne $log.SecurityDescriptor) + { + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'SecurityDescriptor', $log.SecurityDescriptor, $SecurityDescriptor) + $inDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('LogFilePath') ` + -and $LogFilePath -ne $log.LogFilePath) + { + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'LogFilePath', $log.LogFilePath, $LogFilePath) + $inDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('RestrictGuestAccess') ` + -and $RestrictGuestAccess -ne $currentRestrictGuestAccess) + { + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'RestrictGuestAccess', $currentRestrictGuestAccess, $RestrictGuestAccess) + $inDesiredState = $false + } + + if ($PSBoundParameters.ContainsKey('RegisteredSource')) + { + $currentRegisteredSource = Get-WindowsEventLogRegisteredSource ` + -LogName $LogName ` + -SourceName $RegisteredSource + + $currentCategoryResourceFile = Get-WindowsEventLogRegisteredSourceFile ` + -LogName $LogName ` + -SourceName $RegisteredSource ` + -ResourceFileType Category + + $currentMessageResourceFile = Get-WindowsEventLogRegisteredSourceFile ` + -LogName $LogName ` + -SourceName $RegisteredSource ` + -ResourceFileType Message + + $currentParameterResourceFile = Get-WindowsEventLogRegisteredSourceFile ` + -LogName $LogName ` + -SourceName $RegisteredSource ` + -ResourceFileType Parameter + + if ($RegisteredSource -ne $currentRegisteredSource) { - Write-Verbose -Message ($script:localizedData.SetResourceIsInDesiredState -f $LogName, 'IsEnabled') + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'RegisteredSource', $currentRegisteredSource, $RegisteredSource) + $inDesiredState = $false } - if ($PSBoundParameters.ContainsKey('MaximumSizeInBytes') -and $log.MaximumSizeInBytes -ne $MaximumSizeInBytes) + if ($PSBoundParameters.ContainsKey('CategoryResourceFile') ` + -and $CategoryResourceFile -ne $currentCategoryResourceFile) { - Write-Verbose -Message ($script:localizedData.TestingEventlogMaximumSizeInBytes -f $LogName, $MaximumSizeInBytes) - $desiredState = $false + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'CategoryResourceFile', $currentCategoryResourceFile, $CategoryResourceFile) + $inDesiredState = $false } - else + + if ($PSBoundParameters.ContainsKey('MessageResourceFile') ` + -and $MessageResourceFile -ne $currentMessageResourceFile) { - Write-Verbose -Message ($script:localizedData.SetResourceIsInDesiredState -f $LogName, 'MaximumSizeInBytes') + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'MessageResourceFile', $currentMessageResourceFile, $MessageResourceFile) + $inDesiredState = $false } - if ($PSBoundParameters.ContainsKey('LogMode') -and $log.LogMode -ne $LogMode) + if ($PSBoundParameters.ContainsKey('ParameterResourceFile') ` + -and $ParameterResourceFile -ne $currentParameterResourceFile) { - Write-Verbose -Message ($script:localizedData.TestingEventlogLogMode -f $LogName, $LogMode) - $desiredState = $false + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'ParameterResourceFile', $currentParameterResourceFile, $ParameterResourceFile) + $inDesiredState = $false } - else + } + + if ($PSBoundParameters.ContainsKey('LogRetentionDays')) + { + if ($log.IsClassicLog -eq $true -and $LogRetentionDays -ne $currentLogRetentionDays) { - Write-Verbose -Message ($script:localizedData.SetResourceIsInDesiredState -f $LogName, 'LogMode') + Write-Verbose -Message ($script:localizedData.TestTargetResourcePropertyNotInDesiredState ` + -f $LogName, 'LogRetentionDays', $currentLogRetentionDays, $LogRetentionDays) + $inDesiredState = $false } + } - if ($PSBoundParameters.ContainsKey('LogRetentionDays')) - { - if ($LogMode -eq 'AutoBackup') - { - $minimumRetentionDays = Get-EventLog -List | Where-Object -FilterScript { $_.Log -eq $LogName } + return $inDesiredState +} + +<# + .SYNOPSIS + Gets the requested event log and throws an exception if it doesn't exist. + + .PARAMETER LogName + Specifies the name of a valid event log. +#> +function Get-WindowsEventLog +{ + [CmdletBinding()] + [OutputType([System.Diagnostics.Eventing.Reader.EventLogConfiguration])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $LogName + ) + + try + { + $log = Get-WinEvent -ListLog $LogName -ErrorAction Stop + } + catch + { + $message = $script:localizedData.GetWindowsEventLogFailure -f $LogName + New-InvalidOperationException -Message $message -ErrorRecord $_ + } + + return $log +} + +<# + .SYNOPSIS + Gets the registered event source for an event log. + + .PARAMETER LogName + Specifies the name of a valid event log. + + .PARAMETER SourceName + Specifies the specific event source to retrieve. +#> +function Get-WindowsEventLogRegisteredSource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $LogName, + + [Parameter(Mandatory = $true)] + [System.String] + $SourceName + ) + + $source = '' + $logEventSources = Get-CimInstance -Class Win32_NTEventLogFile | + Where-Object -Property LogfileName -EQ $LogName | + Select-Object -ExpandProperty Sources + + if ($logEventSources -contains $SourceName) + { + $source = $SourceName + } + + return $source +} + +<# + .SYNOPSIS + Gets the full path of a registered event source. + + .PARAMETER LogName + Specifies the name of a valid event log. + + .PARAMETER SourceName + Specifies the specific event source. + + .PARAMETER ResourceFileType + Specifies the resource file type to retrieve. +#> +function Get-WindowsEventLogRegisteredSourceFile +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $LogName, - if ($LogRetentionDays -ne $minimumRetentionDays.minimumRetentionDays) + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [System.String] + $SourceName, + + [Parameter(Mandatory = $true)] + [ValidateSet('Category', 'Message', 'Parameter')] + [System.String] + $ResourceFileType + ) + + $file = '' + + if ($SourceName -ne '') + { + $source = Get-ItemProperty ` + -Path "HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\$LogName\$SourceName" ` + -ErrorAction SilentlyContinue + + switch ($ResourceFileType) + { + 'Category' { + if ($null -ne $source.CategoryMessageFile) { - Write-Verbose -Message ($script:localizedData.TestingEventlogLogRetentionDays -f $LogName, $LogRetentionDays) - $desiredState = $false + $file = $source.CategoryMessageFile } - else + } + + 'Message' { + if ($null -ne $source.EventMessageFile) { - Write-Verbose -Message ($script:localizedData.SetResourceIsInDesiredState -f $LogName, 'LogRetentionDays') + $file = $source.EventMessageFile } } - else - { - Write-Verbose -Message ($script:localizedData.EventlogLogRetentionDaysWrongMode -f $LogName) - $desiredState = $false + + 'Parameter' { + if ($null -ne $Source.ParameterMessageFile) + { + $file = $source.ParameterMessageFile + } } } + } - if ($PSBoundParameters.ContainsKey('LogFilePath') -and $log.LogFilePath -ne $LogFilePath) - { - Write-Verbose -Message ($script:localizedData.TestingWindowsEventlogLogFilePath -f $LogName, $LogFilePath) - $desiredState = $false - } - else + return $file +} + +<# + .SYNOPSIS + Gets the status of guest access for an event log. + + .PARAMETER LogName + Specifies the name of a valid event log. +#> +function Get-WindowsEventLogRestrictGuestAccess +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $LogName + ) + + $eventLogRegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\EventLog' + $logRegistryPath = Join-Path -Path $eventLogRegistryPath -ChildPath $LogName + + try + { + $logProperties = Get-ItemProperty -Path $logRegistryPath -ErrorAction Stop + } + catch + { + return $false + } + + return ($logProperties.RestrictGuestAccess -eq 1) +} + +<# + .SYNOPSIS + Gets the retention for an event log and throws an exception if a problem occurs. + + .PARAMETER LogName + Specifies the name of a valid event log. +#> +function Get-WindowsEventLogRetentionDays +{ + [CmdletBinding()] + [OutputType([System.Int32])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $LogName + ) + + $matchingEventLog = Get-EventLog -List | + Where-Object -Property Log -EQ $LogName -ErrorAction Stop + + if ($null -eq $matchingEventLog.MinimumRetentionDays) + { + $message = $script:localizedData.GetWindowsEventLogRetentionDaysFailure -f $LogName + New-InvalidArgumentException -Message $message -ArgumentName 'LogName' + } + + return $matchingEventLog.MinimumRetentionDays +} + +<# + .SYNOPSIS + Registers an event source and throws an exception if the file path is invalid or registration fails. + + .PARAMETER LogName + Specifies the name of a valid event log. + + .PARAMETER SourceName + Specifies the custom source to add to the Windows Event Log. + + .PARAMETER CategoryResourceFile + Specifies the category resource file to register. + + .PARAMETER MessageResourceFile + Specifies the message resource file to register. + + .PARAMETER ParameterResourceFile + Specifies the parameter resource file to register. +#> +function Register-WindowsEventLogSource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $LogName, + + [Parameter(Mandatory = $true)] + [System.String] + $SourceName, + + [Parameter()] + [System.String] + $CategoryResourceFile, + + [Parameter()] + [System.String] + $MessageResourceFile, + + [Parameter()] + [System.String] + $ParameterResourceFile + ) + + $arguments = @{ + LogName = $LogName + Source = $SourceName + } + + if ($PSBoundParameters.ContainsKey('CategoryResourceFile')) + { + if (-not [System.String]::IsNullOrEmpty($CategoryResourceFile) -and ` + -not (Test-Path -Path $CategoryResourceFile -IsValid)) { - Write-Verbose -Message ($script:localizedData.SetResourceIsInDesiredState -f $LogName, 'LogFilePath') + $message = $script:localizedData.RegisterWindowsEventLogSourceInvalidPath ` + -f $SourceName, $CategoryResourceFile + New-InvalidArgumentException -Message $message -ArgumentName 'CategoryResourceFile' } - if ($PSBoundParameters.ContainsKey('SecurityDescriptor') -and $log.SecurityDescriptor -ne $SecurityDescriptor) + $arguments.CategoryResourceFile = $CategoryResourceFile + } + + if ($PSBoundParameters.ContainsKey('MessageResourceFile')) + { + if (-not [System.String]::IsNullOrEmpty($MessageResourceFile) -and ` + -not (Test-Path -Path $MessageResourceFile -IsValid)) { - Write-Verbose -Message ($script:localizedData.TestingWindowsEventlogSecurityDescriptor -f $LogName, $SecurityDescriptor) - $desiredState = $false + $message = $script:localizedData.RegisterWindowsEventLogSourceInvalidPath ` + -f $SourceName, $MessageResourceFile + New-InvalidArgumentException -Message $message -ArgumentName 'MessageResourceFile' } - else + + $arguments.MessageResourceFile = $MessageResourceFile + } + + if ($PSBoundParameters.ContainsKey('ParameterResourceFile')) + { + if (-not [System.String]::IsNullOrEmpty($ParameterResourceFile) -and ` + -not (Test-Path -Path $ParameterResourceFile -IsValid)) { - Write-Verbose -Message ($script:localizedData.SetResourceIsInDesiredState -f $LogName, 'SecurityDescriptor') + $message = $script:localizedData.RegisterWindowsEventLogSourceInvalidPath ` + -f $SourceName, $ParameterResourceFile + New-InvalidArgumentException -Message $message -ArgumentName 'ParameterResourceFile' } + + $arguments.ParameterResourceFile = $ParameterResourceFile } - else + + try { - if ($PSBoundParameters.ContainsKey('IsEnabled') -and $log.IsEnabled -ne $IsEnabled) + if ((Get-WindowsEventLogRegisteredSource -LogName $LogName -SourceName $SourceName) -eq '') { - Write-Verbose -Message ($script:localizedData.TestingEventlogIsEnabled -f $LogName, $IsEnabled) - $desiredState = $false + New-EventLog @arguments -ErrorAction Stop } else { - Write-Verbose -Message ($script:localizedData.SetResourceIsInDesiredState -f $LogName, 'IsEnabled') + Remove-EventLog -Source $SourceName -ErrorAction Stop + New-EventLog @arguments -ErrorAction Stop } } - return $desiredState + catch + { + $message = $script:localizedData.RegisterWindowsEventLogSourceFailure -f $LogName, $RegisteredSource + New-InvalidOperationException -Message $message -ErrorRecord $_ + } } <# .SYNOPSIS - Helper function for the Windows Event Log. + Saves changes to an event log and throws an exception if the operation fails. .PARAMETER Log - Gets the specified Windows Event Log properties. + Specifies the given object of a Windows Event Log. #> -function Get-WindowsEventLog +function Save-WindowsEventLog { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] - [System.String] - $LogName + [System.Diagnostics.Eventing.Reader.EventLogConfiguration] + $log ) - $log = Get-WinEvent -ListLog $LogName - - if (!$log) + try { - Write-Warning ` - -Message ($script:localizedData.WindowsEventLogNotFound -f $LogName) + $log.SaveChanges() } - else + catch { - Write-Verbose -Message ($script:localizedData.WindowsEventLogFound -f $LogName) - return $log + $message = $script:localizedData.SaveWindowsEventLogFailure -f $LogName + New-InvalidOperationException -Message $message -ErrorRecord $_ } } <# .SYNOPSIS - Save the Windows Event Log properties. + Sets the status of guest access for an event log and throws an exception if the operation fails. - .PARAMETER Log - Specifies the given object of a Windows Event Log. + .PARAMETER LogName + Specifies the name of a valid event log. + + .PARAMETER RestrictGuestAccess + Specifies whether to enable or disable guest access. + + .PARAMETER Sddl + Specifies the SDDL to update. #> -function Save-LogFile +function Set-WindowsEventLogRestrictGuestAccess { [CmdletBinding()] + [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] - [System.Object] - $Log + [System.String] + $LogName, + + [Parameter(Mandatory = $true)] + [System.Boolean] + $RestrictGuestAccess, + + [Parameter(Mandatory = $true)] + [System.String] + $Sddl ) + $eventLogRegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\EventLog' + $logRegistryPath = Join-Path -Path $eventLogRegistryPath -ChildPath $LogName + try { - $Log.SaveChanges() - Write-Verbose -Message ($script:localizedData.SaveWindowsEventlogSuccess) + Set-ItemProperty -Path $logRegistryPath ` + -Name 'RestrictGuestAccess' -Value $RestrictGuestAccess -ErrorAction Stop } catch { - Write-Verbose -Message ($script:localizedData.SaveWindowsEventlogFailure) + $message = $script:localizedData.SetWindowsEventLogRestrictGuestAccessFailure -f $LogName + New-InvalidOperationException -Message $message -ErrorRecord $_ } + + $logSddl = '' + $sddlDescriptors = $Sddl.Replace(":", ":`n").Replace(")", ")`n").Split() + + foreach ($sddlDescriptor in $sddlDescriptors) + { + if ($sddlDescriptor -notmatch 'BG\)$') + { + $logSddl += $sddlDescriptor + } + } + + if ($RestrictGuestAccess -eq $false) + { + $logSddl += '(A;;0x1;;;BG)' + } + + return $logSddl } <# .SYNOPSIS - Set the Log Retention for a Windows Event Log. + Sets retention for an event log and throws an exception if the operation fails. .PARAMETER LogName - Specifies the given name of a Windows Event Log. + Specifies the name of a valid event log. + + .PARAMETER LogMode + Specifies the log mode for the specified event log. - .PARAMETER Retention - Specifies the given RetentionDays for LogMode Autobackup. + .PARAMETER LogRetentionDays + Specifies the number of days to retain events when the log mode is AutoBackup. #> -function Set-LogRetentionDays +function Set-WindowsEventLogRetentionDays { [CmdletBinding()] param @@ -432,21 +949,49 @@ function Set-LogRetentionDays [System.String] $LogName, + [Parameter(Mandatory = $true)] + [System.String] + $LogMode, + [Parameter(Mandatory = $true)] [System.Int32] $LogRetentionDays ) - Write-Verbose -Message ($script:localizedData.SettingEventlogLogRetentionDays -f $LogName, $LogRetentionDays) - - try + if ($LogMode -eq 'AutoBackup') { - Limit-Eventlog -LogName $LogName -OverflowAction 'OverwriteOlder' -RetentionDays $LogRetentionDays - Write-Verbose -Message ($script:localizedData.SettingWindowsEventlogRetentionDaysSuccess -f $LogName, $LogRetentionDays) + try + { + $matchingEventLog = Get-EventLog -List | Where-Object -Property Log -EQ $LogName -ErrorAction Stop + } + catch + { + $message = $script:localizedData.GetWindowsEventLogRetentionDaysFailure -f $LogName + New-InvalidOperationException -Message $message -ErrorRecord $_ + } + + $minimumRetentionDaysForLog = $matchingEventLog.MinimumRetentionDays + + if ($LogRetentionDays -ne $minimumRetentionDaysForLog) + { + try + { + Limit-EventLog -LogName $LogName ` + -OverflowAction 'OverwriteOlder' ` + -RetentionDays $LogRetentionDays ` + -ErrorAction Stop + } + catch + { + $message = $script:localizedData.SetWindowsEventLogRetentionDaysFailure -f $LogName + New-InvalidOperationException -Message $message -ErrorRecord $_ + } + } } - catch + else { - Write-Verbose -Message ($script:localizedData.SettingWindowsEventlogRetentionDaysFailed -f $LogName, $LogRetentionDays) + $message = $script:localizedData.SetWindowsEventLogRetentionDaysWrongMode -f $LogName + New-InvalidArgumentException -Message $message -ArgumentName 'LogMode' } } diff --git a/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.schema.mof b/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.schema.mof index 379bfd77..e2294043 100644 --- a/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.schema.mof +++ b/source/DSCResources/DSC_WindowsEventLog/DSC_WindowsEventLog.schema.mof @@ -2,11 +2,16 @@ [ClassVersion("1.0.0.1"), FriendlyName("WindowsEventLog")] class DSC_WindowsEventLog : OMI_BaseResource { - [Key, Description("Specifies the given name of a Windows Event Log")] String LogName; - [Write, Description("Specifies the given state of a Windows Event Log")] Boolean IsEnabled; - [Write, Description("Specifies the given maximum size in bytes for a specified Windows Event Log")] Sint64 MaximumSizeInBytes; - [Write, Description("Specifies the given LogMode for a specified Windows Event Log"), ValueMap{"AutoBackup","Circular","Retain"}, Values{"AutoBackup","Circular","Retain"}] String LogMode; - [Write, Description("Specifies the given SecurityDescriptor for a specified Windows Event Log")] String SecurityDescriptor; - [Write, Description("Specifies the given LogFile path of a Windows Event Log")] String LogFilePath; - [Write, Description("Specifies the given LogRetentionDays for the Logmode 'AutoBackup'")] Sint32 LogRetentionDays; + [Key, Description("Specifies the name of a valid event log")] String LogName; + [Write, Description("Specifies whether the specified event log should be enabled or disabled")] Boolean IsEnabled; + [Write, Description("Specifies the maximum size in bytes for the specified event log")] Sint64 MaximumSizeInBytes; + [Write, Description("Specifies the log mode for the specified event log"), ValueMap{"AutoBackup","Circular","Retain"}, Values{"AutoBackup","Circular","Retain"}] String LogMode; + [Write, Description("Specifies the SDDL for the specified event log")] String SecurityDescriptor; + [Write, Description("Specifies the file name and path for the specified event log")] String LogFilePath; + [Write, Description("Specifies the number of days to retain events when the log mode is AutoBackup")] Sint32 LogRetentionDays; + [Write, Description("Specifies the name of an event source to register for the specified event log")] String RegisteredSource; + [Write, Description("Specifies the category resource file for the event source")] String CategoryResourceFile; + [Write, Description("Specifies the message resource file for the event source")] String MessageResourceFile; + [Write, Description("Specifies the parameter resource file for the event source")] String ParameterResourceFile; + [Write, Description("Specifies whether to allow guests to have access to the specified event log")] Boolean RestrictGuestAccess; }; diff --git a/source/DSCResources/DSC_WindowsEventLog/README.md b/source/DSCResources/DSC_WindowsEventLog/README.md index 3960eec5..3e5dd47b 100644 --- a/source/DSCResources/DSC_WindowsEventLog/README.md +++ b/source/DSCResources/DSC_WindowsEventLog/README.md @@ -1,5 +1,26 @@ # Description -This resource allows the configuration of the Logsize, Logmode, SecurityDescriptor, -RetentionDays and enabled/disabled the state of a specified Windows Event Log. -It is also possible to set the maximum size of the Windows Event Log. +This resource is used to configure the settings of an event log. + +## RestrictGuestAccess and Event Log DACLs + +If you choose to restrict guest access to an event log, the +RestrictGuestAccess registry key will be configured and the event +log's DACL will be checked and updated to ensure the built-in +Guests group has been removed. Conversely, if you choose to +allow guest access, the registry key will be configured and the +DACL will be checked and updated to ensure the built-in Guests +group has been added. + +This DACL behavior also applies if you configure your own custom +DACL via the SecurityDescriptor property and a warning will be +displayed to notify you of the change. + +## RegisteredSource and Resource Files + +The PowerShell cmdlets that define event log sources do not check +for the presence of the resource file on the computer and this +resource follows the same paradigm. If you choose to create your +own resource files and want to register them with the event source, +you must ensure the files have been copied to the computer via a +DSC File resource definition or equivalent. diff --git a/source/DSCResources/DSC_WindowsEventLog/en-US/DSC_WindowsEventLog.strings.psd1 b/source/DSCResources/DSC_WindowsEventLog/en-US/DSC_WindowsEventLog.strings.psd1 index ef6fc6fb..90cbdc21 100644 --- a/source/DSCResources/DSC_WindowsEventLog/en-US/DSC_WindowsEventLog.strings.psd1 +++ b/source/DSCResources/DSC_WindowsEventLog/en-US/DSC_WindowsEventLog.strings.psd1 @@ -1,24 +1,17 @@ -# culture ="en-US" +# Culture = "en-US" ConvertFrom-StringData -StringData @' - GettingEventlogName = Getting the Windows Event Log '{0}'. - TestingWindowsEventlogSecurityDescriptor = Setting the SecurityDescriptor for Windows Event Log '{0}' to '{1}'. - TestingWindowsEventlogLogFilePath = Setting the LogFilePath for Windows Event Log '{0}' to '{1}'. - TestingEventlogMaximumSizeInBytes = Testing the given LogSize '{1}' for Windows Event Log '{0}'. - TestingEventlogLogMode = Testing the given LogMode '{1}' for Windows Event Log '{0}'. - TestingEventlogLogRetentionDays = Testing the given Retention '{1}' days for Windows Event Log '{0}'. - TestingEventlogIsEnabled = Testing the given State '{1}' for Windows Event Log '{0}'. - SettingEventlogLogMode = Setting the LogMode for Windows Event Log '{0}' to '{1}'. - SettingEventlogLogRetentionDays = Setting the Log Retention for Windows Event Log '{0}' to '{1}' days. - SettingEventlogLogSize = Setting the LogSize for Windows Event Log '{0}' to '{1}'. - SettingEventlogLogFilePath = Setting the LogFilePath for Windows Event Log '{0}' to '{1}'. - SettingEventlogIsEnabled = Setting the IsEnabled configuration for Windows Event Log '{0}' to '{1}'. - SettingEventlogSecurityDescriptor = Setting the SecurityDescriptor configuration for Windows Event Log '{0}' to '{1}'. - SettingWindowsEventlogRetentionDaysSuccess = Updating Logfile Retention for Windows Event Log '{0}' successfully to '{1}' days. - SettingWindowsEventlogRetentionDaysFailed = Updating Logfile Retention for Windows Event Log '{0}' to '{1}' failed. - SetResourceIsInDesiredState = Windows Event Log '{0}' is in desired state for configuration '{1}'. - EventlogLogRetentionDaysWrongMode = Setting the Log Retention for Windows Event Log '{0}' failed. LogMode must be AutoBackup. - SaveWindowsEventlogSuccess = Saving Windows Event Log settings successful. - SaveWindowsEventlogFailure = Saving Windows Event Log settings failed. - WindowsEventLogNotFound = Windows Event Log '{0}' is not found. - WindowsEventLogFound = Windows Event Log '{0}' was found. + GetTargetResource = Getting the current state of event log '{0}'. + GetWindowsEventLogFailure = Unable to retrieve event log '{0}' because it was not found. + GetWindowsEventLogRetentionDaysFailure = Unable to retrieve the current retention for event log '{0}' because it was not found. + ModifySystemProvidedSecurityDescriptor = The SecurityDescriptor property (provided by the system) will be modified to ensure alignment with the RestrictGuestAccess property. + ModifyUserProvidedSecurityDescriptor = The SecurityDescriptor property (provided by the user) will be modified to ensure alignment with the RestrictGuestAccess property. + RegisterWindowsEventLogSourceFailure = An error occurred trying to register '{1}' for event log '{0}'. + RegisterWindowsEventLogSourceInvalidPath = Unable to register '{1}' for event source '{0}' because the path is invalid. + SaveWindowsEventLogFailure = An error occurred trying to save the properties for event log '{0}'. + SetWindowsEventLogRestrictGuestAccessFailure = An error occurred trying to configure restricted guest access for event log '{0}'. + SetWindowsEventLogRetentionDaysFailure = An error occurred trying to configure retention for event log '{0}'. + SetWindowsEventLogRetentionDaysWrongMode = Unable to configure retention for event log '{0}' because LogMode must be set to AutoBackup. + SetWindowsEventLogRetentionDaysNotClassic = Unable to configure retention for event log '{0}' because it not a classic event log. + SetTargetResourceProperty = Setting the '{1}' property of event log '{0}'. Current value '{2}'. Requested value '{3}'. + TestTargetResourcePropertyNotInDesiredState = The '{1}' property of event log '{0}' is not in the desired state. Current value '{2}'. Requested value '{3}'. '@ diff --git a/source/Examples/Resources/WindowsEventlog/1-WindowsEventlog_SetWindowsEventlogSize_Config.ps1 b/source/Examples/Resources/WindowsEventlog/1-WindowsEventLog_SetLogSize_Config.ps1 similarity index 67% rename from source/Examples/Resources/WindowsEventlog/1-WindowsEventlog_SetWindowsEventlogSize_Config.ps1 rename to source/Examples/Resources/WindowsEventlog/1-WindowsEventLog_SetLogSize_Config.ps1 index 5690f4b4..6f563860 100644 --- a/source/Examples/Resources/WindowsEventlog/1-WindowsEventlog_SetWindowsEventlogSize_Config.ps1 +++ b/source/Examples/Resources/WindowsEventlog/1-WindowsEventLog_SetLogSize_Config.ps1 @@ -19,21 +19,21 @@ <# .DESCRIPTION - Example script that sets the application Windows Event Log - to a maximum size 4096MB, the logmode to 'Circular' and ensure that it is enabled. + Sets the Application log to a maximum size of 4096MB, + the log mode to circular, and ensure it is enabled. #> -Configuration WindowsEventlog_SetWindowsEventlogSize_Config +Configuration WindowsEventLog_SetLogSize_Config { Import-DSCResource -ModuleName ComputerManagementDsc Node localhost { - WindowsEventLog ApplicationEventlogSize + WindowsEventLog Application { LogName = 'Application' IsEnabled = $true LogMode = 'Circular' - MaximumSizeInBytes = 4096KB - } # End of Windows Event Log Resource - } # End of Node -} # End of Configuration + MaximumSizeInBytes = 4096MB + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/10-WindowsEventLog_RegisterEventSourceWithAllFiles_Config.ps1 b/source/Examples/Resources/WindowsEventlog/10-WindowsEventLog_RegisterEventSourceWithAllFiles_Config.ps1 new file mode 100644 index 00000000..4a717fa7 --- /dev/null +++ b/source/Examples/Resources/WindowsEventlog/10-WindowsEventLog_RegisterEventSourceWithAllFiles_Config.ps1 @@ -0,0 +1,67 @@ +<#PSScriptInfo +.VERSION 1.0.0 +.GUID cabb6778-8f48-4ce7-ad3d-2cc444bc78e9 +.AUTHOR DSC Community +.COMPANYNAME DSC Community +.COPYRIGHT Copyright the DSC Community contributors. All rights reserved. +.TAGS DSCConfiguration +.LICENSEURI https://github.com/dsccommunity/ComputerManagementDsc/blob/master/LICENSE +.PROJECTURI https://github.com/dsccommunity/ComputerManagementDsc +.ICONURI +.EXTERNALMODULEDEPENDENCIES +.REQUIREDSCRIPTS +.EXTERNALSCRIPTDEPENDENCIES +.RELEASENOTES First version. +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core +#> + +#Requires -module ComputerManagementDsc + +<# + .DESCRIPTION + Example script that registers MyEventSource as an event + source with all resource files on the Application log. +#> +Configuration WindowsEventLog_RegisterEventSourceWithAllFiles_Config +{ + Import-DSCResource -ModuleName ComputerManagementDsc + + Node localhost + { + File MyEventSourceCategoryDll + { + Ensure = 'Present' + Type = 'File' + SourcePath = '\\PULLSERVER\Files\MyEventSource.Category.dll' + DestinationPath = 'C:\Windows\System32\MyEventSource.Category.dll' + } + + File MyEventSourceMessageDll + { + Ensure = 'Present' + Type = 'File' + SourcePath = '\\PULLSERVER\Files\MyEventSource.Message.dll' + DestinationPath = 'C:\Windows\System32\MyEventSource.Message.dll' + } + + File MyEventSourceParameterDll + { + Ensure = 'Present' + Type = 'File' + SourcePath = '\\PULLSERVER\Files\MyEventSource.Parameter.dll' + DestinationPath = 'C:\Windows\System32\MyEventSource.Parameter.dll' + } + + WindowsEventLog Application + { + LogName = 'Application' + RegisteredSource = 'MyEventSource' + CategoryResourceFile = 'C:\Windows\System32\MyEventSource.Category.dll' + MessageResourceFile = 'C:\Windows\System32\MyEventSource.Messages.dll' + ParameterResourceFile = 'C:\Windows\System32\MyEventSource.Parameters.dll' + DependsOn = '[File]MyEventSourceCategoryDll', + '[File]MyEventSourceMessageDll', + '[File]MyEventSourceParameterDll' + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/2-WindowsEventlog_SetWindowsEventlogLogMode_Config.ps1 b/source/Examples/Resources/WindowsEventlog/2-WindowsEventLog_SetLogMode_Config.ps1 similarity index 63% rename from source/Examples/Resources/WindowsEventlog/2-WindowsEventlog_SetWindowsEventlogLogMode_Config.ps1 rename to source/Examples/Resources/WindowsEventlog/2-WindowsEventLog_SetLogMode_Config.ps1 index 338ae385..d4ce798d 100644 --- a/source/Examples/Resources/WindowsEventlog/2-WindowsEventlog_SetWindowsEventlogLogMode_Config.ps1 +++ b/source/Examples/Resources/WindowsEventlog/2-WindowsEventLog_SetLogMode_Config.ps1 @@ -19,23 +19,23 @@ <# .DESCRIPTION - Example script that sets the application Windows Event Log - to mode AutoBackup and logsize to a maximum size of 2048MB - with a logfile retention for 10 days and ensure it is enabled. + Example script that sets the MSPaint Admin event channel + to log mode AutoBackup, a maximum size of 2048MB, log + retention for 10 days, and ensure it is enabled. #> -Configuration WindowsEventlog_SetWindowsEventlogLogMode_Config +Configuration WindowsEventLog_SetLogMode_Config { Import-DSCResource -ModuleName ComputerManagementDsc Node localhost { - WindowsEventLog ApplicationEventlogMode + WindowsEventLog MSPaintAdmin { LogName = 'Microsoft-Windows-MSPaint/Admin' IsEnabled = $true LogMode = 'AutoBackup' - LogRetentionDays = '10' - MaximumSizeInBytes = 2048kb - } # End of Windows Event Log Resource - } # End of Node -} # End of Configuration + LogRetentionDays = 10 + MaximumSizeInBytes = 2048KB + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/3-WindowsEventlog_EnableWindowsEventLog_Config.ps1 b/source/Examples/Resources/WindowsEventlog/3-WindowsEventlog_EnableWindowsEventLog_Config.ps1 index 4a2d01ec..9293a8e3 100644 --- a/source/Examples/Resources/WindowsEventlog/3-WindowsEventlog_EnableWindowsEventLog_Config.ps1 +++ b/source/Examples/Resources/WindowsEventlog/3-WindowsEventlog_EnableWindowsEventLog_Config.ps1 @@ -19,22 +19,23 @@ <# .DESCRIPTION - Example script that sets the Dsc Analytic Windows Event Log - to size maximum size 4096MB, with logmode 'Retain' and ensure it is enabled. + Example script that sets the DSC Analytic log + to size maximum size 4096MB, log mode to 'Retain' and + ensures it is enabled. #> -Configuration WindowsEventlog_EnableWindowsEventLog_Config +Configuration WindowsEventLog_EnableWindowsEventLog_Config { Import-DSCResource -ModuleName ComputerManagementDsc Node localhost { - WindowsEventLog Enable-DscAnalytic + WindowsEventLog DscAnalytic { - LogName = 'Microsoft-Windows-Dsc/Analytic' - IsEnabled = $True - LogMode = 'Retain' - MaximumSizeInBytes = 4096kb - LogFilePath = "%SystemRoot%\System32\Winevt\Logs\Microsoft-Windows-DSC%4Analytic.evtx" - } # End of Windows Event Log Resource - } # End of Node -} # End of Configuration + LogName = 'Microsoft-Windows-Dsc/Analytic' + IsEnabled = $true + LogMode = 'Retain' + MaximumSizeInBytes = 4096MB + LogFilePath = '%SystemRoot%\System32\Winevt\Logs\Microsoft-Windows-DSC%4Analytic.evtx' + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/6-WindowsEventlog_DisableWindowsEventlog_Config.ps1 b/source/Examples/Resources/WindowsEventlog/4-WindowsEventLog_DisableWindowsEventLog_Config.ps1 similarity index 65% rename from source/Examples/Resources/WindowsEventlog/6-WindowsEventlog_DisableWindowsEventlog_Config.ps1 rename to source/Examples/Resources/WindowsEventlog/4-WindowsEventLog_DisableWindowsEventLog_Config.ps1 index 1004de27..5f89f65b 100644 --- a/source/Examples/Resources/WindowsEventlog/6-WindowsEventlog_DisableWindowsEventlog_Config.ps1 +++ b/source/Examples/Resources/WindowsEventlog/4-WindowsEventLog_DisableWindowsEventLog_Config.ps1 @@ -19,18 +19,18 @@ <# .DESCRIPTION - Example script that disables the given Windows Event Log. + Example script that disables the DSC Analytic log. #> -Configuration WindowsEventlog_DisableWindowsEventlog_Config +Configuration WindowsEventLog_DisableWindowsEventLog_Config { Import-DSCResource -ModuleName ComputerManagementDsc Node localhost { - WindowsEventLog Enable-DscAnalytic + WindowsEventLog DscAnalytic { - LogName = 'Microsoft-Windows-Dsc/Analytic' - IsEnabled = $false - } # End of Windows Event Log Resource - } # End of Node -} # End of Configuration + LogName = 'Microsoft-Windows-Dsc/Analytic' + IsEnabled = $false + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/5-WindowsEventlog_SetWindowsEventlogSecurityDescriptor_Config.ps1 b/source/Examples/Resources/WindowsEventlog/5-WindowsEventLog_SetSecurityDescriptor_Config.ps1 similarity index 63% rename from source/Examples/Resources/WindowsEventlog/5-WindowsEventlog_SetWindowsEventlogSecurityDescriptor_Config.ps1 rename to source/Examples/Resources/WindowsEventlog/5-WindowsEventLog_SetSecurityDescriptor_Config.ps1 index 0f8c89ee..aa7573ed 100644 --- a/source/Examples/Resources/WindowsEventlog/5-WindowsEventlog_SetWindowsEventlogSecurityDescriptor_Config.ps1 +++ b/source/Examples/Resources/WindowsEventlog/5-WindowsEventLog_SetSecurityDescriptor_Config.ps1 @@ -19,23 +19,19 @@ <# .DESCRIPTION - Example script that sets the application Windows Event Log - logmode to 'Circular' with 30 days retention, - with a Security Desriptor and ensure it is enabled. + Example script that reconfigures the security + descriptor (DACL) of the Application log. #> -Configuration WindowsEventlog_SetWindowsEventlogSecurityDescriptor_Config +Configuration WindowsEventLog_SetSecurityDescriptor_Config { Import-DSCResource -ModuleName ComputerManagementDsc Node localhost { - WindowsEventLog ApplicationEventlogSize + WindowsEventLog Application { LogName = 'Application' - IsEnabled = $true - LogMode = 'Circular' - MaximumSizeInBytes = 2048kb SecurityDescriptor = 'O:BAG:SYD:(A;;0x7;;;BA)(A;;0x7;;;SO)(A;;0x3;;;IU)(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)(A;;0x3;;;S-1-5-33)(A;;0x1;;;S-1-5-32-573)' - } # End of Windows Event Log Resource - } # End of Node -} # End of Configuration + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/4-WindowsEventlog_SetWindowsEventlogLogMode_Config.ps1 b/source/Examples/Resources/WindowsEventlog/6-WindowsEventLog_RestrictGuestAccess_Config.ps1 similarity index 54% rename from source/Examples/Resources/WindowsEventlog/4-WindowsEventlog_SetWindowsEventlogLogMode_Config.ps1 rename to source/Examples/Resources/WindowsEventlog/6-WindowsEventLog_RestrictGuestAccess_Config.ps1 index 792a8818..bddfee12 100644 --- a/source/Examples/Resources/WindowsEventlog/4-WindowsEventlog_SetWindowsEventlogLogMode_Config.ps1 +++ b/source/Examples/Resources/WindowsEventlog/6-WindowsEventLog_RestrictGuestAccess_Config.ps1 @@ -1,6 +1,6 @@ <#PSScriptInfo .VERSION 1.0.0 -.GUID 1e24ee07-cb2f-489b-af15-ebf6ffa864fe +.GUID ab5cc60b-b834-49b0-80f4-f73f18bf9199 .AUTHOR DSC Community .COMPANYNAME DSC Community .COPYRIGHT Copyright the DSC Community contributors. All rights reserved. @@ -19,21 +19,19 @@ <# .DESCRIPTION - Example script that sets the application Windows Event Log - logmode to 'Autobackup' with 30 days retention and ensure it is enabled. + Example script that prohibits guests from accessing + the System event log. #> -Configuration WindowsEventlog_SetWindowsEventlogLogMode_Config +Configuration WindowsEventLog_RestrictGuestAccess_Config { Import-DSCResource -ModuleName ComputerManagementDsc Node localhost { - WindowsEventLog ApplicationEventlogSize + WindowsEventLog System { - LogName = 'Application' - IsEnabled = $true - LogMode = 'AutoBackup' - LogRetentionDays = 30 - } # End of Windows Event Log Resource - } # End of Node -} # End of Configuration + LogName = 'System' + RestrictGuestAccess = $true + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/7-WindowsEventLog_AllowGuestAccess_Config.ps1 b/source/Examples/Resources/WindowsEventlog/7-WindowsEventLog_AllowGuestAccess_Config.ps1 new file mode 100644 index 00000000..14a78890 --- /dev/null +++ b/source/Examples/Resources/WindowsEventlog/7-WindowsEventLog_AllowGuestAccess_Config.ps1 @@ -0,0 +1,37 @@ +<#PSScriptInfo +.VERSION 1.0.0 +.GUID 3f7e83d6-f29c-45f1-a305-2addb69fb0f2 +.AUTHOR DSC Community +.COMPANYNAME DSC Community +.COPYRIGHT Copyright the DSC Community contributors. All rights reserved. +.TAGS DSCConfiguration +.LICENSEURI https://github.com/dsccommunity/ComputerManagementDsc/blob/master/LICENSE +.PROJECTURI https://github.com/dsccommunity/ComputerManagementDsc +.ICONURI +.EXTERNALMODULEDEPENDENCIES +.REQUIREDSCRIPTS +.EXTERNALSCRIPTDEPENDENCIES +.RELEASENOTES First version. +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core +#> + +#Requires -module ComputerManagementDsc + +<# + .DESCRIPTION + Example script that allows guests to access + the Application event log. +#> +Configuration WindowsEventLog_AllowGuestAccess_Config +{ + Import-DSCResource -ModuleName ComputerManagementDsc + + Node localhost + { + WindowsEventLog System + { + LogName = 'System' + RestrictGuestAccess = $false + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/8-WindowsEventLog_RegisterEventSource_Config.ps1 b/source/Examples/Resources/WindowsEventlog/8-WindowsEventLog_RegisterEventSource_Config.ps1 new file mode 100644 index 00000000..78ae35b2 --- /dev/null +++ b/source/Examples/Resources/WindowsEventlog/8-WindowsEventLog_RegisterEventSource_Config.ps1 @@ -0,0 +1,37 @@ +<#PSScriptInfo +.VERSION 1.0.0 +.GUID 857f9f25-082e-4274-9efd-0908f49bb516 +.AUTHOR DSC Community +.COMPANYNAME DSC Community +.COPYRIGHT Copyright the DSC Community contributors. All rights reserved. +.TAGS DSCConfiguration +.LICENSEURI https://github.com/dsccommunity/ComputerManagementDsc/blob/master/LICENSE +.PROJECTURI https://github.com/dsccommunity/ComputerManagementDsc +.ICONURI +.EXTERNALMODULEDEPENDENCIES +.REQUIREDSCRIPTS +.EXTERNALSCRIPTDEPENDENCIES +.RELEASENOTES First version. +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core +#> + +#Requires -module ComputerManagementDsc + +<# + .DESCRIPTION + Example script that registers MyEventSource as an event + source on the Application log. +#> +Configuration WindowsEventLog_RegisterEventSource_Config +{ + Import-DSCResource -ModuleName ComputerManagementDsc + + Node localhost + { + WindowsEventLog Application + { + LogName = 'Application' + RegisteredSource = 'MyEventSource' + } + } +} diff --git a/source/Examples/Resources/WindowsEventlog/9-WindowsEventLog_RegisterEventSourceWithMessageFile_Config.ps1 b/source/Examples/Resources/WindowsEventlog/9-WindowsEventLog_RegisterEventSourceWithMessageFile_Config.ps1 new file mode 100644 index 00000000..0a94cc13 --- /dev/null +++ b/source/Examples/Resources/WindowsEventlog/9-WindowsEventLog_RegisterEventSourceWithMessageFile_Config.ps1 @@ -0,0 +1,47 @@ +<#PSScriptInfo +.VERSION 1.0.0 +.GUID 13b87555-fdf1-4cc7-b033-73074573e0e3 +.AUTHOR DSC Community +.COMPANYNAME DSC Community +.COPYRIGHT Copyright the DSC Community contributors. All rights reserved. +.TAGS DSCConfiguration +.LICENSEURI https://github.com/dsccommunity/ComputerManagementDsc/blob/master/LICENSE +.PROJECTURI https://github.com/dsccommunity/ComputerManagementDsc +.ICONURI +.EXTERNALMODULEDEPENDENCIES +.REQUIREDSCRIPTS +.EXTERNALSCRIPTDEPENDENCIES +.RELEASENOTES First version. +.PRIVATEDATA 2016-Datacenter,2016-Datacenter-Server-Core +#> + +#Requires -module ComputerManagementDsc + +<# + .DESCRIPTION + Example script that registers MyEventSource as an event + source with a message resource file on the Application log. +#> +Configuration WindowsEventLog_RegisterEventSourceWithMessageFile_Config +{ + Import-DSCResource -ModuleName ComputerManagementDsc + + Node localhost + { + File MyEventSourceMessageDll + { + Ensure = 'Present' + Type = 'File' + SourcePath = '\\PULLSERVER\Files\MyEventSource.dll' + DestinationPath = 'C:\Windows\System32\MyEventSource.dll' + } + + WindowsEventLog Application + { + LogName = 'Application' + RegisteredSource = 'MyEventSource' + MessageResourceFile = 'C:\Windows\System32\MyEventSource.dll' + DependsOn = '[File]MyEventSourceMessageDll' + } + } +} diff --git a/tests/Integration/DSC_WindowsEventLog.Integration.Tests.ps1 b/tests/Integration/DSC_WindowsEventLog.Integration.Tests.ps1 index 6976cd78..68a64131 100644 --- a/tests/Integration/DSC_WindowsEventLog.Integration.Tests.ps1 +++ b/tests/Integration/DSC_WindowsEventLog.Integration.Tests.ps1 @@ -26,7 +26,7 @@ try . $configFile Describe "$($script:dscResourceName)_Integration" { - Context 'When setting Windows Event Log to Logmode Retain' { + Context 'When setting the Application log to LogMode Retain' { $currentConfig = 'DSC_WindowsEventLog_RetainSize' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -54,8 +54,8 @@ try } } - Context 'When setting Windows Event Log to Logmode AutoBackup with LogRetentionDays of 30 days' { - $currentConfig = 'DSC_WindowsEventLog_AutobackupLogRetention' + Context 'When setting the Application log to LogMode AutoBackup and 30 day retention' { + $currentConfig = 'DSC_WindowsEventLog_AutoBackupLogRetention' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -82,7 +82,7 @@ try } } - Context 'When setting Windows Event Log to Logmode Circular, MaximumSizeInBytes 20971520, LogFilePath C:\temp\Application.evtx' { + Context 'When setting the Application log to LogMode Circular, MaximumSizeInBytes 20971520, LogFilePath C:\temp\Application.evtx' { $currentConfig = 'DSC_WindowsEventLog_CircularLogPath' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -110,7 +110,7 @@ try } } - Context 'When setting Windows Event Log to Default' { + Context 'When setting the Application log back to default' { $currentConfig = 'DSC_WindowsEventLog_Default' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -138,7 +138,7 @@ try } } - Context 'When enabling a Logfile other than Application Eventlog' { + Context 'When enabling the Microsoft-Windows-CAPI2 Operational channel' { $currentConfig = 'DSC_WindowsEventLog_EnableLog' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -166,7 +166,7 @@ try } } - Context 'When disableing a Logfile other than Application Windows Event Log' { + Context 'When disabling the Microsoft-Windows-CAPI2 Operational channel' { $currentConfig = 'DSC_WindowsEventLog_DisableLog' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -194,7 +194,7 @@ try } } - Context 'When setting Eventlog to Logmode Circular with a SecurityDescriptor' { + Context 'When setting the Application log to LogMode Circular with a SecurityDescriptor' { $currentConfig = 'DSC_WindowsEventLog_CircularSecurityDescriptor' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -222,7 +222,7 @@ try } } - Context 'When enabling a Logfile other than Application Windows Event Log with Retention' { + Context 'When enabling the Microsoft-Windows-Backup channel with LogMode AutoBackup and 30 day retention' { $currentConfig = 'DSC_WindowsEventLog_EnableBackupLog' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -241,8 +241,8 @@ try } | Should -Not -Throw } - It 'Should return a incompliant state' { - (Test-DscConfiguration -ReferenceConfiguration $configMof -Verbose).InDesiredState | Should -BeFalse + It 'Should return a compliant state after being applied' { + (Test-DscConfiguration -ReferenceConfiguration $configMof -Verbose).InDesiredState | Should -BeTrue } It 'Should be able to call Get-DscConfiguration without throwing' { @@ -250,7 +250,7 @@ try } } - Context 'When disabling a Logfile other than Application Eventlog with retention' { + Context 'When disabling the Microsoft-Windows-Backup channel' { $currentConfig = 'DSC_WindowsEventLog_DisableBackupLog' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') @@ -278,6 +278,90 @@ try } } + Context 'When creating an event source in the Application log' { + $currentConfig = 'DSC_WindowsEventLog_CreateCustomResource' + $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) + $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') + + It 'Should compile the MOF without throwing' { + { + . $currentConfig -OutputPath $configDir + } | Should -Not -Throw + } + + It 'Should apply the MOF without throwing' { + { + Reset-DscLcm + + Start-DscConfiguration -Path $configDir -Wait -Verbose -Force + } | Should -Not -Throw + } + + It 'Should return a compliant state after being applied' { + (Test-DscConfiguration -ReferenceConfiguration $configMof -Verbose).InDesiredState | Should -BeTrue + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should -Not -Throw + } + } + + Context 'When allowing guests to have access to the Application log' { + $currentConfig = 'DSC_WindowsEventLog_AppLogGuestsAllowed' + $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) + $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') + + It 'Should compile the MOF without throwing' { + { + . $currentConfig -OutputPath $configDir + } | Should -Not -Throw + } + + It 'Should apply the MOF without throwing' { + { + Reset-DscLcm + + Start-DscConfiguration -Path $configDir -Wait -Verbose -Force + } | Should -Not -Throw + } + + It 'Should return a compliant state after being applied' { + (Test-DscConfiguration -ReferenceConfiguration $configMof -Verbose).InDesiredState | Should -BeTrue + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should -Not -Throw + } + } + + Context 'When prohibiting guests to have access to the Application log' { + $currentConfig = 'DSC_WindowsEventLog_AppLogGuestsProhibited' + $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) + $configMof = (Join-Path -Path $configDir -ChildPath 'localhost.mof') + + It 'Should compile the MOF without throwing' { + { + . $currentConfig -OutputPath $configDir + } | Should -Not -Throw + } + + It 'Should apply the MOF without throwing' { + { + Reset-DscLcm + + Start-DscConfiguration -Path $configDir -Wait -Verbose -Force + } | Should -Not -Throw + } + + It 'Should return a compliant state after being applied' { + (Test-DscConfiguration -ReferenceConfiguration $configMof -Verbose).InDesiredState | Should -BeTrue + } + + It 'Should be able to call Get-DscConfiguration without throwing' { + { Get-DscConfiguration -Verbose -ErrorAction Stop } | Should -Not -Throw + } + } + Context 'When setting Windows Event Log back to the default configuration' { $currentConfig = 'DSC_WindowsEventLog_Default' $configDir = (Join-Path -Path $TestDrive -ChildPath $currentConfig) diff --git a/tests/Integration/DSC_WindowsEventLog.config.ps1 b/tests/Integration/DSC_WindowsEventLog.config.ps1 index 6e090a97..0943ce14 100644 --- a/tests/Integration/DSC_WindowsEventLog.config.ps1 +++ b/tests/Integration/DSC_WindowsEventLog.config.ps1 @@ -2,7 +2,7 @@ Configuration DSC_WindowsEventLog_Default { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -19,7 +19,7 @@ Configuration DSC_WindowsEventLog_Default Configuration DSC_WindowsEventLog_RetainSize { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -34,7 +34,7 @@ Configuration DSC_WindowsEventLog_RetainSize Configuration DSC_WindowsEventLog_AutobackupLogRetention { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -49,7 +49,7 @@ Configuration DSC_WindowsEventLog_AutobackupLogRetention Configuration DSC_WindowsEventLog_CircularLogPath { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -65,7 +65,7 @@ Configuration DSC_WindowsEventLog_CircularLogPath Configuration DSC_WindowsEventLog_EnableLog { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -80,7 +80,7 @@ Configuration DSC_WindowsEventLog_EnableLog Configuration DSC_WindowsEventLog_DisableLog { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -93,7 +93,7 @@ Configuration DSC_WindowsEventLog_DisableLog Configuration DSC_WindowsEventLog_CircularSecurityDescriptor { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -109,14 +109,14 @@ Configuration DSC_WindowsEventLog_CircularSecurityDescriptor Configuration DSC_WindowsEventLog_EnableBackupLog { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { LogName = 'Microsoft-Windows-Backup' IsEnabled = $true LogMode = 'AutoBackup' - LogRetentionDays = '30' + LogRetentionDays = 30 } } } @@ -124,7 +124,7 @@ Configuration DSC_WindowsEventLog_EnableBackupLog Configuration DSC_WindowsEventLog_DisableBackupLog { Import-DscResource -ModuleName ComputerManagementDsc - node 'localhost' + Node 'localhost' { WindowsEventLog Integration_Test { @@ -133,3 +133,45 @@ Configuration DSC_WindowsEventLog_DisableBackupLog } } } + +Configuration DSC_WindowsEventLog_CreateCustomResource +{ + Import-DscResource -ModuleName ComputerManagementDsc + Node 'localhost' + { + WindowsEventLog Integration_Test + { + LogName = 'Application' + RegisteredSource = 'MyCustomSource' + CategoryResourceFile = 'C:\Windows\System32\MCS.Category.dll' + MessageResourceFile = 'C:\Windows\System32\MCS.Message.dll' + ParameterResourceFile = 'C:\Windows\System32\MCS.Parameter.dll' + } + } +} + +Configuration DSC_WindowsEventLog_AppLogGuestsAllowed +{ + Import-DscResource -ModuleName ComputerManagementDsc + Node 'localhost' + { + WindowsEventLog Integration_Test + { + LogName = 'Application' + RestrictGuestAccess = $false + } + } +} + +Configuration DSC_WindowsEventLog_AppLogGuestsProhibited +{ + Import-DscResource -ModuleName ComputerManagementDsc + Node 'localhost' + { + WindowsEventLog Integration_Test + { + LogName = 'Application' + RestrictGuestAccess = $true + } + } +} diff --git a/tests/Unit/DSC_WindowsEventLog.Tests.ps1 b/tests/Unit/DSC_WindowsEventLog.Tests.ps1 index ddcf4b64..d84e7261 100644 --- a/tests/Unit/DSC_WindowsEventLog.Tests.ps1 +++ b/tests/Unit/DSC_WindowsEventLog.Tests.ps1 @@ -32,359 +32,589 @@ Invoke-TestSetup try { InModuleScope $script:dscResourceName { - Describe 'DSC_WindowsEventLog\Get-TargetResource' -Tag 'Get' { + $fullParams = @{ + IsEnabled = $true + LogFilePath = '%SystemRoot%\System32\Winevt\Logs\Application.evtx' + LogMode = 'Circular' + LogName = 'Application' + LogRetentionDays = 0 + MaximumSizeInBytes = [System.Int64] 525074432 + RestrictGuestAccess = $true + SecurityDescriptor = 'O:BAG:SYD:(A;;0x2;;;S-1-15-2-1)' + ` + '(A;;0xf0007;;;SY)(A;;0x7;;;BA)' + ` + '(A;;0x7;;;SO)(A;;0x3;;;IU)' + ` + '(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)' + ` + '(A;;0x3;;;S-1-5-33)(A;;0x1;;;S-1-5-32-573)' + RegisteredSource = 'PesterTest' + CategoryResourceFile = 'C:\WINDOWS\System32\PesterTest.dll' + MessageResourceFile = 'C:\WINDOWS\System32\PesterTest.dll' + ParameterResourceFile = 'C:\WINDOWS\System32\PesterTest.dll' + } - Mock -CommandName Get-WindowsEventLog -MockWith { - $properties = @{ - MaximumSizeInBytes = 4096kb + $mocks = @{ + GetCimInstancePesterTestExist = New-Object -TypeName PSObject -Property @{ + LogfileName = 'Application' + Name = '%SystemRoot%\System32\Winevt\Logs\Application.evtx' + Sources = @( + 'Application', + 'Application Error', + 'Application Hang', + 'Application Management', + 'PesterTest' + ) + } + + GetCimInstancePesterTestNotExist = New-Object -TypeName PSObject -Property @{ + LogfileName = 'Application' + Name = '%SystemRoot%\System32\Winevt\Logs\Application.evtx' + Sources = @( + 'Application', + 'Application Error', + 'Application Hang', + 'Application Management' + ) + } + + GetEventLogAppLogDefaults = New-Object -TypeName PSObject -Property @{ + Log = 'Application' + MinimumRetentionDays = 0 + } + + GetWinEventAppLogDefaults = New-Object ` + -TypeName System.Diagnostics.Eventing.Reader.EventLogConfiguration ` + -ArgumentList 'Application' ` + -Property @{ IsEnabled = $true - LogMode = 'Circular' LogFilePath = '%SystemRoot%\System32\Winevt\Logs\Application.evtx' - SecurityDescriptor = 'TestDescriptor' - LogRetentionDays = '0' - LogName = 'Application' - } - - return (New-Object -TypeName PSObject -Property $properties) + LogMode = 'Circular' + MaximumSizeInBytes = [System.Int64] 525074432 + SecurityDescriptor = 'O:BAG:SYD:(A;;0x2;;;S-1-15-2-1)' + ` + '(A;;0xf0007;;;SY)(A;;0x7;;;BA)' + ` + '(A;;0x7;;;SO)(A;;0x3;;;IU)' + ` + '(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)' + ` + '(A;;0x3;;;S-1-5-33)(A;;0x1;;;S-1-5-32-573)' } - $results = Get-TargetResource -LogName 'Application' -IsEnabled $true - - It 'Should return an hashtable' { - $results.GetType().Name | Should -Be 'Hashtable' + GetWELRegisteredSourceFilePesterTestExist = New-Object -TypeName PSObject -Property @{ + CategoryCount = 1 + CategoryMessageFile = 'C:\WINDOWS\System32\PesterTest.dll' + EventMessageFile = 'C:\WINDOWS\System32\PesterTest.dll' + ParameterMessageFile = 'C:\WINDOWS\System32\PesterTest.dll' } + } - It 'Should return a Logname Application' { - $results.LogName = 'Application' + $setCasesGeneric = @( + @{ + EventLogSetting = 'IsEnabled' + NewValue = $false } - - It 'Should return a MaximumSizeInBytes of 4096kb' { - $results.MaximumSizeInBytes | Should -Be 4096kb + @{ + EventLogSetting = 'LogFilePath' + NewValue = '%SystemRoot%\System32\Winevt\Logs\NewApplication.evtx' } - - It 'Should return IsEnabled is true' { - $results.IsEnabled | Should -BeTrue + @{ + EventLogSetting = 'LogMode' + NewValue = 'AutoBackup' } + @{ + EventLogSetting = 'MaximumSizeInBytes' + NewValue = 1MB + } + @{ + EventLogSetting = 'SecurityDescriptor' + NewValue = 'O:BAG:SYD:(A;;0x2;;;S-1-15-2-1)(A;;0xf0007;;;SY)(A;;0x7;;;BA)' + } + @{ + EventLogSetting = 'RestrictGuestAccess' + NewValue = $false + } + ) - It 'Should return a LogMode is Circular' { - $results.LogMode | Should -Be 'Circular' + $testCasesGeneric = @( + @{ + EventLogSetting = 'IsEnabled' + NewValue = $false + } + @{ + EventLogSetting = 'LogFilePath' + NewValue = '%SystemRoot%\System32\Winevt\Logs\NewApplication.evtx' + } + @{ + EventLogSetting = 'LogMode' + NewValue = 'AutoBackup' + } + @{ + EventLogSetting = 'LogRetentionDays' + NewValue = 30 + } + @{ + EventLogSetting = 'MaximumSizeInBytes' + NewValue = 1MB + } + @{ + EventLogSetting = 'SecurityDescriptor' + NewValue = 'O:BAG:SYD:(A;;0x2;;;S-1-15-2-1)(A;;0xf0007;;;SY)(A;;0x7;;;BA)' } + @{ + EventLogSetting = 'RegisteredSource' + NewValue = 'NewPesterTest' + } + @{ + EventLogSetting = 'RestrictGuestAccess' + NewValue = $false + } + ) - It 'Should return a LogRetentionDays of 0' { - $results.LogRetentionDays | Should -Be 0 + $testCasesEventSource = @( + @{ + EventLogSetting = 'CategoryResourceFile' + NewValue = 'C:\WINDOWS\System32\NewPesterTest.dll' + } + @{ + EventLogSetting = 'MessageResourceFile' + NewValue = 'C:\WINDOWS\System32\NewPesterTest.dll' } + @{ + EventLogSetting = 'ParameterResourceFile' + NewValue = 'C:\WINDOWS\System32\NewPesterTest.dll' + } + ) - It 'Should return a LogFilePath of %SystemRoot%\System32\Winevt\Logs\Application.evtx' { - $results.LogFilePath | Should -Be "%SystemRoot%\System32\Winevt\Logs\Application.evtx" + Describe "DSC_WindowsEventLog\Get-TargetResource" -Tag 'Get' { + Context 'When getting a request for a non-existent target resource' { + $errorMessage = $script:localizedData.GetWindowsEventLogFailure -f 'UndefinedLog' + It 'Should throw when an event log does not exist' { + { Get-TargetResource -LogName 'UndefinedLog' } | Should -Throw $errorMessage + } } - It 'Should return SecurityDescriptor with a value TestDescriptor' { - $results.SecurityDescriptor | Should -Be 'TestDescriptor' + Context 'When getting the default target resource' { + Mock -CommandName Get-EventLog -MockWith { + return $mocks.GetEventLogAppLogDefaults + } + Mock -CommandName Get-WinEvent -MockWith { + return $mocks.GetWinEventAppLogDefaults + } + + It 'Should get the current event log configuration state' { + $eventLogConfiguration = Get-TargetResource -LogName 'Application' + + $eventLogConfiguration | Should -BeOfType Hashtable + $eventLogConfiguration.LogName | Should -Be 'Application' + $eventLogConfiguration.MaximumSizeInBytes | Should -BeOfType Int64 + $eventLogConfiguration.MaximumSizeInBytes | Should -BeGreaterOrEqual 64KB + $eventLogConfiguration.MaximumSizeInBytes | Should -BeLessOrEqual 4GB + $eventLogConfiguration.IsEnabled | Should -Be $true + $eventLogConfiguration.LogMode | Should -BeIn @('AutoBackup', 'Circular', 'Retain') + $eventLogConfiguration.LogRetentionDays | Should -BeIn (0..365) + $eventLogConfiguration.LogFilePath | Should -Not -BeNullOrEmpty + $eventLogConfiguration.SecurityDescriptor | Should -Not -BeNullOrEmpty + $eventLogConfiguration.RestrictGuestAccess | Should -Be $true + } } } - Describe 'DSC_WindowsEventLog\Test-TargetResource' -Tag 'Test' { + Describe "DSC_WindowsEventLog\Test-TargetResource" -Tag 'Test' { + Context 'When testing a request with values that are out of bounds or invalid' { + Mock -CommandName Get-EventLog -MockWith { + return $mocks.GetEventLogAppLogDefaults + } + Mock -CommandName Get-WinEvent -MockWith { + return $mocks.GetWinEventAppLogDefaults + } - Mock -CommandName Get-WindowsEventLog -MockWith { - $properties = @{ - MaximumSizeInBytes = 1028kb - IsEnabled = $true - LogMode = 'Circular' - LogFilePath = '%SystemRoot%\System32\Winevt\Logs\Application.evtx' - SecurityDescriptor = 'TestDescriptor' - LogRetentionDays = '7' - LogName = 'Application' + It 'Should throw when MaximumSizeInBytes is less than 64KB' { + { Test-TargetResource -LogName 'Application' -MaximumSizeInBytes 0 } | Should -Throw } - return (New-Object -TypeName PSObject -Property $properties) - } + It 'Should throw when MaximumSizeInBytes is greater than 4GB' { + { Test-TargetResource -LogName 'Application' -MaximumSizeInBytes 5GB } | Should -Throw + } - Mock -CommandName Get-EventLog -MockWith { - $params = @{ - MinimumRetentionDays = '7' - Log = 'Application' + It 'Should throw when LogMode is not a valid keyword' { + { Test-TargetResource -LogName 'Application' -LogMode Rectangular } | Should -Throw } - return (New-Object -TypeName PSObject -Property $params) - } + It 'Should throw when LogRentionDays is less than 0' { + { Test-TargetResource -LogName 'Application' -LogRetentionDays -1 } | Should -Throw + } - It 'Should not throw when passed an valid Logname' { - { Test-TargetResource -LogName 'Application' -IsEnabled $true -ErrorAction Stop } | Should -Not -Throw + It 'Should throw when LogRentionDays is greater than 365' { + { Test-TargetResource -LogName 'Application' -LogRetentionDays 366 } | Should -Throw + } } - It 'Should throw when passed an invalid LogMode' { - { Test-TargetResource -LogName 'Application' -LogMode 'BadLogmode' -IsEnabled $true -ErrorAction Stop } | Should -Throw - } + Context 'When the event log is in the desired state' { + Mock -CommandName Get-EventLog -MockWith { + return $mocks.GetEventLogAppLogDefaults + } + Mock -CommandName Get-WinEvent -MockWith { + return $mocks.GetWinEventAppLogDefaults + } + Mock -CommandName Get-CimInstance -MockWith { + return $mocks.GetCimInstancePesterTestExist + } + Mock -CommandName Get-ItemProperty -MockWith { + return $mocks.GetWELRegisteredSourceFilePesterTestExist + } + Mock -CommandName Get-WindowsEventLogRestrictGuestAccess -MockWith { + return $true + } - It 'Should not throw when passed an valid LogMode' { - { Test-TargetResource -LogName 'Application' -LogMode 'Circular' -IsEnabled $true -ErrorAction Stop } | Should -Not -Throw + It 'Should return true when all resources are in the desired state' { + $Result = Test-TargetResource @fullParams + $Result | Should -BeTrue + } } - It 'Should return $true if Logmode is in desired state' { - Test-TargetResource -LogName 'Application' -LogMode 'Circular' -IsEnabled $true | Should -BeTrue - } + Context 'When the event log is not in the desired state' { + Mock -CommandName Get-EventLog -MockWith { + return $mocks.GetEventLogAppLogDefaults + } + Mock -CommandName Get-WinEvent -MockWith { + return $mocks.GetWinEventAppLogDefaults + } + Mock -CommandName Get-CimInstance -MockWith { + return $mocks.GetCimInstancePesterTestExist + } + Mock -CommandName Get-ItemProperty -MockWith { + return $mocks.GetWELRegisteredSourceFilePesterTestExist + } + Mock -CommandName Get-WindowsEventLogRestrictGuestAccess -MockWith { + return $true + } - It 'Should return $false if Logmode is not in desired state' { - Test-TargetResource -LogName 'Application' -LogMode 'AutoBackup' -IsEnabled $false | Should -BeFalse - } + It 'Should return false when setting changes are required' ` + -TestCases $testCasesGeneric { - It 'Should throw when passed an invalid MaximumSizeInBytes below 1028kb' { - { Test-TargetResource -LogName 'Application' -LogMode 'Circular' -IsEnabled $true -MaximumSizeInBytes 1027kb -ErrorAction Stop } | Should -Throw - } + param ( + [Parameter()] + $EventLogSetting, - It 'Shoudl throw when passed an invalid MaximumSizeInBytes above 18014398509481983kb' { - { Test-TargetResource -LogName 'Application' -LogMode 'Circular' -IsEnabled $true -MaximumSizeInBytes 18014398509481983kb -ErrorAction Stop } | Should -Throw - } + [Parameter()] + $NewValue + ) - It 'Should return $true if MaximumSizeInBytes is in desired state' { - Test-TargetResource -MaximumSizeInBytes 1028kb -LogName 'Application' -IsEnabled $true | Should -BeTrue - } + $CaseParams = @{ + LogName = 'Application' + $EventLogSetting = $NewValue + } - It 'Should return $false if MaximumSizeInBytes is not in desired state' { - Test-TargetResource -MaximumSizeInBytes 2048kb -LogName 'Application' -IsEnabled $true | Should -BeFalse - } + $Result = Test-TargetResource @CaseParams + $Result | Should -BeFalse + } - It 'Should not throw when passed an valid MaximumSizeInBytes' { - { Test-TargetResource -LogName 'Application' -MaximumSizeInBytes 1028kb -IsEnabled $true -ErrorAction Stop } | Should -Not -Throw - } + It 'Should return false when setting changes are required' ` + -TestCases $testCasesEventSource { - It 'Should throw when passed an invalid LogRetentionDays below 1 day' { - { Test-TargetResource -LogName 'Application' -LogMode 'AutoBackup' -IsEnabled $true -LogRetentionDays 0 -ErrorAction Stop } | Should -Throw - } + param ( + [Parameter()] + $EventLogSetting, - It 'Should throw when passed an invalid LogRetentionDays above 365 days' { - { Test-TargetResource -LogName 'Application' -LogMode 'AutoBackup' -IsEnabled $true -LogRetentionDays 366 -ErrorAction Stop } | Should -Throw - } + [Parameter()] + $NewValue + ) - It 'Should not throw when passed an valid LogRetentionDays' { - { Test-TargetResource -LogName 'Application' -LogMode 'AutoBackup' -LogRetentionDays 30 -IsEnabled $true -ErrorAction Stop } | Should -Not -Throw - } + $CaseParams = @{ + LogName = 'Application' + RegisteredSource = 'PesterTest' + $EventLogSetting = $NewValue + } - It 'Should return $false if LogRetentionDays is not in desired state' { - Test-TargetResource -LogName 'Application' -IsEnabled $true -LogRetentionDays 13 -LogMode 'AutoBackup' | Should -BeFalse + $Result = Test-TargetResource @CaseParams + $Result | Should -BeFalse + } } + } - It 'Should return $true if LogRetentionDays is in desired state' { - Mock -CommandName Get-WindowsEventLog -MockWith { - $properties = @{ - MaximumSizeInBytes = 1028kb - IsEnabled = $true - LogMode = 'AutoBackup' - LogFilePath = '%SystemRoot%\System32\Winevt\Logs\Application.evtx' - SecurityDescriptor = 'TestDescriptor' - LogRetentionDays = '7' - LogName = 'Application' - } - - return (New-Object -TypeName PSObject -Property $properties) + Describe "DSC_WindowsEventLog\Set-TargetResource" -Tag 'Set' { + Context 'When configuration is required' { + Mock -CommandName Get-EventLog -MockWith { + return $mocks.GetEventLogAppLogDefaults } + Mock -CommandName Get-WinEvent -MockWith { + return $mocks.GetWinEventAppLogDefaults + } + Mock -CommandName New-EventLog + Mock -CommandName Remove-EventLog + $NewResFile = 'C:\WINDOWS\System32\NewPesterTest.dll' - Test-TargetResource -LogName 'Application' -IsEnabled $true -LogRetentionDays 7 -LogMode 'AutoBackup' | Should -BeTrue - } + It 'Should set the when it needs to be changed' ` + -TestCases $setCasesGeneric { - It 'Should not throw when passed an invalid LogRetentionDays' { - { Test-TargetResource -LogName 'WrongLog' -LogMode 'AutoBackup' -LogRetentionDays 30 -IsEnabled $true -ErrorAction Stop } | Should -Not -Throw - } + param ( + [Parameter()] + $EventLogSetting, - It 'Should not throw when passed an invalid LogMode with LogRetention' { - { Test-TargetResource -LogName 'Application' -LogMode 'Circular' -LogRetentionDays 30 -IsEnabled $true -ErrorAction Stop } | Should -Not -Throw - } + [Parameter()] + $NewValue + ) - It 'Should not throw when passed an valid LogFilePath' { - { Test-TargetResource -LogName 'Application' -IsEnabled $true -LogFilePath '%SystemRoot%\System32\Winevt\Logs\Application.evtx' -ErrorAction Stop } | Should -Not -Throw - } + $CaseParams = @{ + LogName = 'Application' + $EventLogSetting = $NewValue + } - It 'Should return $true if LogFilePath is in desired state' { - Test-TargetResource -LogName 'Application' -LogFilePath '%SystemRoot%\System32\Winevt\Logs\Application.evtx' -IsEnabled $true | Should -BeTrue - } + Mock -CommandName Save-WindowsEventLog - It 'Should return $false if LogFilePath is not in desired state' { - Test-TargetResource -LogName 'Application' -LogFilePath '%SystemRoot%\System32\Winevt\OtherLogs\Application.evtx' -IsEnabled $true | Should -BeFalse - } + Set-TargetResource @CaseParams + Assert-MockCalled -CommandName Save-WindowsEventLog -Times 1 + } - It 'Should not throw when passed an valid SecurityDescriptor' { - { Test-TargetResource -LogName 'Application' -SecurityDescriptor 'TestDescriptor' -IsEnabled $true -ErrorAction Stop } | Should -Not -Throw - } + It 'Should set the LogRetentionDays when it needs to be changed' ` + -TestCases $SetCasesLogRetention { - It 'Should return $true if SecurityDescriptor is in desired state' { - Test-TargetResource -LogName 'Application' -SecurityDescriptor 'TestDescriptor' -IsEnabled $true | Should -BeTrue - } + Mock -CommandName Limit-EventLog - It 'Should return $false if SecurityDescriptor is not in desired state' { - Test-TargetResource -LogName 'Application' -SecurityDescriptor 'TestTestDescriptor' -IsEnabled $true | Should -BeFalse - } + Set-TargetResource -LogName 'Application' -LogRetentionDays 30 -LogMode AutoBackup + Assert-MockCalled -CommandName Limit-EventLog -Times 1 + } - It 'Should return $true if IsEnabled is in desired state' { - Test-TargetResource -LogName 'Application' -IsEnabled $true | Should -BeTrue - } + It 'Should set the RegisteredSource when it needs to be changed' { + Set-TargetResource -LogName 'Application' -RegisteredSource 'NewPesterTest' + Assert-MockCalled -CommandName New-Eventlog -Times 1 + Assert-MockCalled -CommandName Remove-EventLog -Times 0 + } - It 'Should return $false if IsEnabled is not in desired state' { - Test-TargetResource -LogName 'Application' -IsEnabled $false | Should -BeFalse - } + It 'Should set the CategoryResourceFile when it needs to be changed' { + Mock -CommandName Get-WindowsEventLogRegisteredSource -MockWith { + return 'PesterTest' + } + + Set-TargetResource ` + -LogName 'Application' ` + -RegisteredSource 'PesterTest' ` + -CategoryResourceFile $NewResFile + + Assert-MockCalled -CommandName New-Eventlog -Times 1 + Assert-MockCalled -CommandName Remove-EventLog -Times 1 + } - It 'Should return $false if IsEnabled is not in desired state' { - Mock -CommandName Get-WindowsEventLog -MockWith { - $properties = @{ - MaximumSizeInBytes = 1028kb - IsEnabled = $false - LogName = 'Application' + It 'Should set the MessageResourceFile when it needs to be changed' { + Mock -CommandName Get-WindowsEventLogRegisteredSource -MockWith { + return 'PesterTest' } - return (New-Object -TypeName PSObject -Property $properties) + Set-TargetResource ` + -LogName 'Application' ` + -RegisteredSource 'PesterTest' ` + -MessageResourceFile $NewResFile + + Assert-MockCalled -CommandName New-Eventlog -Times 1 + Assert-MockCalled -CommandName Remove-EventLog -Times 1 } - Test-TargetResource -LogName 'Application' -IsEnabled $true | Should -BeFalse - } + It 'Should set the ParameterResourceFile when it needs to be changed' { + Mock -CommandName Get-WindowsEventLogRegisteredSource -MockWith { + return 'PesterTest' + } + + Set-TargetResource ` + -LogName 'Application' ` + -RegisteredSource 'PesterTest' ` + -ParameterResourceFile $NewResFile - It 'Should return $true if IsEnabled is not in desired state' { - Mock -CommandName Get-WindowsEventLog -MockWith { - $properties = @{ - MaximumSizeInBytes = 1028kb - IsEnabled = $true - LogName = 'Application' + Assert-MockCalled -CommandName New-Eventlog -Times 1 + Assert-MockCalled -CommandName Remove-EventLog -Times 1 + } + + It 'Should set the RestrictGuestAccess and change the user-provided DACL when it needs to be changed' { + Mock -CommandName Get-WindowsEventLogRestrictGuestAccess -MockWith { + return $true } + Mock -CommandName Set-ItemProperty - return (New-Object -TypeName PSObject -Property $properties) + Set-TargetResource ` + -LogName 'Application' ` + -SecurityDescriptor 'O:BAG:SYD:(A;;0x7;;;BA)' ` + -RestrictGuestAccess $false + + Assert-MockCalled -CommandName Save-WindowsEventLog -Times 1 + Assert-MockCalled -CommandName Set-ItemProperty -Times 1 } - Test-TargetResource -LogName 'Application' -IsEnabled $true | Should -BeTrue + It 'Should set the RestrictGuestAccess and change the system-level DACL when it needs to be changed' { + Mock -CommandName Get-WindowsEventLogRestrictGuestAccess -MockWith { + return $true + } + Mock -CommandName Set-ItemProperty + + Set-TargetResource -LogName 'Application' -RestrictGuestAccess $false + Assert-MockCalled -CommandName Save-WindowsEventLog -Times 1 + } } } - Describe 'DSC_WindowsEventLog\Set-TargetResource' -Tag 'Set' { - Mock -CommandName Get-WindowsEventLog -MockWith { - $properties = @{ - MaximumSizeInBytes = 5000kb - IsEnabled = $true - LogMode = 'AutoBackup' - LogFilePath = 'c:\logs\test.evtx' - SecurityDescriptor = 'TestDescriptor' - LogRetentionDays = '7' - LogName = 'TestLog' + Describe "DSC_WindowsEventLog\Get-WindowsEventLogRestrictGuestAccess" -Tag 'Helper' { + Context 'When testing the helper function' { + + It 'Should not throw under any circumstances' { + Mock -CommandName Get-ItemProperty + + { Get-WindowsEventLogRestrictGuestAccess -LogName 'UndefinedLog' } | Should -Not -Throw } - return (New-Object -TypeName PSObject -Property $properties) - } + It 'Should return true when RestrictGuestAccess is 1' { + Mock -CommandName Get-ItemProperty -MockWith { + return [PSCustomObject]@{ + RestrictGuestAccess = 1 + } + } - Mock -CommandName Get-EventLog -MockWith { - $params = @{ - MinimumRetentionDays = '7' - Log = 'TestLog' + ( Get-WindowsEventLogRestrictGuestAccess -LogName 'Application' ) | Should -BeTrue } - return (New-Object -TypeName PSObject -Property $params) - } + It 'Should return false when RestrictGuestAccess is 0' { + Mock -CommandName Get-ItemProperty -MockWith { + return [PSCustomObject]@{ + RestrictGuestAccess = 0 + } + } - It 'Should set MaximumSizeInBytes to 1028kb' { - Mock -CommandName Save-LogFile - Set-TargetResource -MaximumSizeInBytes 1028kb -IsEnabled $true -LogName 'TestLog' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 1 -Scope It + ( Get-WindowsEventLogRestrictGuestAccess -LogName 'Application' ) | Should -BeFalse + } } + } - It 'MaximumSizeInBytes is in desired state' { - Mock -CommandName Save-LogFile - Set-TargetResource -MaximumSizeInBytes 5000kb -IsEnabled $true -LogName 'TestLog' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 0 -Scope It - } + Describe "DSC_WindowsEventLog\Get-WindowsEventLogRetentionDays" -Tag 'Helper' { + Context 'When testing the helper function' { - It 'Should set SecurityDescriptor to OtherTestDescriptor' { - Mock -CommandName Save-LogFile - Set-TargetResource -IsEnabled $true -LogName 'TestLog' -SecurityDescriptor 'OtherTestDescriptor' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 1 -Scope It - } + It 'Should throw when an event log does not exist' { + $errorRecord = Get-InvalidArgumentRecord ` + -Message ` + ($script:localizedData.GetWindowsEventLogRetentionDaysFailure -f 'UndefinedLog') ` + -ArgumentName 'LogName' - It 'SecurityDescriptor is in desired state' { - Mock -CommandName Save-LogFile - Set-TargetResource -IsEnabled $true -LogName 'TestLog' -SecurityDescriptor 'TestDescriptor' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 0 -Scope It + { Get-WindowsEventLogRetentionDays -LogName 'UndefinedLog' } | Should -Throw $errorRecord + } } + } - It 'Should set LogFilePath to default path' { - Mock -CommandName Save-LogFile - Set-TargetResource -IsEnabled $true -LogName 'TestLog' -LogFilePath '%SystemRoot%\System32\Winevt\Logs\Application.evtx' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 1 -Scope It - } + Describe "DSC_WindowsEventLog\Register-WindowsEventLogSource" -Tag 'Helper' { + Context 'When testing a request with values that are out of bounds or invalid' { - It 'LogFilePath is in desired state' { - Mock -CommandName Save-LogFile - Set-TargetResource -IsEnabled $true -LogName 'TestLog' -LogFilePath 'c:\logs\test.evtx' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 0 -Scope It - } + It 'Should throw when CategoryResourceFile is an invalid path' { + $errorRecord = Get-InvalidArgumentRecord ` + -Message ` + ($script:localizedData.RegisterWindowsEventLogSourceInvalidPath -f 'PesterTest', 'foo>bar') ` + -ArgumentName 'CategoryResourceFile' - It 'Should set LogRetentionDays to 14 days' { - Mock -CommandName Set-LogRetentionDays - Set-TargetResource -LogRetentionDays '14' -IsEnabled $true -LogName 'TestLog' -LogMode 'Autobackup' - Assert-MockCalled -CommandName Set-LogRetentionDays -Exactly -Times 1 -Scope It - } + { Register-WindowsEventLogSource ` + -LogName 'Application' ` + -SourceName 'PesterTest' ` + -CategoryResourceFile 'foo>bar' + } | Should -Throw $errorRecord + } - It 'Should set LogRetentionDays to 32 days, wrong Logmode' { - Mock -CommandName Set-LogRetentionDays - Set-TargetResource -LogRetentionDays '32' -IsEnabled $true -LogName 'TestLog' -LogMode 'Circular' - Assert-MockCalled -CommandName Set-LogRetentionDays -Exactly -Times 0 -Scope It - } + It 'Should throw when MessageResourceFile is an invalid path' { + $errorRecord = Get-InvalidArgumentRecord ` + -Message ` + ($script:localizedData.RegisterWindowsEventLogSourceInvalidPath -f 'PesterTest', 'foo>bar') ` + -ArgumentName 'MessageResourceFile' + + { Register-WindowsEventLogSource ` + -LogName 'Application' ` + -SourceName 'PesterTest' ` + -MessageResourceFile 'foo>bar' + } | Should -Throw $errorRecord + } - It 'Should set LogRetentionDays is in desired state' { - Mock -CommandName Set-LogRetentionDays - Set-TargetResource -LogRetentionDays '7' -IsEnabled $true -LogName 'TestLog' -LogMode 'Autobackup' - Assert-MockCalled -CommandName Set-LogRetentionDays -Exactly -Times 0 -Scope It - } + It 'Should throw when ParameterResourceFile is an invalid path' { + $errorRecord = Get-InvalidArgumentRecord ` + -Message ` + ($script:localizedData.RegisterWindowsEventLogSourceInvalidPath -f 'PesterTest', 'foo>bar') ` + -ArgumentName 'ParameterResourceFile' + + { Register-WindowsEventLogSource ` + -LogName 'Application' ` + -SourceName 'PesterTest' ` + -ParameterResourceFile 'foo>bar' + } | Should -Throw $errorRecord + } - It 'Should set IsEnabled to false' { - Mock -CommandName Save-LogFile - Set-TargetResource -IsEnabled $false -LogName 'TestLog' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 1 -Scope It - } + It 'Should throw when the New-EventLog cmdlet encounters an error' { + Mock -CommandName New-EventLog -MockWith { throw 'New-EventLog Error' } - It 'IsEnabled is in desired state' { - Mock -CommandName Save-LogFile - Set-TargetResource -IsEnabled $true -LogName 'TestLog' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 0 -Scope It - } + { Register-WindowsEventLogSource ` + -LogName 'Application' ` + -SourceName 'PesterTest' + } | Should -Throw 'New-EventLog Error' + } - It 'IsEnabled is not in desired state' { - Mock -CommandName Save-LogFile - Set-TargetResource -IsEnabled $false -LogName 'TestLog' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 1 -Scope It - } + It 'Should throw when the Remove-EventLog cmdlet encounters an error' { + Mock -CommandName Remove-EventLog -MockWith { throw } + $errorRecord = Get-InvalidOperationRecord ` + -Message ($script:localizedData.RegisterWindowsEventLogSourceFailure -f 'Application', '') - It 'Should throw if IsEnabled is not in desired state' { - Mock -CommandName Save-LogFile - Mock -CommandName Get-WindowsEventLog -MockWith { throw } - { Set-TargetResource -LogName 'SomeLog' -IsEnabled $false } | Should -Throw + { Register-WindowsEventLogSource ` + -LogName 'Application' ` + -SourceName 'PesterTest' + } | Should -Throw $errorRecord + } } + } - It 'IsEnabled is not in desired state' { - Mock -CommandName Get-WindowsEventLog -MockWith { - $properties = @{ - MaximumSizeInBytes = 5000kb - IsEnabled = $false - LogMode = 'AutoBackup' - LogFilePath = 'c:\logs\test.evtx' - SecurityDescriptor = 'TestDescriptor' - LogRetentionDays = '7' - LogName = 'TestLog' - } + Describe "DSC_WindowsEventLog\Set-WindowsEventLogRestrictGuestAccess" -Tag 'Helper' { + Context 'When testing a request with values that are out of bounds or invalid' { - return (New-Object -TypeName PSObject -Property $properties) - } + It 'Should throw when the Set-ItemProperty cmdlet encounters an error' { + Mock -CommandName Set-ItemProperty -MockWith { throw 'Set-ItemProperty Error' } - Set-TargetResource -IsEnabled $true -LogName 'TestLog' - Assert-MockCalled -CommandName Save-LogFile -Exactly -Times 1 -Scope It + { Set-WindowsEventLogRestrictGuestAccess ` + -LogName 'Application' ` + -RestrictGuestAccess $true ` + -Sddl 'O:BAG:SYD:(A;;0x2;;;S-1-15-2-1)' + } | Should -Throw 'Set-ItemProperty Error' + } } + } - Describe 'DSC_WindowsEventLog\Save-LogFile' -Tag 'Helper' { - Mock -CommandName Limit-Eventlog -MockWith { throw } + Describe "DSC_WindowsEventLog\Set-WindowsEventLogRetentionDays" -Tag 'Helper' { + Context 'When testing the helper function' { - It 'Should throw if we are unable to get a log' { - { Limit-Eventlog -LogName 'Application' -OverflowAction 'OverwriteOlder' -RetentionDays 30 } | Should -Throw + It 'Should throw when an event log does not exist' { + $errorRecord = Get-InvalidArgumentRecord ` + -Message ($script:localizedData.GetWindowsEventLogRetentionDaysFailure -f 'UndefinedLog') ` + -ArgumentName 'LogName' + + { Get-WindowsEventLogRetentionDays -LogName 'UndefinedLog' } | Should -Throw $errorRecord } } - Describe 'DSC_WindowsEventLog\Set-LogRetentionDays' -Tag 'Helper' { - Mock -CommandName Limit-Eventlog -MockWith { throw } + Context 'When testing a request with values that are out of bounds or invalid' { + + It 'Should throw when setting retention days in the wrong log mode' { + $errorRecord = Get-InvalidArgumentRecord ` + -Message ($script:localizedData.SetWindowsEventLogRetentionDaysWrongMode -f 'Application') ` + -ArgumentName 'LogMode' + + { Set-WindowsEventLogRetentionDays ` + -LogName 'Application' ` + -LogRetentionDays 30 ` + -LogMode Circular + } | Should -Throw $errorRecord + } + + It 'Should throw when the Get-EventLog cmdlet encounters an error' { + Mock -CommandName Get-EventLog -MockWith { throw 'Get-EventLog Error' } + + { Set-WindowsEventLogRetentionDays ` + -LogName 'Application' ` + -LogRetentionDays 30 ` + -LogMode AutoBackup + } | Should -Throw 'Get-EventLog Error' + } + + It 'Should throw when the Limit-EventLog cmdlet encounters an error' { + Mock -CommandName Limit-EventLog -MockWith { throw } + $errorRecord = Get-InvalidOperationRecord ` + -Message ($script:localizedData.GetWindowsEventLogRetentionDaysFailure -f 'Application') - It 'Should throw if we are unable to get a log' { - { Limit-Eventlog -LogName 'Application' -OverflowAction 'OverwriteOlder' -RetentionDays 30 } | Should -Throw + { Set-WindowsEventLogRetentionDays ` + -LogName 'Application' ` + -LogRetentionDays 30 ` + -LogMode AutoBackup + } | Should -Throw $errorRecord } } }