Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
61 changes: 61 additions & 0 deletions spoofsentry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
## Overview

SpoofSentry by DomainSeal monitors your domains for email spoofing, DMARC failures, lookalike domain abuse, and phishing campaigns. This integration sends domain security events to Datadog for centralized logging, analysis, and alerting.

Events include:
- DMARC authentication failures with sender details
- Spoofing campaign detections with IP attribution
- Lookalike domain threats with risk scores
- DNS enforcement changes (SPF, DKIM, DMARC policy)
- Takedown orchestration lifecycle (created, dispatched, escalated, resolved)

## Setup

### In SpoofSentry

1. Log in to [SpoofSentry](https://spoofsentry.com)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration READMEs conventionally use reference-style links (e.g., [SpoofSentry][1] with [1]: https://spoofsentry.com at the bottom of the file) rather than inline URLs. Consider converting all links in this README to that format for consistency with the standard template.

2. Go to **Settings > Integrations > SIEM**
3. Select **Datadog**
4. Enter your **Datadog API key** (from Datadog > Organization Settings > API Keys)
5. Select your **Datadog site** (US: `datadoghq.com`, EU: `datadoghq.eu`)
6. Click **Test Connection** to verify
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1. Log in to [SpoofSentry](https://spoofsentry.com)
2. Go to **Settings > Integrations > SIEM**
3. Select **Datadog**
4. Enter your **Datadog API key** (from Datadog > Organization Settings > API Keys)
5. Select your **Datadog site** (US: `datadoghq.com`, EU: `datadoghq.eu`)
6. Click **Test Connection** to verify
1. Log in to [SpoofSentry](https://spoofsentry.com).
2. Go to **Settings > Integrations > SIEM**.
3. Select **Datadog**.
4. Enter your **Datadog API key** (from Datadog > Organization Settings > API Keys).
5. Select your **Datadog site** (US: `datadoghq.com`, EU: `datadoghq.eu`).
6. Click **Test Connection** to verify,


### In Datadog

Events appear automatically in **Logs** with `source:spoofsentry`. The pre-built dashboard is installed with this integration.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Events appear automatically in **Logs** with `source:spoofsentry`. The pre-built dashboard is installed with this integration.
Events appear automatically in **Logs** with `source:spoofsentry`. A prebuilt dashboard is installed with this integration.


### Log Pipeline

A log pipeline is included that:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A log pipeline is included that:
The integration includes a log pipeline that:

- Maps `eventType` to `evt.name`
- Maps `severity` to log status
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "log status" an attribute name? Ideally, this bullet would be parallel with the first and third bullets which include an attribute name.

- Maps `domain` to `network.destination.domain`
- Categorizes severity levels

## Data Collected

### Logs

SpoofSentry sends domain security events as JSON logs via the Datadog Logs API.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SpoofSentry sends domain security events as JSON logs via the Datadog Logs API.
SpoofSentry sends domain security events as JSON logs through the Datadog Logs API.


| Field | Description |
|-------|-------------|
| `eventType` | Event classification (e.g., `SPOOF_THREAT_DETECTED`) |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `eventType` | Event classification (e.g., `SPOOF_THREAT_DETECTED`) |
| `eventType` | Event classification (for example, `SPOOF_THREAT_DETECTED`) |

| `severity` | `critical`, `high`, `medium`, `low`, `info` |
| `domain` | Target domain |
| `tenantId` | Customer tenant identifier |
| `message` | Human-readable event summary |

### Tags

All events include these tags:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
All events include these tags:
All events include the following tags:

- `service:spoofsentry`
- `event_type:<type>`
- `severity:<level>`
- `domain:<domain>`

## Support

- Email: hello@spoofsentry.com
- Documentation: [https://spoofsentry.com/docs/integrations/datadog](https://spoofsentry.com/docs/integrations/datadog)
- Status: [https://spoofsentry.com/status](https://spoofsentry.com/status)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Support section for integrations-extras typically points directly to the creator's support contact. The Documentation: and Status: list items are non-standard here — consider simplifying to match the convention used by other integrations, and folding the docs link into the Setup section if it's useful there:

Suggested change
## Support
- Email: hello@spoofsentry.com
- Documentation: [https://spoofsentry.com/docs/integrations/datadog](https://spoofsentry.com/docs/integrations/datadog)
- Status: [https://spoofsentry.com/status](https://spoofsentry.com/status)
## Support
Need help? Contact [SpoofSentry support](mailto:hello@spoofsentry.com).

160 changes: 160 additions & 0 deletions spoofsentry/assets/dashboards/spoofsentry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
{
"title": "SpoofSentry - Domain Security Overview",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": "SpoofSentry - Domain Security Overview",
"title": "SpoofSentry: Domain Security Overview",

"description": "DMARC monitoring, spoofing detection, lookalike domains, and takedown orchestration events from SpoofSentry.",
"widgets": [
{
"id": 1,
"definition": {
"title": "Security Events (24h)",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The (24h) suffix implies a fixed time window, but this widget uses the dashboard's time selector. Consider removing it or renaming to reflect the dynamic range, for example "Security Events".

"type": "query_value",
"requests": [
{
"queries": [
{
"data_source": "logs",
"name": "query1",
"search": { "query": "source:spoofsentry" },
"indexes": ["*"],
"compute": { "aggregation": "count" }
}
],
"response_format": "scalar"
}
]
}
},
{
"id": 2,
"definition": {
"title": "Critical & High Threats (24h)",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above — the (24h) suffix is misleading since the time range is controlled by the dashboard selector. Consider "Critical & High Threats".

"type": "query_value",
"requests": [
{
"queries": [
{
"data_source": "logs",
"name": "query1",
"search": { "query": "source:spoofsentry (severity:critical OR severity:high)" },
"indexes": ["*"],
"compute": { "aggregation": "count" }
}
],
"response_format": "scalar"
}
]
}
},
{
"id": 3,
"definition": {
"title": "Events by Severity",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": "Events by Severity",
"title": "Events by severity",

"type": "timeseries",
"requests": [
{
"queries": [
{
"data_source": "logs",
"name": "query1",
"search": { "query": "source:spoofsentry" },
"indexes": ["*"],
"compute": { "aggregation": "count" },
"group_by": [
{ "facet": "@severity", "limit": 5, "sort": { "aggregation": "count", "order": "desc" } }
]
}
],
"response_format": "timeseries",
"display_type": "bars"
}
]
}
},
{
"id": 4,
"definition": {
"title": "Events by Type",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": "Events by Type",
"title": "Events by type",

"type": "toplist",
"requests": [
{
"queries": [
{
"data_source": "logs",
"name": "query1",
"search": { "query": "source:spoofsentry" },
"indexes": ["*"],
"compute": { "aggregation": "count" },
"group_by": [
{ "facet": "@eventType", "limit": 10, "sort": { "aggregation": "count", "order": "desc" } }
]
}
],
"response_format": "scalar"
}
]
}
},
{
"id": 5,
"definition": {
"title": "Events by Domain",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": "Events by Domain",
"title": "Events by domain",

"type": "toplist",
"requests": [
{
"queries": [
{
"data_source": "logs",
"name": "query1",
"search": { "query": "source:spoofsentry" },
"indexes": ["*"],
"compute": { "aggregation": "count" },
"group_by": [
{ "facet": "host", "limit": 10, "sort": { "aggregation": "count", "order": "desc" } }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Events by Domain" widget groups by host, but the log pipeline maps domain to @network.destination.domain. Please verify that host is populated with the monitored domain — if not, this facet should likely be @network.destination.domain or @domain.

]
}
],
"response_format": "scalar"
}
]
}
},
{
"id": 6,
"definition": {
"title": "Takedown Activity",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": "Takedown Activity",
"title": "Takedown activity",

"type": "timeseries",
"requests": [
{
"queries": [
{
"data_source": "logs",
"name": "query1",
"search": { "query": "source:spoofsentry @eventType:(TAKEDOWN_*)" },
"indexes": ["*"],
"compute": { "aggregation": "count" },
"group_by": [
{ "facet": "@eventType", "limit": 5, "sort": { "aggregation": "count", "order": "desc" } }
]
}
],
"response_format": "timeseries",
"display_type": "line"
}
]
}
},
{
"id": 7,
"definition": {
"title": "Recent Security Events",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": "Recent Security Events",
"title": "Recent security events",

"type": "log_stream",
"query": "source:spoofsentry",
"columns": ["@eventType", "@severity", "host", "@tenantId"],
"sort": { "column": "time", "order": "desc" },
"message_display": "expanded-md"
}
}
],
"layout_type": "ordered",
"notify_list": [],
"reflow_type": "fixed"
}
67 changes: 67 additions & 0 deletions spoofsentry/assets/logs/spoofsentry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
id: spoofsentry
type: pipeline
name: SpoofSentry
enabled: true
filter:
query: "source:spoofsentry"
processors:
- type: attribute-remapper
name: Map eventType to evt.name
enabled: true
sources:
- eventType
target: evt.name
preserveSource: true
sourceType: attribute
targetType: attribute

- type: attribute-remapper
name: Map severity to log status
enabled: true
sources:
- severity
target: status
preserveSource: true
sourceType: attribute
targetType: attribute

- type: attribute-remapper
name: Map domain to network.destination.domain
enabled: true
sources:
- domain
target: network.destination.domain
preserveSource: true
sourceType: attribute
targetType: attribute

- type: attribute-remapper
name: Map tenantId to usr.id
enabled: true
sources:
- tenantId
target: usr.id
preserveSource: true
sourceType: attribute
targetType: attribute

- type: category-processor
name: Categorize severity levels
enabled: true
categories:
- filter:
query: "@severity:critical"
name: Critical
- filter:
query: "@severity:high"
name: High
- filter:
query: "@severity:medium"
name: Medium
- filter:
query: "@severity:low"
name: Low
- filter:
query: "@severity:info"
name: Info
target: severity_category
1 change: 1 addition & 0 deletions spoofsentry/assets/service_checks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
48 changes: 48 additions & 0 deletions spoofsentry/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{

Check failure on line 1 in spoofsentry/manifest.json

View check run for this annotation

datadog-assets / validate-owner-validator

Error in owner-validator

Owner is a required internal-only field. Use a valid internal team handle. External contributors should leave this unset.

Check failure on line 1 in spoofsentry/manifest.json

View check run for this annotation

datadog-assets / validate-logs

Error in logs

{'assets': {'integration': {'source_type_id': ['Missing data for required field.']}}}

Check failure on line 1 in spoofsentry/manifest.json

View check run for this annotation

datadog-assets / validate-manifests

Error in manifests

{'assets': {'integration': {'source_type_id': ['Missing data for required field.']}}}
"manifest_version": "2.0.0",
"app_uuid": "87ffb85e-b1e8-4f3d-8978-ce5a2d43036f",
"app_id": "spoofsentry",
"display_on_public_website": true,
"tile": {
"overview": "README.md#Overview",
"configuration": "README.md#Setup",
"uninstallation": "README.md#Uninstallation",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manifest references README.md#Uninstallation, but the README doesn't include an ## Uninstallation section. Please add one. For a log-based integration, this can be brief — for example:

## Uninstallation

Remove the SpoofSentry integration from **Integrations > Integrations**.

"support": "README.md#Support",
"changelog": "CHANGELOG.md",
"description": "Ingest DMARC monitoring, spoofing detection, and takedown events from SpoofSentry",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is 81 characters, which exceeds the 80-character limit for tile descriptions. Trim slightly — for example:

Suggested change
"description": "Ingest DMARC monitoring, spoofing detection, and takedown events from SpoofSentry",
"description": "DMARC monitoring, spoofing detection, and takedown events from SpoofSentry",

"title": "SpoofSentry",
"media": [],
"classifier_tags": [
"Category::Security",
"Category::Log Collection",
"Category::Notifications",
"Submitted Data Type::Logs",
"Offering::Integration"
]
},
"assets": {
"dashboards": {
"SpoofSentry - Domain Security Overview": "assets/dashboards/spoofsentry.json"
},
"logs": {
"source": "spoofsentry"
},
"integration": {
"source_type_name": "SpoofSentry",
"auto_install": true,
"configuration": {},
"events": {
"creates_events": false
},
"service_checks": {
"metadata_path": "assets/service_checks.json"
}
}
},
"author": {
"homepage": "https://spoofsentry.com",
"name": "DomainSeal",
"support_email": "hello@spoofsentry.com",
"sales_email": "hello@spoofsentry.com"
}
}
Loading