Created
May 30, 2023 19:10
-
-
Save TiloGit/4a2768fff5fc1b53b4976252d21e89e2 to your computer and use it in GitHub Desktop.
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
##based on https://github.com/12Knocksinna/Office365itpros/blob/master/ReportPermissionsApps.PS1 | |
# | |
# ReportPermissionsApps.PS1 | |
# A script using Azure Automation and a managed identity to scan for apps assigned high-priority permissions and report them | |
# for administrator review | |
##install graph PS | |
Install-Module Microsoft.Graph -Scope CurrentUser | |
#Connect-AzAccount -Identity | |
$AccessToken = Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com" | |
Connect-MgGraph -AccessToken $AccessToken.Token | |
#Define the desired graph endpoint | |
Select-MgProfile Beta | |
# Define Output Files - only used if executed interactively | |
#$OutputFile = "c:\temp\AppsAndPermissions.csv" | |
#$OutputFile2 = "c:\temp\AppsForReview.csv" | |
$OutputFile = "/home/tilo/AppsAndPermissions.csv" | |
$OutputFile2 = "/home/tilo/AppsForReview.csv" | |
# Get tenant information | |
$Tenant = (Get-MgOrganization) | |
$TenantId = $Tenant.Id | |
$TenantName = $Tenant.DisplayName | |
# Define the set of high-priority permissions we're interested in | |
[array]$HighPriorityPermissions = "User.Read.All", "User.ReadWrite.All", "Mail.ReadWrite", ` | |
"Files.ReadWrite.All", "Calendars.ReadWrite", "Mail.Send", "User.Export.All", "Directory.Read.All", ` | |
"Exchange.ManageAsApp", "Directory.ReadWrite.All", "Sites.ReadWrite.All" | |
# Define check period for new service principals | |
[datetime]$CheckforRecent = (Get-Date).AddDays(-360) | |
# Populate a set of hash tables with permissions used for different Office 365 management functions | |
$GraphApp = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'" | |
# Populate hash table with Graph permissions | |
$GraphRoles = @{} | |
ForEach ($Role in $GraphApp.AppRoles) { $GraphRoles.Add([string]$Role.Id, [string]$Role.Value) } | |
# Populate hash table with Exchange Online permissions | |
$ExoPermissions = @{} | |
$ExoApp = Get-MgServicePrincipal -Filter "AppId eq '00000002-0000-0ff1-ce00-000000000000'" | |
ForEach ($Role in $ExoApp.AppRoles) { $ExoPermissions.Add([string]$Role.Id, [string]$Role.Value) } | |
$O365Permissions = @{} | |
$O365API = Get-MgServicePrincipal -Filter "DisplayName eq 'Office 365 Management APIs'" | |
ForEach ($Role in $O365API.AppRoles) { $O365Permissions.Add([string]$Role.Id, [string]$Role.Value) } | |
$AzureADPermissions = @{} | |
$AzureAD = Get-MgServicePrincipal -Filter "DisplayName eq 'Windows Azure Active Directory'" | |
ForEach ($Role in $AzureAD.AppRoles) { $AzureADPermissions.Add([string]$Role.Id, [string]$Role.Value) } | |
$TeamsPermissions = @{} | |
$TeamsApp = Get-MgServicePrincipal -Filter "DisplayName eq 'Skype and Teams Tenant Admin API'" | |
ForEach ($Role in $TeamsApp.AppRoles) { $TeamsPermissions.Add([string]$Role.Id, [string]$Role.Value) } | |
$RightsManagementPermissions = @{} | |
$RightsManagementApp = Get-MgServicePrincipal -Filter "DisplayName eq 'Microsoft Rights Management Services'" | |
ForEach ($Role in $RightsManagementApp.AppRoles) { $RightsManagementPermissions.Add([string]$Role.Id, [string]$Role.Value) } | |
# Create output tables | |
$Report = [System.Collections.Generic.List[Object]]::new() | |
$ProblemApps = [System.Collections.Generic.List[Object]]::new() | |
# Find all service principals belonging to registered apps | |
[array]$SPs = Get-MgServicePrincipal -top 999 -Filter "Tags/any(t:t eq 'WindowsAzureActiveDirectoryIntegratedApp')" | |
# And those for managed identities | |
[array]$ManagedIdentities = Get-MgServicePrincipal -top 999 -Filter "ServicePrincipalType eq 'ManagedIdentity'" | |
[array]$Apps = $SPs + $ManagedIdentities | |
# Loop through the apps and managed identities we've found to resolve the permissions assigned to each app | |
Write-Output ("{0} service principals for Azure AD registered apps found" -f $Apps.Count) | |
$i = 0 | |
ForEach ($App in $Apps) { | |
$i++; $AppRecentFlag = $False | |
Write-Output ("Processing app {0} {1}/{2}" -f $App.DisplayName, $i, $Apps.Count) | |
if ($App.AdditionalProperties.createdDateTime) { | |
Write-Output "createdDateTime not null." | |
[datetime]$AppCreationDate = $App.AdditionalProperties.createdDateTime | |
} | |
else{ | |
Write-Output "createdDateTime is null. set to 1970" | |
[datetime]$AppCreationDate = '1970-01-01' | |
} | |
If ($AppCreationDate -gt $CheckforRecent) {$AppRecentFlag = $True} | |
[array]$AppRoles = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $App.Id | |
If ($AppRoles) { | |
ForEach ($AppRole in $AppRoles) { | |
$Permission = $Null | |
Switch ($AppRole.ResourceDisplayName) { | |
"Microsoft Graph" { | |
[string]$Permission = $GraphRoles[$AppRole.AppRoleId] } | |
"Office 365 Exchange Online" { | |
[string]$Permission = $ExoPermissions[$AppRole.AppRoleId] } | |
"Office 365 Management APIs" { | |
[string]$Permission = $O365Permissions[$AppRole.AppRoleId] } | |
"Windows Azure Active Directory" { | |
[string]$Permission = $AzureADPermissions[$AppRole.AppRoleId] } | |
"Skype and Teams Tenant Admin API" { | |
[string]$Permission = $TeamsPermissions[$AppRole.AppRoleId] } | |
"Microsoft Rights Management Services" { | |
[string]$Permission = $RightsManagementPermissions[$AppRole.AppRoleId] } | |
} | |
If ($App.ServicePrincipalType -ne "ManagedIdentity") { | |
If ($App.AppOwnerOrganizationId -eq $TenantId) { #Resolve tenant name | |
$Name = $TenantName } | |
Else { | |
$LookUpId = $App.AppOwnerOrganizationId.toString() | |
$Uri = "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='$LookUpId')" | |
$ExternalTenantData = Invoke-MgGraphRequest -Uri $Uri -Method Get | |
$Name = $ExternalTenantData.DisplayName } | |
$VerifiedPublisher = $Null | |
If ($App.AdditionalProperties["verifiedpublisher"]) { $VerifiedPublisher = $App.AdditionalProperties["verifiedpublisher"] } | |
} | |
$ReportLine = [PSCustomObject] @{ | |
DisplayName = $App.DisplayName | |
ServicePrincipalId = $App.Id | |
Publisher = $App.PublisherName | |
VerifiedPublisher = $VerifiedPublisher | |
Homepage = $App.Homepage | |
OwnerOrgId = $App.AppOwnerOrganizationId | |
OwnerOrgName = $Name | |
AppRoleId = $AppRole.AppRoleId | |
AppRoleCreation = $AppRole.CreationTimeStamp | |
Id = $AppRole.Id | |
Resource = $AppRole.ResourceDisplayName | |
ResourceId = $AppRole.ResourceId | |
Permission = $Permission | |
SPType = $App.ServicePrincipalType | |
CreatedDate = Get-Date($AppCreationDate) -format g | |
RecentApp = $AppRecentFlag } | |
$Report.Add($ReportLine) } | |
} # End ForEach AppRole | |
} #End ForEach App | |
Write-Output ("{0} apps scanned and {1} permissions found" -f $Apps.Count, $Report.Count) | |
Write-Output "" | |
Write-Output "Permissions found" | |
Write-Output "-----------------" | |
Write-Output "" | |
$Report | Group Permission | Sort-Object Name | Format-Table Name, Count | |
# Uncomment the next two lines if you want to generate the output file (interactive use only) | |
$Report | Export-CSV -NoTypeInformation $OutputFile | |
Write-Output ("Full permissions report is available in {0}" -f $OutputFile) | |
ForEach ($Record in $Report) { | |
If ($Record.Permission -in $HighPriorityPermissions) { | |
$ProblemApps.Add($Record) } | |
} | |
# Uncomment the next two lines if you want to generate the report about problem apps | |
$ProblemApps | Export-CSV -NoTypeInformation $OutputFile2 | |
Write-Output ("List of apps for review is available in {0}" -f $OutputFile2) | |
[array]$AppSet = $ProblemApps | Sort-Object ServicePrincipalId -Unique | |
$AppOutput = [System.Collections.Generic.List[Object]]::new() | |
ForEach ($App in $AppSet) { | |
$Records = $ProblemApps | Where-Object {$_.ServicePrincipalId -eq $App.ServicePrincipalId} | |
$AppPermissions = $Records.Permission -join ", " | |
$ReportLine = [PSCustomObject] @{ | |
DisplayName = $App.DisplayName | |
ServicePrincipalId = $App.ServicePrincipalId | |
Publisher = $App.Publisher | |
Permissions = $AppPermissions | |
SPType = $App.SPType | |
CreatedDate = $App.CreatedDate | |
RecentApp = $App.RecentApp} | |
$AppOutput.Add($ReportLine) | |
} | |
# Add sign-in information for apps | |
[array]$MIAuditRecords = Get-MgAuditLogSignIn -Filter "(signInEventTypes/any(t:t eq 'managedIdentity'))" -Top 2000 -Sort "createdDateTime DESC" | |
[array]$AuditRecords = Get-MgAuditLogSignIn -Filter "(signInEventTypes/any(t:t eq 'servicePrincipal'))" -Top 2000 -Sort "createdDateTime DESC" | |
$AuditRecords = $AuditRecords + $MIAuditRecords | |
ForEach ($AppRecord in $AppOutput) { | |
$SignInFound = $AuditRecords | Where-Object {$_.ServicePrincipalId -eq $AppRecord.ServicePrincipalId} | Select-Object -First 1 | |
If ($SignInFound) { Write-Output ("App {0} last signed in at {1}" -f $AppRecord.DisplayName, $SignInFound.CreatedDateTIme) | |
$AppRecord | Add-Member -NotePropertyName LastSignIn -NotePropertyValue $SignInFound.CreatedDateTime | |
} | |
} | |
##done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment