Skip to content

Commit 44e8373

Browse files
committed
Avoid repeated API calls for delegated permission name lookup
1 parent 7fdc143 commit 44e8373

4 files changed

Lines changed: 46 additions & 116 deletions

File tree

modules/check_AgentIdentities.psm1

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ function Invoke-AgentIdentities {
3333
#Define basic variables
3434
$ProgressCounter = 0
3535
$Inactive = $false
36-
$ApiAppDisplayNameCache = @{}
3736
$SponsorResolutionCache = @{}
3837
$AppLastSignIns = $ServicePrincipalSignInActivityLookup
3938
$AllServicePrincipal = [System.Collections.ArrayList]::new()
@@ -612,44 +611,7 @@ function Invoke-AgentIdentities {
612611
}
613612
}
614613

615-
$DelegatedPermissionDetails = foreach ($permission in $DelegatedPermission) {
616-
617-
# Check if DisplayName for the ResourceId is already cached
618-
if (-not $ApiAppDisplayNameCache.ContainsKey($permission.ResourceId)) {
619-
620-
# Retrieve and cache the DisplayName if not cached
621-
$QueryParameters = @{
622-
'$select' = "DisplayName"
623-
}
624-
#Set odata.metadata=none to avoid having metadata in the response
625-
$headers = @{
626-
'Accept' = 'application/json;odata.metadata=none'
627-
}
628-
$ApiAppDisplayNameCache[$permission.ResourceId] = Send-GraphRequest -AccessToken $GLOBALMsGraphAccessToken.access_token -Method GET -Uri "/servicePrincipals/$($permission.ResourceId)" -QueryParameters $QueryParameters -AdditionalHeaders $headers -BetaAPI -UserAgent $($GlobalAuditSummary.UserAgent.Name)
629-
}
630-
631-
# Split the Scope field by spaces to get individual permissions. Ignores whitespece at the start of the string
632-
$scopes = $permission.Scope.Trim() -split " "
633-
634-
if ($permission.ConsentType -eq "Principal") {
635-
$principal = $permission.PrincipalId
636-
} else {
637-
$principal = "-"
638-
}
639-
# Create a custom object for each scope with ResourceId, ConsentType, Scope, and DisplayName
640-
foreach ($scope in $scopes) {
641-
$resourceAppId = Get-AppRoleReferenceResourceAppId -AppRoleReferenceCache $AppRoleReferenceCache -ResourceId $permission.ResourceId
642-
[pscustomobject]@{
643-
ResourceId = $permission.ResourceId
644-
ResourceAppId = $resourceAppId
645-
ConsentType = $permission.ConsentType
646-
Scope = $scope
647-
APIName = $ApiAppDisplayNameCache[$permission.ResourceId].displayname # Get the cached DisplayName
648-
Principal = $principal
649-
ApiPermissionCategorization = Get-APIPermissionCategory -InputPermission $scope -PermissionType "delegated"
650-
}
651-
}
652-
}
614+
$DelegatedPermissionDetails = Resolve-DelegatedPermissionGrantDetails -AppRoleReferenceCache $AppRoleReferenceCache -DelegatedPermissions @($DelegatedPermission)
653615

654616

655617
#Store unique permission to show in table

modules/check_AgentIdentityBlueprintsPrincipals.psm1

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ function Invoke-AgentIdentityBlueprintsPrincipals {
3434
#Define basic variables
3535
$ProgressCounter = 0
3636
$Inactive = $false
37-
$ApiAppDisplayNameCache = @{}
3837
$AppLastSignIns = $ServicePrincipalSignInActivityLookup
3938
$AllServicePrincipal = [System.Collections.ArrayList]::new()
4039
if ($null -eq $global:GLOBALUserAppRoles) { $global:GLOBALUserAppRoles = @{} }
@@ -464,44 +463,7 @@ function Invoke-AgentIdentityBlueprintsPrincipals {
464463
}
465464
}
466465

467-
$DelegatedPermissionDetails = foreach ($permission in $DelegatedPermission) {
468-
469-
# Check if DisplayName for the ResourceId is already cached
470-
if (-not $ApiAppDisplayNameCache.ContainsKey($permission.ResourceId)) {
471-
472-
# Retrieve and cache the DisplayName if not cached
473-
$QueryParameters = @{
474-
'$select' = "DisplayName"
475-
}
476-
#Set odata.metadata=none to avoid having metadata in the response
477-
$headers = @{
478-
'Accept' = 'application/json;odata.metadata=none'
479-
}
480-
$ApiAppDisplayNameCache[$permission.ResourceId] = Send-GraphRequest -AccessToken $GLOBALMsGraphAccessToken.access_token -Method GET -Uri "/servicePrincipals/$($permission.ResourceId)" -QueryParameters $QueryParameters -AdditionalHeaders $headers -BetaAPI -UserAgent $($GlobalAuditSummary.UserAgent.Name)
481-
}
482-
483-
# Split the Scope field by spaces to get individual permissions. Ignores whitespece at the start of the string
484-
$scopes = $permission.Scope.Trim() -split " "
485-
486-
if ($permission.ConsentType -eq "Principal") {
487-
$principal = $permission.PrincipalId
488-
} else {
489-
$principal = "-"
490-
}
491-
# Create a custom object for each scope with ResourceId, ConsentType, Scope, and DisplayName
492-
foreach ($scope in $scopes) {
493-
$resourceAppId = Get-AppRoleReferenceResourceAppId -AppRoleReferenceCache $AppRoleReferenceCache -ResourceId $permission.ResourceId
494-
[pscustomobject]@{
495-
ResourceId = $permission.ResourceId
496-
ResourceAppId = $resourceAppId
497-
ConsentType = $permission.ConsentType
498-
Scope = $scope
499-
APIName = $ApiAppDisplayNameCache[$permission.ResourceId].displayname # Get the cached DisplayName
500-
Principal = $principal
501-
ApiPermissionCategorization = Get-APIPermissionCategory -InputPermission $scope -PermissionType "delegated"
502-
}
503-
}
504-
}
466+
$DelegatedPermissionDetails = Resolve-DelegatedPermissionGrantDetails -AppRoleReferenceCache $AppRoleReferenceCache -DelegatedPermissions @($DelegatedPermission)
505467

506468

507469
#Store unique permission to show in table

modules/check_EnterpriseApps.psm1

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ function Invoke-CheckEnterpriseApps {
3838
$ProgressCounter = 0
3939
$Inactive = $false
4040
$EnterpriseAppsScriptWarningList = @()
41-
$ApiAppDisplayNameCache = @{}
4241
$AppRegistrations = @{}
4342
$AppLastSignIns = $ServicePrincipalSignInActivityLookup
4443
$AllServicePrincipal = [System.Collections.ArrayList]::new()
@@ -560,42 +559,7 @@ function Invoke-CheckEnterpriseApps {
560559
}
561560
}
562561

563-
$DelegatedPermissionDetails = foreach ($permission in $DelegatedPermission) {
564-
565-
# Check if DisplayName for the ResourceId is already cached
566-
if (-not $ApiAppDisplayNameCache.ContainsKey($permission.ResourceId)) {
567-
568-
# Retrieve and cache the DisplayName if not cached
569-
$QueryParameters = @{
570-
'$select' = "DisplayName"
571-
}
572-
#Set odata.metadata=none to avoid having metadata in the response
573-
$headers = @{
574-
'Accept' = 'application/json;odata.metadata=none'
575-
}
576-
$ApiAppDisplayNameCache[$permission.ResourceId] = Send-GraphRequest -AccessToken $GLOBALMsGraphAccessToken.access_token -Method GET -Uri "/servicePrincipals/$($permission.ResourceId)" -QueryParameters $QueryParameters -AdditionalHeaders $headers -BetaAPI -UserAgent $($GlobalAuditSummary.UserAgent.Name)
577-
}
578-
579-
# Split the Scope field by spaces to get individual permissions. Ignores whitespece at the start of the string
580-
$scopes = $permission.Scope.Trim() -split " "
581-
582-
if ($permission.ConsentType -eq "Principal") {
583-
$principal = $permission.PrincipalId
584-
} else {
585-
$principal = "-"
586-
}
587-
# Create a custom object for each scope with ResourceId, ConsentType, Scope, and DisplayName
588-
foreach ($scope in $scopes) {
589-
[pscustomobject]@{
590-
ResourceId = $permission.ResourceId
591-
ConsentType = $permission.ConsentType
592-
Scope = $scope
593-
APIName = $ApiAppDisplayNameCache[$permission.ResourceId].displayname # Get the cached DisplayName
594-
Principal = $principal
595-
ApiPermissionCategorization = Get-APIPermissionCategory -InputPermission $scope -PermissionType "delegated"
596-
}
597-
}
598-
}
562+
$DelegatedPermissionDetails = Resolve-DelegatedPermissionGrantDetails -AppRoleReferenceCache $AppRoleReferenceCache -DelegatedPermissions @($DelegatedPermission)
599563

600564

601565
#Store unique permission to show in table

modules/shared_Functions.psm1

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6628,6 +6628,48 @@ function Get-AppRoleReferenceApiName {
66286628
return "-"
66296629
}
66306630

6631+
# Build normalized delegated permission rows using the shared app-role reference cache.
6632+
function Resolve-DelegatedPermissionGrantDetails {
6633+
[CmdletBinding()]
6634+
Param (
6635+
[Parameter(Mandatory = $true)][hashtable]$AppRoleReferenceCache,
6636+
[Parameter(Mandatory = $false)][object[]]$DelegatedPermissions = @()
6637+
)
6638+
6639+
$rows = [System.Collections.ArrayList]::new()
6640+
foreach ($permission in @($DelegatedPermissions)) {
6641+
if ($null -eq $permission) { continue }
6642+
6643+
$resourceId = if ($permission.PSObject.Properties['ResourceId']) { [string]$permission.ResourceId } else { '' }
6644+
$resourceAppId = Get-AppRoleReferenceResourceAppId -AppRoleReferenceCache $AppRoleReferenceCache -ResourceId $resourceId
6645+
$apiName = Get-AppRoleReferenceApiName -AppRoleReferenceCache $AppRoleReferenceCache -ResourceId $resourceId -ResourceAppId $resourceAppId
6646+
$scopeText = if ($permission.PSObject.Properties['Scope']) { [string]$permission.Scope } else { '' }
6647+
$scopes = @($scopeText.Trim() -split '\s+' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
6648+
if ($scopes.Count -eq 0) { continue }
6649+
6650+
$consentType = if ($permission.PSObject.Properties['ConsentType']) { [string]$permission.ConsentType } else { '' }
6651+
$principal = if ($consentType -eq "Principal" -and $permission.PSObject.Properties['PrincipalId']) {
6652+
[string]$permission.PrincipalId
6653+
} else {
6654+
"-"
6655+
}
6656+
6657+
foreach ($scope in $scopes) {
6658+
[void]$rows.Add([pscustomobject]@{
6659+
ResourceId = $resourceId
6660+
ResourceAppId = $resourceAppId
6661+
ConsentType = $consentType
6662+
Scope = $scope
6663+
APIName = $apiName
6664+
Principal = $principal
6665+
ApiPermissionCategorization = Get-APIPermissionCategory -InputPermission $scope -PermissionType "delegated"
6666+
})
6667+
}
6668+
}
6669+
6670+
return @($rows)
6671+
}
6672+
66316673
# Build the normalized permission object used by report modules from a cached app-role lookup.
66326674
function Resolve-AppRoleAssignmentRecord {
66336675
[CmdletBinding()]
@@ -7645,4 +7687,4 @@ function Show-EntraFalconBanner {
76457687
Write-Host ""
76467688
}
76477689

7648-
Export-ModuleMember -Function Show-EntraFalconBanner,AuthenticationMSGraph,Get-TenantReportAvailability,Get-TenantDomains,Initialize-TenantReportTabs,Set-GlobalReportManifest,Get-EffectiveEntraLicense,Get-Devices,Get-UsersBasic,Get-AgentObjectBasics,Get-ServicePrincipalSignInActivityLookup,Resolve-DirectoryObjectReference,start-CleanUp,Format-ReportSection,Get-OrgInfo,Get-LogLevel, Write-Log,Invoke-MsGraphRefreshPIM,Write-LogVerbose,Invoke-AzureRoleProcessing,Get-RegisterAuthMethodsUsers,Invoke-EntraRoleProcessing,Get-EntraPIMRoleAssignments,AuthCheckMSGraph,RefreshAuthenticationMsGraph,EnsureAuthSecurityFindingsMsGraph,RefreshAuthenticationSecurityFindingsMsGraph,Get-PimforGroupsAssignments,Invoke-CheckTokenExpiration,Invoke-MsGraphAuthPIM,EnsureAuthMsGraph,Get-AzureRoleDetails,Get-AdministrativeUnitsWithMembers,Get-ConditionalAccessPolicies,Get-EntraRoleAssignments,Get-APIPermissionCategory,New-AppRoleReferenceCache,Resolve-AppRoleReference,Get-AppRoleReferenceApiName,Get-AppRoleReferenceResourceAppId,Resolve-AppRoleAssignmentRecord,Get-ApiPermissionImpactSummary,Get-ObjectInfo,EnsureAuthAzurePsNative,checkSubscriptionNative,Get-AllAzureIAMAssignmentsNative,Get-PIMForGroupsAssignmentsDetails,Show-EnumerationSummary,start-InitTasks,Get-HighestTierLabel,Merge-HigherTierLabel,Get-GroupDetails,Get-GroupActiveRoleMetrics,Get-EntraFalconHostOs,Test-NonWindowsAuthFlowCompatibility
7690+
Export-ModuleMember -Function Show-EntraFalconBanner,AuthenticationMSGraph,Get-TenantReportAvailability,Get-TenantDomains,Initialize-TenantReportTabs,Set-GlobalReportManifest,Get-EffectiveEntraLicense,Get-Devices,Get-UsersBasic,Get-AgentObjectBasics,Get-ServicePrincipalSignInActivityLookup,Resolve-DirectoryObjectReference,start-CleanUp,Format-ReportSection,Get-OrgInfo,Get-LogLevel, Write-Log,Invoke-MsGraphRefreshPIM,Write-LogVerbose,Invoke-AzureRoleProcessing,Get-RegisterAuthMethodsUsers,Invoke-EntraRoleProcessing,Get-EntraPIMRoleAssignments,AuthCheckMSGraph,RefreshAuthenticationMsGraph,EnsureAuthSecurityFindingsMsGraph,RefreshAuthenticationSecurityFindingsMsGraph,Get-PimforGroupsAssignments,Invoke-CheckTokenExpiration,Invoke-MsGraphAuthPIM,EnsureAuthMsGraph,Get-AzureRoleDetails,Get-AdministrativeUnitsWithMembers,Get-ConditionalAccessPolicies,Get-EntraRoleAssignments,Get-APIPermissionCategory,New-AppRoleReferenceCache,Resolve-AppRoleReference,Get-AppRoleReferenceApiName,Get-AppRoleReferenceResourceAppId,Resolve-DelegatedPermissionGrantDetails,Resolve-AppRoleAssignmentRecord,Get-ApiPermissionImpactSummary,Get-ObjectInfo,EnsureAuthAzurePsNative,checkSubscriptionNative,Get-AllAzureIAMAssignmentsNative,Get-PIMForGroupsAssignmentsDetails,Show-EnumerationSummary,start-InitTasks,Get-HighestTierLabel,Merge-HigherTierLabel,Get-GroupDetails,Get-GroupActiveRoleMetrics,Get-EntraFalconHostOs,Test-NonWindowsAuthFlowCompatibility

0 commit comments

Comments
 (0)