pwsh-GC.psm1
function ConvertFrom-UnixTime { [cmdletbinding()] param ( [Parameter(Mandatory,ValueFromPipeline)] [Int64] $UnixDate ) process { foreach ( $ThisUnixDate in $UnixDate ) { $Origin = New-Object DateTime 1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc) # Remember: GuardiCore works with epoch times in milliseconds $Origin.AddSeconds([Int]($ThisUnixDate/1000)).ToLocalTime() } } } function ConvertTo-UnixTime { [cmdletbinding()] param ( [Parameter(Mandatory,ValueFromPipeline)] [DateTime] $DateTime ) process { foreach ( $ThisDateTime in $DateTime ) { $Origin = New-Object DateTime 1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc) [Int64]($ThisDateTime.ToUniversalTime()-$Origin).TotalMilliseconds } } } function Get-Agent { [CmdletBinding()] param ( [String] $Search, [String[]] $Version, [String[]] $Kernel, [ValidateSet("Unknown","Windows","Linux")] [String[]] $OS, [PSTypeName("GCLabel")] $Label, [ValidateSet("Online","Offline")] [String[]] $Status, # = display_status [ValidateSet("undefined",1,2,3,4,5,6,7,8,9,10,11,12,13,14)] $Flag, [ValidateSet("Active","Not Deployed","Disabled")] [String[]] $Enforcement, # = module_status_enforcement [ValidateSet("Active","Not Deployed")] [String[]] $Deception, # = module_status_deception [ValidateSet("Active","Not Deployed")] [String[]] $Detection, # = module_status_detection [ValidateSet("Active","Not Deployed")] [String[]] $Reveal, # = module_status_reveal [ValidateSet("last_month","last_week","last_12_hours","last_24_hours","not_active")] [String[]] $Activity, [ValidateRange(0,1000)] [Int32] $Limit = 20, [ValidateRange(0,500000)] [Int32] $Offset, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/agents" } # Building the request body with given parameters $Body = @{ version = $Version -join "," kernel = $Kernel -join "," os = $OS -join "," labels = $Label.id -join "," display_status = $Status -join "," status_flags = $Flag -join "," module_status_deception = $Deception -join "," module_status_detection = $Detection -join "," module_status_reveal = $Reveal -join "," activity = $Activity -join "," gc_filter = $Search limit = $Limit offset = $Offset } # This one's unique if ( $Enforcement ) { $Add += foreach ($ThisEnforcement in $Enforcement) { if ($ThisEnforcement -eq "Disabled") { $ThisEnforcement = "Enforcement disabled from management console" $ThisEnforcement } else { $ThisEnforcement } } $Body.module_status_enforcement = $Add -join "," } # Removing empty hashtable keys $RequestBody = Remove-EmptyKeys $Body # Making the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCAgent"); $_} } } function Get-Aggregator { [cmdletbinding()] param ( [string] $Search, [ValidateSet("UP","DOWN","RUNTIME_ERROR")] [string[]] $Status, [string[]] $Version, [int32] $Limit = 20, [int32] $Offset, [switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/agent_aggregators" } # Building the request body with given parameters $Body = @{ gc_filter = $Search display_status = $Status -join "," version = $Version -join "," limit = $Limit offset = $Offset } # Removing empty hashtable keys $RequestBody = Remove-EmptyKeys $Body # Making the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCAggregator"); $_} } } function Get-ApiKey { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory=$true,ParameterSetName = "ByName")] [System.String] $Server, [Parameter(Mandatory=$true,ParameterSetName = "ByUri")] [String] $Uri, [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [Alias('Credentials','Cred')] [PSCredential] $Credential, [Switch] $Export ) begin { if ( $Server ) { $Uri = "https://" + $Server + ".cloud.guardicore.com/api/v3.0" } else { $Uri = $Uri + "/api/v3.0" } $TempUri = $Uri + "/authenticate" $Body = [PSCustomObject]@{ "username" = "" "password" = "" } } process { $Body.username = $Credential.UserName $Body.password = $Credential.GetNetworkCredential().Password $BodyJson = $Body | ConvertTo-Json -Depth 99 if ( $pscmdlet.ShouldProcess("$Server","Invoke-RestMethod -Uri $TempUri -Method 'Post'") ) { try { $Token = Invoke-RestMethod -Uri $TempUri -Method "Post" -Body $BodyJson -ContentType "application/json" | Select-Object -ExpandProperty "access_token" } catch { throw $_.Exception } } if ( $Export ) { # Returns the object on the pipeline. [PSCustomObject]@{ PSTypeName = "GCApiKey" Token = $Token Uri = $Uri } } else { # Saves the object in a global (session scope) variable called GCApiKey, so other functions don't need a key input. $Global:GCApiKey = [PSCustomObject]@{ PSTypeName = "GCApiKey" Token = $Token Uri = $Uri } } } } function Get-Asset { [CmdletBinding()] param ( [System.String] $Search, [ValidateSet("on","off")] [System.String] $Status, [ValidateSet("0","1","2","3")] [string[]] $Risk, [Parameter(Mandatory=$false,ValueFromPipeline=$true)] [PSTypeName("GCLabel")] $Label, [Alias("Assets","ID")] $Asset, [ValidateRange(0,1000)] [Int32]$Limit = 20, [ValidateRange(0,500000)] [Int32]$Offset, [Switch]$Raw, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/assets" } } process { # Handling pipeline input $LabelIDs = foreach ($L in $Label) { $L.id } $Body = @{ search = $Search status = $Status risk_level = $Risk labels = $LabelIDs -join "," asset = "" limit = $Limit offset = $Offset } # Handling strange asset case if ( $Asset ) { if ( $Asset[0]._id ) { $Body.asset = "vm:" + $Asset[0]._id } else { $Body.asset = "vm:" + $Asset } } # Removing empty hashtable keys $RequestBody = Remove-EmptyKeys $Body # Making the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCAsset"); $_} } } } function Get-Collector { [cmdletbinding()] param ( [string] $Search, [ValidateSet("UP","DOWN")] [string[]] $Status, [string[]] $Version, [int32] $Limit = 20, [int32] $Offset, [switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/collectors" } # Building the request body with given parameters $Body = @{ gc_filter = $Search display_status = $Status -join "," version = $Version -join "," limit = $Limit offset = $Offset } # Removing empty hashtable keys $RequestBody = Remove-EmptyKeys $Body # Making the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCCollector"); $_} } } function Get-Incident{ [CmdletBinding()] param ( [DateTime] $StartTime, [DateTime] $EndTime, [ValidateSet("Low","Medium","High")] [System.String[]] $Severity, [ValidateSet("Incident","Deception","Network Scan","Reveal","Experimental")] $IncidentType, [String] $SourceAsset, [String] $DestinationAsset, [String] $AnySideAsset, [PSTypeName("GCLabel")] $SourceLabel, [PSTypeName("GCLabel")] $DestinationLabel, [PSTypeName("GCLabel")] $AnySideLabel, [System.Array] $IncludeTag, [System.Array] $ExcludeTag, [ValidateRange(0,1000)] $Limit = 20, [ValidateRange(0,500000)] [Int32] $Offset = 0, [String] $ID, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } # This sort is required for legacy URI building $Uri = "/incidents?sort=-start_time" } # Handling start and end time defaults if ( -not $StartTime ) { $StartTime = $(Get-Date).AddHours(-1) } if ( -not $EndTime ) { $EndTime = Get-Date } [Int64]$StartTime = $StartTime | ConvertTo-GCUnixTime [Int64]$EndTime = $EndTime | ConvertTo-GCUnixTime # Building request body with parameters $Body = @{ from_time = $StartTime to_time = $EndTime severity = $Severity incident_type = $IncidentType tag = $IncludeTag -join "," tags__not = $ExcludeTag -join "," id = $ID limit = $Limit offset = $Offset } # Removing empty keys $RequestBody = Remove-EmptyKeys $Body # This legacy URI building is actually necessary, # due to the complicated way in which the URI needs to be structured. ### SOURCE ### $Uri += "&source=" if ( $SourceLabel ) { $Uri += "labels:" $Uri += $SourceLabel.id -join "|" } if ( $SourceAsset ) { $Uri += "assets:" $Uri += $SourceAsset -join "," } if ( $Uri[$Uri.length-1] -eq "=" ) { $Uri = $Uri.SubString(0,$Uri.Length-8) } ### DESTINATION ### $Uri += "&destination=" if ( $DestinationLabel ) { $Uri += "labels:" $Uri += $DestinationLabel.id -join "|" } if ( $DestinationAsset ) { $Uri += "assets:" $Uri += $DestinationAsset -join "," } if ( $Uri[$Uri.length-1] -eq "=" ) { $Uri = $Uri.SubString(0,$Uri.Length-13) } ### ANY SIDE ### $Uri += "&any_side=" if ( $AnySideLabel ) { $Uri += "labels:" $Uri += $AnySideLabel.id -join "|" } if ( $AnySideAsset ) { $Uri += "assets:" $Uri += $AnySideAsset -join "," } if ( $Uri[$Uri.length-1] -eq "=" ) { $Uri = $Uri.SubString(0,$Uri.Length-10) } # Making the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCIncident"); $_} } } function Get-Label { [CmdletBinding()] param ( [String] $Search, [System.String] $LabelKey, [System.String] $LabelValue, [Switch] $FindMatches, [Int32] $DynamicCriteriaLimit = 10, [ValidateRange(0,1000)] [Int32] $Limit = 20, [ValidateRange(0,500000)] [Int32] $Offset, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/labels" } # Building the request body with given parameters $Body = @{ find_matches = $FindMatches:isPresent text_search = $Search key = $LabelKey value = $LabelValue dynamic_criteria_limit = $DynamicCriteriaLimit limit = $Limit offset = $Offset } # Removing empty keys $RequestBody = Remove-EmptyKeys $Body # Making the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCLabel"); $_} } } function Get-LabelGroup { param ( [String] $Key, [String] $Value, [PSTypeName("GCAsset")] $Asset, [PSTypeName("GCLabel")] $Label, [string[]] $Status, [int32] $Limit = 20, [int32] $Offset, [switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $RequestKey = $ApiKey } else { $RequestKey = $global:GCApiKey } $Uri = "/visibility/label-groups" } # Building the request body based on given parameters $Body = @{ key = $Key value = $Value assets = $Asset.id -join "," criteria = $Label.id -join "," assets_status = $Status -join "," limit = $limit offset = $offset } # Removing empty hashtable keys $RequestBody = Remove-EmptyKeys $Body # Making the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $RequestKey } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $RequestKey | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCLabelGroup"); $_} } } function Get-Policy { [CmdletBinding()] param ( [System.String] $Search, [ValidateSet("allow","alert","block","override","override_allow","override_alert","override_block")] [System.String[]] $Section = @("allow","alert","block"), [ValidateSet("UNCHANGED","CREATED","MODIFIED","DELETED")] [string[]] $State, [ValidateSet("TCP","UDP")] [System.Array] $Protocol = @("TCP","UDP"), [ValidateRange(1,65535)] [System.Array] $Port, [PSTypeName("GCLabel")] $SourceLabel, [PSTypeName("GCLabel")] $DestinationLabel, [PSTypeName("GCLabel")] $AnySideLabel, [System.Array] $SourceProcess, [System.Array] $DestinationProcess, [System.Array] $AnySideProcess, [PSTypeName("GCAsset")] $SourceAsset, [PSTypeName("GCAsset")] $DestinationAsset, [PSTypeName("GCAsset")] $AnySideAsset, [ValidateScript({ foreach ($Subnet in $_) { if ( -not ($Subnet -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|[3][0-2])") ) { throw "The subnet provided is not a valid subnet. Please provide a subnet in 0.0.0.0/0 format." } $true } })] [System.Array] $SourceSubnet, [ValidateScript({ foreach ($Subnet in $_) { if ( -not ($Subnet -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|[3][0-2])") ) { throw "The subnet provided is not a valid subnet. Please provide a subnet in 0.0.0.0/0 format." } $true } })] [System.String] $DestinationSubnet, [ValidateScript({ foreach ($Subnet in $_) { if ( -not ($Subnet -match "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|[3][0-2])") ) { throw "The subnet provided is not a valid subnet. Please provide a subnet in 0.0.0.0/0 format." } $true } })] [System.String] $AnySideSubnet, [System.String] $Ruleset, [System.String] $Comments, [Switch] $SourceInternet, [Switch] $DestinationInternet, [Switch] $AnySideInternet, [ValidateRange(0,1000)] [Int32] $Limit = 20, [ValidateRange(0,500000)] [Int32] $Offset = 0, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/policy/rules?limit=" + $Limit } # Building the request body with given parameters $Body = @{ sections = $Section -join "," protocols = $Protocol -join "," offset = $Offset search = $Search comments = $Comments ruleset = $Ruleset state = $State -join "," port = $Port -join "," } # Removing empty keys $RequestBody = Remove-EmptyKeys $Body # Legacy URI building ##### SOURCES ##### $Uri += "&source=" if ( $SourceLabel ) { $Uri += "labels:" foreach ($Group in $SourceLabel) { $Uri += $Group.id -join ">" $Uri += "|" } $Uri = $Uri.SubString(0,$Uri.length-1) #Remove trailing "|" $Uri += "," } if ( $SourceProcess ) { $Uri += "processes:" $Uri += $SourceProcess -join "|" $Uri += "," } if ( $SourceAsset ) { $Uri += "assets:" $Uri += $SourceAsset.id + "|" $Uri += "," } if ( $SourceSubnet ) { $Uri += "subnet:" + $SourceSubnet + "," } if ( $PSBoundParameters.ContainsKey("SourceInternet") ) { #checks for the existence of the parameter if ( $SourceInternet -eq $true ) { $Uri += "address_classification:Internet," } elseif ( $SourceInternet -eq $false ) { $Uri += "address_classification:Private," } } #If any above parameter was present, remove the trailing ","; if nothing above was present, remove "source=" if ( $Uri.SubString($Uri.length-1) -eq "," ) { $Uri = $Uri.SubString(0,$Uri.length-1) } else { $Uri = $Uri.SubString(0,$Uri.length-8) } ################### ##### DESTINATIONS ##### $Uri += "&destination=" if ( $DestinationLabel ) { $Uri += "labels:" foreach ($Group in $DestinationLabel) { $Uri += $Group.id -join ">" $Uri += "|" } $Uri = $Uri.SubString(0,$Uri.length-1) #Remove trailing "|" $Uri += "," } if ( $DestinationProcesses ) { $Uri += "processes:" $Uri += $DestinationProcesses -join "|" $Uri += "," } if ( $DestinationAsset ) { $Uri += "assets:" $Uri += $DestinationAsset.id -join "|" $Uri += "," } if ( $DestinationSubnet ) { $Uri += "subnet:" + $DestinationSubnet + "," } if ( $PSBoundParameters.ContainsKey("DestinationInternet") ) { if ( $DestinationInternet -eq $true ) { $Uri += "address_classification:Internet," } elseif ( $DestinationInternet -eq $false ) { $Uri += "address_classification:Private," } } #If any above parameter was present, remove the trailing ","; if nothing above was present, remove "&destination=" if ( $Uri.SubString($Uri.length-1) -eq "," ) { $Uri = $Uri.SubString(0,$Uri.length-1) } else { $Uri = $Uri.SubString(0,$Uri.length-13) } ######################## ##### ANY SIDE ##### $Uri += "&any_side=" if ( $AnySideLabel ) { $Uri += "labels:" foreach ($Group in $AnySideLabel) { $Uri += $Group.id -join ">" $Uri += "|" } $Uri = $Uri.SubString(0,$Uri.length-1) #Remove trailing "|" $Uri += "," } if ( $AnySideProcesses ) { $Uri += "processes:" foreach ($Process in $AnySideProcesses) { $Uri += $Process + "|" } $Uri = $Uri.SubString(0,$Uri.length-1) #Remove trailing "|" $Uri += "," } if ( $AnySideAsset ) { $Uri += "assets:" $Uri += $AnySideAsset -join "|" $Uri += "," } if ( $AnySideSubnet ) { $Uri += "subnet:" + $AnySideSubnet + "," } if ( $PSBoundParameters.ContainsKey("AnySideInternet") ) { #checks for the existence of the parameter if ( $AnySideInternet -eq $true ) { $Uri += "address_classification:Internet," } elseif ( $AnySideInternet -eq $false ) { $Uri += "address_classification:Private," } } #If any above parameter was present, remove the trailing ","; if nothing above was present, remove "&any_side=" if ( $Uri.SubString($Uri.length-1) -eq "," ) { $Uri = $Uri.SubString(0,$Uri.length-1) } else { $Uri = $Uri.SubString(0,$Uri.length-10) } #################### # Make the call if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCPolicy"); $_} } } function Get-RawFlow { [cmdletbinding()] param ( [DateTime] $StartTime, [DateTime] $EndTime, [System.Array] $SourceProcess, [System.Array] $DestinationProcess, [System.Array] $AnySideProcess, [System.Array] $SourceAsset, [System.Array] $DestinationAsset, [System.Array] $AnySideAsset, [System.Array] $SourceLabel, [System.Array] $DestinationLabel, [System.Array] $AnySideLabel, [Switch] $SourceInternet, [Switch] $DestinationInternet, [ValidateSet("successful","failed","redirected_to_hpvm")] $Type, [ValidateSet("allowed","alerted_by_management","blocked_by_management","blocked")] $Action, [Int32] $Limit = 20, [Int32] $Offset, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/connections?sort=slot_start_time" } # Handling default time values if ( -not $StartTime ) { $StartTime = $(Get-Date).AddHours(-1) } if ( -not $EndTime ) { $EndTime = Get-Date } # Building the request body $Body = @{ from_time = (ConvertTo-GCUnixTime $StartTime) to_time = (ConvertTo-GCUnixTime $EndTime) connection_type = $Type -join "," policy_verdict = $Action -join "," offset = $Offset limit = $Limit } # Removing empty keys $RequestBody = Remove-EmptyKeys $Body # Legacy URI building ### Source ### if ( $SourceProcess -or $SourceAsset -or $SourceLabel -or $PSBoundParameters.ContainsKey("SourceInternat") ) { $Uri += "&source=" } if ( $SourceInternet -eq $true ) { $Uri += "address_classification:Internet" } elseif ( $PSBoundParameters.ContainsKey("SourceInternet") -and ($SourceInternet -eq $false) ) { $Uri += "address_classification:Private" } if ( $SourceProcess ) { $Uri += "processes:" $Uri += $SourceProcess -Join "," } if ( $SourceAsset ) { $Uri += "assets:" $Uri += $SourceAsset.id -Join "," } if ( $SourceLabel ) { #2D array; outer group is OR, inner groups are AND $Uri += "labels:" foreach ($Group in $SourceLabel) { $Uri += $Group.id -Join ">" $Uri += "|" } $Uri = $Uri.SubString(0,$Uri.Length-1) #Removing last "|" } ### Destination ### if ( $DestinationProcess -or $DestinationAsset -or $DestinationLabel -or $PSBoundParameters.ContainsKey("DestinationInternet") ) { $Uri += "&destination=" } if ( $DestinationInternet -eq $true ) { $Uri += "address_classification:Internet" } elseif ( $PSBoundParameters.ContainsKey("DestinationInternet") -and ($DestinationInternet -eq $false) ) { $Uri += "address_classification:Private" } if ( $DestinationProcess ) { $Uri += "processes:" $Uri += $DestinationProcess -Join "," } if ( $DestinationAsset ) { $Uri += "assets:" $Uri += $DestinationAsset.id -Join "," } if ( $DestinationLabel ) { $Uri += "labels:" foreach ($Group in $DestinationLabel) { $Uri += $Group.id -Join ">" $Uri += "|" } $Uri = $Uri.SubString(0,$Uri.Length-1) #Removing last "|" } ### Any Side ### if ( $AnySideProcess -or $AnySideAsset -or $AnySideLabel ) { $Uri += "&any_side=" } if ( $AnySideProcess ) { $Uri += "processes:" $Uri += $AnySideProcess -Join "," } if ( $AnySideAsset ) { $Uri += "assets:" $Uri += $AnySideAsset.id -Join "," } if ( $AnySideLabel ) { $Uri += "labels:" foreach ($Group in $AnySideLabel) { $Uri += $Group.id -Join ">" $Uri += "|" } $Uri = $Uri.SubString(0,$Uri.Length-1) #Removing last "|" } if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCRawFlow"); $_} } } function Get-SavedMap { [CmdletBinding()] param ( [System.String] $Search, [ValidateSet("READY","IN_PROGRESS","QUEUED","CANCELLED","FAILED","EMPTY")] [System.String] $State, [ValidateSet("include_processes","time_resolution")] $Features, [PSTypeName("GCAsset")] $Asset, [PSTypeName("GCLabel")] $Label, [DateTime[]] $TimeRange, [System.String] $AuthorID, [Int32] $Limit = 20, [Int32] $Offset, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/saved-maps" } # Building request body from parameters $Body = @{ author_id = $AuthorID -join "," state = $State -join "," features = $Features -join "," included_asset_ids = $Asset.id -join "," included_label_ids = $Label.id -join "," time_range_filter = "" search = $Search limit = $Limit offset = $Offset } # Weird parameter if ( $TimeRange ) { if ( $TimeRange.count -ne 2 ) { throw "Incorrect time range syntax" } $Range0 = $TimeRange[0] | ConvertTo-GCUnixTime $Range1 = $TimeRange[1] | ConvertTo-GCUnixTime $Body.time_range_filter = $Range0 + "," + $Range1 } # Removing empty keys $RequestBody = Remove-EmptyKeys $Body if ( $Raw ) { pwsh-GC-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-GC-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCSavedMap"); $_} } } function Get-User { [cmdletbinding()] param ( [String[]] $Name, [int] $Limit = 20, [int] $Offset, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/system/users" } $Body = @{ username = $Name -join "," limit = $Limit offset = $Offset } $RequestBody = Remove-EmptyKeys $Body if ( $Raw ) { pwsh-gc-get-request -Raw -Uri $Uri -Body $RequestBody -ApiKey $Key } else { pwsh-gc-get-request -Uri $Uri -Body $RequestBody -ApiKey $Key | foreach {$_.PSTypeNames.Clear(); $_.PSTypeNames.Add("GCUser"); $_} } } function New-BlankLabel { [cmdletbinding(SupportsShouldProcess)] param ( [Parameter(Mandatory)] [String] $LabelKey, [Parameter(Mandatory)] [String] $LabelValue, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/labels" } $Body = [PSCustomObject]@{ id = $null key = $LabelKey value = $LabelValue criteria = @() } $Should = $Body.key + ": " + $Body.value if ( $PSCmdlet.ShouldProcess($Should,"pwsh-GC-post-request on $Uri with $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } function New-DynamicLabel { [CmdletBinding(SupportsShouldProcess)] param ( [System.String] $LabelKey, [System.String] $LabelValue, [System.String] $Argument, [ValidateSet("name","numeric_ip_addresses","id")] [System.String] $Field, [ValidateSet("STARTSWITH","ENDSWITH","EQUALS","CONTAINS","SUBNET","WILDCARDS")] [System.String] $Operation, [Parameter(ValueFromPipeline)] [Array] $Criteria, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/labels" } $Body = [PSCustomObject]@{ id = $null key = $LabelKey value = $LabelValue criteria = @() #This is an array of "criteria objects" that can be specified by an array of these objects from the pipeline, via the $Criteria parameter. You can also create a rule with just a single criteria by directly specifying Argument, Field, and Operation. } } process { if ( -not ($LabelKey -and $LabelValue -and (($Argument -and $Field -and $Operation) -or $Criteria)) ) { throw "Parameters required: LabelKey, LabelValue, and either one or more Criteria objects, an Argument, Field, and Operation, or a label object" } if ( $Criteria ) { $Body.criteria += $Criteria } else { $Body.criteria += [PSCustomObject]@{ argument = $Argument field = $Field op = $Operation } } } end { $Should = $Body.key + ": " + $Body.value if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-get-request -Raw -Uri $Uri -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } } function New-Policy { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory=$true)] [ValidateSet("allow","alert","block","override_allow","override_alert","override_block")] [string] $Section, [Parameter(Mandatory=$true)] [ValidateSet("allow","alert","block","block_and_alert")] [System.String] $Action, [ValidateSet("TCP","UDP")] [System.Array] $Protocol = @("TCP","UDP"), [ValidateRange(1,65535)] [System.Array] $Port, [System.Array] $PortRange, [System.Array] $SourceLabel, [System.Array] $DestinationLabel, [System.Array] $SourceProcesses, [System.Array] $DestinationProcesses, [System.Array] $SourceAsset, [System.Array] $DestinationAsset, [string[]] $SourceSubnet, [string[]] $DestinationSubnet, [System.String] $Ruleset, [System.String] $Comments, [Switch] $SourceInternet, [Switch] $DestinationInternet, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/policy/sections/" + $Section + "/rules" } $ordering_value = $null #Required to be $null by the API call $ruleset_id = $null #Required to be $null by the API call $Body = [PSCustomObject]@{ ordering_value = $ordering_value rule = [PSCustomObject]@{ ruleset_id = $ruleset_id port_ranges = @() ports = @() source = [PSCustomObject]@{} destination = [PSCustomObject]@{} ip_protocols = $Protocol action = $Action } } if ( $Port ) { $Body.rule.ports = $Port } if ( $PortRange ) { #The validation doesn't work in ValidateScript for some reason, so I'm just doing it here foreach ($P in $PortRange) { if ( $P.length -ne 2 ) { throw "Parameter PortRange: Each range must consist of starting and ending port" } foreach ($Port in $P) { if ( -not (($Port -is [int]) -and ($Port -gt 0) -and ($Port -lt 65536)) ) { throw "Parameter PortRange: Ports may only be integers from 1 to 65535" } } if ( $P[1] -le $P[0] ) { throw "Parameter PortRange: Each range's end value must be greater than its start value" } $port_range = [PSCustomObject]@{ start = $P[0] end = $P[1] } $Body.rule.port_ranges += $port_range } } if ( $SourceLabel ) { $temp = [PSCustomObject]@{} $Body.rule.source | Add-Member -MemberType NoteProperty -Name labels -Value $temp $Body.rule.source.labels | Add-Member -MemberType NoteProperty -Name or_labels -Value @() $or_labels = @() foreach ($Group in $SourceLabel) { $and_labels = [PSCustomObject]@{ and_labels = @() } foreach ($Item in $Group) { $and_labels.and_labels += $Item.id } $or_labels += $and_labels } $Body.rule.source.labels.or_labels = $or_labels } if ( $DestinationLabel ) { $temp = [PSCustomObject]@{} $Body.rule.destination | Add-Member -MemberType NoteProperty -Name labels -Value $temp $Body.rule.destination.labels | Add-Member -MemberType NoteProperty -Name or_labels -Value @() $or_labels = @() foreach ($Group in $DestinationLabel) { $and_labels = [PSCustomObject]@{ and_labels = @() } foreach ($Item in $Group) { $and_labels.and_labels += $Item.id } $or_labels += $and_labels } $Body.rule.destination.labels.or_labels = $or_labels } if ( $SourceProcesses ) { $Body.rule.source | Add-Member -MemberType NoteProperty -Name processes -Value $SourceProcesses } if ( $DestinationProcesses ) { $Body.rule.destination | Add-Member -MemberType NoteProperty -Name processes -Value $DestinationProcesses } if ( $SourceAsset ) { $Body.rule.source | Add-Member -MemberType NoteProperty -Name asset_ids -Value @($SourceAsset.id) } if ( $DestinationAsset ) { $Body.rule.destination | Add-Member -MemberType NoteProperty -Name asset_ids -Value @($DestinationAsset.id) } if ( $SourceSubnet ) { $Body.rule.source | Add-Member -MemberType NoteProperty -Name subnets -Value $SourceSubnet } if ( $DestinationSubnet ) { $Body.rule.destination | Add-Member -MemberType NoteProperty -Name subnets -Value $DestinationSubnet } if ( $PSBoundParameters.ContainsKey("SourceInternet") ) { #checks for the existence of the parameter if ( $SourceInternet -eq $true ) { $Body.rule.source | Add-Member -MemberType NoteProperty -Name address_classification -Value "Internet" } elseif ( $SourceInternet -eq $false ) { $Body.rule.source | Add-Member -MemberType NoteProperty -Name address_classification -Value "Private" } } if ( $PSBoundParameters.ContainsKey("DestinationInternet") ) { if ( $DestinationInternet -eq $true ) { $Body.rule.destination | Add-Member -MemberType NoteProperty -Name address_classification -Value "Internet" } elseif ( $DestinationInternet -eq $false ) { $Body.rule.destination | Add-Member -MemberType NoteProperty -Name address_classification -Value "Private" } } if ( $Comments ) { $Body.rule | Add-Member -MemberType NoteProperty -Name comments -Value $Comments } if ( $Ruleset ) { $Body.rule | Add-Member -MemberType NoteProperty -Name ruleset_name -Value $Ruleset } $Should = $Ruleset if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-post-request -Raw -Uri $Uri -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } function New-SavedMap{ [CmdletBinding(SupportsShouldProcess)] param ( [System.String] $Name, [Switch] $Public, [HashTable] $FilterHashTableInclude, [HashTable] $FilterHashTableExclude, [DateTime] $StartTime, [DateTime] $EndTime, [System.Array] $TimeRange, [Switch] $IncludeProcesses, [Switch] $TimeResolution, [Switch] $EmailOnProgress, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/saved-maps" } # Building the request body based on parameters $Body = [PSCustomObject]@{ name = "" map_type = 1 filters = [PSCustomObject]@{} start_time_filter = $null end_time_filter = $null include_processes = $IncludeProcesses.IsPresent time_resolution = $TimeResolution.IsPresent email_on_progress = $EmailOnProgress.IsPresent } if ( -not $StartTime ) { $Body.start_time_filter = $($(Get-Date).AddHours(-1) | ConvertTo-GCUnixTime) } else { $Body.start_time_filter = $StartTime | ConvertTo-GCUnixTime } if ( -not $EndTime ) { $Body.end_time_filter = $(Get-Date | ConvertTo-GCUnixTime) } else { $Body.end_time_filter = $EndTime | ConvertTo-GCUnixTime } if ( $Name ) { $Body.name = $Name } if ( $Public ) { $Body.map_type = 0 } if ( $FilterHashTableInclude ) { $temp = [PSCustomObject]@{} $Body.filters | Add-Member -MemberType NoteProperty -Name include -Value $temp foreach ($Hash in $FilterHashTableInclude.Keys) { $Body.filters.include | Add-Member -MemberType NoteProperty -Name $Hash -Value @($FilterHashTableInclude[$Hash]) } } if ( $FilterHashTableExclude ) { $temp = [PSCustomObject]@{} $Body.filters | Add-Member -MemberType NoteProperty -Name exclude -Value $temp foreach ($Hash in $FilterHashTableExclude.Keys) { $Body.filters.exclude | Add-Member -MemberType NoteProperty -Name $Hash -Value @($FilterHashTableExclude[$Hash]) } } if ( $TimeRange ) { if ( $TimeRange.count -ne 2 ) { throw "Incorrect time range syntax" } $Start = $TimeRange[0] | ConvertTo-GCUnixTime $End = $TimeRange[1] | ConvertTo-GCUnixTime $Body.start_time_filter = $Start $Body.end_time_filter = $End } $Should = $Name if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-post-request -Raw -Uri $Uri -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } function New-StaticLabel { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(ValueFromPipeline)] [PSTypeName("GCAsset")] $Asset, [Parameter(Mandatory)] [System.String] $LabelKey, [Parameter(Mandatory)] [System.String] $LabelValue, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/assets/labels/" + $LabelKey + "/" + $LabelValue } $Body = [PSCustomObject]@{ "vms" = @() } } process { if ( $Asset ) { $Body.vms += foreach ($ThisAsset in $Asset) { $ThisAsset.id } } } end { $Should = $LabelKey + ": " + $LabelValue if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-post-request -Raw -Uri $Uri -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } } function New-User { [cmdletbinding(SupportsShouldProcess)] param ( [Parameter(Mandatory)] [String] $Name, [String] $Description, [String] $Email, [Parameter(Mandatory)] [String[]] $Permissions, [Switch] $TwoFactor, [Parameter(Mandatory)] [String] $Password, [Switch] $IncidentPasswordAccess, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/system/user" } if ( -not $Description ) { $Description = "Created by the API" } $Body = [PSCustomObject]@{ action = "create" can_access_passwords = $IncidentPasswordAccess.IsPresent description = $Description email = $Email password = $Password password_confirm = $Password permission_scheme_ids = @($Permissions) two_factor_auth_enabled = $TwoFactor.IsPresent username = $Name } $Should = $Name if ( $PSCmdlet.ShouldProcess($Should, "pwsh-gc-post-request -Raw -Uri $Uri -ApiKey $Key") ) { pwsh-gc-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } function Publish-Policy { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [System.String] $Comments, [PSTypeName("GCApiKey")] $ApiKey ) if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/visibility/policy/revisions" } # Building the request body from parameters $Body = [PSCustomObject]@{ action = "publish" comments = $Comments } $Should = $Body.action if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-post-request -Raw -Uri $Uri -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } function Remove-Label { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(ValueFromPipeline)] [PSTypeName("GCLabel")] $Label, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } } } process { foreach ($ThisLabel in $Label) { $Uri = "/visibility/labels/" + $ThisLabel.id $Should = $Uri if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-delete-request -Uri $Uri -ApiKey $Key") ) { pwsh-GC-delete-request -Uri $Uri -ApiKey $Key } } } } function Remove-Policy { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(ValueFromPipeline)] [System.Array] $Policy, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } } $Body = [PSCustomObject]@{ action = "delete" } } process { foreach ($ThisPolicy in $Policy) { $Uri = "/visibility/policy/rules/" + $ThisPolicy.id $Should = $Uri if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } } } function Remove-SavedMap { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(ValueFromPipeline)] [PSTypeName("GCSavedMap")] $Map, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } } $Body = [PSCustomObject]@{ action = "delete" } } process { foreach ($ThisMap in $Map) { $Uri = "/visibility/saved-maps/" + $ThisMap.id $Should = [string]$Uri if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $Body -ApiKey $Key } } } } function Remove-User { [cmdletbinding(SupportsShouldProcess)] param ( [Parameter(ValueFromPipelineByPropertyName)] [String[]] $username, [Switch] $Raw, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/system/user" } } process { foreach ( $ThisUser in $Username ) { $Body = [PSCustomObject]@{ action = "delete" confirm = $true username = $ThisUser } $Should = $username if ( $PSCmdlet.ShouldProcess($Should, "pwsh-gc-post-request -Uri $Uri -Body $Body -ApiKey $Key -Raw:$Raw.IsPresent") ) { pwsh-gc-post-request -Uri $Uri -Body $Body -ApiKey $Key -Raw:$Raw.IsPresent } } } } function Set-Label { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(ValueFromPipeline)] [PSTypeName("GCLabel")] $Label ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } } } process { foreach ( $ThisLabel in $Label ) { $Uri = "/visibility/labels/" + $ThisLabel.id $RequestBody = $ThisLabel | Select-Object -ExcludeProperty id,_id $Should = $Uri if ( $PSCmdlet.ShouldProcess($Should, "pwsh-GC-post-request -Raw -Uri $Uri -Method Put -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $RequestBody -Method Put -ApiKey $Key } } } } function Set-Password { [cmdletbinding(SupportsShouldProcess)] param( [Parameter(ValueFromPipeline)] [Alias("Username","User")] [PSTypeName("GCUser")]$Name, [Parameter(Mandatory)] [String]$Password, [PSTypeName("GCApiKey")]$ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/system/user" } } process { foreach ( $ThisUser in $User ) { # Serialize/deserialize $RequestUser = $ThisUser | ConvertTo-Json -Depth 2 | ConvertFrom-Json $RequestUser | Add-Member -MemberType NoteProperty -Name "action" -Value "update" $RequestUser | Add-Member -MemberType NoteProperty -Name "password" -Value ($Password | ConvertFrom-SecureString) $RequestUser | Add-Member -MemberType NoteProperty -Name "password_confirm" -Value $Password $RequestBody = $RequestUser | Select-Object -Property action,can_access_passwords,description,email,id,permission_scheme_ids,two_factor_auth_enabled,username,password,password_confirm $Should = $ThisUser.username if ( $PSCmdlet.ShouldProcess($Should,"pwsh-GC-post-request -Raw -Uri $Uri -Method Post -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $RequestBody -Method Post -ApiKey $Key } } } } function Set-Policy { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(ValueFromPipeline)] [PSTypeName("GCPolicy")] $Policy, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } } } process { foreach ($ThisPolicy in $Policy) { # Serialize/deserialize data $PCopy = $ThisPolicy | ConvertTo-Json -Depth 99 | ConvertFrom-Json $Uri = "/visibility/policy/rules/" + $PCopy.id # Have to parse the source/destination labels to only contain IDs, # instead of all the other info that they come with from Get-GCLabel # Passing that extra info to the API errors out, # because this api call is just like the one for creating new policy, # and only uses label IDs for the source/destination if ( $PCopy.source.labels ) { $OrCount = $PCopy.source.labels.or_labels.count for ($i = 0; $i -lt $OrCount; $i++) { $AndCount = $PCopy.source.labels.or_labels[$i].and_labels.count for ($j = 0; $j -lt $AndCount; $j++) { $temp = $PCopy.source.labels.or_labels[$i].and_labels[$j].id $PCopy.source.labels.or_labels[$i].and_labels[$j] = $temp } } } if ( $PCopy.destination.labels ) { $OrCount = $PCopy.destination.labels.or_labels.count for ($i = 0; $i -lt $OrCount; $i++) { $AndCount = $PCopy.destination.labels.or_labels[$i].and_labels.count for ($j = 0; $j -lt $AndCount; $j++) { $temp = $PCopy.destination.labels.or_labels[$i].and_labels[$j].id $PCopy.destination.labels.or_labels[$i].and_labels[$j] = $temp } } } $RequestBody = $PCopy $Should = $RequestBody.ruleset_name if ( $PSCmdlet.ShouldProcess($Should,"pwsh-GC-post-request -Raw -Uri $Uri -Method Put -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $RequestBody -Method Put -ApiKey $Key } } } } function Set-User { [cmdletbinding(SupportsShouldProcess)] param( [Parameter(ValueFromPipeline)] [PSTypeName("GCUser")] $User, [PSTypeName("GCApiKey")] $ApiKey ) begin { if ( GCApiKey-present $ApiKey ) { if ( $ApiKey ) { $Key = $ApiKey } else { $Key = $global:GCApiKey } $Uri = "/system/user" } } process { foreach ( $ThisUser in $User ) { # Serialize/deserialize $RequestUser = $ThisUser | ConvertTo-Json -Depth 2 | ConvertFrom-Json $RequestUser | Add-Member -MemberType NoteProperty -Name "action" -Value "update" $RequestBody = $RequestUser | Select-Object -Property action,can_access_passwords,description,email,id,permission_scheme_ids,two_factor_auth_enabled,username $Should = $ThisUser.username if ( $PSCmdlet.ShouldProcess($Should,"pwsh-GC-post-request -Raw -Uri $Uri -Body $RequestBody -Method Post -ApiKey $Key") ) { pwsh-GC-post-request -Raw -Uri $Uri -Body $RequestBody -Method Post -ApiKey $Key } } } } function GCApiKey-present { [cmdletbinding()] param ( $ApiKey ) if ( -not ($ApiKey -or $global:GCApiKey) ) { throw "No API key present." } else { return $true } } function pwsh-GC-delete-request { [cmdletbinding()] param ( [Parameter(Mandatory)] [String]$Uri, [Parameter(Mandatory)] [PSTypeName("GCApiKey")]$ApiKey ) $RequestToken = $ApiKey.Token | ConvertTo-SecureString -AsPlainText -Force $RequestUri = $ApiKey.Uri + $Uri try { Invoke-RestMethod -Uri $RequestUri -Method Delete -Authentication Bearer -Token $RequestToken } catch { throw $_.Exception } } function pwsh-GC-get-request { [cmdletbinding()] param ( [Parameter(Mandatory)] [String]$Uri, [HashTable]$Body, [Parameter(Mandatory)] [PSTypeName("GCApiKey")]$ApiKey, [Switch]$Raw ) begin { $RequestToken = $ApiKey.Token | ConvertTo-SecureString -AsPlainText -Force $RequestUri = $ApiKey.Uri + $Uri } process { $Request = try { Invoke-RestMethod -Uri $RequestUri -Method Get -Body $Body -Authentication Bearer -Token $RequestToken } catch { throw $_.Exception } switch ($Raw) { $true { $Request } default { if ( $Request.objects ) { $Request.objects } } } } } function pwsh-GC-post-request { param ( [Parameter(Mandatory)] [String]$Uri, [PSCustomObject]$Body, [Parameter(Mandatory)] [PSTypeName("GCApiKey")]$ApiKey, [ValidateSet("Post","Put")][String]$Method = "Post", [Switch]$Raw ) $RequestToken = $ApiKey.Token | ConvertTo-SecureString -AsPlainText -Force $RequestUri = $ApiKey.Uri + $Uri $RequestBody = $Body | ConvertTo-Json -Depth 10 $Request = try { Invoke-RestMethod -Uri $RequestUri -Method $Method -Body $RequestBody -ContentType "application/json" -Authentication Bearer -Token $RequestToken } catch { throw $_.Exception } switch ($Raw) { $true { $Request } default { if ( $Request.objects ) { $Request.objects } } } } function Remove-EmptyKeys { param ( $Body ) $KeyList = New-Object -TypeName System.Collections.Generic.List[string] foreach ($HashKey in $Body.Keys) { $KeyList.Add($HashKey) } foreach ($HashKey in $KeyList) { if ([string]::isNullOrEmpty($Body[$HashKey])) { $Body.Remove($HashKey) } } $Body } Set-Alias -Name api -value Get-GCApiKey Export-ModuleMember -Function ConvertFrom-UnixTime,ConvertTo-UnixTime,Get-Agent,Get-Aggregator,Get-ApiKey,Get-Asset,Get-Collector,Get-Incident,Get-Label,Get-LabelGroup,Get-Policy,Get-RawFlow,Get-SavedMap,Get-User,New-BlankLabel,New-DynamicLabel,New-Policy,New-SavedMap,New-StaticLabel,New-User,Publish-Policy,Remove-Label,Remove-Policy,Remove-SavedMap,Remove-User,Set-Label,Set-Password,Set-Policy,Set-User -Alias api |