Skip to content

Instantly share code, notes, and snippets.

@m8r1us
Last active April 8, 2024 14:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m8r1us/2b97604b6dd42809a52ca31315a4998a to your computer and use it in GitHub Desktop.
Save m8r1us/2b97604b6dd42809a52ca31315a4998a to your computer and use it in GitHub Desktop.
Find foreign service principals
# The script is part of the following article: https://www.scip.ch/en/?labs.20240404
# --------------
# Find foreign service principals with application permissions
# --------------
Write-Host "[*] Log in with a user that has at least the Application.Read.All right `n" -ForegroundColor Green
Connect-MgGraph -scopes "Application.Read.All" -NoWelcome
Write-Host "[*] Output the connection context `n" -ForegroundColor Green
$mgcontext = Get-MgContext
$mgcontext
$foreignsp = Get-MgServicePrincipal -All | Where-Object { $_.AppOwnerOrganizationId -ne $mgcontext.TenantId -and $_.AppOwnerOrganizationId -ne $null }
$collSpAppRolePermissions = ""
$collSpAppRolePermissions = New-Object System.Collections.ArrayList
$progress = 0
$TotalCount = $foreignsp.Count
# Query for AppRoles once and store in a hashtable
$appRolesHashTable = @{}
$allAppRoles = Get-MgServicePrincipal -All | Select-Object Id,AppRoles
foreach ($appRole in $allAppRoles) {
foreach ($role in $appRole.AppRoles) {
$appRolesHashTable["$($appRole.Id)-$($role.Id)"] = $role
}
}
foreach ($sp in $foreignsp)
{
$DisplayName = $sp.DisplayName
$Progress += 1
$ProgressPercentage = (($Progress / $TotalCount) * 100) -As [Int]
If ($Progress -eq $TotalCount) {
Write-Host "[*] Processing Service Principals: [${Progress}/${TotalCount}][${ProgressPercentage}%] Current Service Principals: ${DisplayName}`n" -ForegroundColor Green
} else {
If (($Progress % 100) -eq 0) {
Write-Host "[*] Processing Service Principals: [${Progress}/${TotalCount}][${ProgressPercentage}%] Current Service Principals: ${DisplayName}" -ForegroundColor Green
}
}
# AppPermission - What application permissions have been assigned to the service principal?
$spAppRolePermissions = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $sp.id -All | Select-Object PrincipalId,PrincipalType,ResourceId,ResourceDisplayName,Id,PrincipalDisplayName,AppRoleId
foreach ($spAppRolePermission in $spAppRolePermissions)
{
#Translate Rights
$getAppRole = $appRolesHashTable["$($spAppRolePermission.ResourceId)-$($spAppRolePermission.AppRoleId)"]
$customObject = [PSCustomObject]@{
mytenant = $mgcontext.TenantId
foreigntenant = $sp.AppOwnerOrganizationId
principalDisplayName = $spAppRolePermission.PrincipalDisplayName
principalId = $spAppRolePermission.PrincipalId
principalType = $spAppRolePermission.PrincipalType
resourceId = $spAppRolePermission.ResourceId
resourceDisplayName = $spAppRolePermission.ResourceDisplayName
appRoleId = $spAppRolePermission.AppRoleId
appRoleIdd = $getAppRole.Id
appRoleValue = $getAppRole.Value -replace '\.', ''
appDisplayname = $getAppRole.DisplayName
appDescription = $getAppRole.Description
}
$null = $CollSpAppRolePermissions.Add($customObject)
}
}
Write-Host "[*] All foreign service principals found are displayed below for review `n" -ForegroundColor Green
$CollSpAppRolePermissions | select mytenant, foreigntenant, principalDisplayName, principalId, appRoleValue
$CollSpAppRolePermissions | Out-GridView -Title "Foreign Service Principal with AppRoles"
Disconnect-MgGraph | Out-null
@mezzofix
Copy link

mezzofix commented Apr 8, 2024

@m8r1us thank you for the script! Question, since the recommended approach with Graph PowerShell SDK it to be precise about the permissions needed for a script and to state those permissions when connecting to the Grap API, what would be the minimum required permissions that one could pass with the scope’s parameter , .eg. Connect-MgGraph -Scopes for this to work?

@m8r1us
Copy link
Author

m8r1us commented Apr 8, 2024

Hi @mezzofix thanks for your question. I think it should be Application.Read.All. I updated the script and also fixed the tenantid variable which was only set by the POC powershell (https://gist.github.com/m8r1us/86434d2fb7b9e31a71ba4295d6cb2a3a).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment