Working with the Security API (Microsoft Defender XDR)¶
Microsoft Graph exposes one Security API — the /security endpoint
(client.security) — and Microsoft Defender XDR is its main product:
incidents, alerts and advanced hunting. The same endpoint also carries
Microsoft Secure Score, Defender Threat Intelligence, attack-simulation
training, and — used by Purview — eDiscovery, cases, retention
labels and subject-rights requests.
So "Defender" is what you buy; client.security is what you call. This
folder is the guided tour of that endpoint; every script runs against your tenant
and (mostly) only reads, so it's safe to try.
The model in one picture¶
flowchart LR
S["client.security"] --> A["alerts_v2<br/>(detections)"]
S --> I["incidents<br/>(alert groups)"]
S --> H["run_hunting_query<br/>(KQL)"]
S --> SS["secure_score_control_profiles"]
S --> TI["threat_intelligence"]
S --> AS["attack_simulation"]
I --> A
An incident groups related alerts; alerts carry evidence (devices, users, files, processes). Hunting queries read the raw tables those detections were built from.
Start here¶
Alerts — the detections¶
alerts_v2 is the current alert API (alerts and their evidence in one shape).
List them, filter by status, then triage by setting classification and status.
alerts = client.security.alerts_v2.top(20).get().execute_query()
alert = client.security.alerts_v2[alert_id].get().execute_query()
alert.set_property("classification", "truePositive")
alert.set_property("status", "resolved")
alert.update().execute_query()
→ alerts.py (list/filter) · alerts_triage.py (classify & resolve)
Incidents — grouped investigations¶
incidents = client.security.incidents.filter("status eq 'active'").get().execute_query()
incident = client.security.incidents[incident_id].expand(["alerts"]).get().execute_query()
→ incidents.py · incident_details.py (alerts expanded)
· update_incident.py (status, classification, assignment)
· incident_attack_story.py (summarize the evidence)
Advanced hunting — ask your own questions¶
result = client.security.run_hunting_query(
"DeviceProcessEvents | where FileName == 'powershell.exe' | take 50"
).execute_query()
Secure Score — posture & improvements¶
Threat intelligence — enrich an indicator¶
ti = client.security.threat_intelligence
host = ti.hosts["contoso.com"].get().execute_query()
print(host.properties.get("firstSeenDateTime"), ti.intel_profiles.get().execute_query())
Attack simulation — phishing & training¶
sim = client.security.attack_simulation
for campaign in sim.simulations.get().execute_query():
print(campaign.properties.get("displayName"), campaign.properties.get("status"))
Permissions¶
Pick the narrowest that works; security scopes need admin consent.
| Permission | Grants |
|---|---|
SecurityAlert.Read.All / .ReadWrite.All |
Read / triage alerts |
SecurityIncident.Read.All / .ReadWrite.All |
Read / update incidents |
ThreatHunting.Read.All |
Run advanced hunting queries |
SecurityEvents.Read.All |
Secure Score control profiles |
ThreatIntelligence.Read.All |
Threat-intelligence indicators |
AttackSimulation.Read.All |
Attack-simulation campaigns |
Related¶
| Folder | What it covers |
|---|---|
../purview/ |
eDiscovery, records, retention labels, subject rights (also client.security.*) |
../entraid/audit/ |
Directory audit and sign-in logs |