At a glance

VendorMicrosoft Defender for Endpoint (part of Microsoft 365 Defender)
Source typeedr
Vendor ID (slug)defender-for-endpoint
Base URLhttps://graph.microsoft.com/v1.0 — commercial cloud. US Gov / China / Germany customers override this manually.
Auth methodoauth2 — client-credentials flow. Draxis mints an Authorization: Bearer <access_token> per run against https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token.
Schedule defaultdaily — override to hourly for tighter response on incident and malware KRIs.
LicensingDefender for Endpoint Plan 1 or Plan 2. All seven KRIs require a tenant onboarded to MDE — the per-device KRIs run against the advanced-hunting tables (DeviceInfo, DeviceTvm*, DeviceEvents) which only populate for MDE tenants. Plan 2 is required for advanced hunting on TVM tables (missing patches, tamper protection).
AvailabilityNew in 2026.04.

Required scopes & roles

Draxis authenticates as an Entra ID app registration using the client-credentials flow — no user is impersonated. All KRIs are derived from Microsoft Graph, which means exactly three Application permissions (all Read.All, all requiring admin consent):

  • SecurityIncident.Read.All — list incidents with severity and status. Backs GET /security/incidents. Used for the high-severity-open-incidents KRI.
  • SecurityAlert.Read.All — list unified (alerts_v2) security alerts. Backs GET /security/alerts_v2. Used for the unresolved-malware-dwell KRI.
  • ThreatHunting.Read.All — run advanced-hunting KQL queries against Defender telemetry tables. Backs POST /security/runHuntingQuery. Used for the five device-posture KRIs (onboarding, stale devices, tamper protection, missing patches, ASR violations).

Do not grant the app any ReadWrite.All variant, Global Administrator, or Security Administrator role membership. Draxis never writes to incidents, alerts, or Defender config.

Setup steps

  1. Register the app. In the Entra admin center go to Identity → Applications → App registrations → New registration. Name it Draxis Defender Reader. Supported account types: Single tenant. Redirect URI: leave blank. Click Register.
  2. Copy the two IDs you’ll need from the app's Overview page:
    • Application (client) ID — you’ll paste this into Draxis’s Client ID field.
    • Directory (tenant) ID — you’ll paste this into Draxis’s Extra Config JSON.
    If you already have a shared Draxis app registration for Entra ID, you can reuse it — just add the three permissions below. One app per Microsoft service works too; choose based on your rotation/audit preferences.
  3. Create a client secret. Go to Certificates & secrets → Client secrets → New client secret. Name it draxis-connector, pick a rotation window that matches your policy (Microsoft caps at 24 months), and copy the secret Valuenot the Secret ID. You can’t retrieve this value later; if you lose it, create a new secret.
  4. Add the Graph permissions. Go to API permissions → Add a permission → Microsoft Graph → Application permissions. Search for and add each of these three permissions exactly:
    SecurityIncident.Read.All
    SecurityAlert.Read.All
    ThreatHunting.Read.All
    Do not add the Delegated variants — client-credentials flows can only use Application permissions.
  5. Grant admin consent. Back on the API permissions page, click Grant admin consent for <your tenant>. The status column should flip to green checkmarks for all three. If the button is disabled, ask a Global Administrator or Privileged Role Administrator to perform the consent.
  6. (Optional) Restrict by IP. Under Authentication → Conditional Access on the app, require requests to come from your corporate network or from the Draxis egress range. Skip this on first setup and add it after you’ve confirmed the connector works.

Wire it into Draxis

  1. Open Settings → Integrations in your tenant.
  2. Click Add integration and pick Endpoint Detection & Response as the source type.
  3. Pick Microsoft Defender for Endpoint (M365 Defender) from the vendor dropdown. Draxis auto-fills the Graph base URL, the OAuth auth method, the daily schedule, and seeds extra_config_json with {"tenant_id":""}.
  4. In Client ID, paste the Application (client) ID from step 2.
  5. In Client Secret, paste the secret Value from step 3. Draxis encrypts it server-side with encryption.key before storage.
  6. In the Extra Config JSON field, replace the empty tenant_id with your Directory (tenant) ID from step 2, e.g. {"tenant_id":"00000000-0000-0000-0000-000000000000"}.
  7. Click Test. Green means Draxis exchanged the credentials for an access token and listed an incident record successfully.
  8. Under KRIs to import, tick the KRIs you want Draxis to manage. All seven mde_* KRIs are checked by default; uncheck any you don’t need (for instance, a Plan 1 tenant will want to uncheck the TVM-dependent KRIs — see Quirks). Selected rows are created on save with the seeded thresholds. Unchecking a previously-imported KRI deletes it on save.
  9. Save. The connector runs daily by default; use Run now from run history to trigger the first sync immediately.

KRIs produced

SlugMeaningDerivation
mde_devices_not_onboarded Count of devices Defender sees but that are not fully onboarded Advanced-hunting KQL: DeviceInfo | where Timestamp > ago(7d) | summarize arg_max(Timestamp, OnboardingStatus) by DeviceId | where OnboardingStatus != "Onboarded" | count
mde_incidents_high_open Open (non-resolved) incidents with severity high — Graph’s top tier GET /security/incidents?$filter=severity eq 'high' and status ne 'resolved', count the returned page (Graph caps severity at high; it has no critical enum value)
mde_critical_missing_patches Distinct devices with at least one critical software vulnerability Advanced-hunting KQL: DeviceTvmSoftwareVulnerabilities | where VulnerabilitySeverityLevel == "Critical" | summarize dcount(DeviceId)
mde_asr_rule_violations_24h Attack-surface-reduction rules that blocked activity in the last 24h Advanced-hunting KQL: DeviceEvents | where Timestamp > ago(24h) | where ActionType startswith "Asr" and ActionType endswith "Blocked" | count
mde_tamper_protection_disabled Distinct devices non-compliant with the tamper-protection secure-config item Advanced-hunting KQL: DeviceTvmSecureConfigurationAssessment | where ConfigurationId == "scid-2011" | where IsApplicable == 1 | where IsCompliant == 0 | summarize dcount(DeviceId)
mde_devices_stale_7d Devices whose latest DeviceInfo telemetry is older than 7 days Advanced-hunting KQL: DeviceInfo | summarize LastSeen = max(Timestamp) by DeviceId | where LastSeen < ago(7d) | count
mde_malware_unresolved_24h_plus Open malware alerts that have been unresolved for more than 24 hours GET /security/alerts_v2?$filter=category eq 'Malware' and status ne 'resolved' and createdDateTime lt <now-24h>, count the returned page

Each row is a slug the connector writes to. Draxis creates the matching kri rows automatically when you check them in the KRIs to import section of the integration form — no manual API call or seed script needed. Thresholds shown in the table are the seeded defaults; you can edit them freely in the KRIs tab afterwards.

Vendor quirks

  • Graph incidents cap at severity = 'high'. Unlike the legacy MDE portal, Graph's /security/incidents has no critical enum value — its severity ladder is informational | low | medium | high. The KRI slug is mde_incidents_high_open to match what the API actually returns. If you were hoping to split high vs. critical, configure distinct thresholds on the same value instead.
  • Advanced hunting requires tables that only exist on MDE tenants. DeviceInfo, DeviceEvents, and the DeviceTvm* family are populated only for devices onboarded to Defender for Endpoint. A tenant running only Defender for Office 365 (email/identity) will see the hunting queries return zero with no error — the connector logs a warn per failed hunting KRI and still writes the incident/alert KRIs that didn’t depend on hunting.
  • TVM tables require Plan 2. DeviceTvmSoftwareVulnerabilities and DeviceTvmSecureConfigurationAssessment are Threat & Vulnerability Management tables — they populate only for Defender for Endpoint Plan 2. On a Plan 1 tenant the missing-patches and tamper-protection KRIs record as 0; switch to P2 to light them up.
  • ASR KRI is a count of events, not devices. A single misconfigured endpoint can drive this number high on its own if it’s constantly tripping the same rule. Pair the threshold with the stale-devices or onboarding KRI to catch that case.
  • Tamper protection is keyed on scid-2011. Microsoft occasionally renumbers secure-configuration items; if that ID stops matching, this KRI will go to 0 without erroring. Our quarterly smoke test catches these changes — open a support ticket if you see it flatline after a Microsoft portal redesign.
  • Hunting rate limits are real. Graph caps advanced hunting at 45 calls per minute per app-tenant pair and 1000 calls per day. With five hunting KRIs per run on a daily schedule this is nowhere close to the limit, but if you drop the schedule to minutely across many tenants you’ll hit it. Stay at daily or hourly.
  • Client secrets expire. Microsoft caps client-secret lifetime at 24 months. When it expires, every run fails with 401 at token exchange — the Entra portal will not warn you. Schedule a rotation in your calendar.
  • Non-commercial clouds. For US Government, China (21Vianet), or Germany, override the Graph base URL to the correct sovereign endpoint before saving. The token endpoint also differs; the connector currently assumes login.microsoftonline.com — support sovereign clouds via a feature request if you need it.

Troubleshooting

  • HTTP 401 on Test with invalid_client — the client secret is wrong (you copied the Secret ID instead of the Value) or has expired. Generate a new secret and update Draxis.
  • HTTP 401 on Test with AADSTS90002 — the tenant ID in Extra Config is wrong. Copy the Directory (tenant) ID from the app registration’s Overview page.
  • HTTP 403 with Insufficient privileges — a Graph permission is missing or admin consent hasn’t been granted. Re-open API permissions and confirm all three are green-checked.
  • Hunting KRIs all record as 0 but incident/alert KRIs look correct — the tenant isn’t onboarded to Defender for Endpoint, or the onboarded devices haven't emitted enough telemetry yet. The run log will include one warn line per failed hunting query explaining why (typically a 400 stating the table doesn’t exist).
  • mde_critical_missing_patches and mde_tamper_protection_disabled are 0 but other hunting KRIs work — tenant is on Plan 1, not Plan 2. The TVM tables require P2 licensing.
  • rowsSkipped > 0 and rowsWritten = 0 — your tenant hasn’t imported any KRIs for this integration yet. Open the integration in Settings → Integrations, tick the KRIs under KRIs to import, and save.
  • Still stuck? Open a support ticket with the run ID (from Run history) and we’ll dig in.