Skip to main content

Microsoft Graph API

Microsoft Azure Pull

Synopsis

Creates a poller that fetches data from the Microsoft Graph API on a configurable interval and forwards records to downstream pipelines. Supports incremental polling via timestamp cursors or delta queries, automatic pagination, retry logic, and mutual TLS.

Schema

- id: <numeric>
name: <string>
description: <string>
type: graphapi
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
tenant_id: <string>
client_id: <string>
client_secret: <string>
version: <string>
resource: <string>
query_params: <string>
poll_interval: <numeric>
workers: <numeric>
reuse: <boolean>
timeout: <numeric>
max_retries: <numeric>
retry_delay: <numeric>
enable_pagination: <boolean>
max_pages: <numeric>
enable_delta_query: <boolean>
timestamp_field: <string>
tls:
status: <boolean>
cert_name: <string>
key_name: <string>
insecure_skip_verify: <boolean>

Configuration

The following fields are used to define the device:

Device

FieldRequiredDefaultDescription
idYUnique identifier
nameYDevice name
descriptionN-Optional description
typeYMust be graphapi
tagsN-Optional tags
pipelinesN-Optional pre-processor pipelines
statusNtrueEnable/disable the device

Authentication

FieldRequiredDefaultDescription
tenant_idYAzure AD tenant ID
client_idYApp registration client ID
client_secretYApp registration client secret

API

FieldRequiredDefaultDescription
versionNv1.0Graph API version: v1.0 or beta
resourceYGraph API resource path (see Allowed Resources)
query_paramsN""OData query parameters (e.g., $select=id,createdDateTime&$top=100)

Polling

FieldRequiredDefaultDescription
poll_intervalN10Seconds between polls (must be > 0)
workersN1Number of parallel worker goroutines
reuseNtrueReuse HTTP connections across requests

HTTP

FieldRequiredDefaultDescription
timeoutN30Request timeout in seconds
max_retriesN3Number of retry attempts on failure
retry_delayN5Seconds to wait between retries

Pagination

FieldRequiredDefaultDescription
enable_paginationNtrueFollow @odata.nextLink pages automatically
max_pagesN10Maximum pages per poll cycle (0 = unlimited)

Incremental Polling

Two strategies control incremental data retrieval. If both are configured, timestamp_field takes priority.

FieldRequiredDefaultDescription
timestamp_fieldN""JSON field name used as a time-based cursor — injects $filter=<field> ge <lastPollTime> (e.g., createdDateTime)
enable_delta_queryNfalseAppends /$delta to the resource URL for delta query support

TLS

FieldRequiredDefaultDescription
tls.statusNfalseEnable mutual TLS
tls.cert_nameN*client_cert.pemClient certificate file path
tls.key_nameN*client_key.pemClient private key file path
tls.insecure_skip_verifyNfalseSkip server certificate verification

* = Conditionally required (only when tls.status: true)

note

TLS certificate and key files must be placed in the service root directory.

Details

Authentication

The device uses OAuth2 client credentials flow to obtain an access token from Azure AD. Tokens are cached per device/tenant/client combination and automatically refreshed on authentication failure (HTTP 401/403).

Managed Identity

When client_id and client_secret are omitted, the credential provider automatically falls back to Azure Managed Identity. This allows the device to authenticate without explicit credentials when running on an Azure-hosted VM or container with a system-assigned or user-assigned managed identity.

Incremental Polling

Two strategies prevent re-fetching previously collected data:

Timestamp Cursor (timestamp_field): Injects an OData $filter using the poll start time from the previous successful run. Effective for resources that expose a datetime field (e.g., createdDateTime on auditLogs/signIns). The cursor merges with any existing $filter in query_params.

Delta Query (enable_delta_query): Appends /$delta to the resource URL. The Graph API returns an @odata.deltaLink on the final page, which the device stores and uses on the next poll to retrieve only changed records. Supported only by directory resources (users, groups, devices, etc.). If the stored delta link expires or becomes invalid, the device clears it and falls back to a full query.

When both are configured, timestamp_field takes priority. If neither is set, each poll fetches the full result set.

Allowed Resources

The device enforces an allow list of Graph API resource paths. Requests to unlisted resources are rejected. Sub-paths of allowed resources (e.g., auditLogs/directoryAudits/someId) are also accepted.

Audit Logs

ResourceRequired Permission
auditLogs/signInsAuditLog.Read.All
auditLogs/directoryAuditsAuditLog.Read.All
auditLogs/provisioningAuditLog.Read.All

Security

ResourceRequired Permission
security/alertsSecurityEvents.Read.All or SecurityAlert.Read.All
security/alerts_v2SecurityEvents.Read.All or SecurityAlert.Read.All
security/incidentsSecurityEvents.Read.All or SecurityAlert.Read.All
security/secureScoresSecurityEvents.Read.All
security/secureScoreControlProfilesSecurityEvents.Read.All
security/attackSimulationAttackSimulation.Read.All
security/cloudAppSecurityProfilesSecurityEvents.Read.All
security/tiIndicatorsThreatIndicators.Read.All
security/cases/ediscoveryCaseseDiscovery.Read.All
security/threatIntelligence/articlesThreatIntelligence.Read.All
security/threatIntelligence/hostsThreatIntelligence.Read.All

Identity Protection

ResourceRequired Permission
identityProtection/riskDetectionsIdentityRiskEvent.Read.All
identityProtection/riskyUsersIdentityRiskyUser.Read.All
identityProtection/riskyServicePrincipalsIdentityRiskyServicePrincipal.Read.All

Reports

ResourceRequired Permission
reports/getEmailActivityUserDetailReports.Read.All
reports/getEmailActivityCountsReports.Read.All
reports/getEmailAppUsageUserDetailReports.Read.All
reports/getMailboxUsageDetailReports.Read.All
reports/getOffice365ActivationsUserDetailReports.Read.All
reports/getOffice365ActiveUserDetailReports.Read.All
reports/getOffice365GroupsActivityDetailReports.Read.All
reports/getOneDriveActivityUserDetailReports.Read.All
reports/getOneDriveUsageAccountDetailReports.Read.All
reports/getSharePointActivityUserDetailReports.Read.All
reports/getSharePointSiteUsageDetailReports.Read.All
reports/getTeamsUserActivityUserDetailReports.Read.All
reports/getTeamsDeviceUsageUserDetailReports.Read.All
reports/getYammerActivityUserDetailReports.Read.All
reports/authenticationMethods/userRegistrationDetailsReports.Read.All + UserAuthenticationMethod.Read.All
reports/credentialUserRegistrationDetailsReports.Read.All + UserAuthenticationMethod.Read.All
reports/userCredentialUsageDetailsReports.Read.All + UserAuthenticationMethod.Read.All
reports/applicationSignInDetailedSummaryReports.Read.All + AuditLog.Read.All
reports/messageTraceReports.Read.All

Service Announcements

ResourceRequired Permission
admin/serviceAnnouncement/issuesServiceHealth.Read.All
admin/serviceAnnouncement/messagesServiceHealth.Read.All
admin/serviceAnnouncement/healthOverviewsServiceHealth.Read.All

Required Permissions

To cover all allowed resources, add the following Application permissions to the Azure App Registration and grant admin consent:

  • AuditLog.Read.All
  • SecurityEvents.Read.All
  • SecurityAlert.Read.All
  • AttackSimulation.Read.All
  • ThreatIndicators.Read.All
  • eDiscovery.Read.All
  • ThreatIntelligence.Read.All
  • IdentityRiskEvent.Read.All
  • IdentityRiskyUser.Read.All
  • IdentityRiskyServicePrincipal.Read.All
  • Reports.Read.All
  • UserAuthenticationMethod.Read.All
  • ServiceHealth.Read.All
note

All permissions require admin consent. After adding them in the Azure portal, click Grant admin consent for [your tenant] to activate them. Only add permissions for the resources you intend to poll.

Examples

The following are commonly used configuration types.

Basic

Polling sign-in logs with a timestamp cursor for incremental collection...

devices:
- id: 1
name: graphapi_signins
type: graphapi
properties:
tenant_id: "00000000-0000-0000-0000-000000000000"
client_id: "11111111-1111-1111-1111-111111111111"
client_secret: "your-client-secret"
resource: "auditLogs/signIns"
poll_interval: 30
timestamp_field: "createdDateTime"

Delta Query

Using delta query for directory resources to fetch only changed records...

devices:
- id: 2
name: graphapi_users
type: graphapi
properties:
tenant_id: "00000000-0000-0000-0000-000000000000"
client_id: "11111111-1111-1111-1111-111111111111"
client_secret: "your-client-secret"
resource: "security/alerts_v2"
query_params: "$select=id,title,severity,status,createdDateTime"
enable_delta_query: true
poll_interval: 60

Security Alerts

Collecting security alerts with OData filtering and preprocessing pipelines...

devices:
- id: 3
name: graphapi_alerts
type: graphapi
pipelines:
- alert_enricher
- severity_classifier
properties:
tenant_id: "00000000-0000-0000-0000-000000000000"
client_id: "11111111-1111-1111-1111-111111111111"
client_secret: "your-client-secret"
version: "v1.0"
resource: "security/incidents"
query_params: "$filter=severity eq 'high'"
poll_interval: 15
timestamp_field: "createdDateTime"

High-Volume

Optimizing for high data volumes with multiple workers and increased pagination...

devices:
- id: 4
name: graphapi_reports
type: graphapi
properties:
tenant_id: "00000000-0000-0000-0000-000000000000"
client_id: "11111111-1111-1111-1111-111111111111"
client_secret: "your-client-secret"
resource: "reports/getOffice365ActiveUserDetail"
poll_interval: 300
workers: 4
timeout: 60
max_retries: 5
max_pages: 50

Secure Connection

Enabling mutual TLS for outbound Graph API requests...

devices:
- id: 5
name: graphapi_secure
type: graphapi
properties:
tenant_id: "00000000-0000-0000-0000-000000000000"
client_id: "11111111-1111-1111-1111-111111111111"
client_secret: "your-client-secret"
resource: "identityProtection/riskDetections"
poll_interval: 60
timestamp_field: "activityDateTime"
tls:
status: true
cert_name: "graphapi.crt"
key_name: "graphapi.key"