Monad Security Pipeline Evaluation
Overview
Evaluation of Monad as an ETL pipeline for SIEM migration: QRadar → Microsoft Sentinel.
Problem: Sentinel charges per GB ingested. Sending all logs = expensive.
Solution: Monad sits between log sources and SIEM, filtering/enriching before ingestion.
What Monad Does
| Stage | Function |
|---|---|
Ingest |
Collect logs via Syslog, API, eStreamer, S3, HTTP |
Transform |
Filter (drop low-value), Normalize (OCSF), Enrich (175+ sources) |
Route |
Critical → Sentinel, Bulk → Cold Storage (S3) |
Filtering Strategy
Critical → Sentinel
High-value security events that require real-time analysis:
-
Authentication failures
-
Policy violations
-
TACACS admin commands
-
FTD deny/threat events
-
Configuration changes
Bulk → Cold Storage
High-volume, low-signal logs retained for compliance:
-
Passed authentications
-
Accounting records
-
Health checks
-
Informational syslog
-
Flow/allow logs
Log Sources (Scope)
| Source | Components | Volume | Protocol |
|---|---|---|---|
ISE RADIUS |
pPAN/sPAN, pMNT/sMNT, 4 PSNs |
HIGH |
Syslog |
ISE TACACS |
2 Standalone servers |
MEDIUM |
Syslog |
Firewall |
FTD Sensors, FMC |
HIGH |
Syslog (no native eStreamer) |
ASA VPN |
AnyConnect RAS |
MEDIUM |
Syslog |
Network |
Switches, Routers, WLC |
MEDIUM |
Syslog |
Microsoft Defender |
EDR, XDR, Defender for Cloud |
MEDIUM |
Native API |
Microsoft 365 |
Exchange, DLP, SharePoint |
MEDIUM |
Native API |
Meraki |
Network config changes |
LOW |
Native API |
Connector Mapping (Discovered 2026-03-11)
| Source | Monad Connector | Credentials |
|---|---|---|
ISE RADIUS/TACACS |
|
None (syslog forwarding) |
FTD/ASA/Network |
|
None (syslog forwarding) |
Meraki |
|
Meraki API key |
Defender EDR |
|
Azure AD app |
Defender XDR |
|
Azure AD app |
Defender Cloud |
|
Azure AD app |
M365 Exchange |
|
Azure AD app |
M365 DLP |
|
Azure AD app |
M365 General |
|
Azure AD app |
No native ISE, FTD, or ASA connectors. Cisco sources require syslog forwarding to <pipeline-id>.l4.monad.com:6514.
|
Expected Impact
Based on Monad documentation and case studies:
| Metric | Expectation |
|---|---|
Volume Reduction |
50-70% fewer logs to Sentinel |
Cost Savings |
50-70% reduction in Sentinel ingestion costs |
Enrichment |
175+ sources available for pre-SIEM enrichment |
Compliance |
Full archive in S3 for retention requirements |
Open Questions
-
ISE Log Splitting - Can ISE MnT send different categories to different syslog targets?
-
FMC eStreamer - Does Monad have native eStreamer connector or syslog only? → Answered: Syslog only
-
Deployment Model - SaaS vs On-prem for healthcare environment?
-
Compliance - SOC 2, HIPAA certifications?
-
Sentinel Connector - Native integration or HTTP output? → Answered: Native
msft-sentinelconnector
API Access (Discovered 2026-03-10)
Authentication
| Setting | Value |
|---|---|
Base URL |
|
Auth Header |
|
Org ID |
Required in URL path |
beta.monad.com redirects (308) to app.monad.com. Use X-API-Key header, NOT Authorization: Bearer.
|
Key Endpoints
Base: app.monad.com/api
# Organization pipelines
GET /v1/{organization_id}/pipelines
GET /v1/{organization_id}/pipelines/{pipeline_id}
# Inputs/Outputs/Transforms
GET /v1/{organization_id}/inputs
GET /v1/{organization_id}/outputs
GET /v1/{organization_id}/transforms
# Logs and monitoring
GET /v1/{organization_id}/logs
GET /v1/{organization_id}/logs/pipelines
GET /v1/{organization_id}/logs/pipelines/{pipeline_id}
# API Keys (v2)
GET /v2/{organization_id}/api_keys
Environment Setup
export MONAD_API_KEY="<your-api-key>"
export MONAD_ORG_ID="c2ac89fc-4a8a-49a2-99ba-f2701cc51efa"
API Examples
List Pipelines:
curl -s -H "X-API-Key: $MONAD_API_KEY" \
https://app.monad.com/api/v1/$MONAD_ORG_ID/pipelines | jq .
Get Pipeline Details:
curl -s -H "X-API-Key: $MONAD_API_KEY" \
https://app.monad.com/api/v1/$MONAD_ORG_ID/pipelines/<pipeline-id> | jq .
List Inputs:
curl -s -H "X-API-Key: $MONAD_API_KEY" \
https://app.monad.com/api/v1/$MONAD_ORG_ID/inputs | jq .
List Outputs:
curl -s -H "X-API-Key: $MONAD_API_KEY" \
https://app.monad.com/api/v1/$MONAD_ORG_ID/outputs | jq .
JWT Debugging
Decode API key to inspect claims:
echo $MONAD_API_KEY | cut -d. -f2 | base64 -d 2>/dev/null | jq .
Key fields: org (organization ID), role (permission level), exp (expiration).
OpenAPI Specification
Full API spec available at:
curl -s https://raw.githubusercontent.com/monad-inc/sdk/main/openapi.json | jq '.paths | keys'
Infrastructure as Code
-
Terraform Provider: monad-inc/monad
-
SDK (Java/Python/Go/TS): monad-inc/sdk
Connector Discovery (2026-03-10)
Connectors discovered via API for QRadar → Sentinel migration:
Inputs (Log Sources):
| Type ID | Name | Use Case |
|---|---|---|
|
Syslog |
ISE RADIUS/TACACS, network devices, FTD |
|
Meraki Organization Configuration Changes |
Meraki config audit (if applicable) |
Outputs (Destinations):
| Type ID | Name | Use Case |
|---|---|---|
|
Microsoft Azure Sentinel |
Target SIEM - critical events |
|
S3 |
Cold storage - compliance archive |
|
Azure Blob Storage |
Alternative archive destination |
| No native eStreamer connector found. FTD logs may need syslog forwarding from FMC. |
Trial Environment Inventory (2026-03-10)
Pipelines (2):
| Name | Description | ID |
|---|---|---|
chla-eval-demo |
Testing Monad filtering with sample data |
|
Example: Crowdstrike Vulnerabilities to OCSF |
Demo pipeline for CrowdStrike → OCSF transform |
|
Inputs (6):
| Type | Name | Description |
|---|---|---|
|
Crowdstrike Vulnerabilities (Event Generator) |
Synthetic CrowdStrike vulnerability data |
|
HTTP Input |
Generic HTTP endpoint for log ingestion |
|
Known Exploited Vulnerabilities |
CISA KEV feed integration |
|
Organization Logs |
Internal Monad platform logs |
|
Security Advisories |
GitHub security advisory database |
|
Splunk HEC Input |
Splunk HTTP Event Collector compatible endpoint |
Outputs (4):
| Name | Description |
|---|---|
/dev/null |
Default discard output |
AWS S3 Archive Example |
Archive to S3 before transformation (placeholder) |
AWS Security Lake Example |
Security Lake destination (placeholder) |
Splunk Example |
Splunk destination (placeholder) |
Trial API Limitations
| Resource | API Create | Notes |
|---|---|---|
Pipelines |
✓ Yes |
v2 endpoint required |
Inputs |
✓ Yes |
Requires proper config (credentials for API-based inputs) |
Transforms |
✗ No |
403 "Feature Not Enabled For Entity" - UI only |
Outputs |
✗ No |
400 "Invalid output type" - UI only |
| Trial accounts have limited API access. Use UI for transforms and outputs. |
API Discovery Notes
Key findings during reverse-engineering:
-
Auth header:
X-API-Keyworks,Authorization: Bearerreturns 401 -
Base URL:
beta.monad.com→ 308 redirect →app.monad.com -
Path prefix: Must include
/api(e.g.,/api/v1/…) -
SvelteKit frontend: Uses
__data.jsonpattern for page data (cookie auth) -
API responses: All include
paginationobject withtotal,limit,offset -
Pipeline creation: Requires v2 API (
/api/v2/{org}/pipelines) -
Pipeline structure: Must include nodes (input+output) and edges connecting them
Pipeline Created via API (2026-03-11)
Successfully created pipeline using CLI toolkit:
monad_pipeline_create "api-http-test" "Created via CLI" \
"9b6d3546-1a0a-40ab-bbbd-f45631084244" \ # HTTP Input
"43fcd1d6-04df-44b1-9959-21f32c85ba9c" # /dev/null output
Result:
Pipeline ID |
|
Flow |
HTTP Input → /dev/null |
Edges |
1 (always) |
Proof of concept: Pipelines can be fully managed via API without UI.
Syslog Input Discovery (2026-03-11)
Key finding: Syslog endpoints use pipeline ID in hostname.
Endpoint pattern:
<pipeline-id>.l4.monad.com:6514
Example:
d4b83eb2-cbfb-474a-8dda-67c4921d1bab.l4.monad.com:6514
Protocol: TLS TCP on port 6514 (RFC 6587 framing)
Test command:
PIPELINE_ID="d4b83eb2-cbfb-474a-8dda-67c4921d1bab"
MSG='<34>1 2024-01-15T10:30:00Z myhost testapp 1234 - - Test message'
echo -n "${#MSG} ${MSG}" | openssl s_client -connect ${PIPELINE_ID}.l4.monad.com:6514 -quiet
rsyslog configuration:
# /etc/rsyslog.d/99-monad.conf
*.* action(type="omfwd"
target="<pipeline-id>.l4.monad.com"
port="6514"
protocol="tcp"
StreamDriver="gtls"
StreamDriverMode="1"
StreamDriverAuthMode="anon")
Syslog pipeline created:
Pipeline ID |
|
Input |
CHLA Syslog ( |
Output |
/dev/null (testing) |
Endpoint |
|
| Endpoint not exposed via API - discovered in built-in docs. |
Input Creation via API
Inputs require v2 endpoint (same as pipelines):
curl -s -X POST \
-H "X-API-Key: $MONAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "CHLA Syslog", "type": "monad-syslog"}' \
"https://app.monad.com/api/v2/$MONAD_ORG_ID/inputs" | jq .
Transform Types Reference
| Type | Name | Use Case |
|---|---|---|
|
jq Transform |
Full JSON transformation, OCSF normalization, complex routing logic |
|
Add Timestamp |
Add ingestion timestamp for latency tracking |
|
Add Field |
Add static fields (environment, source tags) |
|
Drop Key |
Remove sensitive fields (passwords, tokens) |
|
Drop Record |
Filter records by field value (routing logic) |
|
Rename Key |
Normalize field names across sources |
|
Flatten |
Flatten nested JSON structures |
|
Copy Value |
Duplicate field values |
|
Mutate Value |
Conditional value transformation |
|
Convert Timestamp |
Timestamp format conversion (epoch ↔ ISO8601) |
|
Add Identifier |
Add unique record ID |
|
Conditional Create |
Create field based on another field’s value |
jq Transform Example (MITRE ATT&CK Routing):
# Route by severity/event type
if (.severity == "critical" or .severity == "high" or
.event_type == "auth_failure" or
.event_type == "intrusion_detected") then
. + {"route": "sentinel", "mitre": "T1078"}
else
. + {"route": "s3_archive"}
end
| jq transforms require full trial or production license. Use GJSON-based transforms below for trial accounts. |
GJSON Transform Patterns (UI Workflow)
Since trial accounts cannot create transforms via API, use native operations with GJSON paths in the UI.
GJSON Path Syntax:
| Pattern | Example Path | Returns |
|---|---|---|
Dot notation |
|
Nested field value |
Array index |
|
First endpoint IP |
Array query |
|
IP of first active endpoint |
All matches |
|
All active endpoint IPs |
Wildcards |
|
All name fields at depth 1 |
Query Operators:
| Operator | Meaning |
|---|---|
|
Equals |
|
Not equals |
|
Less than |
|
Greater than |
|
Pattern match (like SQL LIKE) |
UI Transform Workflow for CHLA Routing:
-
Drop Info-Level Logs (reduce volume 40-60%)
Type
drop_record_where_value_eqKey
severityValue
info -
Tag Critical for Sentinel
Type
addKey
destinationValue
sentinel -
Add MITRE Tag for Auth Failures
Type
create_key_value_if_key_valueCondition Key
event_typeCondition Value
auth_failureNew Key
mitre_techniqueNew Value
T1078 -
Normalize Field Names
Type
rename_keyOld Key
src_ipNew Key
source.ip
ISE RADIUS Log Paths:
severity → "high"
event_type → "auth_failure"
user.name → "jdoe"
user.domain → "CHLA"
endpoint.mac → "aa:bb:cc:dd:ee:ff"
endpoint.ip → "10.50.10.100"
ise.policy_set → "Wired_802.1X_Closed"
ise.authorization_profile → "DENY_ACCESS"
FTD Firewall Log Paths:
action → "deny"
src.ip → "10.50.10.50"
dst.ip → "8.8.8.8"
dst.port → 443
protocol → "tcp"
rule.name → "Block_Malicious"
threat.signature → "ET TROJAN"
CHLA API Toolkit
Custom toolkit built for this evaluation:
examples/monad/
├── shell/monad-cli.sh # Bash wrapper functions
├── python/monad_client.py # Full Python client
├── python/examples.py # Usage examples
├── jq/monad-patterns.jq # jq parsing patterns
└── README.adoc # Toolkit documentation
See examples/monad/README.adoc in this repository for toolkit documentation.
Notes
This is a personal evaluation document. No sensitive infrastructure data included. Concepts only.