status.ps1
# Status and Progress APIs # Get Infocyte HUNT Jobs (Active jobs or all jobs) function Get-ICJob { [cmdletbinding()] param( [parameter(ValueFromPipelineByPropertyName)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('jobId')] [String]$Id, [Switch]$All, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { $endpoint = 'jobs' if ($Id) { $CountOnly = $false $endpoint += "/$Id" $where = $null $NoLimit = $false } else { if ($All) { Write-Verbose "Getting All Jobs." } else { Write-Verbose "Getting Active Jobs." if (-NOT $where['state']) { $where['state'] = "active" } } } Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly } } # Get Infocyte HUNT User Audit Logs function Get-ICAuditLog { [cmdletbinding()] param( [parameter(ValueFromPipeline)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [String]$Id, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) BEGIN { $users = Get-ICAPI -endpoint users -nolimit } PROCESS { $endpoint = 'useractivities' if ($Id) { $CountOnly = $false $endpoint += "/$Id" } Write-Verbose "Getting User Activity Logs" if ($CountOnly) { Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly } else { Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly | foreach-object { $userid = $_.userId $user = $users | where { $_.id -eq $userid } $_ | Add-Member -Type NoteProperty -Name username -Value $user.username $_.query = $_.query | ConvertTo-Json -Depth 10 -Compress $_ } } } } # Get Infocyte HUNT User Tasks. These are the items in the task dropdown in the UI. function Get-ICTask { [cmdletbinding()] param( [parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('id')] [alias('taskId')] [String]$userTaskId, [Switch]$All, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { $endpoint = "usertasks" if ($userTaskId) { $CountOnly = $false $endpoint += "/$userTaskId" } else { if (-NOT $All -AND $where.keys.count -eq 0) { Write-Verbose "Filtering for running and recently ended tasks (Default)." $where = @{ and = @() } $where['and'] += @{ type = @{ neq = "RTS"} } $where['and'] += @{ or = @( @{ status = "Active" }, @{ endedOn = @{ gte = (Get-Date).ToUniversalTime().AddDays(-1).ToString() } } )} $where['and'] += @{ archived = $false } Write-Verbose "Using filter: $($Where | convertto-json)" } } $Tasks = Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly $Tasks | ForEach-Object { $_ | Add-Member -Type NoteProperty -Name totalSeconds -Value $null if ($_.endedOn) { $_.totalSeconds = [math]::round(([datetime]$_.endedOn - [DateTime]$_.createdOn).TotalSeconds) } } Write-Output $Tasks } } function Get-ICTaskItems { [cmdletbinding()] param( [parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('id')] [alias('TaskId')] [String]$userTaskId, [parameter()] [Switch]$IncludeProgress, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$Where=@{}, [String[]]$Fields, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { $Endpoint = "userTaskItems" $where['userTaskId'] = $userTaskId if ($CountOnly) { return (Get-ICAPI -Endpoint $Endpoint -where $where -fields $fields -NoLimit:$NoLimit -CountOnly:$CountOnly) } Write-Verbose "Getting All TaskItems with TaskId $userTaskId." $Items = Get-ICAPI -Endpoint $Endpoint -where $where -fields $fields -NoLimit:$NoLimit -CountOnly:$CountOnly ForEach ($item in $items) { $item | Add-Member -Type NoteProperty -Name totalSeconds -Value $null if ($item.endedOn) { $item.totalSeconds = [math]::round(([datetime]$item.endedOn - [DateTime]$item.createdOn).TotalSeconds) } if ($item.type -eq "host-access" -OR $item.type -eq "enumeration") { $type = $item.type $item | Add-Member -Type NoteProperty -Name queryId -Value $null $item | Add-Member -Type NoteProperty -Name queryName -Value $null if ($type -eq "enumeration") { $item.queryId = $item.result.queryId } elseif ($type -eq "host-access") { Write-Verbose "Getting QueryId from job" try { $j = Get-ICJob -Id $item.jobId } catch { } $item.queryId = $j.data.queryId } if ($item.queryId) { Write-Verbose "Getting QueryName" $q = Get-ICQuery -Id $item.queryId $item.queryName = $q.Name } } } if (-NOT $IncludeProgress) { Write-Output $Items } else { $n = 0 if ($Id) { $cnt = 1 } else { $cnt = Get-ICAPI -Endpoint $Endpoint -where $where -CountOnly } Write-Verbose "Found $cnt TaskItems. Getting progress for each." ForEach ($item in $items) { $item | Add-Member -Type NoteProperty -Name lastMessage -Value $null if ($item.type -eq "host-access") { $item | Add-Member -Type NoteProperty -Name accessible -Value $null } $n += 1 try { $pc = [math]::floor($n*100/$cnt); if ($pc -gt 100) { $pc = 100 } } catch { $pc = -1 } if ($item.id) { Write-Progress -Id 101 -Activity "Enriching with Task Progress Information" -status "Getting progress on $($item.name) [$n of $cnt]" -PercentComplete $pc $progresstext = @() _Get-ICTaskItemProgress -taskItemId $item.id | ForEach-Object { $p = $_ $p | foreach-object { $progresstext += "$($_.createdOn) - $($_.text)" if (-NOT $LastProgressMsg) { $LastProgressMsg = "$($_.createdOn) - $($_.text)" } if ($type -eq "host-access" -AND $_.text -match "^ACCESSIBLE:") { $item.accessible = $true $item.lastMessage = $_.text } elseif ($type -eq "host-access" -AND $_.text -match "^INACCESSIBLE:") { $item.accessible = $false $item.lastMessage = $_.text } } } if ($item.status -ne "complete" -AND -NOT $item.message) { $item.lastMessage = $LastProgressMsg } $item | Add-Member -MemberType "NoteProperty" -name "progress" -value ([string[]]$progresstext) } } Write-Output $items } } } function _Get-ICTaskItemProgress { [cmdletbinding()] param( [parameter( Mandatory=$true, ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('userTaskItemId')] [alias('id')] [String]$taskItemId, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit ) PROCESS { $Endpoint = "userTaskItemProgresses" if ($_.id -AND $_.taskItemId) { # disambuguation $where['taskItemId'] = $_.taskItemId } else { $where['taskItemId'] = $taskItemId } Get-ICAPI -Endpoint $Endpoint -where $where -fields @("createdOn", "text") -NoLimit:$NoLimit | Sort-Object createdOn -Descending } } function Wait-ICTask { [cmdletbinding()] param( [parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateScript( { if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid." } })] [alias('id')] [alias('userTaskId')] [String]$TaskId ) BEGIN {} PROCESS { $Task = Get-ICTaskItems -userTaskId $TaskId -IncludeProgress while (-NOT $Task.complete) { Start-Sleep 20 $Task = Get-ICTaskItems -userTaskId $TaskId -IncludeProgress } return $true } END{} } function Get-ICLastScanTask { [cmdletbinding()] param( [parameter(Mandatory, Position=0)] [ValidateSet("Scan", "Enumerate")] [String]$Type, [parameter(Position=1)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [String]$targetGroupId ) if ($targetGroupId) { $Task = Get-ICTask -where @{ targetGroupId = $targetGroupId; type = $Type } | Select-Object -Last 1 if (-NOT $Task) { Write-Error "No $Type task was found within target group with Id: $targetGroupId" return } } else { $where = @{ and = @()} #$where['and'] += @{ endedOn = @{ gte = (Get-Date).ToUniversalTime().AddDays(-1).ToString() } } $where['and'] += @{ type = $Type; } $where['and'] += @{ archived = $false } $Task = Get-ICTask -where $where | Select-Object -Last 1 if (-NOT $Task) { Write-Error "No task was found with type: $Type" return } } $Progress = Get-ICTaskItems -userTaskId $Task.id -IncludeProgress -NoLimit $result = @{ userTaskId = $Task.Id name = $Task.name createdOn = $Task.createdOn endedOn = $Task.endedOn totalSeconds = $task.totalSeconds status = $Task.status type = $Task.type accessibleCount = ([Array]($Progress | Where-Object { $_.Accessible })).count inaccessibleCount = ([Array]($Progress | Where-Object { -NOT $_.Accessible })).count totalItems = ([Array]$Progress).count items = $Progress } $result['coverage'] = try { [math]::Round(($($result.accessibleCount)/$($result.totalItems)), 2) } catch { $null } return [PSCustomObject]$result } # SIG # Begin signature block # MIINFwYJKoZIhvcNAQcCoIINCDCCDQQCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUYTAXZgQOloABTzYApT8fAqeG # gXSgggpZMIIFITCCBAmgAwIBAgIQD1SHruUyzkN01AFx5d7oATANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMTExNzAwMDAwMFoXDTIyMTEy # OTIzNTk1OVowXjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQH # EwZBdXN0aW4xFjAUBgNVBAoTDUluZm9jeXRlLCBJbmMxFjAUBgNVBAMTDUluZm9j # eXRlLCBJbmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNUhaEiZbu # H7Q6oqA0uq0klkstXkdJU3eJukMrrLpxKdtFqtJwFXcSYp5G/WFlwDRJ8v8fisfp # SiPS1WajFUHe3EWLh2oXjf44eQYVWQ8SqAn2J8dDLNJ5bWY0w7MD2GrSiTwN0Vi9 # X9pJKJDdm7mJo7bSlZ9p7XvNoraSAx/hkODalPSMvCIVAEOZutlzeWyJ4p0DbTDA # kjQPF4EZ7JqxYXFeItoi0uYZQNEHbBxr+5SG45ziC8vuwyljIbo+mKD/PwT48OQl # 9cdnI651Hz+r5kL3t48WvxYrAUJ7g8EJyw2uYnVnSroIC3TmUQHeXS6FuqeObuX7 # MqapBKRcTHvxAgMBAAGjggHFMIIBwTAfBgNVHSMEGDAWgBRaxLl7KgqjpepxA8Bg # +S32ZXUOWDAdBgNVHQ4EFgQUxKDwshqav/aGaGVOFv67CuwSjcYwDgYDVR0PAQH/ # BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGA1UdHwRwMG4wNaAzoDGGL2h0 # dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMDWg # M6Axhi9odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcx # LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRw # czovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEE # eDB2MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYB # BQUHMAKGQmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJB # c3N1cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3 # DQEBCwUAA4IBAQByJW5tIcmouIY7tdngPLdEOM4FYqLGf9IjKPMS0s+NeTaP/0hp # dmNeGFEvMozfgDA/gPFCUaRVJwy4rKsGnCznCE1YDA6UFDGZq3VLUbzC6GDP4aY8 # EbfDMbF54TVuOKRue9a6KnVE67gOj+g862qAR6fm/GdeO/KrdvCT1A7xbyg02cCq # +QgdkYoxI3bsiUwgZ33I2rn2T2zSp8C+RX2bZ8rgtXHxgYLCJdayqMptRsPbxOlQ # Z7dRhkQXg5D/PyUnpWASF+sLQQ0IMvx8ZKy/P01IhKU0pTJ8OFSYKwPLQnYm1Zp0 # JT/IXZ/tzmtY/StdhaCs3LlOkuHxl2iERxdtMIIFMDCCBBigAwIBAgIQBAkYG1/V # u2Z1U0O1b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UE # ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD # VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAw # WhcNMjgxMDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl # cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdp # Q2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG # 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/ # 5aid2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH # 03sjlOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxK # hwjfDPXiTWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr # /mzLfnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi # 6CxR93O8vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCC # AckwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAww # CgYIKwYBBQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8v # b2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6 # MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy # ZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1s # AAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw # CgYIYIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1Ud # IwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+ # 7A1aJLPzItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbR # knUPUbRupY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7 # uq+1UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7 # qPjFEmifz0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPa # s7CM1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR # 6mhsRDKyZqHnGKSaZFHvMYICKDCCAiQCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEx # MC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBD # QQIQD1SHruUyzkN01AFx5d7oATAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEK # MAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3 # AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUQGBjWnW4lld9u+h3 # L8ecVRo+HZgwDQYJKoZIhvcNAQEBBQAEggEAVcoFUwZ/5lkUh8ifwk3n2w2K61EU # /vz6x1rGleAfy0qO6OFcboux5zdqWbOGkU6/kc6ZzVFFkDadxm/gkgdHC2F7AFIq # cLVZ1c+i5k1Buv3MrojUqHB54FlZyW7oqlrRQdvsIzfu13mIZ2z/BpEPMS/qqthn # ye4vrtXMlqJwj5EqzoX1rBvXlTdJ8HgDvlcg9pdc+FYPJ9YdpmyYJ2eKcsWcG4ap # vmyRMo7uxfc1MjxLdzYPNP6wVJ7rLNOYqgrNgfvmJWZwilQRpaLKPqG//DmkQa/y # 6UM/bdG8/n/ql6LjzHx1voi4QGO/CjMmyikZUAUrSZEo22VqvHgROWhLNQ== # SIG # End signature block |