Getty Images
Microsoft Teams lifecycle management with PowerShell and Graph
A rushed Microsoft Teams deployment could lead to unintended gaps in security and governance. Here's how to use PowerShell and the Microsoft Graph to regain control.
The early coronavirus pandemic days saw many organizations rush to implement remote-work apps, such as Microsoft Teams, which now has administrators looking to avoid some of the same mistakes by implementing a more automated management approach.
The Microsoft Teams business communications app is a platform and service on the Microsoft 365 and Office 365 suites. Historically, it worked great as a service, but many organizations struggled with deployment and adoption. Unlike other collaboration platforms, Microsoft Teams is tied to Azure Active Directory for authentication, which makes it complicated for organizations that don't subscribe to Microsoft 365/Office 365 to use it. When the coronavirus pandemic changed how we work, many organizations did not have access to video conferencing, calls, chat and general collaboration tools and rapidly deployed Microsoft Teams to fill this need. This speed fostered a lack of a standardized approach for configurations and controls in the service.
Many teams in Microsoft Teams were deployed with no governance or proper security controls due to their urgency and need. Users were allowed to create as many teams as they needed with no thought about the dependency components and how this sprawl would affect the Microsoft 365 tenant. Some organizations later found material shared in Microsoft Teams was open to any external guest and included personally identifiable information, protected health information and other sensitive data, and was often duplicated by other teams.
What is the issue with this type of Microsoft Teams deployment?
With any rushed deployment, best practices are left by the wayside. In the case of Microsoft Teams, the deployed components will add up over time and often become orphaned as certain pieces get removed or cleaned up.
Microsoft Teams provides chat and video services layered over existing components, such as Azure Active Directory, Exchange Online, SharePoint Online, OneDrive and other services. Microsoft Teams uses Office 365 groups -- which Microsoft also calls Microsoft 365 groups -- which provisions multiple services and components together. When organizations jumped to Microsoft Teams without a thorough plan, they deployed many teams, which resulted in many Office 365 groups. Each Office 365 group also includes several supporting services, including a SharePoint site, Exchange mailbox and a plan in Planner.
Microsoft Teams requires specific governance and management due to its complexity within Microsoft 365. For example, the Microsoft 365 security group controls the permissions, SharePoint Online stores files and enables sharing, and Exchange provides the fabric for email both in and out of the team. Too often, none of these components are vetted for security and whether they are still being used.
How do we control Microsoft Teams?
Microsoft offers some tooling to manage the lifecycle of the team, which includes three core areas:
- group and team creation and naming;
- group and team expiration, retention and archiving; and
- group and team membership management.
Most of these are manageable with the admin portals, but some are only available within PowerShell. One effective approach is to build a script in PowerShell that connects to Microsoft Graph to make the process repeatable. The Microsoft Graph API allows administrators to make configuration changes in Microsoft's cloud services, including Microsoft Teams and Azure Active Directory, from one endpoint.
Using PowerShell for Microsoft Teams lifecycle management
First, you must install and import the required modules and then define the scopes (permissions) needed to manage each step.
Install-Module Microsoft.Graph Select-MgProfile -Name "beta" Import-Module Microsoft.Graph $scopes = @( "User.ReadWrite.All" "Group.ReadWrite.All" "GroupMember.ReadWrite.All" "Directory.ReadWrite.All" ) Connect-MgGraph -Scopes $scopes
How to create groups and teams
Microsoft 365 groups creation uses a setting template object to store the configuration. You can modify the default values by retrieving the specific configuration and passing new values using the Update-MgDirectorySetting command. This command creates a new Azure AD directory setting to restrict who can create groups and teams.
$securitygroupname = "sg-Engineering" $allowgroupcreation = $false $groupcreationallowedgroupid = (Get-MgGroup ` -Search "DisplayName:$securitygroupname" ` -ConsistencyLevel eventual).Id $setting = 'Group.Unified' $directorysetting = Get-MgDirectorySetting | ` Where-Object DisplayName -EQ $setting $directorysetting.Values.foreach{ [MicrosoftGraphSettingValue]@{ Name = $PSItem.Name Value = $PSItem.DefaultValue } } ($updates | Where-Object Name -eq 'GroupCreationAllowedGroupId').Value = $groupcreationallowedgroupid ($updates | Where-Object Name -eq 'EnableGroupCreation').Value = $false Update-MgDirectorySetting -DirectorySettingId $directorysetting.id - Values $updates
Once you set the security group to create the Office 365 groups and teams, the next task is to define the naming convention. The following command sets the naming convention settings, forcing each group or team to use a prefix of TEAMS followed by the chosen group name and department.
$prefixnamingrequirement = "TEAM_[GroupName]_[Department]" $customblockedwordslist = "HR,IT,LEGAL" $setting = 'Group.Unified' $directorysetting = Get-MgDirectorySetting | ` Where-Object DisplayName -EQ $setting $directorysetting.Values.foreach{ [MicrosoftGraphSettingValue]@{ Name = $PSItem.Name Value = $PSItem.DefaultValue } } ($updates | Where-Object Name -eq 'PrefixSuffixNamingRequirement').Value = $prefixnamingrequirement ($updates | Where-Object Name -eq 'CustomBlockedWordsList').Value = $customblockedwordslist Update-MgDirectorySetting -DirectorySettingId $directorysetting.id - Values $updates
How to set up group and team expiration, retention and archiving
You may have requirements to set expiration, retention and archiving policies on teams and their data. You can configure group expiration policies to manage the lifecycle of the group automatically. Retention policies preserve or delete the content. You can archive teams to preserve a point-in-time view of a team that's no longer active.
The first task is to define and set a group expiration policy. The policy property ManagedGroupTypes can be None, Selected or All, depending on the groups you want to apply it to. For this example, use All with an expiration of 100 days.
$grouplifetimeindays = 100 $managedgrouptypes = "All" $alternatenotificationemails = [email protected] $properties = @{ GroupLifeTimeInDays = $grouplifetimeindays ManagedGroupTypes = $managedgrouptypes AlternateNotificationEmails = $alternatenotificationemails } $policy = $properties | New-MgGroupLifecyclePolicy
Next, you can set a retention policy for groups and teams.
Install-Module ExchangeOnlineManagement Import-Module ExchangeOnlineManagement Connect-IPPSSession $teamsname = "Teams Policy" $teamsnamerule = "Teams Policy Rule" $teamsdescription = "Teams Policy" $teamspolicy = New-RetentionCompliancePolicy -Name $teamsname -Comment $teamsdescription -TeamsChannelLocation All -TeamsChatLocation All -Enabled $true New-RetentionComplianceRule -Name $teamsnamerule -Policy $teamspolicy.Id -RetentionDuration 2555 -RetentionComplianceAction KeepAndDelete
Lastly, as needed, you can archive and restore a team.
$groupname = "Sales and Marketing" $groupid = (Get-MgGroup -Filter "DisplayName eq '$groupname'").Id Invoke-MgArchiveTeam -TeamId $groupid Invoke-MgUnarchiveTeam -TeamId $groupid
Group and team membership management
Users who require access to a Microsoft 365 team or group need to be added directly to the supporting security group. Each group or team uses multiple components, one of which includes an Azure Active Directory security group.
Controlling who has access to the team when owners of the team manage the access is complicated. However, for organizations with an Azure AD Premium Plan 2 license in the Microsoft 365/Office 365 tenant, they can execute access reviews for any security group. Administrators set up regular access reviews. An access review can be for internal users or guest users to give you better control over the groups and teams within the organization. An access review process lets the group's owners (team) or selected users modify the current permission set. Once the review completes, this process can then be automated to make the permissions adjustments.
The following PowerShell code connects to the Microsoft Graph and creates an access review for all members of the Sales and Marketing security group within Azure AD. The admin account is the owner. The code sets the review process to recur every month; if the access review is not executed, it will deny any users access.
$scopes = @( "User.ReadWrite.All" "Group.ReadWrite.All" "GroupMember.ReadWrite.All" "Directory.ReadWrite.All" "AccessReview.Read.All" "AccessReview.ReadWrite.All" "AccessReview.ReadWrite.Membership" ) Connect-MgGraph -Scopes $scopes $body = @{ "displayName" = "Sales and Marketing Access Review" "startDateTime" = "2021-12-01T09:00:00.000Z" "endDateTime" = "2025-12-01T09:00:00.000Z" "reviewerType" = "delegated" "description" = "Sales and Marketing Access Review - Executed Monthly" "businessFlowTemplateId" = "6e4f3d20-c5c3-407f-9695-8460952bcc68" "createdBy" = @{ "id" = "8d32fa65-361a-4aef-9716-60b44082eaab" "displayName" = "Microsoft Admin" "userPrincipalName" = [email protected] "mail" = [email protected] } "settings" = @{ "mailNotificationsEnabled" = "true" "remindersEnabled" = "true" "justificationRequiredOnApproval" = "true" "autoReviewEnabled" = "true" "activityDurationInDays" = 30 "autoApplyReviewResultsEnabled" = "true" "accessRecommendationsEnabled" = "true" "recurrenceSettings" = @{ "recurrenceType" = "monthly" "recurrenceEndType" = "occurrences" "durationInDays" = 7 "recurrenceCount" = 30 } "autoReviewSettings" = @{ "notReviewedResult" = "Deny" } } "reviewedEntity" = @{ "id" = "0c83236a-7484-4128-b43c-f7f5011a581b" "displayName" = "Sales and Marketing" } } Invoke-MgGraphRequest -Method POST -Uri https://graph.microsoft.com/beta/accessReviews -Body $body
There are many more areas to implement PowerShell and Microsoft Graph for Microsoft 365 groups and Microsoft Teams governance: teams, feature management, and security and compliance components such as auditing and reporting, compliance content search, e-discovery and legal hold. PowerShell combined with the Microsoft Graph is all you need to develop a script that you can reuse repeatedly.