2018-11-14 01:16:29 +01:00
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
##
## ----------
## Test Note:
## ----------
## Since these tests change session and system state (constrained language and system lockdown)
## they will all use try/finally blocks instead of Pester AfterEach/AfterAll to ensure session
## and system state is restored.
## Pester AfterEach, AfterAll is not reliable when the session is constrained language or locked down.
##
Import-Module HelpersSecurity
$defaultParamValues = $PSDefaultParameterValues . Clone ( )
$PSDefaultParameterValues [ " it:Skip " ] = ! $IsWindows
try
{
Describe " Export-ModuleMember should not work across language boundaries " -Tags 'Feature' , 'RequireAdminOnWindows' {
BeforeAll {
$script = @ '
function IEXInjectableFunction
{
param ( [ string ] $path )
Invoke-Expression -Command " dir $path "
}
function PrivateAddTypeAndRun
{
param ( [ string ] $source )
$type = Add-Type -TypeDefinition $source -passthru
$type :: new ( )
}
Export-ModuleMember -Function IEXInjectableFunction
' @
$modulePathName = " modulePath_ $( Get-Random -Max 9999 ) "
$modulePath = Join-Path $testdrive $modulePathName
mkdir $modulePath
$trustedModuleFile = Join-Path $modulePath " T1TestModule_System32.psm1 "
$script | Out-File -FilePath $trustedModuleFile
}
AfterAll {
Remove-Module -Name T1TestModule_System32 -Force -ErrorAction Ignore
}
It " Verifies that IEX running in ConstrainedLanguage cannot export functions from trusted module " {
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
Import-Module -Name $trustedModuleFile -Force
# Use the vulnerable IEXInjectableFunction function to export all functions from module
# Note that Invoke-Expression will run in constrained language mode because it is known to be vulnerable
T1TestModule_System32 \ IEXInjectableFunction -path 'c:\windows\system32\CodeIntegrity; Export-ModuleMember -Function *'
throw " No Error! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -EnableFullLanguageMode -RevertLockdownMode
}
# A security error should be thrown
$expectedError . FullyQualifiedErrorId | Should -BeExactly " Modules_CannotExportMembersAccrossLanguageBoundaries,Microsoft.PowerShell.Commands.ExportModuleMemberCommand "
# PrivateAddTypeAndRun private function should not be exposed
$result = Get-Command -Name T1TestModule_System32 \ PrivateAddTypeAndRun 2 > $null
$result | Should -BeNullOrEmpty
}
}
Describe " Dot-source operator is not allowed in modules on locked down systems that export functions with wildcards " -Tags 'Feature' , 'RequireAdminOnWindows' {
BeforeAll {
$TestModulePath = Join-Path $TestDrive " Modules_ $( Get-Random -Maximum 99999 ) "
New-Item -Path $TestModulePath -ItemType Directory -Force -ErrorAction SilentlyContinue
# Module that dot sources ps1 file while and exports functions with wildcard.
$scriptModuleNameA = " ModuleDotSourceWildcard_System32 "
$moduleFilePathA = Join-Path $TestModulePath ( $scriptModuleNameA + " .psm1 " )
$dotSourceNameA = " DotSourceFileNoWildCard_System32 "
$dotSourceFilePathA = Join-Path $TestModulePath ( $dotSourceNameA + " .ps1 " )
@ '
function PublicDSFnA { " PublicDSFnA " ; PrivateDSFnA }
function PrivateDSFnA { " PrivateDSFnA " }
' @ | Out-File -FilePath $dotSourceFilePathA
@ '
. { 0 }
function PublicFnA { { " PublicFnA " ; PublicDSFnA } }
function PrivateFnA { { " PrivateFnA " ; PrivateDSFnA } }
Export-ModuleMember -Function " * "
' @ -f $dotSourceFilePathA | Out-File -FilePath $moduleFilePathA
# Module that dot sources ps1 file that exports module functions. Parent module exports nothing.
$scriptModuleNameB = " ModuleDotSourceNoExport_System32 "
$moduleFilePathB = Join-Path $TestModulePath ( $scriptModuleNameB + " .psm1 " )
$dotSourceNameB = " DotSourceFileWildCard_System32 "
$dotSourceFilePathB = Join-Path $TestModulePath ( $dotSourceNameB + " .ps1 " )
@ '
function PublicDSFnB { " PublicDSFnB " ; PrivateDSFnB }
function PrivateDSFnB { " PrivateDSFnB " }
Export-ModuleMember -Function " * "
' @ | Out-File -FilePath $dotSourceFilePathB
@ '
. { 0 }
function PublicFnB { { " PublicFnB " ; PrivateFnB } }
function PrivateFnB { { " PrivateFnB " } }
' @ -f $dotSourceFilePathB | Out-File -FilePath $moduleFilePathB
# Module that dot sources ps1 file and exports functions with wildcard, but has overriding manifest.
$scriptModuleNameC = " ModuleDotSourceWildCardM_System32 "
$moduleFilePathC = Join-Path $TestModulePath ( $scriptModuleNameC + " .psm1 " )
$dotSourceNameC = " DotSourceFileNoWildCardM_System32 "
$dotSourceFilePathC = Join-Path $TestModulePath ( $dotSourceNameC + " .ps1 " )
$manifestFilePathC = Join-Path $TestModulePath ( $scriptModuleNameC + " .psd1 " )
@ '
function PublicDSFnC { " PublicDSFnC " ; PrivateDSFnC }
function PrivateDSFnC { " PrivateDSFnC " }
' @ | Out-File -FilePath $dotSourceFilePathC
@ '
. { 0 }
function PublicFnC { { " PublicFnC " ; PublicDSFnC } }
function PrivateFnC { { " PrivateFnC " ; PrivateDSFnC } }
Export-ModuleMember -Function " * "
' @ -f $dotSourceFilePathC | Out-File -FilePath $moduleFilePathC
'@{{ ModuleVersion = "1.0"; RootModule = "{0}"; FunctionsToExport = @("PublicFnC","PublicDSFnC") }}' -f $moduleFilePathC | Out-File -FilePath $manifestFilePathC
# Module that dot sources ps1 file while and exports functions with no wildcards.
$scriptModuleNameD = " ModuleDotSourceNoWildcard_System32 "
$moduleFilePathD = Join-Path $TestModulePath ( $scriptModuleNameD + " .psm1 " )
$dotSourceNameD = " DotSourceFileNoWildCardD_System32 "
$dotSourceFilePathD = Join-Path $TestModulePath ( $dotSourceNameD + " .ps1 " )
@ '
function PublicDSFnD { " PublicDSFnD " ; PrivateDSFnD }
function PrivateDSFnD { " PrivateDSFnD " }
' @ | Out-File -FilePath $dotSourceFilePathD
@ '
. { 0 }
function PublicFnD { { " PublicFnD " ; PublicDSFnD } }
function PrivateFnD { { " PrivateFnD " ; PrivateDSFnD } }
Export-ModuleMember -Function " PublicFnD " , " PublicDSFnD "
' @ -f $dotSourceFilePathD | Out-File -FilePath $moduleFilePathD
# Module that dot sources ps1 file but does not use Export-ModuleMember
$scriptModuleNameE = " ModuleDotSourceNoExportE_System32 "
$moduleFilePathE = Join-Path $TestModulePath ( $scriptModuleNameE + " .psm1 " )
$dotSourceNameE = " DotSourceFileNoExportE_System32 "
$dotSourceFilePathE = Join-Path $TestModulePath ( $dotSourceNameE + " .ps1 " )
@ '
function PublicDSFnE { " PublicDSFnE " ; PrivateDSFnE }
function PrivateDSFnE { " PrivateDSFnE " }
' @ | Out-File -FilePath $dotSourceFilePathE
@ '
. { 0 }
function PublicFnE { { " PublicFnE " ; PublicDSFnE } }
function PrivateFnE { { " PrivateFnE " ; PrivateDSFnE } }
' @ -f $dotSourceFilePathE | Out-File -FilePath $moduleFilePathE
# Module with dot source ps1 file and nested modules that do use Export-ModuleMember
$scriptModuleNameF = " ModuleDotSourceNestedExport_System32 "
$moduleFilePathF = Join-Path $TestModulePath ( $scriptModuleNameF + " .psm1 " )
$manifestFilePathF = Join-Path $TestModulePath ( $scriptModuleNameF + " .psd1 " )
$nestedSourceNameF = " NestedSourceWithExport_System32 "
$nestedSourceFilePathF = Join-Path $TestModulePath ( $nestedSourceNameF + " .psm1 " )
@ '
. { 0 }
function NestedPubFnF { { " NestedPubFnF " ; PublicDSFnE } }
Export-ModuleMember -Function *
' @ -f $dotSourceFilePathE | Out-File -FilePath $nestedSourceFilePathF
@ '
function PublicFnF { " PublicFnF " ; NestedPubFnF }
' @ | Out-File -FilePath $moduleFilePathF
'@{{ ModuleVersion = "1.0"; RootModule = "{0}"; NestedModules = "{1}"; FunctionsToExport = "PublicFnF","NestedPubFnF" }}' -f $moduleFilePathF , $nestedSourceFilePathF | Out-File -FilePath $manifestFilePathF
# Module with dot source ps1 file and import module and Export-ModuleMember with wildcard
$scriptModuleNameG = " ModuleDotSourceImportExport_System32 "
$moduleFilePathG = Join-Path $TestModulePath ( $scriptModuleNameG + " .psm1 " )
$importModNameG = " ImportModWitExport_System32 "
$importModFilePathG = Join-Path $TestModulePath ( $importModNameG + " .psm1 " )
@ '
. { 0 }
function ImportPubFnG { { " ImportPubFnG " ; PublicDSFnE } }
Export-ModuleMember -Function *
' @ -f $dotSourceFilePathE | Out-File $importModFilePathG
@ '
Import-Module { 0 }
function PublicFnG { { " PublicFnG " ; ImportPubFnG } }
Export-ModuleMember -Function PublicFnG
' @ -f $importModFilePathG | Out-File -FilePath $moduleFilePathG
# Module with dot source and with multiple Export-ModuleMember use.
$scriptModuleNameH = " ModuleDotSourceImportExportH_System32 "
$moduleFilePathH = Join-Path $TestModulePath ( $scriptModuleNameH + " .psm1 " )
@ '
. { 0 }
function PublicFnH { { " PublicFnH " ; PrivateFnH } }
function PrivateFnH { { " PrivateFnH " } }
Export-ModuleMember -Function *
Export-ModuleMember -Function PublicFnH
' @ -f $dotSourceFilePathE | Out-File $moduleFilePathH
# Module with dot source and only class definition, and no functions exported.
$scriptModuleNameI = " ModuleDotSourceClassesOnly_System32 "
$moduleFilePathI = Join-Path $TestModulePath ( $scriptModuleNameI + " .psm1 " )
@ '
class Class1 { { static [ string ] GetMessage ( ) { { . { 0 } ; return " Message " } } } }
' @ -f $dotSourceFilePathE | Out-File $moduleFilePathI
# Module manifest with dot source and only class definition, and no functions exported.
$scriptManifestNameI = " ManifestDotSourceClassesOnly_System32 "
$moduleManifestPathI = Join-Path $TestModulePath ( $scriptManifestNameI + " .psd1 " )
" @{ ModuleVersion='1.0'; RootModule=' $moduleFilePathI ' } " | Out-File $moduleManifestPathI
# Module with using directive
$sriptModuleNameJ = " ModuleWithUsing_System32 "
$moduleFilePathJ = Join-Path $TestModulePath ( $sriptModuleNameJ + " .psm1 " )
@ '
using module { 0 }
function PublicUsingFn { { [ Class1 ] :: GetMessage ( ) } }
Export-ModuleMember -Function PublicUsingFn
' @ -f $moduleManifestPathI | Out-File $moduleFilePathJ
Write-Verbose " Test module files created "
}
It " Verifies that importing trusted module in system lockdown which dot sources a ps1 file while exporting all functions with wildcard throws expected error " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Import-Module -Name $moduleFilePathA -Force 2 > $null
throw " No Exception! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError . FullyQualifiedErrorId | Should -BeExactly " Modules_SystemLockDown_CannotUseDotSourceWithWildCardFunctionExport,Microsoft.PowerShell.Commands.ImportModuleCommand "
}
It " Verifies that importing trusted module in system lockdown which dot sources a ps1 file that exports functions with wildcard throws expected error " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Import-Module -Name $moduleFilePathB -Force 2 > $null
throw " No Exception! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError . FullyQualifiedErrorId | Should -BeExactly " Modules_SystemLockDown_CannotUseDotSourceWithWildCardFunctionExport,Microsoft.PowerShell.Commands.ImportModuleCommand "
}
It " Verifies that importing trusted module in system lockdown which dot sources a ps1 file while exporting functions with wildcard but has overriding manifest export does not throw error " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
$module = Import-Module -Name $manifestFilePathC -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 2
$module . ExportedCommands [ " PublicFnC " ] | Should -Not -BeNullOrEmpty
$module . ExportedCommands [ " PublicDSFnC " ] | Should -Not -BeNullOrEmpty
}
It " Verifies that importing trusted module in system lockdown which dot sources ps1 file but does not export functions with wildcard does not throw error " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
$module = Import-Module -Name $moduleFilePathD -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 2
$module . ExportedCommands [ " PublicFnD " ] | Should -Not -BeNullOrEmpty
$module . ExportedCommands [ " PublicDSFnD " ] | Should -Not -BeNullOrEmpty
}
It " Verifies that importing trusted module with dotsource and wildcard function export works when not in lock down mode " {
$module = Import-Module -Name $moduleFilePathA -Force -PassThru
$module . ExportedCommands . Count | Should -Be 4
$module . ExportedCommands [ " PublicFnA " ] | Should -Not -BeNullOrEmpty
$module . ExportedCommands [ " PrivateFnA " ] | Should -Not -BeNullOrEmpty
$module . ExportedCommands [ " PublicDSFnA " ] | Should -Not -BeNullOrEmpty
$module . ExportedCommands [ " PrivateDSFnA " ] | Should -Not -BeNullOrEmpty
}
It " Verifies that importing trusted module with dotsource and no function export works without error in lockdown mode " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
$module = Import-Module -Name $moduleFilePathE -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 0
}
It " Verifies that dot source manifest and module with nested module works as expected in system lock down " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
$module = Import-Module -Name $manifestFilePathF -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 2
$module . ExportedCommands [ " PublicFnF " ] | Should -Not -BeNullOrEmpty
$module . ExportedCommands [ " NestedPubFnF " ] | Should -Not -BeNullOrEmpty
}
It " Verifies that an imported module that dot sources and exports via wilcard is detected and disallowed " {
try
{
$expectedError = $null
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
$module = Import-Module -Name $moduleFilePathG -Force -PassThru -ErrorVariable expectedError 2 > $null
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError [ 0 ] . FullyQualifiedErrorId | Should -BeExactly " Modules_SystemLockDown_CannotUseDotSourceWithWildCardFunctionExport,Microsoft.PowerShell.Commands.ImportModuleCommand "
}
It " Verifies that a module with dot source file and multiple Export-ModuleMember calls still errors with wildcard " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
$module = Import-Module -Name $moduleFilePathH -Force -PassThru 2 > $null
throw " No Exception! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError . FullyQualifiedErrorId | Should -BeExactly " Modules_SystemLockDown_CannotUseDotSourceWithWildCardFunctionExport,Microsoft.PowerShell.Commands.ImportModuleCommand "
}
It " Verifies that a classes only module with dot-source and with using directive loads successfully " {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
$module = Import-Module -Name $moduleFilePathJ -Force -PassThru
$result = PublicUsingFn
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module | Should -Not -BeNullOrEmpty
$result | Should -BeExactly " Message "
}
}
Describe " Call operator invocation of trusted module private function " -Tags 'Feature' , 'RequireAdminOnWindows' {
BeforeAll {
$scriptModuleName = " ImportTrustedManifestWithCallOperator_System32 "
$moduleFileName = Join-Path $TestDrive ( $scriptModuleName + " .psm1 " )
$manifestFileName = Join-Path $TestDrive ( $scriptModuleName + " .psd1 " )
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; FunctionsToExport = 'PublicFn' } " > $manifestFileName
}
It " Verifies expected error when call operator attempts to access trusted module scope function " {
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
& $module PrivateFn
throw " No Exception! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError . FullyQualifiedErrorId | Should -BeExactly " CantInvokeCallOperatorAcrossLanguageBoundaries "
}
}
Describe " Tests module table restrictions " -Tags 'Feature' , 'RequireAdminOnWindows' {
BeforeAll {
# Module directory
$moduleName = " Modules_ " + ( Get-RandomFileName )
$modulePath = Join-Path $TestDrive $moduleName
New-Item -ItemType Directory -Path $modulePath
# Parent module directory
$scriptModuleName = " TrustedParentModule_System32 "
$scriptModulePath = Join-Path $modulePath $scriptModuleName
$moduleFileName = Join-Path $scriptModulePath ( $scriptModuleName + " .psm1 " )
$manifestFileName = Join-Path $scriptModulePath ( $scriptModuleName + " .psd1 " )
New-Item -ItemType Directory -Path $scriptModulePath
# Import module directory
$scriptModuleImportName = " TrustedImportModule_System32 "
$scriptModuleImportPath = Join-Path $modulePath $scriptModuleImportName
$moduleImportFileName = Join-Path $scriptModuleImportPath ( $scriptModuleImportName + " .psm1 " )
New-Item -ItemType Directory -Path $scriptModuleImportPath
@ '
Import-Module -Name { 0 }
function PublicFn
{ {
Write-Host " "
Write-Host " PublicFn "
PrivateFn1
} }
' @ -f $scriptModuleImportName > $moduleFileName
@ '
function PrivateFn1
{
Write-Host " "
Write-Host " PrivateFn1 "
Write-Host " Language mode: $( $ExecutionContext . SessionState . LanguageMode ) "
}
' @ > $moduleImportFileName
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileName '; FunctionsToExport = 'PublicFn' } " > $manifestFileName
$savedPSModulePath = $env:PSModulePath
$env:PSModulePath + = ( " ; " + $modulePath )
}
AfterAll {
if ( $savedPSModulePath -ne $null ) { $env:PSModulePath = $savedPSModulePath }
}
It " Verifies that Get-Command does not expose private module function under system lock down " {
$GetCommandPublicFnCmdInfo = $null
$GetCommandPrivateFnCmdInfo = $null
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
# Imports both TrustedParentModule_System32 and TrustedImportModule_System32 modules
Import-Module -Name $scriptModuleName -Force
# Public functions should be available in the session
$GetCommandPublicFnCmdInfo = Get-Command -Name " PublicFn " 2 > $null
# Private functions should not be available in the session
# Get-Command will import the TrustedImportModule_System32 module from the PSModulePath to find PrivateFn1
# However, it should not get TrustedImportModule_System32 from the module cache because it was loaded in a
# different language mode, and should instead re-load it (equivalent to Import-Module -Force)
$GetCommandPrivateFnCmdInfo = Get-Command -Name " PrivateFn1 " 2 > $null
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$GetCommandPublicFnCmdInfo | Should -Not -BeNullOrEmpty
$GetCommandPrivateFnCmdInfo | Should -BeNullOrEmpty
}
It " Verifies that Get-Command does not expose private function after explicitly importing nested module file under system lock down " {
$ReImportPublicFnCmdInfo = $null
$ReImportPrivateFnCmdInfo = $null
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
# Imports both TrustedParentModule_System32 and TrustedImportModule_System32 modules
Import-Module -Name $scriptModuleName -Force
# Directly import nested TrustedImportModule_System32 module.
# This makes TrustedImportModule_System32 functions visible but should not use the existing loaded module
# since all functions are visible, but instead should re-load the module with the correct language context,
# ensuring only explictly exported functions are visible.
Import-Module -Name $scriptModuleImportName
# Public functions should be available in the session
$ReImportPublicFnCmdInfo = Get-Command -Name " PublicFn " 2 > $null
# Private functions should not be available in the session
$ReImportPrivateFnCmdInfo = Get-Command -Name " PrivateFn1 " 2 > $null
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$ReImportPublicFnCmdInfo | Should -Not -BeNullOrEmpty
$ReImportPrivateFnCmdInfo | Should -BeNullOrEmpty
}
}
Describe " Import mix of trusted and untrusted manifest and module files " -Tags 'Feature' , 'RequireAdminOnWindows' {
It " Verifies that an untrusted manifest with a trusted module will not load under system lockdown " {
$manifestFileName = Join-Path $TestDrive " ImportUnTrustedManifestWithFnExport.psd1 "
$moduleFileName = Join-Path $TestDrive " ImportUnTrustedManifestWithFnExport_System32.psm1 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; FunctionsToExport = 'PublicFn','PrivateFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
Import-Module -Name $manifestFileName -Force -ErrorAction Stop
throw " No Exception! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError . FullyQualifiedErrorId | Should -BeExactly " Modules_MismatchedLanguageModes,Microsoft.PowerShell.Commands.ImportModuleCommand "
}
It " Verifies that an untrusted manifest with a trusted binary module does load under system lockdown " {
$modulePath = " $PSScriptRoot \Modules "
New-Item -Path $modulePath -ItemType Directory -Force
$manifestFileName = Join-Path $modulePath " ImportUnTrustedManifestWithBinFnExport.psd1 "
$moduleFileName = Join-Path $modulePath " ImportUnTrustedManifestWithBinFnExport_System32.dll "
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileName '; CmdletsToExport = 'Invoke-Hello' } " > $manifestFileName
$code = @ '
using System ;
using System . Management . Automation ;
[ Cmdlet ( " Invoke " , " Hello " ) ]
public sealed class InvokeHello : PSCmdlet
{
protected override void EndProcessing ( )
{
System . Console . WriteLine ( " Hello! " ) ;
}
}
' @
try { Add-Type -TypeDefinition $code -OutputAssembly $moduleFileName -ErrorAction Ignore } catch { }
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module | Should -Not -BeNullOrEmpty
$module . ExportedCommands [ " Invoke-Hello " ] | Should -Not -BeNullOrEmpty
if ( $module -ne $null ) { Remove-Module -Name $module . Name -Force -ErrorAction Ignore }
}
It " Verifies that an untrusted module with nested trusted modules cannot load in a locked down system " {
$manifestFileName = Join-Path $TestDrive " ImportUnTrustedManifestWithTrustedModule.psd1 "
$moduleFileName = Join-Path $TestDrive " ImportUnTrustedManifestWithTrustedModule_System32.psm1 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileName '; FunctionsToExport = 'PublicFn','PrivateFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
Import-Module -Name $manifestFileName -Force -ErrorAction Stop
throw " No Exception! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError . FullyQualifiedErrorId | Should -BeExactly " Modules_MismatchedLanguageModes,Microsoft.PowerShell.Commands.ImportModuleCommand "
}
It " Verifies that an untrusted manifest containing all trusted modules does not load under system lock down " {
$moduleFileName1 = Join-Path $TestDrive " ImportUnTrustedManifestWithTrustedModules1_System32.psm1 "
$moduleFileName2 = Join-Path $TestDrive " ImportUnTrustedManifestWithTrustedModules2_System32.psm1 "
$manifestFileName = Join-Path $TestDrive " ImportUnTrustedManifestWithTrustedModules.psd1 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName1
@ '
function PublicFn2
{
Write-Output " PublicFn2 "
}
' @ > $moduleFileName2
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileName1 '; RootModule = ' $moduleFileName2 '; FunctionsToExport = 'PublicFn','PrivateFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
Import-Module -Name $manifestFileName -Force -ErrorAction Stop
throw " No Exception! "
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError . FullyQualifiedErrorId | Should -BeExactly " Modules_MismatchedLanguageModes,Microsoft.PowerShell.Commands.ImportModuleCommand "
}
# End Describe Block
}
Describe " Import trusted module files in system lockdown mode " -Tags 'Feature' , 'RequireAdminOnWindows' {
function CreateModuleNames
{
param (
[ string ] $moduleName
)
$script:scriptModuleName = $moduleName
$script:moduleFileName = Join-Path $TestDrive ( $moduleName + " .psm1 " )
}
It " Verifes that trusted module file exports no functions in system lockdown " {
CreateModuleNames " ImportTrustedModuleWithNoFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $moduleFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 0
}
It " Verifies that trusted module file exports only exported function in system lockdown " {
CreateModuleNames " ImportTrustedModuleWithFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
Export-ModuleMember -Function PublicFn
' @ > $moduleFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $moduleFileName -Force -PassThr
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly " PublicFn "
}
It " Verifies that trusted module with wild card function export in system lockdown " {
CreateModuleNames " ImportTrustedModuleWithWildcardFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
Export-ModuleMember -Function *
' @ > $moduleFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $moduleFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 2
}
}
Describe " Import trusted manifest files in system lockdown mode " -Tags 'Feature' , 'RequireAdminOnWindows' {
function CreateManifestNames
{
param (
[ string ] $moduleName ,
[ switch ] $twoModules ,
[ switch ] $noExtension ,
[ switch ] $dotSourceModule
)
$script:scriptModuleName = $moduleName
$script:moduleFileName = Join-Path $TestDrive ( $moduleName + " .psm1 " )
$script:manifestFileName = Join-Path $TestDrive ( $moduleName + " .psd1 " )
if ( $twoModules )
{
$script:moduleFileName2 = Join-Path $TestDrive ( $moduleName + " 2.psm1 " )
}
if ( $noExtension )
{
$script:moduleFileNameNoExt = Join-Path $TestDrive $scriptModuleName
}
if ( $dotSourceModule )
{
$script:dotmoduleFileName = Join-Path $TestDrive ( $moduleName + " Dot " + " .ps1 " )
}
}
It " Verifies that trusted manifest exports no functions by default in lock down mode " {
CreateManifestNames " ImportTrustedManifestWithNoFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName ' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 0
}
It " Verifies that trusted manifest exports no functions through wildcard in lock down mode " {
CreateManifestNames " ImportTrustedManifestWithWildcardFnExport1_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; FunctionsToExport = '*' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 0
}
It " Verifies that trusted manifest exports no functions through name wildcard in lock down mode " {
CreateManifestNames " ImportTrustedManifestWithWildcardNameFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; FunctionsToExport = '*Fn*' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 0
}
It " Verifies that trusted manifest exports a single module function and ignores wildcard in lock down mode " {
CreateManifestNames " ImportTrustedManifestWithWildcardModFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
Export-ModuleMember -Function " PublicFn "
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; FunctionsToExport = '*' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly " PublicFn "
}
It " Verifies that trusted manifest exports no functions through the cmdlets export keyword " {
CreateManifestNames " ImportTrustedManifestWithCmdletExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; CmdletsToExport = '*' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 0
}
It " Verifies that trusted manifest with wildcard exports a single function from two modules " {
CreateManifestNames " ImportTrustedManifestWithTwoMods_System32 " -TwoModules
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
Export-ModuleMember -Function PublicFn
' @ > $moduleFileName
@ '
function PrivateFn3
{
Write-Output " PublicFn "
}
function PrivateFn4
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName2
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; NestedModules = ' $moduleFileName2 '; FunctionsToExport = '*' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly " PublicFn "
}
It " Verifies that trusted manifest explicitly exports a single function " {
CreateManifestNames " ImportTrustedManifestWithExportFn_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; FunctionsToExport = 'PublicFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly " PublicFn "
}
It " Verifies that trusted manifest with nested modules exports explicit function " {
CreateManifestNames " ImportTrustedManifestWithNestedModsAndFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileName '; FunctionsToExport = 'PublicFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly " PublicFn "
}
It " Verifies that trusted manifest with nested modules exports no functions by default " {
CreateManifestNames " ImportTrustedManifestWithNestedModsAndNoFnExport_System32 "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileName ' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 0
}
It " Verifies that trusted manifest with nested modules and no extension module exports explicit function " {
CreateManifestNames " ImportTrustedManifestWithNestedModsAndNoExtNoFnExport_System32 " -NoExtension
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileNameNoExt '; FunctionsToExport = 'PublicFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly " PublicFn "
}
It " Verifies that trusted manifest with dot source module file respects lock down mode " {
CreateManifestNames " ImportTrustedManifestWithDotSourceModAndFnExport_System32 " -DotSourceModule
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $dotmoduleFileName
@ '
. { 0 }
function PrivateFn1
{ {
Write-Output " PrivateFn1 "
} }
function PrivateFn2
{ {
Write-Output " PrivateFn2 "
} }
' @ -f $dotmoduleFileName > $moduleFileName
" @{ ModuleVersion = '1.0'; NestedModules = ' $moduleFileName '; FunctionsToExport = 'PublicFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly " PublicFn "
}
}
Describe " Untrusted manifest and module files import in lock down mode " -Tags 'Feature' , 'RequireAdminOnWindows' {
function CreateManifestNames
{
param (
[ string ] $moduleName
)
$script:scriptModuleName = $moduleName
$script:moduleFileName = Join-Path $TestDrive ( $moduleName + " .psm1 " )
$script:manifestFileName = Join-Path $TestDrive ( $moduleName + " .psd1 " )
}
It " Verifies that importing untrusted manifest in lock down mode exports all functions by default " {
CreateManifestNames " ImportUntrustedManifestWithNoFnExport "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName ' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 2
}
It " Verifies that importing untrusted manifest in lock down mode exports explicit function " {
CreateManifestNames " ImportUntrustedManifestWithFnExport "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
" @{ ModuleVersion = '1.0'; RootModule = ' $moduleFileName '; FunctionsToExport = 'PrivateFn' } " > $manifestFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $manifestFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly 'PrivateFn'
}
It " Verifies that importing untrusted module file in lock down mode exports all functions by default " {
CreateManifestNames " ImportUnTrustedModuleWithNoFnExport "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
' @ > $moduleFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $moduleFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 2
}
It " Verifies that importing untrusted module file in lock down mode exports explicit function " {
CreateManifestNames " ImportUnTrustedModuleWithFnExport "
@ '
function PublicFn
{
Write-Output " PublicFn "
}
function PrivateFn
{
Write-Output " PrivateFn "
}
Export-ModuleMember -Function PublicFn
' @ > $moduleFileName
try
{
$ExecutionContext . SessionState . LanguageMode = " ConstrainedLanguage "
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$module = Import-Module -Name $moduleFileName -Force -PassThru
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$module . ExportedCommands . Count | Should -Be 1
$module . ExportedCommands . Values [ 0 ] . Name | Should -BeExactly 'PublicFn'
}
}
2018-11-30 20:45:33 +01:00
Describe " Export-ModuleMember should succeed in FullLanguage mode with scriptblock created without context " -Tag 'Feature' {
BeforeAll {
$typeDef = @ '
using System ;
using System . Management . Automation ;
using System . Management . Automation . Runspaces ;
public class TestScriptBlockCreate
{
private ScriptBlock _scriptBlock ;
public ScriptBlock CreateScriptBlock ( )
{
var thread = new System . Threading . Thread ( ThreadProc ) ;
thread . Start ( null ) ;
thread . Join ( ) ;
return _scriptBlock ;
}
private void ThreadProc ( object state )
{
/ / Create script block on thread with no PowerShell context
_scriptBlock = ScriptBlock . Create ( @ " function Do-Nothing {}; Export-ModuleMember -Function Do-Nothing " ) ;
}
}
' @
try
{
Add-Type -TypeDefinition $typeDef
}
catch { }
}
It " Verfies that Export-ModuleMember does not throw error with context-less scriptblock " {
$scriptBlockCreator = [ TestScriptBlockCreate ] :: new ( )
$testScriptBlock = $scriptBlockCreator . CreateScriptBlock ( )
$testScriptBlock | Should -Not -BeNullOrEmpty
{ New-Module -ScriptBlock $testScriptBlock -ErrorAction Stop } | Should -Not -Throw -Because " Scriptblock without execution context is allowed in Full Language "
}
}
2018-11-14 01:16:29 +01:00
}
finally
{
if ( $defaultParamValues -ne $null )
{
$Global:PSDefaultParameterValues = $defaultParamValues
}
}