Recently I prepared an au2mator Solution to Self Service Azure App Registrations and Enterprise App Management. So I decided to show you a Report of your Enterprise Apps, Owners, and Usage Count with the Logins. So you can easily see which Apps are not used anymore.
Prerequisites
First, we need to create an Azure App to provide all permissions required.
MS Graph References:
- List applications – Microsoft Graph v1.0 | Microsoft Docs
- List signIns – Microsoft Graph v1.0 | Microsoft Docs
- List owners – Microsoft Graph v1.0 | Microsoft Docs
Create an Azure App Registration and add the following GRAPH API Application Permissions
- Application.ReadWrite.All
- Directory.Read.All
- Directory.ReadWrite.All
- AuditLog.Read.All
Create a Secret and copy the Value
If your are not familiar with Azur eapp Regs, and how als this work together, see my Blogs Post for Details:
To learn more from Microsoft GRAPH API, see my Blog Series:
Part 1 – Authentication and Azure App – Use Microsoft Graph API with PowerShell – Part 1 » TechGuy
Part 2 – Oauth2.0 – Use Microsoft Graph API with PowerShell – Part 2 » TechGuy
Part 3 – First Powershell Script to get a Teams Lis and Walkthrough – Use Microsoft Graph API with PowerShell – Part 3 » TechGuy
Part 4 – this one – Use Microsoft Graph API with PowerShell – Part 4 » TechGuy
With all those information, we can take a look at the Script
The Script
$clientID = 'yourClientID'
$tenantId = 'yourTenantID'
$Clientsecret = 'yourSecret'
$BaseURL = "https://graph.microsoft.com/v1.0"
#Enter the Timefram in Days for the Usage
$TimeFrameInDays = 30
#Build a Dateformat for the Filter
$TimeFrameDate = Get-Date -format yyyy-MM-dd ((Get-Date).AddDays(-$TimeFrameInDays))
#Build Array to store PSCustomObject
$Array = @()
#Auth MS Graph API and Get Header
$tokenBody = @{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $clientID
Client_Secret = $Clientsecret
}
$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token" -Method POST -Body $tokenBody
$headers = @{
"Authorization" = "Bearer $($tokenResponse.access_token)"
"Content-type" = "application/json"
}
#Get all Enterprise Apps
$URLGetApplications = "$BaseURL/applications"
$Applications = Invoke-RestMethod -Method GET -Uri $URLGetApplications -Headers $headers
foreach ($App in $Applications.value) {
#Get Sign In/Usage
$SignIns = Invoke-RestMethod -Method GET -Uri "https://graph.microsoft.com/v1.0/auditLogs/signIns?`$filter=appid eq '$($App.appId)' and createdDateTime gt $TimeFrameDate" -Headers $headers
Start-Sleep -Seconds 1
#Get Owners
$URLGetOwner = "$BaseURL/applications/$($App.id)/owners"
$Owner = Invoke-RestMethod -Method GET -Uri $URLGetOwner -Headers $headers
if ($Owner) {
foreach ($O in $Owner.value) {
$Array += [PSCustomObject]@{
"App ID" = $App.id
"App AppID" = $App.appId
"App Name" = $App.displayName
"Owner UPN" = $o.userprincipalname
"Owner Name" = $o.displayName
"Owner ID" = $o.id
"Usage Count" = ($SignIns.value ).count
}
}
}
else {
$Array += [PSCustomObject]@{
"App ID" = $App.id
"App AppID" = $App.appId
"App Name" = $App.displayName
"Owner UPN" = "NONE"
"Owner Name" = "NONE"
"Owner ID" = "NONE"
"Usage Count" = ($SignIns.value ).count
}
}
}
$Array | Select-Object -Property "App Name", "Owner UPN", "Usage Count" | Sort-Object -Property "Usage Count" -Descending
The Result
You will get the following Result
GitHub Repo
Here you can find the GitHub Repo: Seidlm/Microsoft-Azure: Azure Rest API Examples (github.com) with the Script
Michael Seidl aka Techguy
au2mate everything
Will this limit to 100 apps? What do you do if you need to extract all apps?
Hi
will see this week an update the code
Cool, I hope you find a solution 🙂
@Michael @Sven
There was a great session presented by Robert Prüst at PSConfEU 2023 which I can highly recommend:
Diving deeper in the Microsoft Graph API with PowerShell
YouTube Recording:
Diving Deeper in the MS Graph API with PowerShell – solving problems – Robert Prüst – PSConfEU 2023
https://www.youtube.com/watch?v=tA15OwtObC8
Among other, he illustrated how to deal with Paging and Throttling in Microsoft Graph.
See code on GitHub:
https://github.com/psconfeu/2023/blob/main/RobertPrust/Diving%20deeper%20in%20the%20Microsoft%20Graph%20API%20with%20PowerShell/3.%20Paging%20%26%20Throttling.ps1
You can either make use of /?$top=999 (max. 999 – at least for /users end point) to return 999 users.
Or you must deal with paging – the @odata.nextLink
Works in PAYG but not in EA Subscription with same Permissions, maybe the api endpoint is different in EA.
Greeted with 403 on EA while calling the /applications endpoint.(ln 40) , works fine on PAYG
Hi, there should be no difference on the Subscription Type.
This is a great script and thank you for making it available.
Having a couple of issues, I have been trying to work out. I have 250 plus apps, and many have no Owner. The first issue is, I am not getting all the apps from the cmd $Applications = Invoke-RestMethod -Method GET -Uri $URLGetApplications -Headers $headers. I added a $App.displayname to see which ones are being processed. Maybe half of the apps are getting processed.
The second issue is that the output only shows the apps with owners. I never see an output of an app with no owner and displaying a “NONE” for the owner.
Thank you for any help you can provide.
We have more than 200+ apps in our environment. Saw the post to add ?/top=999 to I changed $URLGetApplications = “$BaseURL/applications to $URLGetApplications = “$BaseURL/applications/?$top=999” and still only get the first 100.
Did I miss something or is there another way to get more than 100 apps.
Also I got past the issue of the apps with no owner displaying by changing if ($Owner) to if ($Owner.value.userprincipalname -ne $null). Now the report shows the apps with no owners.
Hi all, I have updated the Github Repo with a new Paging Function, so you get more then 100 Apps
Please see latest GitHub Update.
Please see latest GitHub Update.
Please help, I tried both scripts, the one on this page and the one in github https://github.com/Seidlm/Microsoft-Azure/blob/main/Get%20Enterprise%20Apps.ps1
Both return nothing, no errors, no results…
Hi
an error message would help us to help you 🙂
Got it owork but only returned 165 out about 500 apps, still does not show “NONE” for apps without owners just blanks
Finally got it to work, used this script https://github.com/Seidlm/Microsoft-Azure/blob/main/Get%20Enterprise%20Apps.ps1
Changes:
To show all apps: added /?$top=999 at the end of the following 2 lines:
$URLGetApplications = “$BaseURL/applications
$URLGetOwner = “$BaseURL/applications/$($App.id)/owners
To show apps with no owners =None: changed if ($Owner) to if ($null -ne $Owner.value.userprincipalname)
Still only returning 100 apps even though there are hundreds in the tenant.
please use version from GitHub