Last active
August 24, 2024 05:15
-
-
Save darrenjrobinson/d9e7828013fb3d8c970388cd54c27201 to your computer and use it in GitHub Desktop.
Enumerate Azure AD Registered Apps for expiring credentials and sign-in activity. Associated blogpost https://blog.darrenjrobinson.com/auditing-azure-ad-registered-applications/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Creds | |
$tenantID = 'yourAADTenantID' | |
$clientID = 'aadAppID' | |
$clientSecret = (ConvertTo-SecureString 'aadAppSecret' -AsPlainText -Force) | |
$accessToken = Get-MsalToken -clientID $clientID -clientSecret $clientSecret -tenantID $tenantID | Select-Object -Property AccessToken | |
# MS Graph Apps URI | |
$aadAppsURI = 'https://graph.microsoft.com/v1.0/applications' | |
# Get Expiring Creds in x Days | |
$expiryCheck = 60 | |
$now = (Get-Date).ToUniversalTime() | |
$expiryLimit = $now.AddDays($expiryCheck) | |
# MS Graph Directory Audit URI | |
$signInsURI = 'https://graph.microsoft.com/beta/auditLogs/directoryAudits' | |
# Report Template | |
$aadAppReportTemplate = [pscustomobject][ordered]@{ | |
displayName = $null | |
createdDateTime = $null | |
signInAudience = $null | |
} | |
# Get Apps | |
$aadApplications = @() | |
$aadApps = Invoke-RestMethod -Headers @{Authorization = "Bearer $($accessToken.AccessToken)" } ` | |
-Uri $aadAppsURI ` | |
-Method Get | |
$aadApps.value.Count | |
if ($aadApps.value) { | |
$aadApplications += $aadApps.value | |
# More Apps? | |
if ($aadApps.'@odata.nextLink') { | |
$nextPageURI = $aadApps.'@odata.nextLink' | |
do { | |
$aadApps = $null | |
$aadApps = Invoke-RestMethod -Headers @{Authorization = "Bearer $($accessToken.AccessToken)" } ` | |
-Uri $nextPageURI ` | |
-Method Get | |
if ($aadApps.value) { | |
$aadApplications += $aadApps.value | |
$aadApplications.value.Count | |
} | |
if ($aadApps.'@odata.nextLink') { | |
$nextPageURI = $aadApps.'@odata.nextLink' | |
} | |
else { | |
$nextPageURI = $null | |
} | |
} until (!$nextPageURI) | |
} | |
} | |
$aadApplications = $aadApplications | Sort-Object -Property createdDateTime -Descending | |
$aadAppsReport = @() | |
$expiringCredsApps = @() | |
foreach ($app in $aadApplications) { | |
$blnExpiringCreds = $false | |
# Report Output | |
$reportData = $aadAppReportTemplate.PsObject.Copy() | |
$reportData.displayName = $app.displayName | |
$reportData.createdDateTime = $app.createdDateTime | |
$reportData.signInAudience = $app.signInAudience | |
# Key Expiry | |
if ($app.keyCredentials) { | |
$keys = @() | |
foreach ($cred in $app.keyCredentials) { | |
[datetime]$keyExpiry = $cred.endDateTime | |
if ($keyExpiry -lt $expiryLimit) { | |
Write-Warning "$($app.displayName): Key expired/expiring on $($keyExpiry)" | |
$blnExpiringCreds = $true | |
} | |
$keys += $app.keyCredentials | Select-Object -Property @{Name = 'displayName'; Expression = { $cred.displayName } }, @{Name = 'keyId'; Expression = { $cred.keyId } }, @{Name = 'startDateTime'; Expression = { $cred.startDateTime } }, @{Name = 'endDateTime'; Expression = { $cred.endDateTime } } | |
} | |
$reportData | Add-Member -Type NoteProperty -Name "keyCredentials" -Value @($keys) | |
} | |
# Password Expiry | |
if ($app.passwordCredentials) { | |
$passwords = @() | |
foreach ($cred in $app.passwordCredentials) { | |
[datetime]$keyExpiry = $cred.endDateTime | |
if ($keyExpiry -lt $expiryLimit) { | |
Write-Warning "$($app.displayName): Password expired/expiring on $($keyExpiry)" | |
$blnExpiringCreds = $true | |
} | |
$passwords += $app.passwordCredentials | Select-Object -Property @{Name = 'displayName'; Expression = { $cred.displayName } }, @{Name = 'keyId'; Expression = { $cred.keyId } }, @{Name = 'startDateTime'; Expression = { $cred.startDateTime } }, @{Name = 'endDateTime'; Expression = { $cred.endDateTime } } | |
} | |
$reportData | Add-Member -Type NoteProperty -Name "passwordCredentials" -Value @($passwords) | |
} | |
# SignIns | |
$appSignIns = $null | |
$appSignIns = Invoke-RestMethod -Headers @{Authorization = "Bearer $($accessToken.AccessToken)" } ` | |
-Uri "$($signInsURI)?&`$filter=targetResources/any(t: t/id eq `'$($app.id)`')" ` | |
-Method Get | |
if ($appSignIns.value) { | |
"$($app.displayName): $($appSignIns.value.Count) recent signIns" | |
$reportData | Add-Member -Type NoteProperty -Name "recentSignIns" -Value $appSignIns.value.Count | |
} | |
else { | |
"$($app.displayName): $($appSignIns.value.Count) recent signIns" | |
$reportData | Add-Member -Type NoteProperty -Name "recentSignIns" -Value '0' | |
} | |
$aadAppsReport += $reportData | |
if ($blnExpiringCreds) { | |
$expiringCredsApps += $reportData | |
} | |
} | |
$expiringCredsApps.count | |
$expiringCredsApps | Format-Table | |
# Report | |
$aadAppsReport | Format-Table -AutoSize |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment