Recent Discussions
Is there a way to monitor CATO IPSec degraded status
Hello, We recently enhanced our resilience on CATO side by switching from a single IPSec peering tunnel to a dual active/passive IPSec tunnel, enabling automatic failover in case of POP incident. However, monitoring via the basic API request does not return a “Degraded” status; it only returns ‘Connected’ or “Disconnected”. The API request uses the Account Snapshot one. Investigating deeper in the CATO API, it doesn't seem possible to get the “Degraded” status for IPSec connectivity. Is this a limitation of the API? Is an update to the API on CATO’s roadmap to monitor this status ? Looking forward to your response. CorentinSolvedInfraTeam1 month agoMaking Connections297Views0likes5CommentsI 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 -----------------------------------------------------------------------------Solvedddaniel1 month agoStaying Involved329Views1like8CommentsPermission errors when testing Cato API with Python
HI all, I am currently working on a project to automate workflows in Cato with Python. I've already set and reviewed my API permissions and they should already inherit my account which is able to edit and view most of the resources. However, I still get this error: HTTP 200 { "errors": [ { "message": "permission denied", "path": [ "licensing", "licensingInfo" ], "extensions": { "code": "Code104" } } ], "data": { "licensing": { "licensingInfo": null } } } I've been scouting the documentation on specific troubleshooting steps but I couldn't seem to find the answers i'm looking for. Any chance some folks could give me a quick guide on how to ensure I get the right permissions for my API keys? This is the sample script i'm testing btw, it is to pull available licensing information for monitoring. API_KEY = os.getenv("CATO_API_KEY") API_URL = "https://api.catonetworks.com/api/v1/graphql2" QUERY = """ { licensing(accountId: <ID_HERE>) { licensingInfo { globalLicenseAllocations { ztnaUsers { total allocated available } } } } } """ async def main(): headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } async with aiohttp.ClientSession(headers=headers) as session: async with session.post(API_URL, json={"query": QUERY}) as resp: print("HTTP", resp.status) print(json.dumps(await resp.json(), indent=4)) asyncio.run(main())SolvedElmark3 months agoJoining the Conversation303Views0likes6CommentsTerraform: IPsec site creation with Responder-only and destination type FQDN possible?
Hi, see subject. When trying to setup an ipsec site (IKEv2) in responder only mode and with destination type FQDN for primary and secondary tunnel, terraform (in fact opentofu), gives this error: │ Error: Cato API error in SiteAddIpsecIkeV2SiteTunnels │ │ with cato_ipsec_site.Vienna, │ on main.tf line 73, in resource "cato_ipsec_site" "Vienna": │ 73: resource "cato_ipsec_site" "Vienna" { │ │ {"networkErrors":{"code":422,"message":"Response body {\"errors\":[{\"message\":\"input: │ variable.updateIpsecIkeV2SiteTunnelsInput.primary.tunnels[0].tunnelId is not a valid │ IPSecV2InterfaceId\",\"path\":[\"variable\",\"updateIpsecIkeV2SiteTunnelsInput\",\"primary\",\"tunnels\",0,\"tunnelId\"]}],\"data\":null}"},"graphqlErrors":[{"message":"input: │ variable.updateIpsecIkeV2SiteTunnelsInput.primary.tunnels[0].tunnelId is not a valid │ IPSecV2InterfaceId","path":["variable","updateIpsecIkeV2SiteTunnelsInput","primary","tunnels",0,"tunnelId"]}]} ╵ That appears when adding the "tunnels" section. Without that section, a deployment if possible. Obviously, the tunnels section is required. --------------------snip-------------------- connection_mode = "RESPONDER_ONLY" identification_type = "IPV4" primary = { destination_type = "FQDN" tunnels = [ { public_site_ip = "10.10.10.10" psk = "abcABC1234567!!" //last_mile_bw = { //downstream = 10 //upstream = 10 } ] } ---------------snap------------------------------------- Is that supported with the terraform provider currently? Thanks, ChristianSolvedDeckel5 months agoJoining the Conversation259Views0likes4CommentsHow to get license id ?
Hi, I want to use the assignSiteBwLicense mutation to automate site licensing, but I cannot find the correct licenseId to pass in the input. Mutation I want to use: mutation assignSiteBwLicense($accountId: ID!, $input: AssignSiteBwLicenseInput!) { sites(accountId: $accountId) { assignSiteBwLicense(input: $input) { license { __typename id sku ... on SiteLicense { site { id } total } } } } } Variables: { "accountId": "123", "input": { "site": { "input": "123" }, // <-- I have the correct Site ID and Account ID "licenseId": "???", // <-- MISSING: How to find this ID? Troubleshooting steps: I tried using the pool ID seen in browser debug ("4436"), but the mutation returns "internal upstream error". I tried listing licenses via licensing { bwLicenses } but the query fails (field does not exist). I tried accountManagement { licenses } but it returns empty or generic IDs. Question: Which query should I use to get the specific licenseId required for this mutation? Thanks for your helpSolvedSR5 months agoJoining the Conversation112Views0likes1CommentReporting on Max amount of licenses reached
It's rather embarrassing to run out of SDP licenses as it provides for a negative new joiner experience when their Cato connection won't come up as expected. As Cato in their wisdom has decided there is no need to alert admins when the license count is reached (they'd probably rather we waste money purchasing a sufficient surplus of said licenses), is there a way to use the API to query for this status? Yes, I submitted an RMA for this last year that went nowhere. And yes, I know we can probably hack something together on our end that statically compares the number of licenses to the membership count in our provisioning groups. But this feels like it should be a basic feature of a SaaS service, especially as there is a hard stop when the license count is reached.SolvedJM1 year agoStaying Involved234Views1like4CommentsPull network rules via API
Hi community, I am trying to pull network settings for several sites. To be more precise, I would like to create a list of bypass rules per site. I tried the following query with empty results: query entityLookup ($accountID: ID!, $type: EntityType!, $parent: EntityInput!) { entityLookup (accountID: $accountID, type: $type, parent: $parent) { items { entity { id name type } description helperFields } } } { "accountID": "{{accountID}}", "type": "localRouting", "parent": { "id": 0, "type": "site" } } Other "type" like lanFirewall worked. Any suggestions how to proceed and get details about bypass ruleset per site?SolvedPhil1 year agoJoining the Conversation191Views1like3CommentsIs there an API applicable to IP Ranges in the Resources topic?
Hello. We need to create about 4,000 objects in IP Ranges, is there an API available for this? thanks.SolvedESCARE-Team1 year agoMaking Connections435Views0likes13CommentsBulk import error: Concurrent edits in account for Site
Hi Guys, We need to import static hosts reservations into CATO. I found this helpful documentation: https://registry.terraform.io/providers/catonetworks/cato/latest/docs/guides/guide_cato_static_host_from_csv However when running the import for multiple hosts I'm getting the following error: The first host is created successfully, however the others are not working because of error: Concurrent edits in account for Site Any ideas on how to solve this?SolvedNielsn1 year agoJoining the Conversation169Views0likes2CommentsAdd Interface Subnets to User Defined Groups
Hi, using the Cato API is it possible to add Site Interface Subnets to a user defined group? The use case here would be to create a script that creates a Site, creates routes networks, and then adds those routed networks to several groups. I checked the API documentation, but didn't see any options initially. Thanks!SolvedJeremy1 year agoJoining the Conversation218Views1like3Comments