Add Fortinet FortiGate active response integration#83
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new Wazuh Active Response integration that blocks/unblocks source IPv4 addresses on a Fortinet FortiGate firewall by creating a /32 address object and appending/removing it from a configured deny address group via the FortiGate REST API.
Changes:
- Added
fortigate-block.shactive response script implementing Wazuhcheck_keyshandshake + FortiGate CMDB API calls. - Added an example configuration file and an integration-local
.gitignoreto prevent committing live secrets. - Added integration documentation and a manual test harness script.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| integrations/fortinet_fortigate-active-response/active-response/fortigate-block.sh | Implements FortiGate REST API block/unblock logic and Wazuh execd handshake. |
| integrations/fortinet_fortigate-active-response/active-response/fortigate-ar.conf.example | Provides example configuration for FortiGate host/token/group/vdom and tuning settings. |
| integrations/fortinet_fortigate-active-response/tests/test-ar.sh | Adds a manual test harness that feeds JSON to the AR script. |
| integrations/fortinet_fortigate-active-response/README.md | Documents prerequisites, installation, configuration, testing, and security considerations. |
| integrations/fortinet_fortigate-active-response/.gitignore | Prevents committing live config/token and other local artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| sudo chmod 750 /var/ossec/active-response/bin/fortigate-block.sh | ||
|
|
||
| # 2. Config | ||
| sudo cp integrations/fortinet_fortigate-active-response/active-response/fortigate-ar.conf \ |
| sudo cp integrations/fortinet_fortigate-active-response/active-response/fortigate-ar-whitelist.example \ | ||
| /var/ossec/etc/lists/fortigate-ar-whitelist | ||
| sudo chown root:wazuh /var/ossec/etc/lists/fortigate-ar-whitelist | ||
| sudo chmod 640 /var/ossec/etc/lists/fortigate-ar-whitelist |
| ``` | ||
|
|
||
| All available options are documented in | ||
| [`active-response/fortigate-ar.conf`](active-response/fortigate-ar.conf). |
| </active-response> | ||
| ``` | ||
|
|
||
| `<location>server</location>` is required — the script runs on the Manager because it needs to reach the FortiGate API. See [`active-response/ossec-fortigate-ar.conf`](active-response/ossec-fortigate-ar.conf) for more trigger examples. |
| # Dry-run — prints the JSON without calling the API | ||
| sudo bash integrations/fortinet_fortigate/tests/test-ar.sh block 198.51.100.99 dry | ||
|
|
||
| # Live block test | ||
| sudo bash integrations/fortinet_fortigate/tests/test-ar.sh block 198.51.100.99 | ||
|
|
| integrations/ | ||
| └── fortinet_fortigate/ | ||
| ├── active-response/ | ||
| │ ├── fortigate-block.sh - AR script - /var/ossec/active-response/bin/ | ||
| │ ├── fortigate-ar.conf - config template - /var/ossec/etc/ | ||
| │ ├── fortigate-ar-whitelist - whitelist template | ||
| │ └── ossec-fortigate-ar.conf - ossec.conf snippets |
| printf '%s\n%s\n' "${ALERT_JSON}" "${CONTINUE_MSG}" \ | ||
| | bash "${SCRIPT_PATH}" > /dev/null | ||
| EXIT_CODE=$? |
| VDOM_PARAM="vdom=${FGT_VDOM}" | ||
|
|
||
| fgt_api() { | ||
| local method="$1" endpoint="$2" data="${3:-}" | ||
| local url="${BASE_URL}/${endpoint}?${VDOM_PARAM}" |
| local cmd=( | ||
| curl --silent --max-time "${FGT_CURL_TIMEOUT}" | ||
| ${CURL_SSL_FLAG} | ||
| -w "\n__STATUS__%{http_code}" | ||
| -X "${method}" | ||
| -H "Authorization: Bearer ${FGT_API_TOKEN}" | ||
| -H "Content-Type: application/json" | ||
| ) |
|
@lakecide could you update based on copilot suggestions? Regards, |
- README: use fortigate-ar.conf.example in install step - README: replace whitelist cp with install command - README: fix test script paths to fortinet_fortigate-active-response - README: fix structure block dir name - test-ar.sh: wrap pipeline in if/else to capture exit code under set -e - fortigate-block.sh: add validate_name_field() for URL-path config values - fortigate-block.sh: add --show-error to curl for better failure diagnostics - active-response: add ossec-fortigate-ar.conf with ossec.conf trigger examples
…ME references - Rename ossec-fortigate-ar.conf - fortigate-ar.conf for consistency - Update all README references accordingly - modified .gitignore to only exclude live config, not .example file
|
@MiguelCasaresRobles All Copilot review comments have been addressed. Thank you |
|
Hi @lakecide — thanks for this, it's well-structured and clearly security-aware (allowlist-validated URL params, IP strictly validated before use, no committed secrets, TLS-off documented as a warning). One blocker before it can merge: Auto-unblock is broken (critical). In Non-blocking nits:
No CI runs on this repo, so please also paste a manual add/delete test against a real FortiGate once the handshake fix is in. |
Summary
Adds a Fortinet FortiGate active response integration for Wazuh.
The integration automatically blocks malicious source IPs on a FortiGate firewall when matching Wazuh rules trigger. The script dynamically creates firewall address objects and safely appends them to a preconfigured deny group through the FortiGate REST API.
Features
Tested Environment
Notes
The integration intentionally uses the FortiGate address-group member append endpoint instead of PUT operations on the group object to avoid overwriting existing members.