Skip to content
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
acfcd29
Add Huntress.io integration
kyletaylored May 28, 2026
d29312f
Update codeowners for huntress
kyletaylored May 28, 2026
04bf61c
Fix ddev formatting issues
kyletaylored May 28, 2026
f054ec8
Fix changelog formatting
kyletaylored May 28, 2026
d52a491
Remove media, use unclaimed source id
kyletaylored May 28, 2026
9f0f722
Fix validation issues
kyletaylored May 28, 2026
c1b2128
Add multiple log query support per API key
kyletaylored May 28, 2026
785969d
Run formatter
kyletaylored May 28, 2026
ba274ff
Already moved mock data file
kyletaylored May 28, 2026
9cfceb8
Add query_name, remove md5, fix monitors
kyletaylored May 28, 2026
a9ec4af
Add escape hatch for hitting rate limit
kyletaylored May 28, 2026
f1c4d69
Fix monitor schema
kyletaylored May 29, 2026
c31b9e0
Merge branch 'master' into huntress
kyletaylored May 29, 2026
5d97e9d
Fix ascii validation
kyletaylored May 29, 2026
157d3d6
Drop secret from hash
kyletaylored May 29, 2026
accc689
Use non-secret stable discriminator not derived from keys
kyletaylored May 29, 2026
27671cf
Apply linting
kyletaylored May 29, 2026
57b2113
Update codecov (add huntress)
kyletaylored May 29, 2026
a92e10d
Add Huntress to test-all.yml
kyletaylored May 29, 2026
c31bf35
Add missing spec item
kyletaylored May 29, 2026
27956f1
Merge branch 'master' into huntress
kyletaylored Jun 1, 2026
9c1c205
Remove old conf artifact
kyletaylored Jun 1, 2026
752339c
Apply suggestions from code review
kyletaylored Jun 2, 2026
26f4835
Move validation to dedicated section
kyletaylored Jun 2, 2026
e41ae65
Replace "Data Collected" section with recommendation
kyletaylored Jun 2, 2026
13b35ee
Fix metadata column issue (suggestion added a comma that broke valida…
kyletaylored Jun 2, 2026
a4d6820
Remove en dash as validation rejects it as a non-ascii character
kyletaylored Jun 2, 2026
0085008
Fix config default value
kyletaylored Jun 2, 2026
3ac80f3
Fix config validation issue
kyletaylored Jun 2, 2026
820fb75
Merge branch 'master' into huntress
kyletaylored Jun 3, 2026
31bf819
Apply suggestions from code review
kyletaylored Jun 3, 2026
1d44e32
Update README with recommendations:
kyletaylored Jun 4, 2026
29045e1
Fix timestamp parsing, 429 retry loop, and org tag lookup; add run su…
kyletaylored Jun 9, 2026
29771cd
Update timestamp parsing
kyletaylored Jun 9, 2026
e98e03c
Update log format
kyletaylored Jun 9, 2026
739534e
Add log batching fallback and log declaration
kyletaylored Jun 9, 2026
982c08a
Apply suggestions from code review
kyletaylored Jun 10, 2026
7511713
Reorder readme sections
kyletaylored Jun 10, 2026
49381e0
Add esql name as log tag
kyletaylored Jun 10, 2026
933d83d
Fix missing reference
kyletaylored Jun 22, 2026
ad8d214
Fix linting error
kyletaylored Jun 22, 2026
eb133bb
Add last missing reference
kyletaylored Jun 22, 2026
0e50bc7
Merge branch 'master' into huntress
kyletaylored Jun 22, 2026
6a29a08
Apply suggestions from code review
domalessi Jul 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ coverage:
target: 75
flags:
- grafana
Huntress:
target: 75
flags:
- huntress
JFrog_Platform:
target: 75
flags:
Expand Down Expand Up @@ -469,6 +473,11 @@ flags:
paths:
- hikaricp/datadog_checks/hikaricp
- hikaricp/tests
huntress:
carryforward: true
paths:
- huntress/datadog_checks/huntress
- huntress/tests
jfrog_platform_self_hosted:
carryforward: true
paths:
Expand Down
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,8 @@ code-coverage.datadog.yml @DataDog/agent-integr
/aerospike_enterprise/ @support-aerospike @DataDog/ecosystems-review
/scamalytics/ @ScamalyticsDev @DataDog/ecosystems-review

/huntress/ @kyletaylored kyle.taylor@datadoghq.com

# LEAVE THE FOLLOWING LOG OWNERSHIP LAST IN THE FILE
# Make sure logs team is the full owner for all logs related files
**/assets/logs/ @DataDog/logs-integrations-reviewers
19 changes: 19 additions & 0 deletions .github/workflows/test-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,25 @@ jobs:
test-py3: ${{ inputs.test-py3 }}
setup-env-vars: "${{ inputs.setup-env-vars }}"
secrets: inherit
j8ecbaad:
uses: DataDog/integrations-core/.github/workflows/test-target.yml@574d63ba88365ffbab915280ceddbaa333c63d6a
with:
job-name: Huntress
target: huntress
platform: linux
runner: '["ubuntu-22.04"]'
repo: "${{ inputs.repo }}"
context: ${{ inputs.context }}
python-version: "${{ inputs.python-version }}"
latest: ${{ inputs.latest }}
agent-image: "${{ inputs.agent-image }}"
agent-image-py2: "${{ inputs.agent-image-py2 }}"
agent-image-windows: "${{ inputs.agent-image-windows }}"
agent-image-windows-py2: "${{ inputs.agent-image-windows-py2 }}"
test-py2: ${{ inputs.test-py2 }}
test-py3: ${{ inputs.test-py3 }}
setup-env-vars: "${{ inputs.setup-env-vars }}"
secrets: inherit
j43aee0d:
uses: DataDog/integrations-core/.github/workflows/test-target.yml@574d63ba88365ffbab915280ceddbaa333c63d6a
with:
Expand Down
9 changes: 9 additions & 0 deletions huntress/CHANGELOG.md
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.
199 changes: 199 additions & 0 deletions huntress/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Huntress

## Overview

[Huntress](https://www.huntress.com/) is a managed security platform providing endpoint detection and response (EDR), antivirus, security awareness training, and a Managed SIEM product that continuously collects and analyzes endpoint telemetry.
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

This integration polls the Huntress Managed SIEM API using ES|QL queries and forwards all security events to Datadog as logs. Each collection run:
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

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 + secret key) from the Huntress Partner Portal under **Settings > API Credentials**
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

### Installation

Install the integration package from the Agent:

```bash
datadog-agent integration install -t datadog-huntress==1.0.0
```

### Configuration

1. Create the configuration file at `/etc/datadog-agent/conf.d/huntress.yaml` (Linux/macOS) or `C:\ProgramData\Datadog\conf.d\huntress.yaml` (Windows). A fully-annotated example is at `datadog_checks/huntress/data/conf.yaml.example`.
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

2. Edit `huntress.yaml` 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"
tags:
- "source:huntress"
- "service:huntress-siem"
- "env:production"
```

3. Restart the Agent:

```bash
# Linux (systemd)
sudo systemctl restart datadog-agent

# macOS
sudo launchctl stop com.datadoghq.agent && sudo launchctl start com.datadoghq.agent
```

### Validation

Run the Agent status command and look for `huntress` under the **Checks** section:
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

```bash
sudo datadog-agent check huntress
```

Logs appear in Datadog Log Explorer filtered by `source:huntress` within one collection interval (default: 15 minutes).
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

### Multiple Huntress accounts
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

Add additional blocks under `instances:`. 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"
tags: ["source:huntress", "env:production"]

- huntress_api_key: "<account2_key>"
huntress_secret_key: "<account2_secret>"
log_queries:
- name: "all-logs"
esql_query: "FROM logs"
tags: ["source:huntress", "env:staging"]
```

### 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` | No\* | - | 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 |
| `metrics.agents.enabled` | No\* | `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 |

\* At least one of `log_queries` or `metrics.agents.enabled: true` must be configured per instance.
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

### Rate limit considerations
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

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 this budget. For large accounts with high log volume or thousands of agents, consider splitting concerns across two instances using separate API key pairs:
Comment thread
domalessi marked this conversation as resolved.
Outdated

```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"

# Instance 2: agent metrics only (isolated rate limit budget)
- huntress_api_key: "<metrics-key>"
huntress_secret_key: "<metrics-secret>"
metrics:
agents:
enabled: true
```

## Data Collected
Comment thread
kyletaylored marked this conversation as resolved.

### Logs

All logs collected from the Huntress Managed SIEM API are forwarded to Datadog with:

- `ddsource: huntress`: enables automatic log pipeline processing
Comment thread
kyletaylored marked this conversation as resolved.
Outdated
- 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][2] for a list of service checks provided by this integration.
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

## Troubleshooting

**No logs in Datadog after first run**

- Run `sudo datadog-agent check huntress` and inspect the output
- Verify the API key pair is valid by checking the Huntress Partner Portal
- Confirm the Managed SIEM feature is enabled on the account
- Check that each `log_queries[].esql_query` begins with `FROM logs`

**`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` / `huntress_secret_key` |
Comment thread
kyletaylored marked this conversation as resolved.
Outdated
| `timeout` | ES\|QL query too broad | Add a `KEEP` or `WHERE` clause to the query |
Comment thread
domalessi marked this conversation as resolved.
Outdated
| `invalid_query` | Malformed ES\|QL | Fix the `esql_query` value in the failing `log_queries` entry |
Comment thread
domalessi marked this conversation as resolved.
Outdated
| `server_error` | Transient Huntress API error | Check [Huntress status page](https://status.huntress.com) |
Comment thread
kyletaylored marked this conversation as resolved.
Outdated
| `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 very low or zero**
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

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 is only advanced after all pages are successfully sent.
Comment thread
kyletaylored marked this conversation as resolved.
Outdated

## 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/
121 changes: 121 additions & 0 deletions huntress/assets/configuration/spec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: Huntress
files:
- name: huntress.yaml
options:
- template: init_config
options:
- template: init_config/default
- name: request_timeout
description: |
HTTP request timeout in seconds applied to all Huntress API calls.
Increase this if the Huntress SIEM API is slow to respond on large queries.
value:
type: number
example: 30
default: 30
- template: instances
options:
- template: instances/default
overrides:
min_collection_interval.value.default: 900
min_collection_interval.value.example: 900
- name: huntress_api_key
required: true
secret: true
description: |
Huntress public API key. Obtain from the Huntress Partner Portal under
Settings > API Credentials. Each instance uses its own key pair, enabling
multiple Huntress accounts to feed into the same Datadog organization.
value:
type: string
example: <HUNTRESS_API_KEY>
- name: huntress_secret_key
required: true
secret: true
description: |
Huntress private (secret) API key paired with huntress_api_key.
value:
type: string
example: <HUNTRESS_SECRET_KEY>
- name: log_queries
description: |
List of ES|QL queries to execute against the Huntress SIEM API. Each entry
requires an esql_query string (must begin with "FROM logs", case-insensitive)
and an optional tags list attached only to logs produced by that query.
Multiple queries run independently with separate checkpoints, enabling
targeted collection for different log types within the same account.
Do not add time range filters — range_start and range_end are managed
automatically by the check.
value:
type: array
items:
type: object
properties:
- name: name
type: string
- name: esql_query
type: string
- name: tags
type: array
items:
type: string
example:
- name: "all-logs"
esql_query: "FROM logs"
tags:
- "log_type:all"
- name: enrich_with_org_tags
description: |
When true, the check fetches Huntress organization metadata (org name,
org key, account ID) and attaches it as log tags. The org cache is
refreshed according to org_cache_ttl_seconds.
value:
type: boolean
example: true
default: true
- name: org_cache_ttl_seconds
description: |
How long (in seconds) to cache organization metadata before re-fetching
from the Huntress API. Set to 0 to refresh on every run.
value:
type: integer
example: 3600
default: 3600
- name: max_pages_per_run
description: |
Maximum number of result pages to fetch per query per run. Each page
contains up to 200 log events. Protects against runaway pagination on
large backlogs. If this cap is hit, the checkpoint does not advance and
remaining pages are fetched on the next run.
value:
type: integer
example: 100
default: 100
- name: huntress_base_url
description: |
Huntress API base URL. Override for sandbox or testing environments.
value:
type: string
example: "https://api.huntress.io"
default: "https://api.huntress.io"
- name: metrics
description: |
Controls which Huntress data is collected as Datadog metrics beyond the
standard SIEM run metrics. Omit this section to disable additional metric
collection (logs-only instance). Configure a separate instance with only
this section and different API credentials to isolate the agent metrics
API call budget from SIEM log collection.
value:
type: object
properties:
- name: agents
type: object
properties:
- name: enabled
type: boolean
- name: max_pages
type: integer
example:
agents:
enabled: true
max_pages: 20
Loading
Loading