rinoxRinox
TIPSIEM

MISP to Microsoft Sentinel Integration

Push MISP threat intelligence into Microsoft Sentinel's Threat Intelligence indicator API so detection rules and workbooks can pivot on IOCs from MISP without manual import. The integration converts MISP attributes into STIX 2.1 indicator objects and submits them via the Sentinel Threat Intelligence Upload Indicators API.

Sentinel's TI API is OAuth2-protected (Entra ID app registration) and expects STIX-shaped indicators. The integration handles both the transformation and the auth flow.

What you get

A real excerpt from a generated MISP-to-Microsoft Sentinel integration. The full script ships with logging, env-var loading, error handling, FIFO-capped dedup state, and a README.

misp_to_sentinel.py
# RINOX INTEGRATION: MISP -> Microsoft Sentinel TI
def to_stix(attr):
    return {
        "type": "indicator",
        "spec_version": "2.1",
        "id": f"indicator--{attr['uuid']}",
        "created": iso_from_ts(attr["timestamp"]),
        "modified": iso_from_ts(attr["timestamp"]),
        "valid_from": iso_from_ts(attr["timestamp"]),
        "pattern": stix_pattern(attr),  # [file:hashes.'SHA-256' = '...']
        "pattern_type": "stix",
        "labels": [attr["category"].lower().replace(" ", "-")],
    }

def deliver(batch):
    token = get_aad_token()  # client_credentials flow, scope=https://management.azure.com/.default
    url = f"https://api.ti.sentinel.azure.com/workspaces/{WS}/threatintelligenceindicators:upload?api-version=2022-07-01"
    resp = requests.post(url, headers={"Authorization": f"Bearer {token}"},
                         json={"sourcesystem": "MISP-Rinox", "indicators": batch})
    return 200 <= resp.status_code < 300

Common pitfalls

The mistakes that turn this integration from "works once" into "loses data silently for three weeks."

  • 01Sentinel's TI API is rate-limited per workspace; chunk submissions at 100 indicators per request and back off on 429.
  • 02STIX `valid_from` and `valid_until` must be RFC 3339. MISP's `timestamp` is UNIX seconds; convert explicitly, do not rely on string serialisation defaults.
  • 03Use the right Entra app permission: `ThreatIndicators.ReadWrite.OwnedBy` for app-only auth. Delegated permissions will not work for unattended cron jobs.
  • 04MISP's `to_ids: false` attributes are intel context, not detection IOCs. Filter them out before submission unless the use case explicitly asks for them.

Generate this for your environment.

Pre-fills the form with MISP and Microsoft Sentinel. You write a sentence about your use case, we write the rest.

Generate MISPMicrosoft Sentinel

Frequently asked

  • Why STIX 2.1 and not plain JSON?

    Sentinel's TI Upload API speaks STIX 2.1 patterns natively. Other Sentinel intel surfaces (the older TI API) accept simpler shapes but the Upload API is the strategic endpoint.

  • What's the right Entra permission?

    `ThreatIndicators.ReadWrite.OwnedBy` on Microsoft Graph, app-only. The script fails fast if the token does not contain it.

  • How does deletion work?

    The script does not delete indicators it previously inserted. Sentinel ages indicators by `valid_until`. Set `MISP_INDICATOR_TTL_DAYS` to populate `valid_until` automatically.

  • Does this support TAXII?

    Not by default — TAXII is an alternative transport. The Upload Indicators API is faster and cheaper for the MISP-to-Sentinel pair, so we use it.