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

monad-syslog

None (syslog forwarding)

FTD/ASA/Network

monad-syslog

None (syslog forwarding)

Meraki

cisco-meraki-config-logs

Meraki API key

Defender EDR

endpoint-alerts

Azure AD app

Defender XDR

microsoft-defender-xdr-alerts

Azure AD app

Defender Cloud

microsoft-defender-for-cloud-alerts

Azure AD app

M365 Exchange

microsoft-365-exchange-audit-logs

Azure AD app

M365 DLP

microsoft-365-dlp-events

Azure AD app

M365 General

microsoft-365-general-audit-logs

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

  1. ISE Log Splitting - Can ISE MnT send different categories to different syslog targets?

  2. FMC eStreamer - Does Monad have native eStreamer connector or syslog only?Answered: Syslog only

  3. Deployment Model - SaaS vs On-prem for healthcare environment?

  4. Compliance - SOC 2, HIPAA certifications?

  5. Sentinel Connector - Native integration or HTTP output?Answered: Native msft-sentinel connector

API Access (Discovered 2026-03-10)

Authentication

Setting Value

Base URL

app.monad.com/api

Auth Header

X-API-Key: <API_KEY>

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

# 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

Connector Discovery (2026-03-10)

Connectors discovered via API for QRadar → Sentinel migration:

Inputs (Log Sources):

Type ID Name Use Case

monad-syslog

Syslog

ISE RADIUS/TACACS, network devices, FTD

cisco-meraki-config-logs

Meraki Organization Configuration Changes

Meraki config audit (if applicable)

Outputs (Destinations):

Type ID Name Use Case

msft-sentinel

Microsoft Azure Sentinel

Target SIEM - critical events

s3

S3

Cold storage - compliance archive

azure-blob-storage

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

fb66d7eb-…​

Example: Crowdstrike Vulnerabilities to OCSF

Demo pipeline for CrowdStrike → OCSF transform

92aa6f45-…​

Inputs (6):

Type Name Description

demo

Crowdstrike Vulnerabilities (Event Generator)

Synthetic CrowdStrike vulnerability data

monad-http

HTTP Input

Generic HTTP endpoint for log ingestion

cisa-kev

Known Exploited Vulnerabilities

CISA KEV feed integration

monad-logs

Organization Logs

Internal Monad platform logs

github-advisory-db

Security Advisories

GitHub security advisory database

monad-splunk-hec

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:

  1. Auth header: X-API-Key works, Authorization: Bearer returns 401

  2. Base URL: beta.monad.com → 308 redirect → app.monad.com

  3. Path prefix: Must include /api (e.g., /api/v1/…​)

  4. SvelteKit frontend: Uses __data.json pattern for page data (cookie auth)

  5. API responses: All include pagination object with total, limit, offset

  6. Pipeline creation: Requires v2 API (/api/v2/{org}/pipelines)

  7. 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

765ecf0e-20fe-494c-9406-f38ddd8fda1a

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

d4b83eb2-cbfb-474a-8dda-67c4921d1bab

Input

CHLA Syslog (c0edb4d2-2fd9-4c8d-9f86-a5f3043f285c)

Output

/dev/null (testing)

Endpoint

d4b83eb2-cbfb-474a-8dda-67c4921d1bab.l4.monad.com:6514

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

jq Transform

Full JSON transformation, OCSF normalization, complex routing logic

timestamp

Add Timestamp

Add ingestion timestamp for latency tracking

add

Add Field

Add static fields (environment, source tags)

drop_key

Drop Key

Remove sensitive fields (passwords, tokens)

drop_record_where_value_eq

Drop Record

Filter records by field value (routing logic)

rename_key

Rename Key

Normalize field names across sources

flatten / flatten-all

Flatten

Flatten nested JSON structures

duplicate_key_value_to_key

Copy Value

Duplicate field values

mutate_value_where_key_eq

Mutate Value

Conditional value transformation

convert_timestamp

Convert Timestamp

Timestamp format conversion (epoch ↔ ISO8601)

add_identifier

Add Identifier

Add unique record ID

create_key_value_if_key_value

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

user.name

Nested field value

Array index

endpoints.0.ip

First endpoint IP

Array query

endpoints.#(status=="active").ip

IP of first active endpoint

All matches

endpoints.(status=="active").ip

All active endpoint IPs

Wildcards

*.name

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:

  1. Drop Info-Level Logs (reduce volume 40-60%)

    Type

    drop_record_where_value_eq

    Key

    severity

    Value

    info

  2. Tag Critical for Sentinel

    Type

    add

    Key

    destination

    Value

    sentinel

  3. Add MITRE Tag for Auth Failures

    Type

    create_key_value_if_key_value

    Condition Key

    event_type

    Condition Value

    auth_failure

    New Key

    mitre_technique

    New Value

    T1078

  4. Normalize Field Names

    Type

    rename_key

    Old Key

    src_ip

    New 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.