diff --git a/Get Entra Enterprise App Permission Report/GetEnterpriseAppPermissions.ps1 b/Get Entra Enterprise App Permission Report/GetEnterpriseAppPermissions.ps1 new file mode 100644 index 0000000..f302362 --- /dev/null +++ b/Get Entra Enterprise App Permission Report/GetEnterpriseAppPermissions.ps1 @@ -0,0 +1,221 @@ +<# +============================================================================================= +Name: Get All Enterprise Applications with Their Permissions +Version: 1.0 +Website: blog.admindroid.com + + +Script Highlights: +~~~~~~~~~~~~~~~~~ +1. Exports all enterprise apps along with its API permissions in Microsoft Entra. +2. The script installs MS Graph PowerShell SDK (if not installed already) upon your confirmation. +3. Allows to filter applications with specific permissions (eg.,"User.Read.All") assigned. + -> Admin consented app permissions + -> Admin consented delegated permissions + -> User consented permissions +4. Fetches the list of ownerless applications in Microsoft Entra. +5. Find Entra app permissions granted thorough user consent and admin consent. +6. Generates report for sign-in enabled and disabled applications. +7. Assists in filtering based on following properties: + -> Application Name + -> Application Id + -> Object Id + -> API Name +8. Filters apps that are restricted to specific users and accessible to all users. +9. Lists applications that are hidden and visible to all users in the organization. +10. Assists in filtering home tenant and external tenant applications. +11. Allows to retrieve enterprise apps with no permissions too. +12. Exports the result to CSV. +13. The script can be executed with an MFA enabled account too. +14. It can be executed with certificate-based authentication (CBA) too. +15. The script is schedular-friendly. + +For detailed Script execution: https://blog.admindroid.com/export-all-enterprise-apps-and-their-assigned-permission-in-microsoft-entra/ + + +============================================================================================ +#> + +Param ( + [Parameter(Mandatory = $false)] + [switch]$CreateSession, + [string]$TenantId, + [string]$ClientId, + [string]$CertificateThumbPrint, + [string]$ApplicationId, + [string]$ApplicationName, + [string]$ObjectId, + [string]$APIName, + [ValidateSet("VisibleApps","HiddenApps")] + [string]$AppVisibility, + [ValidateSet("HomeTenant","ExternalTenant")] + [string]$AppOrigin, + [ValidateSet("Enabled", "Disabled")] + [string]$UsersSignIn, + [ValidateSet("AdminConsent", "UserConsent")] + [string]$ConsentType, + [string[]]$AdminConsentApplicationPermissions, + [string[]]$AdminConsentDelegatedPermissions, + [string[]]$UserConsents, + [switch]$AccessScopeToAllUsers, + [switch]$RoleAssignmentRequiredApps, + [switch]$OwnerlessApps, + [switch]$IncludeAppsWithNoPermissions +) + +function Connect_MgGraph { + $MsGraphModule = Get-Module Microsoft.Graph -ListAvailable + if ($MsGraphModule -eq $null) { + Write-Host "`nImportant: Microsoft Graph module is unavailable. It is mandatory to have this module installed in the system to run the script successfully." + $confirm = Read-Host "Are you sure you want to install Microsoft Graph module? [Y] Yes [N] No" + if ($confirm -match "[yY]") { + Write-Host "Installing Microsoft Graph Module..." + Install-Module Microsoft.Graph -Scope CurrentUser -AllowClobber -Force + } + else { + Write-Host "Microsoft Graph PowerShell module is required to run this script. Please install module using 'Install-Module Microsoft.Graph' cmdlet." + Exit + } + } + + if ($CreateSession.IsPresent) { + Disconnect-MgGraph + } + + Write-Host "`nConnecting to Microsoft Graph..." + if (($TenantId -ne "") -and ($ClientId -ne "") -and ($CertificateThumbPrint -ne "")) { + Connect-MgGraph -TenantId $TenantId -AppId $ClientId -CertificateThumbprint $CertificateThumbPrint -NoWelcome + } + else { + Connect-MgGraph -Scopes "Application.Read.All" -NoWelcome + } +} + +Connect_MgGraph + +$ExportCSV = "$(Get-Location)\EnterpriseApps_and_their_Permissions_report_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm-ss` tt).ToString()).csv" +$TenantGUID= (Get-MgOrganization).Id +Write-Host "`nRetreiving the Enterprise applications with admin consents and user consents" +$AppCount = 0 +$PrintCount = 0 + +Get-MgServicePrincipal -All | ForEach-Object { + $Print = 1 + $AppCount++ + $ServicePrincipalType = $_.ServicePrincipalType + $AppName = $_.DisplayName + Write-Progress -Activity "Processed Enterprise apps: $($AppCount) $($AppName)" + $AppId = $_.AppId + $ObjId = $_.Id + $CreatedDateTime = [datetime]@($_.AdditionalProperties.Values)[0] + $AccountEnabled = if ($_.AccountEnabled) { "Enabled" } else { "Disabled" } + $Owners = (Get-MgServicePrincipalOwner -ServicePrincipalId $_.Id | ForEach-Object { $_.AdditionalProperties["displayName"] }) -join ", " + $Tags = $_.Tags + $IsRoleAssignmentRequired = $_.AppRoleAssignmentRequired + + if (-not $Owners) { $Owners = "-" } + if ($Tags -contains "HideApp") { $UserVisibility="Hidden" } + else { $UserVisibility="Visible" } + if ($IsRoleAssignmentRequired -eq $true){ $AccessScope="Only assigned users can access" } + else { $AccessScope="All users can access" } + $AppOwnerOrgId=$_.AppOwnerOrganizationId + if ($AppOwnerOrgId -eq $TenantGUID){ $AppOrg="Home tenant" } + else { $AppOrg="External tenant" } + + if (($ApplicationId.Length -ne 0) -and ($ApplicationId -ne $AppId)) { $Print = 0 } + if (($ApplicationName.Length -ne 0) -and ($ApplicationName -ne $AppName)) { $Print = 0 } + if (($ObjectId.Length -ne 0) -and ($ObjectId -ne $ObjId)) { $Print = 0 } + if ($UsersSignIn -eq "Enabled" -and $_.AccountEnabled -ne $true) { $Print = 0 } + if ($UsersSignIn -eq "Disabled" -and $_.AccountEnabled -ne $false) { $Print = 0 } + if (($AppVisibility -eq "VisibleApps") -and ($UserVisibility -ne "Visible")){ $Print=0 } + if (($AppVisibility -eq "HiddenApps") -and ($UserVisibility -ne "Hidden")){ $Print=0 } + if (($AccessScopeToAllUsers.IsPresent) -and ($AccessScope -eq "Only assigned users can access")){ $Print=0 } + if (($RoleAssignmentRequiredApps.IsPresent) -and ($AccessScope -eq "All users can access")){ $Print=0 } + if (($OwnerlessApps.IsPresent) -and ($Owners -ne "-")){ $Print=0 } + if ($AppOrigin -eq "HomeTenant" -and ($AppOrg -eq "External tenant")){ $Print=0 } + if ($AppOrigin -eq "ExternalTenant" -and ($AppOrg -eq "Home tenant")){ $Print=0 } + + $DelegatedGrants = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipalId $ObjId -All + $AppAssignments = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ObjId -All + $AllAPIids = @($DelegatedGrants.ResourceId; $AppAssignments.ResourceId) | Sort-Object -Unique + + if (-not $AllAPIids) { $AllAPIids = @('-') } + + foreach ($ResourceId in $AllAPIids) { + if ($ResourceId -eq '-') { + $ResourceName = '-' + $AdminDelegated = '-' + $UserDelegated = '-' + $AdminApps = '-' + } + else { + $ResourceSp = Get-MgServicePrincipal -ServicePrincipalId $ResourceId + $ResourceName = $ResourceSp.DisplayName + + $AdminDelegated = $DelegatedGrants | Where-Object { $_.ResourceId -eq $ResourceId -and $_.ConsentType -eq "AllPrincipals" } | ForEach-Object{ $_.Scope.Trim()} + $AdminDelegated = if(-not $AdminDelegated) {"-"} else {$AdminDelegated -split "\s+" -join ", "} + + $UserDelegated = $DelegatedGrants | Where-Object { $_.ResourceId -eq $ResourceId -and $_.ConsentType -eq "Principal" } | ForEach-Object {$_.Scope.Trim()} + $UserDelegated = if(-not $UserDelegated){"-"} else {$UserDelegated -split "\s+" -join ", "} + + $AdminApps = $AppAssignments | Where-Object { $_.ResourceId -eq $ResourceId } | + ForEach-Object { + $role = $ResourceSp.AppRoles | Where-Object Id -eq $_.AppRoleId + if ($role) { $role.Value } + } + $AdminApps = if(-not $AdminApps){"-"} else {$AdminApps -join ", "} + } + + if ((-not $IncludeAppsWithNoPermissions.IsPresent) -and ($AdminDelegated[0] -eq "-" -and $AdminApps[0] -eq "-" -and $UserDelegated[0] -eq "-")) { $Print = 0 } + if ($AdminConsentApplicationPermissions -and ((($AdminApps -split ", ") | Where-Object { $_ -in $AdminConsentApplicationPermissions }).Count -eq 0)) { $Print = 0 } + if ($AdminConsentDelegatedPermissions -and ((($AdminDelegated -split ", ") | Where-Object { $_ -in $AdminConsentDelegatedPermissions}).Count -eq 0)) { $Print = 0 } + if ($UserConsents -and ((($UserDelegated -split ", ") | Where-Object {$_ -in $UserConsents}).Count -eq 0)) { $Print = 0 } + if (($APIName.Length -ne 0) -and ($APIName -ne $ResourceName)) { $Print = 0 } + if ($ConsentType -eq "AdminConsent" -and $UserDelegated -ne '-') { $Print = 0 } + if ($ConsentType -eq "UserConsent" -and ($AdminApps -ne '-' -or $AdminDelegated -ne '-')) { $Print = 0 } + + if ($Print -eq 1){ + $PrintCount++ + [PSCustomObject]@{ + 'App Name' = $AppName + 'Object Id'= $ObjId + 'API Name' = $ResourceName + 'Admin Consented App Permissions' = $AdminApps + 'Admin Consented Delegated Permissions' = $AdminDelegated + 'User Consented Permissions' = $UserDelegated + 'Owners' = $Owners + 'Users Sign In' = $AccountEnabled + 'User Visibility'= $UserVisibility + 'Role Assignment Required'= $AccessScope + 'Service Principal Type'= $ServicePrincipalType + 'App Id' = $AppId + 'App Origin'= $AppOrg + 'App Org Id'= $AppOwnerOrgId + 'API Id' = $ResourceId + 'Created Date' = $CreatedDateTime + } | Export-Csv -Path $ExportCSV -Append -NoTypeInformation + } + } +} + +Disconnect-MgGraph | Out-Null + +Write-Host `nScript executed successfully. +Write-Host `n~~ Script prepared by AdminDroid Community ~~`n -ForegroundColor Green +Write-Host "~~ Check out " -NoNewline -ForegroundColor Green; Write-Host "admindroid.com" -ForegroundColor Yellow -NoNewline; Write-Host " to access 3,000+ reports and 450+ management actions across your Microsoft 365 environment. ~~" -ForegroundColor Green `n`n + +if(((Test-Path -Path $ExportCSV) -eq "True")) +{ + Write-Host `nThe script processed $AppCount enterprise apps and the output file contains $PrintCount records. + $Prompt = New-Object -ComObject wscript.shell + $UserInput = $Prompt.popup("Do you want to open output file?",` 0,"Open Output File",4) + if ($UserInput -eq 6) + { + Invoke-Item "$ExportCSV" + } + Write-Host "The generated report is available in: " -NoNewline -ForegroundColor Yellow; Write-Host "$($ExportCSV)" +} +else +{ + Write-Host "No user found" -ForegroundColor Red +} \ No newline at end of file