mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
249 lines
12 KiB
PowerShell
249 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 -Be $False # 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 -Be $True # 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 = 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 be $True # verifies that Transcription policy works
|
|
$Log.Contains("Command start time:") | should be $True # 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
|
|
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 be $True
|
|
Remove-Item -Path $LogPath -Force
|
|
}
|
|
|
|
$KeyPath = Join-Path $KeyRoot 'ConsoleSessionConfiguration'
|
|
if (-not (Test-Path $KeyPath)) {$null = New-Item $KeyPath}
|
|
|
|
TestFeature -KeyPath $KeyPath
|
|
}
|
|
}
|
|
}
|