functions/Get-XdrAdvancedHuntingFunction.ps1

function Get-XdrAdvancedHuntingFunction {
    <#
    .SYNOPSIS
        Retrieves Advanced Hunting functions from Microsoft Defender XDR.

    .DESCRIPTION
        Gets saved functions for Advanced Hunting queries in Microsoft Defender XDR.
        Functions can be filtered by ID or retrieved all at once.
        This function includes caching support with a 30-minute TTL to reduce API calls.

    .PARAMETER Id
        Optional ID of a specific function to retrieve.
        If not specified, all functions will be returned.

    .PARAMETER Force
        Bypasses the cache and forces a fresh retrieval from the API.

    .EXAMPLE
        Get-XdrAdvancedHuntingFunction
        Retrieves all Advanced Hunting functions using cached data if available.

    .EXAMPLE
        Get-XdrAdvancedHuntingFunction -Force
        Forces a fresh retrieval of all functions, bypassing the cache.

    .EXAMPLE
        Get-XdrAdvancedHuntingFunction -Id 6
        Retrieves a specific function by ID.

    .EXAMPLE
        Get-XdrAdvancedHuntingFunction | Where-Object { $_.IsShared -eq $true }
        Retrieves only shared functions.

    .EXAMPLE
        Get-XdrAdvancedHuntingFunction | Where-Object { $_.Path -like "MyFolder*" }
        Retrieves functions in a specific folder path.

    .OUTPUTS
        Object[]
        Returns an array of Advanced Hunting function objects containing:
        - Id: Unique identifier for the function
        - Name: Function name
        - Body: KQL query body
        - Description: Function description
        - Path: Folder path
        - IsShared: Sharing status
        - CreatedBy: Creator's UPN
        - LastUpdatedBy: Last updater's UPN
        - LastUpdateTime: Last update timestamp
        - InputParameters: Function parameters (if any)
        - OutputColumns: Schema of the function output
        - IsReadOnly: Whether the function is read-only
    #>

    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$Id,

        [Parameter()]
        [switch]$Force
    )

    begin {
        Update-XdrConnectionSettings
    }

    process {
        # If ID is specified, query the specific function directly
        if ($PSBoundParameters.ContainsKey('Id')) {
            Write-Verbose "Retrieving specific function with ID: $Id"
            $Uri = "https://security.microsoft.com/apiproxy/mtp/huntingService/functions/defender/savedfunctions/$Id"
            
            try {
                $result = Invoke-RestMethod -Uri $Uri -Method Get -ContentType "application/json" -WebSession $script:session -Headers $script:headers
                return $result
            } catch {
                Write-Warning "No function found with ID: $Id"
                return $null
            }
        }

        # Otherwise, retrieve all functions with caching
        Write-Warning "Without specifying an ID, all functions will be retrieved but the KQL query will not be included in the output."
        $currentCacheValue = Get-XdrCache -CacheKey "XdrAdvancedHuntingFunction" -ErrorAction SilentlyContinue
        if (-not $Force -and $currentCacheValue.NotValidAfter -gt (Get-Date)) {
            Write-Verbose "Using cached XDR Advanced Hunting functions"
            $result = $currentCacheValue.Value
        } elseif ($Force) {
            Write-Verbose "Force parameter specified, bypassing cache"
            Clear-XdrCache -CacheKey "XdrAdvancedHuntingFunction"
        }
        
        if (-not $result) {
            Write-Verbose "XDR Advanced Hunting functions cache is missing or expired"
            
            $Uri = "https://security.microsoft.com/apiproxy/mtp/huntingService/savedFunctions"
            Write-Verbose "Retrieving XDR Advanced Hunting functions"
            try {
                $result = Invoke-RestMethod -Uri $Uri -Method Get -ContentType "application/json" -WebSession $script:session -Headers $script:headers
            } catch {
                Write-Error "Failed to retrieve Advanced Hunting functions: $_"
                $result = @()
            }

            if ($null -eq $result) {
                $result = @()
            }

            Write-Verbose "Retrieved $($result.Count) Advanced Hunting function(s)"
            Set-XdrCache -CacheKey "XdrAdvancedHuntingFunction" -Value $result -TTLMinutes 30
        }

        return $result
    }

    end {

    }
}