0

I have a very simple script that is connecting to AzureAD and pulling Roles and Members of said roles within AD.

I can get it to run fine within powershell, however when i start to add Out-File or similar i obvioulsy need to call from a stored item, I add $Export to the foreach, it runs fine however when i preview it, it is missing the $Write-Host $ADRole.Displaname from the foreach.

## CONNECT AZURE AD ##
Connect-AzureAD

## Get Administrator Account Users 
$Export = ForEach ($ADRole in Get-AzureADDirectoryRole) {
    Write-Host $ADRole.DisplayName
    Get-AzureADDirectoryRoleMember -ObjectId $ADRole.objectID | Format-Table DisplayName,UserPrincipalName,UserType,ObjectId
}

$Export | Out-File -FilePath C:\Temp\Test.txt

As per my comment below i think the output of this doesnt work as efficient as it should as there is no specific way to filter by user etc, which ofcourse is a limitation with a .txt file so i think i need to make this output to a csv.

Upon initial output of CSV it would output all as 1 column and 1 line so not very functional, give the $ADRole.DisplayName is shown above the users i think this would be best to show inline for the CSV so it would output as follows.

$ADRole.DisplayName, $Member.DisplayName,$Member.UserPrincipalName,$Member.UserType,$Member.ObjectID

Although there are roles which have no users assigned to it, however those roles still need to show for any external audits?

What is the best way to achieve this?

  • Because...........`Write-Host` does just as the name implies. Writes to the host (*console*) and does nothing else. You want to use `Write-Output` to write to the pipeline. So, it's definitely outputting as it should. – Abraham Zinala Aug 05 '21 at 00:23
  • 1
    Literally as I looked at it after posting, I simply removed Write-Host and well, as you mentioned fixed! – Andrew Waters Aug 05 '21 at 00:24
  • Yeah, using single/double-quotes by themselves without specifying a cmdlet, default to `Write-Output`, so that will work as well. Glad you got it figured out tho:) – Abraham Zinala Aug 05 '21 at 00:26
  • 1
    [`Write-Host` is typically the wrong tool to use](http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/), unless the intent is to write _to the display only_, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file. To output a value, use it _by itself_; e.g., `$value` instead of `Write-Host $value` (or use `Write-Output $value`, though that is rarely needed); see [this answer](https://stackoverflow.com/a/60534138/45375) – mklement0 Aug 05 '21 at 00:48
  • Have made additional edits to the original post. – Andrew Waters Aug 05 '21 at 01:21

1 Answers1

1

Similar to what Abraham and mklement0 pointed out in their comments in regards to Write-Host, something similar happens with Format-Table, it is intended to display your object on the console and should not be used to export the data.

Select the properties you need to export with Select-Object instead or loop through the object and cast a [pscustomobject].

$Export = ForEach ($ADRole in Get-AzureADDirectoryRole)
{
    Write-Host $ADRole.DisplayName
    $members = Get-AzureADDirectoryRoleMember -ObjectId $ADRole.objectID

    if(-not $members)
    {
        $ADRole | Select-Object @{n='ADRoleDisplayName';e={$_.DisplayName}},
                                @{n='MemberDisplayName';e={'No Members'}},
                                UserPrincipalName, UserType, ObjectId
        continue
    }

    $members | Select-Object @{n='ADRoleDisplayName';e={$ADRole.DisplayName}},
                             @{n='MemberDisplayName';e={$_.DisplayName}},
                             UserPrincipalName, UserType, ObjectId
}

$Export | Export-Csv C:\Temp\Test.txt -NoTypeInformation
  • For casting [pscustomobject] you can do something like this:
$Export = ForEach ($ADRole in Get-AzureADDirectoryRole)
{
    Write-Host $ADRole.DisplayName
    $members = Get-AzureADDirectoryRoleMember -ObjectId $ADRole.objectID
    
    if(-not $members)
    {
        [pscustomobject]@{
            ADRoleDisplayName = $ADRole.DisplayName
            MemberDisplayName = 'No Members'
            UserPrincipalName = ''
            UserType = ''
            ObjectId = ''
        }

        continue
    }

    foreach($member in $members)
    {
        [pscustomobject]@{
            ADRoleDisplayName = $ADRole.DisplayName
            MemberDisplayName = $member.DisplayName
            UserPrincipalName = $member.UserPrincipalName
            UserType = $member.UserType
            ObjectId = $member.ObjectId
        }
    }
}

$Export | Export-Csv C:\Temp\Test.txt -NoTypeInformation
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • Thanks mate, whilst this is all good and working (Appreciate it) the issue would now rely around rolls that have no members, soley from an audit perspective that it shows the role has no members. – Andrew Waters Aug 05 '21 at 02:12
  • @AndrewWaters if its related to this question _Although there are roles which have no users assigned to it, however those roles still need to show for any external audits?_ not sure how can we decide that for you. – Santiago Squarzon Aug 05 '21 at 02:14
  • Yeah, for the purpose of clarity, for any audits we are required to show all roles with members or no members. Whilst i understand it is pointless to show them with no roles, for our auditors that want to see that there is nothing. Again it if i had it my way i wouldnt bother with showing them. – Andrew Waters Aug 05 '21 at 02:19
  • @AndrewWaters I see what you mean, for some roles, `Get-AzureADDirectoryRoleMember -ObjectId $ADRole.objectID` doesn't produce any output hence it doesn't get exported. I know how to fix that but I need to know if the code is throwing any errors. – Santiago Squarzon Aug 05 '21 at 02:22
  • No errors are shown, i am using the second method with the [pscustomobject] – Andrew Waters Aug 05 '21 at 02:24
  • @AndrewWaters ok, I _think_ it should give you the output you expect now. I edited both code snippets. – Santiago Squarzon Aug 05 '21 at 02:38