Fortinet FortiGate / FortiManager
Pulls firmware state, FortiGuard subscription health, firewall policy, VPN user config, IPS / botnet log hits, and SD-WAN link health from FortiGate (or FortiManager) to derive network-security KRIs across patch cadence, policy hygiene, and real-time threat signal.
At a glance
| Vendor | Fortinet — FortiGate (NGFW) or FortiManager (central management). Same REST API shape on both; FortiManager acts as a proxy to the managed device set. |
|---|---|
| Source type | network |
| Vendor ID (slug) | fortigate-fortimanager |
| Base URL | Per-tenant — https://<your-fortigate>.company.com or the FortiManager management URL. No trailing slash or path. |
| Auth method | api-key — FortiGate REST API accepts Authorization: Bearer <token>, which is exactly what Draxis's dispatcher emits for the api-key authType. No header override needed. |
| Schedule default | daily — override to hourly if you want tighter response on the botnet C&C and SD-WAN-health KRIs. |
| Licensing | Core KRIs (firmware lag, policy hygiene, VPN users) work on any FortiGate. Botnet C&C detection requires an active FortiGuard IPS subscription; web-filtering KRI benefits from a FortiGuard Web Filter subscription; SD-WAN health KRI only populates on devices with SD-WAN members configured. Unlicensed / unconfigured features record 0 with a warn log. |
| Availability | New in 2026.04. |
Required scopes & roles
FortiGate has a dedicated REST API Admin account type — separate from human admin users. Tokens inherit the profile attached to the REST API admin at creation and use a mandatory Trusted Host IP allowlist.
- Create an admin-profile with read-only access to:
system,fwgrp(firewall),vpngrp,loggrp,fortiview,utmgrp. All other scopes: Deny. No write, no execute. - Attach that profile to the REST API Admin user (admin type REST API Admin, not Regular).
- Trusted Hosts: set to the Draxis runner's egress IP range. FortiGate rejects API calls from any IP not in this list — there is no "allow all" option for REST API admins, which is good security hygiene but means you must know your egress range before setup.
Do not use a regular admin account with "API access" toggled on. That pattern works but the token inherits the admin's full CLI/webUI privileges — if the token leaks, the blast radius is your entire FortiGate config. REST API Admin type is locked to API-only access with no interactive login path.
Setup steps
- Create a custom admin profile. In the FortiGate web UI, System → Admin Profiles → Create New. Name:
draxis-readonly. Set every permission to None, then enable Read on: System, Firewall, VPN, Log & Report, FortiView, Security Profile. Save. - Create the REST API admin. System → Administrators → Create New → REST API Admin. Username:
draxis-connector. Admin Profile:draxis-readonly(from step 1). PKI Group: leave off. CORS Allow Origin: leave blank. - Configure Trusted Hosts. On the same admin, add Trusted Hosts entries for the Draxis runner's egress IP range. FortiGate requires at least one entry — there is no wildcard. If you don't know the egress range, check Draxis platform docs or open a support request to retrieve it.
- Generate the API token. After saving the admin, FortiGate shows the New API key modal with the token value. Copy it immediately — it is shown once and cannot be retrieved later. Store in your password manager. If lost, regenerate via Administrators → draxis-connector → Generate New API Key.
- Verify connectivity from the Draxis runner. Before wiring up Draxis:
Should printcurl -sk -H "Authorization: Bearer <token>" \ 'https://<your-fortigate>/api/v2/monitor/system/status' \ | jq '.status, .results.version'"success"and your FortiOS version. If you get 401, the Trusted Hosts list doesn't include the calling IP. If 403, the admin profile is missing a required scope.
Wire it into Draxis
- Open Settings → Integrations in your tenant.
- Click Add integration and pick Network Security as the source type.
- Pick Fortinet FortiGate / FortiManager from the vendor dropdown. Draxis pre-fills the auth method and daily schedule.
- In API Base URL, paste your FortiGate (or FortiManager) management URL — e.g.
https://fortigate.acme.com. No trailing slash or path. - In API Key / Token, paste the REST API token from step 4. Draxis encrypts it server-side with
encryption.keybefore storage. - Click Test. Green means Draxis reached
/api/v2/monitor/system/statussuccessfully — the message includes your FortiOS version, build number, and hostname. - Under KRIs to import, tick the KRIs you want Draxis to manage. All seven
fg_*KRIs are checked by default; uncheck the botnet C&C and SD-WAN KRIs if you don't have FortiGuard IPS or SD-WAN configured (otherwise they report 0, which can look like a clean posture). Selected rows are created on save. Unchecking a previously-imported KRI deletes it on save. - Save. The connector runs
dailyby default; use Run now from run history to trigger the first sync immediately.
KRIs produced
| Slug | Meaning | Derivation |
|---|---|---|
fg_firmware_patch_lag_days |
Days between installed firmware and latest available firmware | GET /api/v2/monitor/system/firmware → compute (max(available[].release-date) − current.release-date). Falls back to available_count × 30 if release dates aren't exposed (older FortiOS) — warn logged. |
fg_ips_signature_age_days |
Days since IPS signature package was last updated | GET /api/v2/monitor/system/fortiguard → results.ips.update timestamp → days to today. |
fg_any_any_policies |
Active accept-policies with srcaddr=all AND dstaddr=all | GET /api/v2/cmdb/firewall/policy → count policies where status=enable, action=accept, srcaddr[].name='all', AND dstaddr[].name='all'. |
fg_vpn_users_no_cert_auth |
Local users whose two-factor method isn't PKI / certificate | GET /api/v2/cmdb/user/local → count users where two-factor != 'pki'. Includes password-only, token-only, and disabled-2FA users — all susceptible at the VPN edge. |
fg_botnet_cnc_24h |
IPS log hits matching botnet signatures in 24h | GET /api/v2/monitor/log/{disk|memory|fortianalyzer}/ips?filter=logdesc=%22Botnet*%22&since=<now-24h>. Tries disk → memory → FortiAnalyzer locations until one responds with a valid envelope. |
fg_policies_without_webfilter |
Active accept-policies with no webfilter profile attached | Same policy dump as #3; count policies where webfilter-profile is empty. |
fg_sdwan_health_degradation_24h |
SD-WAN members currently in a failing state | GET /api/v2/monitor/virtual-wan/health-check → count entries where status is down, degraded, sla-fail, or dead. Snapshot count — documented as a proxy for the 24h "degradation events" the slug name implies. |
Each row is a slug the connector writes to. Draxis creates the matching kri rows automatically when you check them in the KRIs to import section of the integration form — no manual API call or seed script needed. Thresholds shown in the table are the seeded defaults; you can edit them freely in the KRIs tab afterwards.
Vendor quirks
- REST API Admin is a distinct admin type. It cannot log into the web UI or CLI — only the REST API. Don't try to make a regular admin into an API user by toggling "API access"; the token you get has the user's full interactive privileges, which is a bigger blast radius than you want.
- Trusted Hosts is mandatory. FortiGate won't accept API calls from IPs outside the Trusted Hosts list on the REST API admin. If you're testing from a laptop and production-calling from the Draxis runner, both IPs need to be added during testing. This is good security hygiene but a common cause of "why am I getting 401?" confusion.
- Firmware release-date availability depends on FortiOS version. FortiOS 7.2+ exposes release dates in
/monitor/system/firmware. Older builds (6.x, early 7.0) return only version/build numbers. The connector falls back to a count-of-available-updates × 30 days proxy in that case, with a warn log so you know the value is approximate. - Botnet KRI log location varies. FortiGate writes logs to disk, memory, or off-box to FortiAnalyzer depending on config. The connector tries all three locations and uses whichever responds first. If your device logs only to FortiAnalyzer and the token profile doesn't include FortiAnalyzer proxy permission, the KRI reports 0 with a warn.
- SD-WAN KRI is a snapshot, not a 24h event count. FortiGate doesn't expose a "degradation events in last 24h" counter via REST API — you'd need to parse the event log. The KRI reports the current snapshot of unhealthy SD-WAN members, which tracks the same underlying concern but lags actual events by up to 24h. A dedicated event-log-based KRI is on the roadmap.
- VPN cert-auth detection assumes local users. Users authenticated via external providers (LDAP, RADIUS, SAML) don't show up in
/cmdb/user/local. For an authoritative VPN-MFA count on an org with external auth, the KRI value needs to be interpreted alongside your identity provider's 2FA stats. - Webfilter coverage is boolean-per-policy. The KRI counts policies with no webfilter profile attached. A policy with a webfilter profile that has all categories set to "allow" still counts as covered (it has a profile). For a deeper semantic check, review each profile's category-action mapping manually — that level of introspection isn't a daily-KRI question.
- Any-any detection is structural, not semantic. A policy with srcaddr=MyLan_192.168 and dstaddr=all isn't counted because srcaddr isn't literally "all". That's the correct behavior — the KRI catches the pattern policy reviewers actually hunt for.
- FortiManager vs. FortiGate. The REST API URLs and auth are identical. FortiManager aggregates across all managed devices, so the KRI values reflect the entire fleet. Pointing at a standalone FortiGate gives just that device. Choose the scope that matches your KRI question.
- Rate limits. FortiGate's default REST API rate limit is 500 req/min per source. The connector makes ~8 calls per run (probe + KRIs), well under the cap even at hourly scheduling.
- Token rotation is manual. FortiGate API tokens don't expire. Rotate by clicking Generate New API Key on the admin — the old token is invalidated immediately (no overlap period). Update Draxis quickly after rotating.
Troubleshooting
- HTTP 401 on Test with
Invalid username or password— most commonly the Draxis runner's IP is not in the REST API admin's Trusted Hosts list. The token is valid but FortiGate blocks the call before checking it. Also verify the token value hasn't been truncated on copy-paste. - HTTP 403 on a specific endpoint — the admin profile is missing the read permission for that scope (System, Firewall, VPN, Log, etc.). Edit
draxis-readonlyprofile and enable the missing Read permission. fg_firmware_patch_lag_daysis suspiciously large — the fallback proxy (available_count × 30) kicked in because release dates weren't exposed. Check the run log forfortigate.firmware dates unavailable; upgrade FortiOS to 7.2+ for accurate date-based computation.fg_botnet_cnc_24his always 0 — either FortiGuard IPS isn't licensed, logs don't include botnet category entries, or the admin profile lacks log access. Verify in the web UI: Log & Report → IPS should show entries with logdesc containing "Botnet".fg_sdwan_health_degradation_24his always 0 — normal on devices without SD-WAN members configured. Run the connector on a device with SD-WAN enabled and verify/api/v2/monitor/virtual-wan/health-checkreturns non-empty results.rowsSkipped > 0androwsWritten = 0— your tenant hasn't imported any KRIs for this integration yet. Open the integration in Settings → Integrations, tick the KRIs under KRIs to import, and save.- Still stuck? Open a support ticket with the run ID (from Run history) and we'll dig in.