Resources/Locations-GET.ps1

function Get-S1Locations {
<#
    .SYNOPSIS
        Get the locations of Agents in a given scope that match the filter.
 
    .DESCRIPTION
        The Get-S1Locations cmdlet gets the locations of Agents in a given scope that match the filter.
 
        Agent locations are based on endpoint network parameters
            IP, DNS, NIC, Registry Key,
            or SentinelOne connection set for all true, at least one true,
            or none true and applied to a Site, Account, or Global
 
        Agents detect their location settings and apply Firewall Control rules that have Location Aware parameters
        that match the Agent location. Agents can be in multiple locations at the same time.
        If an Agent that supports Locations does not detect that it is in a defined location,
        it uses the Firewall rules assigned to the Fallback location.
 
        Use this command with a filter for "hasFirewallRules" to find Locations that do not have matching Firewall Control rules.
        The response to this request includes the ID of the location, which you can use in other commands.
 
        Firewall Control and Location Awareness require Control SKU.
 
    .PARAMETER accountIds
        List of Account IDs to filter by.
 
        Example: "225494730938493804,225494730938493915".
 
    .PARAMETER countOnly
        If true, only total number of items will be returned, without any of the actual objects.
 
    .PARAMETER creator__contains
        Free-text filter by creator of the location
 
        Example: "max,mike".
 
    .PARAMETER cursor
        Cursor position returned by the last request. Use to iterate over more than 1000 items.
 
        Found under pagination
 
        Example: "YWdlbnRfaWQ6NTgwMjkzODE=".
 
    .PARAMETER description__contains
        Free-text filter by description
 
        Example: "out of office".
 
    .PARAMETER groupIds
        List of Group IDs to filter by.
 
        Example: "225494730938493804,225494730938493915".
 
    .PARAMETER hasFirewallRules
        Filter by locations with/without firewall rules associated to them
 
    .PARAMETER hostname__contains
        Free-text filter by hostname
 
        Example: "sentinelone.com,localhost".
 
    .PARAMETER ids
        Filter results by location IDs.
 
        Example: "225494730938493804,225494730938493915".
 
    .PARAMETER ipAddress__contains
        Free-text filter by IP address
 
        Example: "29.213.22.17".
 
    .PARAMETER limit
        Limit number of returned items (1-1000).
 
        Example: "10".
 
    .PARAMETER name__contains
        Free-text filter by location name
 
        Example: "office".
 
    .PARAMETER registryKey__contains
        Free-text filter by registry key
 
        Example: "system\software,sentinel".
 
    .PARAMETER scopeName__contains
        Free-text filter by scope name
 
        Example: "my_group,my_site".
 
    .PARAMETER scopes
        Filter results by scope.
 
        Allowed values
        'account', 'global', 'group', 'site'
 
    .PARAMETER siteIds
        List of Site IDs to filter by.
 
        Example: "225494730938493804,225494730938493915".
 
    .PARAMETER skip
        Skip first number of items (0-1000). To iterate over more than 1000 items, use "cursor".
 
        Example: "150".
 
    .PARAMETER skipCount
        If true, total number of items will not be calculated, which speeds up execution time.
 
    .PARAMETER sortBy
        Sorts the returned results by a defined value
 
        Allowed values:
        'id', 'scope'
 
    .PARAMETER sortOrder
        Sort direction
 
        Allowed values:
        'asc', 'desc'
 
    .EXAMPLE
        Get-S1Locations
 
        Returns the first 10 locations
 
    .EXAMPLE
        Get-S1Locations -countOnly
 
        Returns the number of locations without any data that match a filter.
 
    .EXAMPLE
        Get-S1Locations -siteIds 225494730938493804 -scopes global
 
        Returns the first 10 locations from the defined siteIds that are applied from a global scope down
 
    .EXAMPLE
        Get-S1Locations -cursor 'YWdlbnRfaWQ6NTgwMjkzODE='
 
        Returns data after the first 10 results
 
        The cursor value can be found under pagination
 
    .NOTES
        N\A
 
    .LINK
        https://celerium.github.io/SentinelOne-PowerShellWrapper/site/Locations/Get-S1Locations.html
 
#>


    [CmdletBinding( DefaultParameterSetName = 'index' )]
    Param (
        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [Int64[]]$accountIds,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [Switch]$countOnly,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String[]]$creator__contains,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String]$cursor,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String[]]$description__contains,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [Int64[]]$groupIds,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [Switch]$hasFirewallRules,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String[]]$hostname__contains,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [Int64[]]$ids,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String[]]$ipAddress__contains,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateRange(1, 1000)]
        [Int64]$limit,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String[]]$name__contains,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String[]]$registryKey__contains,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [String[]]$scopeName__contains,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateSet( 'account', 'global', 'group', 'site' )]
        [String[]]$scopes,

        [Parameter( Mandatory = $false, ValueFromPipeline = $true, ParameterSetName = 'index' )]
        [ValidateNotNullOrEmpty()]
        [Int64[]]$siteIds,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateRange(1, 1000)]
        [Int64]$skip,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [Switch]$skipCount,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateSet( 'id', 'scope' )]
        [String]$sortBy,

        [Parameter( Mandatory = $false, ParameterSetName = 'index' )]
        [ValidateSet( 'asc', 'desc' )]
        [String]$sortOrder

    )

    process {

        Write-Verbose "Running the [ $($PSCmdlet.ParameterSetName) ] parameterSet"

        Switch ($PSCmdlet.ParameterSetName){
            'index'  {$resource_uri = "/locations"}
        }

        $excludedParameters =   'Debug','ErrorAction','ErrorVariable','InformationAction',
                                'InformationVariable','OutBuffer','OutVariable','PipelineVariable',
                                'Verbose','WarningAction','WarningVariable'

        $body = @{}

        ForEach ( $Key in $PSBoundParameters.GetEnumerator() ){

            if( $excludedParameters -contains $Key.Key ){$null}
            elseif ( $Key.Value.GetType().IsArray ){
                Write-Verbose "[ $($Key.Key) ] is an array parameter"
                $body += @{ $Key.Key = $Key.Value -join (',') }
            }
            elseif ( $Key.Value.GetType().FullName -eq 'System.DateTime' ){
                Write-Verbose "[ $($Key.Key) ] is a dateTime parameter"
                $universalTime = ($Key.Value).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.ffffffZ')

                Write-Verbose "Converting [ $($Key.Value) ] to [ $universalTime ]"
                $body += @{ $Key.Key = $universalTime }
            }
            else{
                $body += @{ $Key.Key = $Key.Value }
            }

        }

        try {
            $ApiToken = Get-S1APIKey -PlainText
            $S1_Headers.Add('Authorization', "ApiToken $ApiToken")

            $rest_output = Invoke-RestMethod -Method Get -Uri ( $S1_Base_URI + $resource_uri ) -Headers $S1_Headers -Body $body -ErrorAction Stop -ErrorVariable rest_error
        } catch {
            Write-Error $_
        } finally {
            [void] ( $S1_Headers.Remove('Authorization') )
        }

        $data = @{}
        $data = $rest_output
        return $data

    }

}