Find AzureAD IDP Enterprise Apps with Users/Groups AND Owners

Hello! - This script to pull owners with users and groups of all our Enterprise IDP apps in Azure but having an issue with multiple owners. If an app has multiple owners, the app generates an error the user exists (meaning a value is already there) for both OwnerUserPrincipalName and OwnerDisplayName"

“Add-Member : Cannot add a member with the name “OwnerUserPrincipalName” because a member with that name already exists.”

The report does pull the multiple users “PrincipleDisplayName” assigned to the application but does not produce any columns for Owners. Thanks in advance.

$date = Get-Date -Format "yyyyMMddHHmmss"
$ServicePrincipalList = Get-AzureADServicePrincipal -All $true

foreach($servicePrincipal in $ServicePrincipalList){  
    $owners = Get-AzureADServicePrincipalOwner -ObjectId $servicePrincipal.ObjectId | Select-Object DisplayName, UserPrincipalName
    $appRoles = Get-AzureADServiceAppRoleAssignment -ObjectId $servicePrincipal.ObjectId | Select-Object ResourceDisplayName, ResourceId, PrincipalDisplayName, PrincipalType
    $report = $appRoles | Select-Object ResourceDisplayName, ResourceId, PrincipalDisplayName, PrincipalType
    $owners | ForEach-Object {
        $owner = $_
        $report | Add-Member -MemberType NoteProperty -Name "OwnerDisplayName" -Value $owner.DisplayName
        $report | Add-Member -MemberType NoteProperty -Name "OwnerUserPrincipalName" -Value $owner.UserPrincipalName
    }
    $report | Export-Csv -Path "C:\\Users\\Documents\\folder1\\important-$date.csv" -NoTypeInformation -Append -Force
}

bacjac38,
Welcome to the forum. :wave:t3:

I’m not completely sure what kind of result you’re looking for because you’re mixing single properties with arrays of properties but this may help getting started anyway:

$date = Get-Date -Format "yyyyMMddHHmmss"
$ServicePrincipalList = Get-AzureADServicePrincipal -All $true
$report = 
foreach ($servicePrincipal in $ServicePrincipalList) {
    $appRoles = 
        Get-AzureADServiceAppRoleAssignment -ObjectId $servicePrincipal.ObjectId | 
            Select-Object ResourceDisplayName, ResourceId, PrincipalDisplayName, PrincipalType
    $ownerList = 
        Get-AzureADServicePrincipalOwner -ObjectId $servicePrincipal.ObjectId 
    foreach ($owner in $ownerList) {
        [PSCustomObject]@{
            OwnerDisplayName       = $owner.DisplayName
            OwnerUserPrincipalName = $owner.UserPrincipalName
            AppRoles               = $appRoles
        }
    }
}
$report | 
    Export-Csv -Path "C:\\Users\\Documents\\folder1\\important-$date.csv" -NoTypeInformation

The script posted is pulling Enterprise Azure IDP apps with roles assigned to both users and groups and owners. It produces all the info except for multiple owners. The screenshot is the result of the script minus the owners. The arrays used was an attempt to get the multiple owners to be listed. Adding -Force to last 2 lines of the arrays wipes the columns out altogether.

Thanks much for the code.

If you want to output a hierarchical data structure as structured data you need to flatten the “sub properties”. This way you probably loose some of the information bits.

The other approach would be to use some more nested loops to achieve some kind of data normalization.

BTW: Please do not post images of code, console output or sample data. Instead post the plain text formatted as code.

What’s the actual purpose of that? Documentation? Backup? Audit?

If you have users and groups and you want to display the users of the groups as well you may use a separate table for each group. :man_shrugging:t3:

Audit. No groups are assigned to the apps just individual users and owners. Maybe it’s just better to have 2 separate scripts - 1 for users and 1 for owners then match them up

Ah … now I’ve got it.

Are “Owners” always “Users” as well? If yes you could check for this relation inside your loop and use an additional boolean property in the [PSCustomObject] for it.

Owners are not Users. There are many apps with registered Users with no owners at all. Owners can only be assigned via Azure by a GA to manage the app

In this case it wouldn’t make sense for me to put them to the same listing. I’d probably have a list of users and a separate list of owners for each app. :man_shrugging:t3:

This fixed it:

Connect-AzureAD
$date = Get-Date -Format “yyyyMMddHHmmss”
$ServicePrincipalList = Get-AzureADServicePrincipal -All $true

foreach($servicePrincipal in $ServicePrincipalList){
$owners = Get-AzureADServicePrincipalOwner -ObjectId $servicePrincipal.ObjectId | Select-Object DisplayName, UserPrincipalName
$appRoles = Get-AzureADServiceAppRoleAssignment -ObjectId $servicePrincipal.ObjectId | Select-Object ResourceDisplayName, ResourceId, PrincipalDisplayName, PrincipalType*
$report = $appRoles | Select-Object ResourceDisplayName, ResourceId, PrincipalDisplayName, PrincipalType
$report | Add-Member -MemberType NoteProperty -Name “OwnerDisplayName” -Value ($owners.DisplayName -join ‘;’)
$report | Add-Member -MemberType NoteProperty -Name “OwnerUserPrincipalName” -Value ($owners.UserPrincipalName -join ‘;’)
$report | Export-Csv -Path “C:\PSReports\AzureAD_IDP_Apps-$date.csv” -NoTypeInformation -Append -Force
}

Please go back and edit your post once again to fix the formatting of your code.

If this fixes your issue you may mark your own reply as the solution to make it easier for others to find this solution.

Thanks in advance.

Edit:

Why did you remove the code you had posted? Don’t you like others to benefit from your findings?