core/modules/monkeyjob/public/Start-MonkeyJob.ps1
# Monkey365 - the PowerShell Cloud Security Tool for Azure and Microsoft 365 (copyright 2022) by Juan Garrido # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. Function Start-MonkeyJob{ <# .SYNOPSIS Starts a MonkeyJob using runspaces .DESCRIPTION .INPUTS .OUTPUTS .EXAMPLE .NOTES Author : Juan Garrido Twitter : @tr1ana File Name : Start-MonkeyJob Version : 1.0 .LINK https://github.com/silverhack/monkey365 #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "", Scope="Function")] [cmdletbinding(DefaultParameterSetName='ScriptBlock')] Param ( [Parameter(Mandatory=$True,position=0,ParameterSetName='ScriptBlock')] [System.Management.Automation.ScriptBlock]$ScriptBlock, [Parameter(Mandatory=$True,Position = 0, ParameterSetName = 'Command')] [String]$Command, [Parameter(Mandatory = $True, Position = 0, ParameterSetName = 'FilePath', HelpMessage = 'PowerShell Script file')] [ValidateScript( { if( -Not ($_ | Test-Path) ){ throw ("The PowerShell file does not exist in {0}" -f (Split-Path -Path $_)) } if(-Not ($_ | Test-Path -PathType Leaf) ){ throw "The argument must be a ps1 file. Folder paths are not allowed." } if($_ -notmatch "(\.ps1)"){ throw "The script specified argument must be of type ps1" } return $true })] [System.IO.FileInfo]$File, [Parameter(Mandatory=$false, HelpMessage="arguments")] [Object]$Arguments, [Parameter(Mandatory=$false,ValueFromPipeline=$true)] $InputObject, [Parameter(Mandatory=$false, HelpMessage="Job name")] [String]$JobName, [Parameter(HelpMessage="Variables to import into runspace")] [Object]$ImportVariables, [Parameter(HelpMessage="runspace")] [System.Management.Automation.Runspaces.RunspacePool]$Runspacepool, [Parameter(HelpMessage="modules to import into sessionState")] [Object]$ImportModules, [Parameter(HelpMessage="commands to import into sessionState")] [Object]$ImportCommands, [Parameter(HelpMessage="commands as AST to import into sessionState")] [Object]$ImportCommandAst, [Parameter(HelpMessage="Startup scripts (*ps1 files) to execute")] [System.Object[]]$StartUpScripts, [Parameter(HelpMessage="Minimum number of runspaces")] [ValidateRange(1,65535)] [int32]$MinThrottle = 1, [Parameter(HelpMessage="Maximum number of runspaces")] [ValidateRange(1,65535)] [int32]$Throttle = 2, [Parameter(HelpMessage="ApartmentState of the thread")] [ValidateSet("STA","MTA")] [String]$ApartmentState = "STA", [Parameter(Mandatory=$False, HelpMessage='ThrowOnRunspaceOpenError')] [Switch]$ThrowOnRunspaceOpenError ) Begin{ #Set null $Pipeline = $monkeyJob = $Job = $null; #Add runspaceOpenError var If (-not $PSBoundParameters.ContainsKey('ThrowOnRunspaceOpenError')) { $ThrowOnRunspaceOpenError = $False } $Verbose = $False; $Debug = $False; $InformationAction = 'SilentlyContinue' If($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose){ $Verbose = $True } If($PSBoundParameters.ContainsKey('Debug') -and $PSBoundParameters.Debug){ $DebugPreference = 'Continue' $Debug = $True } If($PSBoundParameters.ContainsKey('InformationAction')){ $InformationAction = $PSBoundParameters['InformationAction'] } #Create new runspace or reuse existing If (-not $PSBoundParameters.ContainsKey('Runspacepool')) { #Create a new runspacePool $localparams = @{ ImportVariables = $ImportVariables; ImportModules = $ImportModules; ImportCommands = $ImportCommands; ImportCommandsAst = $ImportCommandAst; ApartmentState = $ApartmentState; MinThrottle = $MinThrottle; Throttle = $Throttle; StartUpScripts = $StartUpScripts; ThrowOnRunspaceOpenError = $ThrowOnRunspaceOpenError; Verbose = $Verbose; Debug = $Debug; InformationAction = $InformationAction; } #Get runspace pool $Runspacepool = New-RunspacePool @localparams If($null -ne $Runspacepool -and $Runspacepool -is [System.Management.Automation.Runspaces.RunspacePool]){ #Open runspace Write-Verbose $script:messages.OpenRunspaceMessage $Runspacepool.Open() } } Else{ if($Runspacepool.RunspacePoolStateInfo.State -eq [System.Management.Automation.Runspaces.RunspaceState]::BeforeOpen){ #Open runspace Write-Verbose $script:messages.OpenRunspaceMessage $Runspacepool.Open() } } } Process{ If($null -ne $Runspacepool -and $Runspacepool.RunspacePoolStateInfo.State -eq [System.Management.Automation.Runspaces.RunspaceState]::Opened){ #Get PowerShell Param $MetaData = New-Object -TypeName "System.Management.Automation.CommandMetaData" (Get-Command -Name "Get-PowerShellParam") $newPsboundParams = @{} If($null -ne $MetaData){ $param = $MetaData.Parameters.Keys ForEach($p in $param.GetEnumerator()){ If($PSBoundParameters.ContainsKey($p)){ $newPsboundParams.Add($p,$PSBoundParameters[$p]) } } } #Check if RunspacePool If(-NOT $newPsboundParams.ContainsKey('RunspacePool')){ [void]$newPsboundParams.Add('RunspacePool',$Runspacepool); } $psParams = Get-PowerShellParam @newPsboundParams If($null -ne $psParams){ $Pipeline = New-PowerShellObject @psParams } If($null -ne $Pipeline){ #Get Command Name $MetaData = New-Object -TypeName "System.Management.Automation.CommandMetaData" (Get-Command -Name "Format-CommandName") $newPsboundParams = [ordered]@{} If($null -ne $MetaData){ $param = $MetaData.Parameters.Keys ForEach($p in $param.GetEnumerator()){ If($PSBoundParameters.ContainsKey($p)){ $newPsboundParams.Add($p,$PSBoundParameters[$p]) } } } $commandName = Format-CommandName @newPsboundParams #Set new Job object $MetaData = New-Object -TypeName "System.Management.Automation.CommandMetaData" (Get-Command -Name "New-MonkeyJobObject") $jobObjectParams = [ordered]@{} If($null -ne $MetaData){ $param = $MetaData.Parameters.Keys ForEach($p in $param.GetEnumerator()){ If($PSBoundParameters.ContainsKey($p)){ $jobObjectParams.Add($p,$PSBoundParameters[$p]) } } } #Get new MonkeyJob object $monkeyJob = New-MonkeyJobObject @jobObjectParams -CommandName $commandName IF($null -ne $monkeyJob){ #Create a new Job $Job = [MonkeyJob]::new($Pipeline,$monkeyJob.Name); } } If($null -ne $Job){ #Populate job $monkeyJob.RunspacePoolId = $Pipeline.RunspacePool.InstanceId; $monkeyJob.Job = $Job; #Start task $monkeyJob.Task = $monkeyJob.Job.StartTask(); #Add to monkeyJob var [void]$Script:MonkeyJobs.Add($monkeyJob) #return Job $monkeyJob } } Else{ If($Runspacepool.RunspacePoolStateInfo.State -ne [System.Management.Automation.Runspaces.RunspaceState]::Opened){ Write-Error ($script:messages.RunspaceError) return } Else{ Write-Error ($script:messages.UnknownError) return } } } End{ #Nothing to do here } } |