Skip to content

Instantly share code, notes, and snippets.

@ztrhgf
Last active February 20, 2024 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ztrhgf/96445c23b25c1682238b8b52e9218430 to your computer and use it in GitHub Desktop.
Save ztrhgf/96445c23b25c1682238b8b52e9218430 to your computer and use it in GitHub Desktop.
#requires -modules Microsoft.Graph.Intune
function Get-AzureAuditAggregatedSignInEvent {
<#
.SYNOPSIS
Function for getting aggregated types of Azure sign-in logs.
A.k.a. 'User sign-ins (non-interactive)', 'Service principal sign-ins', 'Managed identity sign-ins'.
.DESCRIPTION
Function for getting aggregated types of Azure sign-in logs.
A.k.a. 'User sign-ins (non-interactive)', 'Service principal sign-ins', 'Managed identity sign-ins'.
.PARAMETER type
Type of the sign in logs:
- summarizedUserNonInteractive ('User sign-ins (non-interactive)')
- summarizedServicePrincipal ('Service principal sign-ins')
- summarizedMSI ('Managed identity sign-ins')
.PARAMETER tenantId
Id of your tenant.
.PARAMETER userPrincipalName
(optional) UPN of the user whose sign-ins should be searched.
.PARAMETER appId
(optional) Application ID of the enterprise app whose sign-ins should be searched.
.PARAMETER from
(optional) Date when the search should start.
Only 30 days old events are stored by default anyway.
.PARAMETER to
(optional) Date when the search should end.
.PARAMETER aggregationWindow
How the data should be aggregated:
- 1h
- 6h
- 1d
By default 1d.
.EXAMPLE
Get-AzureAuditAggregatedSignInEvent -type summarizedServicePrincipal -appId 'aca0ba6e-7b50-4aa1-af0e-327222ba584c'
Get all 'Service principal sign-ins' events for selected enterprise app aggregated by 1 day.
.NOTES
Token can be created using (Get-AzAccessToken -ResourceTypeName AadGraph).token.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateSet('summarizedUserNonInteractive', 'summarizedServicePrincipal', 'summarizedMSI')]
[string] $type,
[ValidateNotNullOrEmpty()]
[string] $tenantId = $_tenantId,
[string] $userPrincipalName,
[string] $appId,
[ValidateScript({
if (($_.getType().name -eq "string" -and [DateTime]::Parse($_)) -or ($_.getType().name -eq "dateTime")) {
$true
} else {
throw "Enter in format per your culture. For cs-CZ: 15.2.2019 15:00. For en-US: 2.15.2019 15:00."
}
})]
$from,
[ValidateScript({
if (($_.getType().name -eq "string" -and [DateTime]::Parse($_)) -or ($_.getType().name -eq "dateTime")) {
$true
} else {
throw "Enter in format per your culture. For cs-CZ: 15.2.2019 15:00. For en-US: 2.15.2019 15:00."
}
})]
$to,
[ValidateSet('1d', '1h', '6h')]
[string] $aggregationWindow = '1d'
)
if (!$tenantId) {
throw "TenantId cannot be empty"
}
Connect-MSGraph2 -ErrorAction Stop
(Get-Variable type).Attributes.Clear()
switch ($type) {
'summarizedUserNonInteractive' { $type = 'getSummarizedNonInteractiveSignIns' }
'summarizedServicePrincipal' { $type = 'getSummarizedServicePrincipalSignIns' }
'summarizedMSI' { $type = 'getSummarizedMSISignIns' }
}
if ($from -and $from.getType().name -eq "string") { $from = [DateTime]::Parse($from) }
if ($to -and $to.getType().name -eq "string") { $to = [DateTime]::Parse($to) }
if ($from -and $to -and $from -gt $to) {
throw "From cannot be after To"
}
$filter = @()
if ($userPrincipalName) {
Write-Warning "Beware that filtering by UPN is case sensitive!"
$filter += "UserPrincipalName eq '$userPrincipalName'"
}
if ($appId) {
$filter += "(appId eq '$appId' or contains(tolower(appDisplayName), '$appId'))"
}
if ($from) {
# Azure logs use UTC time
$from = $from.ToUniversalTime()
$filterDateTime = Get-Date -Date $from -Format "yyyy-MM-ddTHH:mm:ss"
$filter += "CreatedDateTime ge $filterDateTime`Z"
}
if ($to) {
# Azure logs use UTC time
$to = $to.ToUniversalTime()
$filterDateTime = Get-Date -Date $to -Format "yyyy-MM-ddTHH:mm:ss"
$filter += "CreatedDateTime le $filterDateTime`Z"
}
$finalFilter = $filter -join ' and '
Write-Verbose "filter: $finalFilter"
$url = "https://graph.windows.net/$tenantId/activities/$type(aggregationWindow='$aggregationWindow')?`$filter=$finalFilter"
Write-Verbose "url: $url"
$url = $url -replace " ", "%20" -replace "'", "%27"
Write-Verbose "escaped url: $url"
$response = Invoke-MSGraphRequest -Url $url
$response.value
$nextLink = $response."@odata.nextLink"
while ($nextLink -ne $null) {
$response = Invoke-MSGraphRequest -Url $nextLink
$nextLink = $response."@odata.nextLink"
$response.value
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment