-
Notifications
You must be signed in to change notification settings - Fork 836
Add Huntress.io integration #3019
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kyletaylored
wants to merge
44
commits into
DataDog:master
Choose a base branch
from
kyletaylored:huntress
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
acfcd29
Add Huntress.io integration
kyletaylored d29312f
Update codeowners for huntress
kyletaylored 04bf61c
Fix ddev formatting issues
kyletaylored f054ec8
Fix changelog formatting
kyletaylored d52a491
Remove media, use unclaimed source id
kyletaylored 9f0f722
Fix validation issues
kyletaylored c1b2128
Add multiple log query support per API key
kyletaylored 785969d
Run formatter
kyletaylored ba274ff
Already moved mock data file
kyletaylored 9cfceb8
Add query_name, remove md5, fix monitors
kyletaylored a9ec4af
Add escape hatch for hitting rate limit
kyletaylored f1c4d69
Fix monitor schema
kyletaylored c31b9e0
Merge branch 'master' into huntress
kyletaylored 5d97e9d
Fix ascii validation
kyletaylored 157d3d6
Drop secret from hash
kyletaylored accc689
Use non-secret stable discriminator not derived from keys
kyletaylored 27671cf
Apply linting
kyletaylored 57b2113
Update codecov (add huntress)
kyletaylored a92e10d
Add Huntress to test-all.yml
kyletaylored c31bf35
Add missing spec item
kyletaylored 27956f1
Merge branch 'master' into huntress
kyletaylored 9c1c205
Remove old conf artifact
kyletaylored 752339c
Apply suggestions from code review
kyletaylored 26f4835
Move validation to dedicated section
kyletaylored e41ae65
Replace "Data Collected" section with recommendation
kyletaylored 13b35ee
Fix metadata column issue (suggestion added a comma that broke valida…
kyletaylored a4d6820
Remove en dash as validation rejects it as a non-ascii character
kyletaylored 0085008
Fix config default value
kyletaylored 3ac80f3
Fix config validation issue
kyletaylored 820fb75
Merge branch 'master' into huntress
kyletaylored 31bf819
Apply suggestions from code review
kyletaylored 1d44e32
Update README with recommendations:
kyletaylored 29045e1
Fix timestamp parsing, 429 retry loop, and org tag lookup; add run su…
kyletaylored 29771cd
Update timestamp parsing
kyletaylored e98e03c
Update log format
kyletaylored 739534e
Add log batching fallback and log declaration
kyletaylored 982c08a
Apply suggestions from code review
kyletaylored 7511713
Reorder readme sections
kyletaylored 49381e0
Add esql name as log tag
kyletaylored 933d83d
Fix missing reference
kyletaylored ad8d214
Fix linting error
kyletaylored eb133bb
Add last missing reference
kyletaylored 0e50bc7
Merge branch 'master' into huntress
kyletaylored 6a29a08
Apply suggestions from code review
domalessi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # CHANGELOG - Huntress | ||
|
|
||
| ## Unreleased | ||
|
|
||
| ***Added***: | ||
|
|
||
| * Initial release of the Huntress SIEM integration for Datadog. | ||
| * Polls the Huntress Managed SIEM API via ES|QL, enriches logs with organization metadata, and forwards all events to Datadog Logs. | ||
| * Emits collection health metrics and a pre-built overview dashboard with monitor templates. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,207 @@ | ||
| # Huntress | ||
|
|
||
| ## Overview | ||
|
|
||
| [Huntress][5] is a managed security platform that provides endpoint detection and response (EDR), antivirus, security awareness training, and a Managed SIEM product that continuously collects and analyzes endpoint telemetry. | ||
|
|
||
| This integration polls the Huntress Managed SIEM API using ES|QL queries and forwards all security events to Datadog as logs. During each collection run, the integration: | ||
|
|
||
| 1. Loads a checkpoint (the timestamp of the last successful collection) | ||
| 2. Executes a configurable ES|QL query for the elapsed time window | ||
| 3. Paginates through all result pages | ||
| 4. Optionally enriches each log with Huntress organization metadata (org name, key, account ID) | ||
| 5. Forwards logs to Datadog preserving all Elastic Common Schema (ECS) field names | ||
| 6. Advances the checkpoint only after all pages are successfully sent | ||
|
|
||
| This integration is designed for managed security providers (MSPs) and enterprise teams who want to correlate Huntress threat detections alongside infrastructure and application telemetry in Datadog. | ||
|
|
||
| ## Setup | ||
|
|
||
| ### Prerequisites | ||
|
|
||
| - Datadog Agent 7.x or later | ||
| - A Huntress account with the Managed SIEM feature enabled | ||
| - Huntress API credentials (public API key and secret key) from the Huntress Partner Portal under **Settings > API Credentials** | ||
|
|
||
| ### Installation | ||
|
|
||
| Install the integration package from the Agent: | ||
|
|
||
| ```bash | ||
| datadog-agent integration install -t datadog-huntress==1.0.0 | ||
| ``` | ||
|
|
||
| ### Configuration | ||
|
|
||
| 1. Copy the [example configuration file][4] to `/etc/datadog-agent/conf.d/huntress/conf.yaml` (Linux/macOS) or `C:\ProgramData\Datadog\conf.d\huntress\conf.yaml` (Windows) and edit it with your credentials: | ||
|
|
||
| ```yaml | ||
| init_config: {} | ||
|
|
||
| instances: | ||
| - huntress_api_key: "<your_public_api_key>" | ||
| huntress_secret_key: "<your_secret_api_key>" | ||
| log_queries: | ||
| - name: "all-logs" | ||
| esql_query: "FROM logs | KEEP @timestamp, message, host.hostname, event.category, event.code, event.provider, event.id, user.target.name, user.target.domain, winlog.system.EventID" | ||
| tags: | ||
| - "source:huntress" | ||
| - "service:huntress-siem" | ||
| - "env:production" | ||
| ``` | ||
|
|
||
| 2. Restart the Agent: | ||
|
|
||
| ```bash | ||
| # Linux (systemd) | ||
| sudo systemctl restart datadog-agent | ||
|
|
||
| # macOS | ||
| sudo launchctl stop com.datadoghq.agent && sudo launchctl start com.datadoghq.agent | ||
| ``` | ||
|
|
||
| #### Multiple Huntress accounts | ||
|
|
||
| If you manage multiple Huntress accounts, add an additional block under `instances:` for each account. Each block runs independently with its own checkpoint, org metadata cache, and metrics: | ||
|
|
||
| ```yaml | ||
| instances: | ||
| - huntress_api_key: "<account1_key>" | ||
| huntress_secret_key: "<account1_secret>" | ||
| log_queries: | ||
| - name: "all-logs" | ||
| esql_query: "FROM logs | KEEP @timestamp, message, host.hostname, event.category, event.code, event.provider, event.id, user.target.name, user.target.domain, winlog.system.EventID" | ||
| tags: ["source:huntress", "env:production"] | ||
|
|
||
| - huntress_api_key: "<account2_key>" | ||
| huntress_secret_key: "<account2_secret>" | ||
| log_queries: | ||
| - name: "all-logs" | ||
| esql_query: "FROM logs | KEEP @timestamp, message, host.hostname, event.category, event.code, event.provider, event.id, user.target.name, user.target.domain, winlog.system.EventID" | ||
| tags: ["source:huntress", "env:staging"] | ||
| ``` | ||
|
|
||
| #### Rate limits | ||
|
|
||
| The Huntress API allows 60 requests per minute per API key pair. A typical run with 3 SIEM queries and agent metrics uses roughly 5 to 25 requests, well within the limit. For large accounts with high log volume or thousands of agents, consider distributing the load across two instances using separate API key pairs: | ||
|
|
||
| ```yaml | ||
| instances: | ||
| # Instance 1: SIEM log collection only | ||
| - huntress_api_key: "<logs-key>" | ||
| huntress_secret_key: "<logs-secret>" | ||
| log_queries: | ||
| - name: "all-logs" | ||
| esql_query: "FROM logs | KEEP @timestamp, message, host.hostname, event.category, event.code, event.provider, event.id, user.target.name, user.target.domain, winlog.system.EventID" | ||
|
|
||
| # Instance 2: agent metrics only (isolated rate limit budget) | ||
| - huntress_api_key: "<metrics-key>" | ||
| huntress_secret_key: "<metrics-secret>" | ||
| metrics: | ||
| agents: | ||
| enabled: true | ||
| ``` | ||
|
|
||
| #### Configuration reference | ||
|
|
||
| **`init_config` options** (apply to all instances): | ||
|
|
||
| | Field | Required | Default | Description | | ||
| | ----------------- | -------- | ------- | ------------------------------------------------- | | ||
| | `request_timeout` | No | `30` | HTTP request timeout in seconds for all API calls | | ||
|
|
||
| **`instances` options** (per Huntress account): | ||
|
|
||
| | Field | Required | Default | Description | | ||
| | -------------------------- | ----------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | `huntress_api_key` | Yes | - | Huntress public API key | | ||
| | `huntress_secret_key` | Yes | - | Huntress secret API key | | ||
| | `log_queries` | Conditional | - | List of query objects; each has `name` (required), `esql_query` (required, must begin with `FROM logs`), and `tags` (optional). `name` is used as the `query_name` tag on metrics. Always include a `KEEP` clause. Queries without `KEEP` return only `uuid` and `organization_id`. | | ||
| | `metrics.agents.enabled` | Conditional | `false` | Collect agent fleet metrics (total, by platform, by Defender/firewall status) | | ||
| | `metrics.agents.max_pages` | No | `20` | Max pages of agents to fetch per run (500 agents/page) | | ||
| | `enrich_with_org_tags` | No | `true` | Fetch and attach org metadata as log tags | | ||
| | `org_cache_ttl_seconds` | No | `3600` | How long to cache org metadata (seconds) | | ||
| | `max_pages_per_run` | No | `100` | Page cap per query per run (~20,000 logs maximum) | | ||
| | `huntress_base_url` | No | `https://api.huntress.io` | Override for sandbox environments | | ||
| | `tags` | No | `[]` | Extra tags on every forwarded metric and log | | ||
|
|
||
| **Note:** At least one of `log_queries` or `metrics.agents.enabled: true` must be configured per instance. | ||
|
|
||
| ### Validation | ||
|
|
||
| Run the following command to validate the integration is collecting data: | ||
|
|
||
| ```bash | ||
| sudo datadog-agent check huntress | ||
| ``` | ||
|
|
||
| Logs appear in Datadog Log Explorer filtered by `source:huntress`. Allow up to 15 minutes for the first logs to appear. | ||
|
|
||
| ## Data Collected | ||
|
|
||
| ### Logs | ||
|
|
||
| All logs collected from the Huntress Managed SIEM API are forwarded to Datadog with: | ||
|
|
||
| - `ddsource: huntress`: a reserved log attribute that identifies the log source and triggers automatic pipeline processing | ||
| - ECS field names preserved as top-level log attributes (for example, `event.category`, `host.hostname`, `user.name`) | ||
| - Organization metadata tags when `enrich_with_org_tags: true` (for example, `huntress_org_name`, `huntress_org_key`, `huntress_account_id`) | ||
|
|
||
| ### Metrics | ||
|
|
||
| See [metadata.csv][1] for a list of metrics provided by this integration. | ||
|
|
||
| ### Events | ||
|
|
||
| The Huntress integration does not include any events. | ||
|
|
||
| ### Service Checks | ||
|
|
||
| See [service_checks.json][3] for a list of service checks provided by this integration. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| **No logs in Datadog after first run** | ||
|
|
||
| - Run `sudo datadog-agent check huntress` and inspect the output. The summary line reports how many logs were collected and the exact time range queried. | ||
| - Verify the API key pair is valid by checking the Huntress Partner Portal. | ||
| - Confirm the Managed SIEM feature is enabled on the account. | ||
| - Confirm `min_collection_interval: 900` is set in your instance config. Otherwise, the Agent uses its default 15-second interval, and each run queries only a 15-second window with no new events. | ||
| - Check that each `log_queries[].esql_query` begins with `FROM logs`. | ||
| - The Huntress SIEM API requires an explicit `KEEP` clause to return log fields. Without one, responses contain only `uuid` and `organization_id`. Add `| KEEP @timestamp, message, host.hostname, event.category, event.code, ...` to your query. The Agent logs show a warning if this is detected. | ||
|
|
||
| **`LogsSent: 0` in `datadog-agent status` even though logs are being collected** | ||
|
|
||
| This is expected. The integration sends logs directly to the Datadog Logs Intake API rather than through the Agent's internal log pipeline, so the Logs Agent counters (`LogsProcessed`, `LogsSent`) always read 0. Use the Agent check output or Datadog Log Explorer filtered by `source:huntress` to confirm logs are arriving. | ||
|
|
||
| **`huntress.siem.errors` count is increasing** | ||
|
|
||
| Inspect the `error_type` tag to identify the root cause: | ||
|
|
||
| | `error_type` | Cause | Resolution | | ||
| | ------------------ | ---------------------------------- | ------------------------------------------------------------- | | ||
| | `auth_failure` | Invalid or rotated API credentials | Update `huntress_api_key` or `huntress_secret_key` | | ||
| | `timeout` | ES|QL query too broad | Add a `KEEP` or `WHERE` clause to the query | | ||
| | `invalid_query` | Malformed ES|QL | Fix the `esql_query` value in the failing `log_queries` entry | | ||
| | `server_error` | Transient Huntress API error | Check [Huntress status page][6] | | ||
| | `connection_error` | Network issue | Verify connectivity from the Agent host to `api.huntress.io` | | ||
| | `run_failure` | Unexpected error during collection | Check Agent logs for the full stack trace | | ||
|
|
||
| **`huntress.siem.api_call_remaining` is low or zero** | ||
|
|
||
| The Huntress API allows 60 requests per minute. The integration logs a warning when fewer than 10 requests remain in a given minute. If this happens regularly, reduce `max_pages_per_run` or increase `min_collection_interval` to spread out collection runs. | ||
|
|
||
| **Duplicate logs after Agent restart** | ||
|
|
||
| This is expected on the first restart after a failed run. The checkpoint advances only after all pages are successfully sent. | ||
|
|
||
| ## Support | ||
|
|
||
| For questions and support, [contact Datadog support][2]. | ||
|
|
||
| [1]: https://github.com/DataDog/integrations-extras/blob/master/huntress/metadata.csv | ||
| [2]: https://docs.datadoghq.com/help/ | ||
| [3]: https://github.com/DataDog/integrations-extras/blob/master/huntress/assets/service_checks.json | ||
| [4]: https://github.com/DataDog/integrations-extras/blob/master/huntress/datadog_checks/huntress/data/conf.yaml.example | ||
| [5]: https://www.huntress.com/ | ||
| [6]: https://status.huntress.com/ | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.