Skip to content

Commit df94bb8

Browse files
committed
Various bugfixes and improvements related to agent identities
1 parent 064f858 commit df94bb8

3 files changed

Lines changed: 396 additions & 213 deletions

File tree

modules/check_AgentIdentities.psm1

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -516,10 +516,14 @@ function Invoke-AgentIdentities {
516516
$AppApiPermissionUncategorized = if ($counts.ContainsKey('Uncategorized')) { $counts['Uncategorized'] } else { 0 }
517517

518518
# For all sp check if there are Azure IAM assignments
519+
$AllAzureRoleDetails = @()
519520
$AzureRoleDetails = @()
521+
$EligibleAzureRoleDetails = @()
520522
if ($GLOBALAzurePsChecks) {
521523
#Use function to get the Azure Roles for each object
522-
$AzureRoleDetails = Get-AzureRoleDetails -AzureIAMAssignments $AzureIAMAssignments -ObjectId $item.Id
524+
$AllAzureRoleDetails = @(Get-AzureRoleDetails -AzureIAMAssignments $AzureIAMAssignments -ObjectId $item.Id)
525+
$AzureRoleDetails = @($AllAzureRoleDetails | Where-Object { "$($_.AssignmentType)".Trim() -eq "Active" })
526+
$EligibleAzureRoleDetails = @($AllAzureRoleDetails | Where-Object { "$($_.AssignmentType)".Trim() -eq "Eligible" })
523527
# Update the Roles property only if there are matching roles
524528
$AzureRoleCount = ($AzureRoleDetails | Measure-Object).Count
525529
} else {
@@ -560,19 +564,22 @@ function Invoke-AgentIdentities {
560564
# Enumerate all roles including scope the app is assigned to (note: Get-MgBetaServicePrincipalMemberOf do not return custom roles or scoped roles)
561565
$MatchingRoles = $TenantRoleAssignments[$item.Id]
562566

563-
$AppEntraRoles = @()
564-
$AppEntraRoles = foreach ($Role in $MatchingRoles) {
567+
$AllAppEntraRoles = @()
568+
$AllAppEntraRoles = foreach ($Role in $MatchingRoles) {
565569
[PSCustomObject]@{
566570
Type = "Roles"
567571
DisplayName = $Role.DisplayName
568572
Enabled = $Role.IsEnabled
569573
IsBuiltin = $Role.IsBuiltIn
570574
RoleTier = $role.RoleTier
571575
IsPrivileged = $Role.IsPrivileged
576+
AssignmentType = $Role.AssignmentType
572577
Scoped = $Role.DirectoryScopeId
573578
ScopeResolved = $Role.ScopeResolved
574579
}
575580
}
581+
$AppEntraRoles = @($AllAppEntraRoles | Where-Object { "$($_.AssignmentType)".Trim() -eq "Active" })
582+
$EligibleAppEntraRoles = @($AllAppEntraRoles | Where-Object { "$($_.AssignmentType)".Trim() -eq "Eligible" })
576583

577584
$DirectAzureMaxTier = if ($GLOBALAzurePsChecks) { Get-HighestTierLabel -Assignments $AzureRoleDetails } else { "?" }
578585
$DirectEntraMaxTier = Get-HighestTierLabel -Assignments $AppEntraRoles
@@ -709,13 +716,13 @@ function Invoke-AgentIdentities {
709716
}
710717
}
711718

712-
# Group ownership tier inheritance: active + eligible paths.
719+
# Group ownership tier inheritance: active-only paths.
713720
foreach ($group in $OwnedGroups) {
714-
$entraMetrics = Get-GroupActiveRoleMetrics -Group $group -RoleSystem Entra -IncludeEligible
721+
$entraMetrics = Get-GroupActiveRoleMetrics -Group $group -RoleSystem Entra
715722
$EntraMaxTierThroughGroupOwnership = Merge-HigherTierLabel -CurrentTier $EntraMaxTierThroughGroupOwnership -CandidateTier $entraMetrics.MaxTier
716723

717724
if ($GLOBALAzurePsChecks) {
718-
$azureMetrics = Get-GroupActiveRoleMetrics -Group $group -RoleSystem Azure -IncludeEligible
725+
$azureMetrics = Get-GroupActiveRoleMetrics -Group $group -RoleSystem Azure
719726
$AzureMaxTierThroughGroupOwnership = Merge-HigherTierLabel -CurrentTier $AzureMaxTierThroughGroupOwnership -CandidateTier $azureMetrics.MaxTier
720727
}
721728
}
@@ -989,20 +996,20 @@ function Invoke-AgentIdentities {
989996

990997
#Check each owned group
991998
foreach ($OwnedGroup in $OwnedGroups) {
992-
# Ownership inherits the group's full impact (active + eligible role paths).
999+
# Ownership inherits only the group's active-path impact.
9931000
$groupInheritedImpact = 0
994-
if (-not [int]::TryParse([string]$OwnedGroup.Impact, [ref]$groupInheritedImpact)) {
1001+
if (-not [int]::TryParse([string]$OwnedGroup.ImpactOrgActiveOnly, [ref]$groupInheritedImpact)) {
9951002
[void][int]::TryParse([string]$OwnedGroup.ImpactOrg, [ref]$groupInheritedImpact)
9961003
}
9971004
$ImpactScore += $groupInheritedImpact
9981005

999-
$entraMetrics = Get-GroupActiveRoleMetrics -Group $OwnedGroup -RoleSystem Entra -IncludeEligible
1006+
$entraMetrics = Get-GroupActiveRoleMetrics -Group $OwnedGroup -RoleSystem Entra
10001007
$TotalAssignedRoleCount += $entraMetrics.RoleCount
10011008
$TotalAssignedPrivilegedRoles += $entraMetrics.PrivilegedCount
10021009

10031010
$groupAzureRoleCount = 0
10041011
if ($GLOBALAzurePsChecks) {
1005-
$azureMetrics = Get-GroupActiveRoleMetrics -Group $OwnedGroup -RoleSystem Azure -IncludeEligible
1012+
$azureMetrics = Get-GroupActiveRoleMetrics -Group $OwnedGroup -RoleSystem Azure
10061013
$groupAzureRoleCount = $azureMetrics.RoleCount
10071014
$TotalAzureRoles += $groupAzureRoleCount
10081015
}
@@ -1124,6 +1131,7 @@ function Invoke-AgentIdentities {
11241131
GroupMember = $GroupMember
11251132
AppOwnerOrganizationId = $appOwnerOrganizationId
11261133
EntraRoleDetails = $AppEntraRoles
1134+
EligibleEntraRoleDetails = $EligibleAppEntraRoles
11271135
GroupOwner = $OwnedGroups
11281136
AppPermission = $AppAssignments
11291137
Foreign = $ForeignTenant
@@ -1136,6 +1144,7 @@ function Invoke-AgentIdentities {
11361144
CreationInDays = $CreationInDays
11371145
AppsignInData = $AppsignInData
11381146
AzureRoleDetails = $AzureRoleDetails
1147+
EligibleAzureRoleDetails = $EligibleAzureRoleDetails
11391148
Owners = $OwnersCount
11401149
Sponsors = $SponsorsCount
11411150
AgentUsers = $AssignedAgentUsersCount

modules/check_AgentsFinalize.psm1

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,17 @@ Execution Warnings = $($WarningList -join ' / ')
13161316
}
13171317
}
13181318
)
1319+
$ReportingEligibleRoles = @(
1320+
foreach ($object in @($item.EligibleEntraRoleDetails)) {
1321+
[pscustomobject]@{
1322+
"Role name" = $object.DisplayName
1323+
"Tier Level" = $object.RoleTier
1324+
"Privileged" = $object.isPrivileged
1325+
"IsBuiltin" = $object.IsBuiltin
1326+
"Scoped to" = "$($object.ScopeResolved.DisplayName) ($($object.ScopeResolved.Type))"
1327+
}
1328+
}
1329+
)
13191330
$ReportingAzureRoles = @(
13201331
foreach ($object in @($item.AzureRoleDetails)) {
13211332
[pscustomobject]@{
@@ -1327,6 +1338,17 @@ Execution Warnings = $($WarningList -join ' / ')
13271338
}
13281339
}
13291340
)
1341+
$ReportingEligibleAzureRoles = @(
1342+
foreach ($object in @($item.EligibleAzureRoleDetails)) {
1343+
[pscustomobject]@{
1344+
"Role name" = $object.RoleName
1345+
"RoleType" = $object.RoleType
1346+
"Tier Level" = $object.RoleTier
1347+
"Conditions" = $object.Conditions
1348+
"Scoped to" = $object.Scope
1349+
}
1350+
}
1351+
)
13301352
$ReportingGroupOwner = @(
13311353
foreach ($object in @($item.GroupOwner)) {
13321354
[pscustomobject]@{
@@ -1510,7 +1532,9 @@ Execution Warnings = $($WarningList -join ' / ')
15101532
}
15111533
)
15121534
"Active Entra Role Assignments" = $ReportingRoles
1513-
"Azure IAM assignments" = $ReportingAzureRoles
1535+
"Eligible Entra Role Assignments" = $ReportingEligibleRoles
1536+
"Active Azure IAM assignments" = $ReportingAzureRoles
1537+
"Eligible Azure IAM assignments" = $ReportingEligibleAzureRoles
15141538
"Owner of Groups" = $ReportingGroupOwner
15151539
"Owned App Registrations" = $ReportingAppOwner
15161540
"Owned Service Principals" = $ReportingSPOwner

0 commit comments

Comments
 (0)