Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tora1104/e5419a1768d935d40f35bfacce1e60b3 to your computer and use it in GitHub Desktop.
Save tora1104/e5419a1768d935d40f35bfacce1e60b3 to your computer and use it in GitHub Desktop.
PowerShell script using the Microsoft Function App and Microsoft Graph REST API to retrieve Azure AD Risk Detection events with email notification. Go to https://medium.com/@zaab_it/azure-ad-risky-sign-ins-email-notification-6cbfac32f6de for more details. Rewritten with Risk Detections as Risky Sign Ins is no longer supported in Azure.
<#
Changes from the original
This script retrieves Azure Active Directory Risk Detection Events as Azure no longer supports the Risky Sign Ons. Only the At Risk and Confirmed Compromised events from the last 3 days will be sent.
Removed the ipInfo portion.
#>
$ClientID = $env:ClientID
$ClientSecret = $env:ClientSecret
$tenantDomain = $env:TenantDomain
$emailSender = $env:EmailSender
$emailRecipient = $env:EmailRecipient
$emailSubject = "Azure AD Risk Detections Report $(Get-Date -Format MM/dd/yyyy)"
$emailBody = "<h1>Azure Active Directory Risk Detections Report</h1>`n"
#$emailBody += "<p>Date: $(Get-Date)</p>`n"
#$emailBody += "<p>Tenant: $($tenantdomain)</p>`n"
$emailBody += "<p>More detail at: <a href='https://portal.azure.com/#blade/Microsoft_AAD_IAM/SecurityMenuBlade/RiskDetections' target='_blank'>Azure AD Risk Detections</a></p>`n"
$emailBody += "<br>`n"
$loginURL = "https://login.microsoft.com"
$resource = "https://graph.microsoft.com"
$body = @{grant_type="client_credentials";resource=$resource;client_id=$ClientID;client_secret=$ClientSecret}
$oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$tenantdomain/oauth2/token?api-version=1.0 -Body $body
if ($oauth.access_token -ne $null) {
$reqBody='{
"message": {
"subject": "",
"body": {
"contentType": "",
"content": ""
},
"toRecipients": [
{
"emailAddress": {
"address": ""
}
}
]
}
}' | ConvertFrom-Json
$reqBody.message.subject = $emailSubject
$reqBody.message.body.contentType = "Html"
$reqBody.message.toRecipients.emailAddress.address = $emailRecipient
$headerParams = @{'Authorization'="$($oauth.token_type) $($oauth.access_token)"}
#email will contain only risk state of atRisk or confirmedCompromised
[uri]$uriGraphEndpoint = "https://graph.microsoft.com/beta/riskDetections?`$filter=activityDateTime gt $(Get-Date -date (Get-Date).AddDays(-3).ToUniversalTime() -Format o) and (riskState eq 'atRisk' or riskState eq 'confirmedCompromised') "
$response = Invoke-RestMethod -Method Get -Uri $uriGraphEndpoint.AbsoluteUri -Headers $headerParams
if ($response.value -ne $null) {
#sorts the list in the email by most recent first
$sortedResponses = $response.value | Sort-Object activityDateTime -Descending
#adjusts time to CST
$timeZone = [System.TimeZoneInfo]::FindSystemTimeZoneById("Central Standard Time")
foreach ( $event in $sortedResponses ) {
#changes the time of activityDateTime to CST
$eventTimeInCst = [System.TimeZoneInfo]::ConvertTimeFromUtc($event.activityDateTime, $timeZone)
$emailBody += "<p>`n"
$emailBody += "User: $($event.userDisplayName)<br>`n"
$emailBody += "UserPrincipalName: $($event.userPrincipalName)<br>`n"
$emailBody += "Event time: $eventTimeInCst<br>`n"
$emailBody += "Risk type: $($event.riskEventType)<br>`n"
$emailBody += "Risk state: $($event.riskState)<br>`n"
$emailBody += "IP address: $($event.ipAddress)<br>"
$emailBody += "Location: $($event.location)<br>"
$emailBody += "</p>`n"
}
$reqBody.message.body.content = $emailBody
Invoke-RestMethod -Method Post -Uri "https://graph.microsoft.com/v1.0/users/$($emailSender)/sendMail" -Headers @{'Authorization'="$($oauth.token_type) $($oauth.access_token)"; 'Content-type'="application/json"} -Body ($reqBody | ConvertTo-Json -Depth 4 | Out-String)
}
else {
$emailBody += "<p>No risk detection events.</p>"
$reqBody.message.body.content = $emailBody
Invoke-RestMethod -Method Post -Uri "https://graph.microsoft.com/v1.0/users/$($emailSender)/sendMail" -Headers @{'Authorization'="$($oauth.token_type) $($oauth.access_token)"; 'Content-type'="application/json"} -Body ($reqBody | ConvertTo-Json -Depth 4 | Out-String)
}
}
else {
Write-Output "ERROR: No Access Token"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment