PowerShell Script: Microsoft Teams membership and ownership information
Since Microsoft introduced Microsoft Teams in fall 2017, they have rightly bragged about its quick adoption—more than 140,000 customers have deployed Teams in some form or another, and the Teams product group has done quite a good job of executing on their planned roadmap and delivering features as promised. We use it extensively at Quadrotech and it has quickly become a key part of our daily operations.
Teams isn’t perfect, of course. There are bugs (spend some time in the Meetings tab if you don’t believe me), missing features (why can’t I create a new meeting from the iOS mobile app?), and a dizzying rate of change. On balance, though, the overall user experience is pretty good.
Do you know what’s not so good? The Administrator experience.
Two common Teams headaches
Let’s take one common scenario. You’re an IT admin and want to know which Teams a specific user is in. You load up the Microsoft Teams PowerShell module and crack your knuckles to prepare for a little cmdlet fun.
“That can’t be right!” you mutter. So you go look up the documentation for Get-Team.
Cue sad trombone sound. This might be the least useful PowerShell cmdlet in the entire world.
Then let’s consider another common request. You have a user named Ashley in the Marketing department. You’re hiring another Marketing expert named Petah. You want Petah to be in all the same Teams that Ashley is in. Hope you like pointing and clicking in the Teams client! (And that you’re already an owner of the Teams that Petah needs to be added to.)
Fast-acting headache relief
There’s some hope on the horizon for these headaches, though. You probably remember that a Team object is really an aggregate of several other object types, but mostly it’s an Office 365 Group. The Group object provides a mailbox and calendar, file storage (courtesy of SharePoint Online), a OneNote notebook, access to Planner, and some glue metadata to make all that accessible. While the Teams PowerShell module is currently super lame, there are much more useful cmdlets for managing Office 365 Group objects. For some odd reason, these cmdlets are actually part of Exchange Online PowerShell; if you load that module and look at the Get-UnifiedGroup and Get-UnifiedGroupLinks cmdlets, you’ll find part of what we need to solve these problems.
To get a list of which Teams object a user is a member of, we need a couple of basic capabilities:
- We need to know which Teams exist on the system. Any user who holds the Office 365 Global administrator or Exchange administrator roles can get this with Get-UnifiedGroup… except that just running the cmdlet will give you all Group objects, not just Teams. To just get the Teams objects by themselves, we can filter for objects where the WelcomeMessageEnabled property is false. It will always be false for Teams, so this is not a bad heuristic until we get a better one.
- For each Team we find, we need to know who its members or owners are. Get-UnifiedGroupLinks will do that for us as long as we specify the correct MemberType
- We need to see whether our user is in that list. This turns out to be surprisingly easy because PowerShell can coerce comparison operators against an array of properties. You can say ($teamMembers.primarySMTPAddress -eq $theUser) to compare the value of theUser against all of the primary SMTP addresses for members of a Team in a single operation.
So that turns out to be a fairly easy problem to solve: get the list of Teams, iterate over them, and look at the members and/or owners to see if the target user is in them.
Cloning membership and ownership is just a small step forward from there: as we inspect each Team, if our source user (remember Ashley?) is a member or owner, we add the target user (Hi, Petah!)
Better living through automation
Faced with ongoing requests for these two use cases, I did what any self-respecting admin would do: I wrote a PowerShell script, available from the PowerShell Gallery here, to do this. The script, Get-TeamsMembership, depends on the Exchange Online Remote PowerShell module being installed. When you run it, it will connect to ExO if you’re not already connected, then give you back an object pipeline containing the Teams that the selected user is a member or owner of. When run with the -Clone or -CloneOwner switches, it will grant the targeted user member or owner access to any Team that the selected user is in. It doesn’t automatically favorite channels or anything for the cloned user, and it will happily give the target user access to any Team, so be careful with Teams that have sensitive information or limited membership.
It’s a pretty basic script, and there is certainly room for improvement. Its error handling is minimal. I don’t think Pancake the cat is very impressed with the overall code quality either, judging by the disdainful expression on his face.
Good news for our Office 365 reporting customers
When I showed the script to Doug Davis, product owner for our Office 365 reporting tool, he was, if not exactly gleeful, then at least excited. We’ll be adding Teams membership and ownership information to the User Details page very soon. Doug wouldn’t let me say when, but it won’t be long. Until then, enjoy the script!