Site icon Office 365 for IT Pros

Using the Get-AssociatedTeam Cmdlet to Report Team Memberships


Includes Shared Channel Direct Membership Too

I’ve written several articles describing how to write PowerShell scripts to create membership reports for groups and teams in the past (here’s a recent example). Usually, the scripts involve interrogating groups about their membership or finding sets of users and checking what groups they are members of. For this kind of processing, Graph API requests are the fastest way to generate results because of the number of user accounts or groups to be processed.

This brings me to the Get-AssociatedTeam cmdlet, a new cmdlet that makes its debut in version 4.6 of the MicrosoftTeams PowerShell module. Microsoft hasn’t published documentation for the cmdlet yet, but its purpose is obvious: it reports all the teams a user is a member of. As such, the Get-AssociatedTeam cmdlet could be the basis for a script to report the membership of all Teams.

Before plunging into the details of how to write such a script, the interesting thing about the Get-AssociatedTeam cmdlet is that it reports membership of shared channels. Or rather, direct membership of shared channels, which is when a user is explicitly invited to share a channel hosted in their tenant or in an external tenant. The information returned by the cmdlet includes all instances where a user is a regular member of a team and where they are a direct member of a shared channel. Unfortunately, the information returned for a team doesn’t tell you if the membership is of a regular team or shared channel. Here’s an example of the information for a team:

GroupId     : a53141d5-54ef-4a6d-877d-63b0cbda409f
DisplayName : Marketing Department
TenantId    : a662313f-14fc-43a2-9a7a-d2e27f4f3478

Being able to report membership of shared channels is the unique added value of the Get-AssociatedTeam cmdlet. There doesn’t seem to be a way to extract this information using a Graph API request, nor is there a way to report the membership of private channels without checking each of these channels.

Writing a Report Script

The script I wrote to explore the possibilities of Get-AssociatedTeam is available from GitHub. It:

  • Uses Get-MgUser to find the set of licensed Azure AD member accounts in the tenant. The Get-AssociatedTeam cmdlet doesn’t process guest accounts.
  • For each account, run Get-AssociatedTeam to return the set of teams for the user.
  • For each team, use the findTenantInformationByTenantId Graph API to resolve the tenant identifier to find the tenant name. This helps to highlight access to external tenants.
  • Report the information.

The code for the main loop is:

[int]$i = 0
$UserTeamInfo =  [System.Collections.Generic.List[Object]]::new()
ForEach ($User in $Users) {
  Write-Host ("Processing team membership for {0} ({1}/{2})..." -f $User.DisplayName, $i, $Users.Count)
  [array]$TeamInfo = Get-AssociatedTeam -User $User.UserPrincipalName
  ForEach ($Team in $TeamInfo) {
   If ($Team.TenantId -eq $TenantId) { # Resolve the tenant identifier to a name
      $Name = $TenantName }
   Else {
      $LookUpId = $Team.TenantId.toString()
      $Uri = "'$LookUpId')"
      $ExternalTenantData = Invoke-MgGraphRequest -Uri $Uri -Method Get
      $Name = $ExternalTenantData.DisplayName 
   $TeamData = [PSCustomObject][Ordered]@{  # Write out details of the team
       Id          = $User.Id
       DisplayName = $User.DisplayName 
       UPN         = $User.UserPrincipalName
       Team        = $Team.DisplayName
       TeamId      = $Team.GroupId
       Tenant      = $Name
       TenantId    = $Team.TenantId}
  } #End ForEach Team
} # End ForEach User

Analyzing the Data

Figure 1 shows the kind of information generated by the script.

Report of Teams membership generated by the Get-AssociatedTeam cmdlet
Figure 1: Report of Teams membership generated by the Get-AssociatedTeam cmdlet

Once the membership data is available, we can slice and dice it in different ways. For example, some simple analysis reveals nuggets like the average number of teams a user belongs to, how many external teams people are members of, and so on.

[array]$ExternalTeams = $UserTeamInfo | Where-Object {$_.TenantId -ne $TenantId} | Sort-Object TeamId -Unique
$ExternalPeople = $UserTeamInfo | Where-Object {$_.TenantId -ne $TenantId} | Sort-Object UPN -Unique
$ExternalPeople = $ExternalPeople.DisplayName -Join ", "
$ExternalTenants = $ExternalTeams.Tenant | Sort-Object -Unique
$AvgTeams = [math]::round(($UserTeamInfo.Count/$Users.Count),2)

Write-Host ""
Write-Host ("Each of the {0} users belongs to an average of {1} teams" -f $Users.Count, $AvgTeams)
Write-Host ("Membership of {0} teams found in {1} external tenant(s)" -f $ExternalTeams.Count, $ExternalTenants.Count)
Write-Host ("These accounts have membership of external teams: {0}" -f $ExternalPeople)

Each of the 28 users belongs to an average of 15.54 teams
Membership of 2 teams found in 1 external tenant(s)
These accounts have membership of external teams: Chris Bishop, James Ryan, Ken Bowers, Sean Landy, Tony Redmond

Generating Report Files

Carefully sliced and diced data makes an excellent foundation for reports, which can be generated as CSV files, Excel spreadsheets, HTML files, and so on.

I’ve mentioned the PSWriteHTML module before as an easy way to generate good-looking reports from PowerShell. Apart from its ability to format data in various ways, PSWriteHTML includes a very nice search builder capability to filter data. For instance, in Figure 2 I used the search builder to find the members of a specific team. When I’m happy with the data, generating a PDF, Excel, or CSV file is as easy as clicking a button.

Figure 2: Reporting Teams membership with PSWriteHTML

New Cmdlet is Useful

I’m always amazed by the number of organizations that want to report memberships of groups and teams. The Get-AssociatedTeam cmdlet certainly makes it easier to create reports for Teams. As always, the caveat for these kinds of reports is that the scripts to generate the report can take a long time to run as the number of users and teams increases into the thousands. At that point, it’s time to investigate the use of Azure Automation to create reports as scheduled jobs. Finally, if you need to generate PDF reports from PowerShell, check out the PSWriteHTML module.

Keep up to date with developments like new PowerShell cmdlets by subscribing to the Office 365 for IT Pros eBook. Our monthly updates make sure that our subscribers understand the most important changes happening across Office 365.

Exit mobile version