Skip to content

Block Unapproved AI Through Your Palo Alto Firewall

CyberArmor publishes your AI policy as External Dynamic Lists (EDLs) — plain-text lists your PAN-OS firewall fetches on a schedule and enforces in an ordinary security policy. Nothing installs on any endpoint, list updates need no firewall commit, and turning it off is deleting one rule. If you run Palo Alto, this is the fastest CyberArmor control you can deploy.

What you get per tenant:

List Contents
unapproved-ai-domains every AI service in CyberArmor's catalog except the providers you have approved
blocked-by-incident destinations added by incident response, each with an expiry (default 24 h)
custom lists anything you manage through the CyberArmor admin API

Prerequisites

Requirement Detail
PAN-OS 9.x or newer (EDL type Domain)
Reachability the firewall's management plane can reach your CyberArmor host on 443
Credentials an EDL fetch token minted by your CyberArmor operator (below)
Approvals your approved AI providers set in policy — otherwise the derived list refuses to serve (see Failure behavior)

1. Mint the fetch token (CyberArmor side)

curl -sX POST https://<cyberarmor-host>/admin/<tenant-id>/token \
  -H "x-api-key: $EDL_API_SECRET"

The token is shown exactly once. It is a fetch-only credential: it cannot read or change anything but the tenant's own list contents.

Then set the tenant's approved providers. They live in a policy artifact named approved-ai-providers (kind keyword_list) whose items are catalog service names — e.g. "OpenAI", "Anthropic":

curl -sX POST https://<cyberarmor-host>/policies/artifacts \
  -H "x-api-key: $POLICY_API_SECRET" -H "Content-Type: application/json" \
  -d '{"tenant_id":"<tenant-id>","name":"approved-ai-providers",
       "kind":"keyword_list","items":["Anthropic"]}'

An absent artifact means "no provider is approved" — a definite answer, not a failure. Verify what will be served before the firewall ever fetches it:

curl -s "https://<cyberarmor-host>/admin/<tenant-id>/preview?list_name=unapproved-ai-domains" \
  -H "x-api-key: $EDL_API_SECRET"

The preview is exactly the firewall's view, plus the counts a plain-text response cannot carry (total, cap, anything dropped).

2. Create the EDL object (firewall side)

Objects → External Dynamic Lists → Add

Field Value
Type Domain List
Source https://<cyberarmor-host>/edl/<tenant-id>/unapproved-ai-domains
Server Authentication Basic — username <tenant-id>, password = the minted token
Check for updates Five Minute
Expand for subdomains enable, if your PAN-OS version offers it

Repeat for blocked-by-incident. If your device cannot send Basic auth on EDL sources, append ?token=<token> to the URL instead — it works, but the token then appears in URL logs on both sides, so prefer Basic where possible.

Use Test Source URL on the EDL object, then check Objects → External Dynamic Lists → List Entries shows entries after the first refresh.

3. Enforce it — alert-only first week, then block

Create a security rule (or two) referencing the EDL as the destination:

  1. Week one — alert only. Action Allow with a log-forwarding profile, or action Alert where available, destination = the EDL. You see exactly what would have been blocked, and who, before anything breaks. Review the traffic log filtered to the rule; move genuinely-needed providers into your approved list in CyberArmor policy — the next EDL refresh removes them from the block list, no commit needed.
  2. Then — block. Flip the rule action to Deny. From here, approving a provider in CyberArmor policy unblocks it within one refresh interval, and an incident-response block lands the same way — no change window, no commit.

Order both rules above any general-allow web rule.

Failure behavior — read this before relying on it

  • CyberArmor unreachable at refresh time: PAN-OS keeps enforcing the last list it fetched. Nothing flaps.
  • CyberArmor's policy service is down internally: the EDL serves the last known approved-provider set and reports its staleness on the status API.
  • CyberArmor has never successfully read your approvals: the derived list returns 503 and serves nothing rather than guessing — a guessed full-catalog list would block providers you approved; a guessed empty list would block nothing while claiming coverage. Note the distinction: an artifact that is absent is an answer (nothing approved, block everything cataloged); only a policy service CyberArmor cannot reach at all produces the 503.
  • List larger than the cap (50 000 entries by default): the served list is a deterministic sorted prefix and the truncation is visible in the status API and metrics. You will not silently lose the tail.

Verifying it end to end

curl -s "https://<cyberarmor-host>/admin/<tenant-id>/status" -H "x-api-key: $EDL_API_SECRET"

lists[].last_fetched_at and fetch_count record the firewall's actual pulls — configured and fetching are different states, and this is the field that tells them apart. On the firewall, List Entries on the EDL object shows what it holds right now.

Scope, stated plainly

This control blocks destinations by domain at your perimeter. It does not see the process or user behind a connection (that is telemetry correlation, a separate capability), does not cover endpoints that leave your network, and a determined user can still reach a provider by IP or through a tunnel your firewall permits. It is the fastest way to turn "we have no control over AI egress" into "unapproved AI services are blocked at the firewall, and approving one is a policy click" — it is not endpoint DLP, and does not claim to be.


Sending your firewall logs to CyberArmor — authenticate the feed

The EDL above is CyberArmor → your firewall. The reverse direction (your firewall's logs → CyberArmor) has a choice worth making deliberately.

Plain syslog identifies your firewall by its source address. That is a routing lookup, not a proof of identity: a UDP source address can be forged, and because your firewall's egress address is shared by everything behind that NAT, an address identifies a network rather than a device. Anyone who can reach the port and knows the address could write invented events into your tenant — invented hosts, invented users — and so manufacture findings naming your staff.

Use mutual TLS (RFC 5425, port 6514). Your firewall presents a client certificate issued by your own CA; CyberArmor resolves the tenant from that certificate and never looks at the address. Practical consequences: the feed keeps working when the firewall's address changes or fails over, and a device that has not been issued a certificate cannot write into your tenant at all.

  1. Issue a client certificate to the firewall from your CA.
  2. Give CyberArmor your CA (so it can verify the certificate) and register the certificate's subject against the source — e.g. CN=fw01,O=YourCo.
  3. Point the firewall's syslog server profile at port 6514 with TLS and that client certificate. [VERIFY: the exact PAN-OS certificate-profile steps against your PAN-OS version's docs at configuration time.]

Check which mode each feed is really using — CyberArmor will tell you rather than leaving you to assume:

curl -s "https://<cyberarmor-host>/admin/<tenant-id>/sources" \
  -H "x-api-key: $TELEMETRY_API_SECRET"

Each source reports auth: "client_certificate" or auth: "source_address".

If your sender cannot do client certificates (some appliances cannot), carry plain syslog inside a VPN or IPsec tunnel instead, and restrict the port to the tunnel. That way the address CyberArmor trusts is one only your peer can present. Exposing plain syslog directly to the internet is the one option we would argue against.