Forum Discussion

ddaniel's avatar
ddaniel
Icon for Staying Involved rankStaying Involved
2 hours ago

I could use some help with a Powershell script for the events feed.

For some work I am doing trying to track DHCP events, I have been looking at the Events Feed API and am having trouble getting code working in Powershell.  I know my API key/Account ID are good because I have other scripts/tasks running daily, but I am struggling on the event feed.   I would rather avoid Python because I already have other things happening in Powershell and am not very comfortable in Python.  I think I have events enabled in my account correctly.

I asked ChatGPT to review my efforts and add debugging and this is my current script.  It returns 0 events.  you can toggle $DEBUG_MODE = $true/$false as needed

Can someone let me know if you return results with this code?  thanks.

# start script -----------------------------------------------------------------------------

# ====== CONFIGURATION ======
$API_URL    = "https://api.catonetworks.com/api/v1/graphql2"
$API_KEY    = "YOUR_CATO_API_KEY"
$ACCOUNT_ID = "YOUR_ACCOUNT_ID"

$DEBUG_MODE = $true
$MAX_LOOPS  = 3
# ===========================

$query = @"
query EventsFeed(`$accountIDs: [ID!], `$marker: String) {
  eventsFeed(accountIDs: `$accountIDs, marker: `$marker) {
    marker
    fetchedCount
    accounts {
      id
      records {
        time
        fieldsMap
      }
    }
  }
}
"@

function Write-DebugLog {
    param(
        [string]$Message,
        $Data = $null
    )

    if (-not $DEBUG_MODE) { return }

    Write-Output "[DEBUG] $Message"

    if ($null -ne $Data) {
        try {
            if ($Data -is [string]) {
                Write-Output $Data
            }
            else {
                $json = $Data | ConvertTo-Json -Depth 20
                Write-Output $json
            }
        }
        catch {
            Write-Output "[DEBUG] Could not serialize debug data."
            Write-Output ($Data | Out-String)
        }
    }

    Write-Output ("=" * 80)
}

function Print-Event {
    param($Record)

    $timeStr = $Record.time
    try {
        $dt = [datetime]::Parse($Record.time)
        $timeStr = $dt.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss 'UTC'")
    }
    catch {}

    $f = $Record.fieldsMap

    Write-Output "[$timeStr] $($f.event_type) / $($f.event_sub_type): $($f.message)"
    Write-Output "  User: $($f.user_display_name)"
    Write-Output "  App:  $($f.application)"
    Write-Output "  Src:  $($f.src_ip)"
    Write-Output "  Dst:  $($f.dest_ip)"
    Write-Output ("-" * 80)
}

function Fetch-Events {
    $headers = @{
        "x-api-key"    = $API_KEY
        "Content-Type" = "application/json"
    }

    $marker = ""
    $totalEvents = 0
    $loopCount = 0

    while ($true) {
        $loopCount++
        if ($loopCount -gt $MAX_LOOPS) {
            Write-Output "[INFO] Reached MAX_LOOPS limit ($MAX_LOOPS)."
            break
        }

        $variables = @{
            accountIDs = @($ACCOUNT_ID)
            marker     = $marker
        }

        $bodyObject = @{
            query     = $query
            variables = $variables
        }

        $body = $bodyObject | ConvertTo-Json -Depth 20

        try {
            Write-DebugLog "Request URI" $API_URL
            Write-DebugLog "Request headers" @{
                "x-api-key"    = "***REDACTED***"
                "Content-Type" = "application/json"
            }
            Write-DebugLog "Request variables" $variables
            Write-DebugLog "Request body object" $bodyObject
            Write-DebugLog "Request body JSON" $body

            $response = Invoke-RestMethod `
                -Uri $API_URL `
                -Method Post `
                -Headers $headers `
                -Body $body `
                -TimeoutSec 30

            Write-DebugLog "Parsed API response" $response
        }
        catch {
            Write-Error "[ERROR] API request failed: $($_.Exception.Message)"

            if ($_.ErrorDetails -and $_.ErrorDetails.Message) {
                Write-Output "[DEBUG] ErrorDetails:"
                Write-Output $_.ErrorDetails.Message
                Write-Output ("=" * 80)
            }

            break
        }

        if ($response.errors) {
            Write-Error "[ERROR] API returned GraphQL errors."
            Write-DebugLog "GraphQL errors" $response.errors
            break
        }

        if (-not $response.data) {
            Write-Output "[DEBUG] Response has no 'data' property."
            Write-DebugLog "Full parsed response" $response
            break
        }

        $feed = $response.data.eventsFeed
        if (-not $feed) {
            Write-Output "[DEBUG] Response has no 'data.eventsFeed'."
            Write-DebugLog "Full parsed response" $response
            break
        }

        Write-DebugLog "eventsFeed object" $feed

        $batchCount = 0

        if (-not $feed.accounts) {
            Write-Output "[DEBUG] eventsFeed.accounts is null or empty."
        }
        else {
            Write-Output "[DEBUG] Number of accounts returned: $($feed.accounts.Count)"
        }

        foreach ($account in $feed.accounts) {
            Write-Output "[DEBUG] Inspecting account id: $($account.id)"

            if (-not $account.records) {
                Write-Output "[DEBUG] No records returned for this account."
                continue
            }

            Write-Output "[DEBUG] Records returned for account $($account.id): $($account.records.Count)"

            foreach ($record in $account.records) {
                if ($DEBUG_MODE -and $batchCount -lt 3) {
                    Write-DebugLog "Sample record" $record

                    if ($record.fieldsMap) {
                        Write-DebugLog "Sample fieldsMap keys" ($record.fieldsMap.PSObject.Properties.Name)
                    }
                }

                Print-Event $record
                $totalEvents++
                $batchCount++
            }
        }

        Write-Output "[INFO] Batch fetched: $($feed.fetchedCount)"
        Write-Output "[DEBUG] Batch printed: $batchCount"
        Write-Output "[DEBUG] Next marker: $($feed.marker)"

        if (($feed.fetchedCount -eq 0) -or [string]::IsNullOrWhiteSpace($feed.marker)) {
            Write-Output "[INFO] Stopping because fetchedCount is 0 or marker is empty."
            break
        }

        $marker = $feed.marker
    }

    Write-Output "[INFO] Total events retrieved: $totalEvents"
}

Fetch-Events


# end script -----------------------------------------------------------------------------

No RepliesBe the first to reply