248 lines
12 KiB
PowerShell
248 lines
12 KiB
PowerShell
# Copyright (c) Microsoft Corporation.
|
|
# Licensed under the MIT License.
|
|
|
|
Describe 'Group policy settings tests' -Tag CI,RequireAdminOnWindows {
|
|
BeforeAll {
|
|
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
|
if ( ! $IsWindows ) {
|
|
$PSDefaultParameterValues["it:skip"] = $true
|
|
}
|
|
else {
|
|
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('BypassGroupPolicyCaching', $true)
|
|
}
|
|
}
|
|
AfterAll {
|
|
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
|
if ( $IsWindows ) {
|
|
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('BypassGroupPolicyCaching', $false)
|
|
}
|
|
}
|
|
|
|
Context 'Group policy settings tests' {
|
|
|
|
BeforeEach {
|
|
$KeyRoot = 'HKCU:\Software\Policies\Microsoft\PowerShellCore'
|
|
if (-not (Test-Path $KeyRoot)) {$null = New-Item $KeyRoot}
|
|
|
|
$WinPSKeyRoot = 'HKCU:\Software\Policies\Microsoft\Windows\PowerShell'
|
|
if (-not (Test-Path $WinPSKeyRoot)) {$null = New-Item $WinPSKeyRoot}
|
|
}
|
|
|
|
AfterEach {
|
|
Remove-Item $KeyRoot -Recurse -Force > $null
|
|
Remove-Item $WinPSKeyRoot -Recurse -Force > $null
|
|
}
|
|
|
|
It 'Execution policy test' {
|
|
function TestFeature
|
|
{
|
|
param([string]$KeyPath)
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name EnableScripts -Value 1 -Force
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name ExecutionPolicy -Value 'Unrestricted' -Force
|
|
(Get-ExecutionPolicy) | Should -Be 'Unrestricted'
|
|
Set-ItemProperty -Path $KeyPath -Name ExecutionPolicy -Value 'AllSigned' -Force
|
|
(Get-ExecutionPolicy) | Should -Be 'AllSigned'
|
|
Set-ItemProperty -Path $KeyPath -Name ExecutionPolicy -Value 'RemoteSigned' -Force
|
|
(Get-ExecutionPolicy) | Should -Be 'RemoteSigned'
|
|
|
|
Remove-ItemProperty -Path $KeyPath -Name ExecutionPolicy -Force
|
|
}
|
|
|
|
TestFeature -KeyPath $KeyRoot
|
|
|
|
Set-ItemProperty -Path $KeyRoot -Name UseWindowsPowerShellPolicySetting -Value 1 -Force
|
|
TestFeature -KeyPath $WinPSKeyRoot
|
|
}
|
|
|
|
It 'Module logging policy test' {
|
|
function TestFeature
|
|
{
|
|
param([string]$KeyPath)
|
|
|
|
$ModuleToLog = 'Microsoft.PowerShell.Utility'
|
|
$ModuleNamesKeyPath = Join-Path $KeyPath 'ModuleNames'
|
|
if (-not (Test-Path $ModuleNamesKeyPath)) {$null = New-Item $ModuleNamesKeyPath}
|
|
|
|
Remove-Module $ModuleToLog -ErrorAction SilentlyContinue
|
|
Import-Module $ModuleToLog
|
|
(Get-Module $ModuleToLog).LogPipelineExecutionDetails | Should -BeFalse # without GP logging for the module should be OFF
|
|
|
|
# enable GP
|
|
[string]$RareCommand = Get-Random
|
|
Set-ItemProperty -Path $KeyPath -Name EnableModuleLogging -Value 1 -Force
|
|
Set-ItemProperty -Path $ModuleNamesKeyPath -Name $ModuleToLog -Value $ModuleToLog -Force
|
|
|
|
Remove-Module $ModuleToLog -ErrorAction SilentlyContinue
|
|
Import-Module $ModuleToLog # this will read and start using GP setting
|
|
(Get-Module $ModuleToLog).LogPipelineExecutionDetails | Should -BeTrue # with GP logging for the module should be ON
|
|
|
|
Get-Alias $RareCommand -ErrorAction SilentlyContinue | Out-Null
|
|
|
|
(Get-Module $ModuleToLog).LogPipelineExecutionDetails = $false # turn off logging
|
|
Remove-ItemProperty -Path $KeyPath -Name EnableModuleLogging -Force # turn off GP setting
|
|
Remove-Item $ModuleNamesKeyPath -Recurse -Force
|
|
# usually event becomes visible in the log after ~500 ms
|
|
# set timeout for 5 seconds
|
|
Wait-UntilTrue -sb { Get-WinEvent -FilterHashtable @{ ProviderName="PowerShellCore"; Id = 4103 } -MaxEvents 5 | ? {$_.Message.Contains($RareCommand)} } -TimeoutInMilliseconds (5*1000) -IntervalInMilliseconds 100 | Should -BeTrue
|
|
}
|
|
|
|
$KeyPath = Join-Path $KeyRoot 'ModuleLogging'
|
|
if (-not (Test-Path $KeyPath)) {$null = New-Item $KeyPath}
|
|
|
|
TestFeature -KeyPath $KeyPath
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name UseWindowsPowerShellPolicySetting -Value 1 -Force
|
|
$WinKeyPath = Join-Path $WinPSKeyRoot 'ModuleLogging'
|
|
if (-not (Test-Path $WinKeyPath)) {$null = New-Item $WinKeyPath}
|
|
|
|
TestFeature -KeyPath $WinKeyPath
|
|
}
|
|
|
|
It 'ScriptBlock logging policy test' {
|
|
function TestFeature
|
|
{
|
|
param([string]$KeyPath)
|
|
|
|
[string]$RareCommand = Get-Random
|
|
Set-ItemProperty -Path $KeyPath -Name EnableScriptBlockLogging -Value 1 -Force
|
|
Set-ItemProperty -Path $KeyPath -Name EnableScriptBlockInvocationLogging -Value 1 -Force
|
|
Invoke-Expression "$RareCommand | Out-Null"
|
|
Remove-ItemProperty -Path $KeyPath -Name EnableScriptBlockLogging -Force
|
|
Remove-ItemProperty -Path $KeyPath -Name EnableScriptBlockInvocationLogging -Force
|
|
# usually event becomes visible in the log after ~500 ms
|
|
# set timeout for 5 seconds
|
|
Wait-UntilTrue -sb { $script:CreatingScriptblockEvent = Get-WinEvent -FilterHashtable @{ ProviderName="PowerShellCore"; Id = 4104 } -MaxEvents 5 | ? {$_.Message.Contains($RareCommand)}; $script:CreatingScriptblockEvent } -TimeoutInMilliseconds (5*1000) -IntervalInMilliseconds 100 | Should -BeTrue
|
|
|
|
$sbStringStart = $script:CreatingScriptblockEvent.Message.IndexOf('ScriptBlock ID:')
|
|
$sbStringEnd = $script:CreatingScriptblockEvent.Message.IndexOf(0x0D, $sbStringStart)
|
|
$sbString = $script:CreatingScriptblockEvent.Message.Substring($sbStringStart, $sbStringEnd - $sbStringStart)
|
|
|
|
$StartedScriptBlockInvocationEvent = Get-WinEvent -FilterHashtable @{ ProviderName="PowerShellCore"; Id = 4105 } -MaxEvents 5 | ? {$_.Message.Contains($sbString)}
|
|
$StartedScriptBlockInvocationEvent | Should -Not -BeNullOrEmpty
|
|
$CompletedScriptBlockInvocationEvent = Get-WinEvent -FilterHashtable @{ ProviderName="PowerShellCore"; Id = 4106 } -MaxEvents 5 | ? {$_.Message.Contains($sbString)}
|
|
$CompletedScriptBlockInvocationEvent | Should -Not -BeNullOrEmpty
|
|
}
|
|
|
|
$KeyPath = Join-Path $KeyRoot 'ScriptBlockLogging'
|
|
if (-not (Test-Path $KeyPath)) {$null = New-Item $KeyPath}
|
|
|
|
TestFeature -KeyPath $KeyPath
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name UseWindowsPowerShellPolicySetting -Value 1 -Force
|
|
$WinKeyPath = Join-Path $WinPSKeyRoot 'ScriptBlockLogging'
|
|
if (-not (Test-Path $WinKeyPath)) {$null = New-Item $WinKeyPath}
|
|
|
|
TestFeature -KeyPath $WinKeyPath
|
|
}
|
|
|
|
It 'Transcription policy test' {
|
|
|
|
function TestFeature
|
|
{
|
|
param([string]$KeyPath)
|
|
|
|
$OutputDirectory = Join-Path $([System.IO.Path]::GetTempPath()) $(Get-Random)
|
|
$null = New-Item -Type Directory -Path $OutputDirectory -Force
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name EnableTranscripting -Value 1 -Force
|
|
Set-ItemProperty -Path $KeyPath -Name OutputDirectory -Value $OutputDirectory -Force
|
|
Set-ItemProperty -Path $KeyPath -Name EnableInvocationHeader -Value 1 -Force
|
|
|
|
$number = Get-Random
|
|
$null = & "$PSHOME/pwsh" -NoProfile -NonInteractive -c "$number"
|
|
|
|
Remove-ItemProperty -Path $KeyPath -Name OutputDirectory -Force
|
|
Remove-ItemProperty -Path $KeyPath -Name EnableInvocationHeader -Force
|
|
|
|
$LogPath = (gci -Path $OutputDirectory -Filter "PowerShell_transcript*.txt" -Recurse).FullName
|
|
$Log = Get-Content $LogPath -Raw
|
|
|
|
$Log.Contains("$number") | Should -BeTrue # verifies that Transcription policy works
|
|
$Log.Contains("Command start time:") | Should -BeTrue # verifies that EnableInvocationHeader works
|
|
|
|
Remove-Item -Path $OutputDirectory -Recurse -Force
|
|
}
|
|
|
|
$KeyPath = Join-Path $KeyRoot 'Transcription'
|
|
if (-not (Test-Path $KeyPath)) {$null = New-Item $KeyPath}
|
|
|
|
TestFeature -KeyPath $KeyPath
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name UseWindowsPowerShellPolicySetting -Value 1 -Force
|
|
$WinKeyPath = Join-Path $WinPSKeyRoot 'Transcription'
|
|
if (-not (Test-Path $WinKeyPath)) {$null = New-Item $WinKeyPath}
|
|
|
|
TestFeature -KeyPath $WinKeyPath
|
|
}
|
|
|
|
It 'Default SourcePath on Update-Help policy test' {
|
|
function TestFeature
|
|
{
|
|
param([string]$KeyPath)
|
|
|
|
$HelpPath = Join-Path 'TestDrive:\' $(Get-Random)
|
|
$null = New-Item -Type Directory -Path $HelpPath -ErrorAction SilentlyContinue
|
|
$ModuleName = 'Microsoft.PowerShell.Utility'
|
|
Save-Help -Module $ModuleName -DestinationPath $HelpPath -Force
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name EnableUpdateHelpDefaultSourcePath -Value 1 -Force
|
|
Set-ItemProperty -Path $KeyPath -Name DefaultSourcePath -Value $HelpPath -Force
|
|
|
|
# this should throw error cause we didn't save the help for this module locally;
|
|
# this ensures that Update-Help is not going to Internet to download help
|
|
{ Update-Help -Module Microsoft.PowerShell.Management -Force -ErrorAction Stop } | Should -Throw -ErrorId "UnableToRetrieveHelpInfoXml,Microsoft.PowerShell.Commands.UpdateHelpCommand"
|
|
|
|
# this should use saved help in location specified in the policy and should NOT throw error
|
|
Update-Help -Module Microsoft.PowerShell.Utility -Force
|
|
}
|
|
|
|
$HKLM_KeyRoot = 'HKLM:\Software\Policies\Microsoft\PowerShellCore'
|
|
if (-not (Test-Path $HKLM_KeyRoot)) {$null = New-Item $HKLM_KeyRoot}
|
|
$KeyPath = Join-Path $HKLM_KeyRoot 'UpdatableHelp'
|
|
if (-not (Test-Path $KeyPath)) {$null = New-Item $KeyPath}
|
|
|
|
TestFeature -KeyPath $KeyPath
|
|
|
|
Set-ItemProperty -Path $KeyPath -Name UseWindowsPowerShellPolicySetting -Value 1 -Force
|
|
$HKLM_WinPSKeyRoot = 'HKLM:\Software\Policies\Microsoft\Windows\PowerShell'
|
|
if (-not (Test-Path $HKLM_WinPSKeyRoot)) {$null = New-Item $HKLM_WinPSKeyRoot}
|
|
$WinKeyPath = Join-Path $HKLM_WinPSKeyRoot 'UpdatableHelp'
|
|
if (-not (Test-Path $WinKeyPath)) {$null = New-Item $WinKeyPath}
|
|
|
|
TestFeature -KeyPath $WinKeyPath
|
|
|
|
Remove-Item $HKLM_KeyRoot -Recurse -Force
|
|
Remove-Item $HKLM_WinPSKeyRoot -Recurse -Force
|
|
}
|
|
|
|
It 'Session configuration policy test' {
|
|
function TestFeature
|
|
{
|
|
param([string]$KeyPath)
|
|
|
|
# set policy to use unique non-existing configuration session name
|
|
$SessionName = "TestSessionConfiguration-$(Get-Random)"
|
|
Set-ItemProperty -Path $KeyPath -Name EnableConsoleSessionConfiguration -Value 1 -Force
|
|
Set-ItemProperty -Path $KeyPath -Name ConsoleSessionConfigurationName -Value $SessionName -Force
|
|
|
|
$LogPath = (New-TemporaryFile).FullName
|
|
& "$PSHOME/pwsh" -NoProfile -NonInteractive -c "1" *> $LogPath # this implicitly uses SessionConfiguration from the policy
|
|
|
|
# Log should have an error that has our configuration session name; e.g.:
|
|
# 'The shell cannot be started. A failure occurred during initialization:
|
|
# Cannot create or open the configuration session 116337267.'
|
|
|
|
$Log = Get-Content $LogPath -Raw
|
|
$Log.Contains("$SessionName") | Should -BeTrue
|
|
Remove-Item -Path $LogPath -Force
|
|
}
|
|
|
|
$KeyPath = Join-Path $KeyRoot 'ConsoleSessionConfiguration'
|
|
if (-not (Test-Path $KeyPath)) {$null = New-Item $KeyPath}
|
|
|
|
TestFeature -KeyPath $KeyPath
|
|
}
|
|
}
|
|
}
|