Every Team is a Microsoft 365 Group. That single fact is the whole governance story. When a user clicks “Create team,” they are not creating a chat app — they are provisioning a Microsoft 365 Group, and Microsoft 365 fans out a connected mailbox, a SharePoint site, a OneNote, a Planner plan, and a membership/owner list, all bound to that one group object. The group is the identity, the membership, the lifecycle anchor, and the security boundary. Govern the group and you govern the Team, the files, the channels, the guests, and the expiration — all at once. Govern only “Teams” and you are governing a workload while the object underneath it sprawls unchecked.
This is why uncontrolled Teams adoption becomes a governance crisis so fast. In a tenant with self-service creation left on, a 5,000-seat organization routinely accumulates 8,000–15,000 Microsoft 365 Groups inside eighteen months: duplicate “Project Phoenix” teams, single-message teams created for a meeting that never recurred, teams whose only owner left the company two reorganizations ago, teams full of external guests nobody remembers inviting, and teams holding regulated data with external sharing wide open. None of that is a Teams problem. It is a group lifecycle problem wearing a Teams costume, and it is solved with five interlocking controls that all operate on the Microsoft 365 Group: a naming policy, an expiration policy, a creation restriction, container sensitivity labels, and guest access reviews.
This guide builds that control plane end to end — in Entra ID directory settings, Microsoft Graph PowerShell, Microsoft Purview, and Entra ID Governance. It enumerates every option, value, default, and gotcha for each control, lays the reference material out as scannable tables you keep open during a rollout, and sequences the whole thing into a staged program that pilots each control before it goes tenant-wide. By the end you will understand not just how to set a naming policy or publish a container label, but why these five controls are one system — and how they fail catastrophically when you treat them as five independent projects.
What problem this solves
Self-service collaboration is the entire value proposition of Teams: a user has a need, creates a space in ten seconds, and the work happens. Take that away with heavy-handed governance and people route around you — they collaborate in personal OneDrive, in a consumer WhatsApp group, in email attachments flying to external addresses, in shadow tenants. So the goal is never to stop creation; it is to make self-service safe and legible — every team named consistently, owned by a human, classified by sensitivity, lifecycle-bounded, and with guests that get re-attested rather than accumulated forever.
What breaks without this, concretely. Sprawl: ten thousand groups, most dormant, drowning legitimate ones in search and in the Teams left rail, and inflating your SharePoint storage and backup footprint. Ownerless data: groups whose owners left, so nobody can manage membership, approve a guest, or respond to a renewal prompt — the data is stranded and unmanageable. Unclassified regulated data: a team holding M&A documents or PII with external sharing on “anyone with the link,” because the user who made it never thought about classification and nothing forced them to. Guest accumulation: a partner’s three contractors invited two years ago, the project long finished, still members with standing access to the SharePoint site. Naming chaos: forty teams called “Marketing,” “marketing-team,” “Mktg Final,” impossible to find or audit. Each of these is a real incident waiting in a compliance audit, a data-loss event, or a help-desk queue.
Who hits this: every organization that turned on Teams (which is everyone) and left the defaults (which is most of them). It bites hardest in regulated industries (finance, healthcare, government) where unclassified or externally-shared data is a reportable event; in organizations with heavy external collaboration (consulting, manufacturing supply chains) where guest sprawl is the dominant risk; and in any tenant past ~2,000 seats where the sheer volume makes manual cleanup impossible and only policy scales. The fix is to recognize the Microsoft 365 Group as the single object all five controls act on, then build them in the right order.
To frame the whole field before the deep dive, here is every governance concern this article covers, where its control actually lives, and what tool configures it:
| Governance concern | What it controls | Where the control lives | Primary tooling | License floor |
|---|---|---|---|---|
| Naming consistency | Prefix/suffix + blocked words on group name and alias | Entra ID directory setting Group.Unified |
Graph PowerShell / Entra admin center | Entra ID P1 (per member) |
| Lifecycle / sprawl | Expiration lifetime + renewal of inactive groups | Microsoft 365 Groups expiration policy | Entra admin center / Graph | Entra ID P1 (per member) |
| Who can create | Restrict group/Team creation to a security group | Entra ID directory setting Group.Unified |
Graph PowerShell | Entra ID P1 (per member) |
| Privacy, guest, device, sharing | Container behaviors on the group + SharePoint site | Container sensitivity labels | Microsoft Purview + Graph | Purview Information Protection |
| Guest lifecycle | Recurring re-attestation; auto-remove stale guests | Access reviews | Entra ID Governance (P2) | Entra ID P2 / Governance SKU |
| Guest invitation | Who may invite; allowed/blocked domains | External collaboration / cross-tenant access | Entra admin center | Entra ID Free+ |
| Ownerless / drift | Detect under-owned groups; reassign ownership | Ownerless group policy + audit queries | Admin center + Graph PowerShell | Varies |
| Archival | Read-only retire without delete | Teams archive + retention | Teams admin / Graph / Purview | Varies |
Licensing reality check. Group naming policy, expiration, and creation restriction each require Entra ID P1 for every member of the governed groups — not just the admin. Access reviews and lifecycle workflows need Entra ID P2 (or the standalone Microsoft Entra ID Governance SKU). Container sensitivity labels are part of Microsoft Purview Information Protection (included in many E3/E5 stacks; confirm yours). Confirm entitlements before you promise any of this to a steering committee — discovering mid-rollout that 2,000 frontline workers lack P1 derails the program and the credibility.
Install the two module families used throughout. The Microsoft Graph PowerShell SDK supersedes the deprecated AzureAD and MSOnline modules; the Exchange/Purview Security & Compliance connection carries the sensitivity-label cmdlets.
# Graph SDK — directory settings, expiration, groups, access reviews
Install-Module Microsoft.Graph -Scope CurrentUser
# Security & Compliance (Purview) PowerShell — sensitivity labels & label policies
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Connect-MgGraph -Scopes @(
"Directory.ReadWrite.All", # directory settings (naming, creation)
"Group.ReadWrite.All", # group reads/writes, label backfill
"Policy.ReadWrite.Authorization",# authorization policy (default user role)
"AccessReview.ReadWrite.All" # access review definitions
)
Learning objectives
By the end of this article you can:
- Explain why every Team is a Microsoft 365 Group, and map each governance control to the exact object property and directory setting it manipulates.
- Author a group naming policy with a prefix/suffix (fixed text plus Entra attribute tokens) and a blocked-words list, and predict exactly how it transforms a user-typed name and alias.
- Configure a Microsoft 365 Groups expiration policy with the right lifetime, scope (
All/Selected/None), and renewal mechanics — and explain why activity-based auto-renewal and ownerless groups interact dangerously. - Restrict group and Team creation to an approved security group without blocking legitimate need, by pairing the restriction with a request workflow.
- Design a small, opinionated set of container sensitivity labels that enforce privacy, guest access, unmanaged-device access (via Conditional Access), and external SharePoint sharing — and publish them with a label policy that makes labeling mandatory at creation.
- Govern guest access in three stacked layers — external collaboration settings, Conditional Access for guests, and recurring access reviews with auto-apply — so guests are re-attested rather than accumulated.
- Detect and remediate drift: ownerless groups, unlabeled groups, dormant teams, and orphaned guests — and decide between archival, soft-delete, and hard-delete for retirement.
- Compare sensitivity labels vs classic group classification and choose correctly, and sequence a staged governance rollout that pilots every control before tenant-wide enforcement.
Prerequisites & where this fits
You should understand the Microsoft 365 Groups model: a Microsoft 365 Group (formerly “Office 365 Group” / “Unified Group”) is a directory object with groupTypes containing Unified, carrying members and owners, that provisions connected workloads (Exchange mailbox, SharePoint site, Teams, Planner). You should know the difference between a security group (used for access control and as the target of these policies) and a Microsoft 365 Group (the thing being governed), and between assigned membership (static, owner-managed) and dynamic membership (rule-driven by membershipRule). Comfort with running Microsoft Graph PowerShell, reading JSON, and the Microsoft Purview compliance portal is assumed.
This sits in the Microsoft 365 governance and information protection track. It is the collaboration-surface counterpart to Governing SharePoint and OneDrive External Sharing: Tenant vs Site Controls, Sensitivity Labels, and Access Reviews — every team has a SharePoint site, so the two governance models overlap directly at the container label. The labels themselves are the container scope of the labels covered in Sensitivity Labels in Microsoft Purview: Auto-Labeling, Encryption, Co-Authoring, and Container Inheritance. The guest-lifecycle layer leans on identity governance from Building an Access Reviews Program in Entra ID: Recertifying Privileged Roles, Groups, and Guest Access at Scale and Securing B2B Collaboration with Entra External ID: Cross-Tenant Access Settings and Custom Onboarding. The unmanaged-device control on a container label is enforced through the same Conditional Access machinery as Designing Conditional Access at Scale: A Persona-Based Policy Framework with Authentication Context and Filters.
A quick map of who owns what, so the program lands on the right teams:
| Layer | What lives here | Who typically owns it | Governance failure it causes if neglected |
|---|---|---|---|
| Directory settings (Entra) | Naming, creation restriction | Identity / IAM team | Naming chaos; unrestricted self-service sprawl |
| Lifecycle policy (Entra) | Expiration, renewal | Collaboration / M365 ops | Infinite group accumulation; ownerless data |
| Information protection (Purview) | Container sensitivity labels | Security / compliance | Unclassified regulated data; external oversharing |
| Identity governance (Entra P2) | Access reviews, entitlement, lifecycle workflows | Identity governance team | Guest accumulation; stale standing access |
| Teams / SharePoint admin | Teams policies, site controls, archival | Workplace / collaboration ops | Inconsistent retirement; archive vs delete confusion |
| Audit & reporting | Drift detection, usage reports, SIEM | SecOps / platform | Policy drift goes unnoticed until an audit |
Core concepts
Six mental models make every later configuration obvious.
One object, many workloads — govern the group. A Team is a façade over a Microsoft 365 Group. The group object owns membership, owners, the mailbox, the SharePoint site collection, and the lifecycle properties (expirationDateTime, assignedLabels). Teams, Planner, and the rest are connected resources that read from the group. There is deliberately no Teams-specific naming toggle, no Teams-specific creation toggle, no Teams-specific expiration — because those controls live on the group and therefore govern every connected workload simultaneously. Internalize this and you stop hunting for “the Teams setting” that doesn’t exist.
Naming policy is a directory setting, applied at write time. The naming policy lives in the Group.Unified directory setting template (there is no first-class Set-NamingPolicy cmdlet — you instantiate and patch the template). It does two things on creation and rename: stamps a deterministic prefix/suffix onto the group’s displayName and mailNickname (alias), and rejects names whose user-supplied portion contains a blocked word. It is enforced across all creation surfaces — Teams, Outlook, Planner, SharePoint, the Microsoft 365 admin center, Graph API — with one critical exemption: Global Administrators (and a few other high-privilege roles) bypass it entirely, which is why admin-account testing produces false confidence.
Expiration is an owner-driven, activity-aware lifecycle. The Microsoft 365 Groups expiration policy assigns a lifetime in days. As a group nears expiry, the platform emails its owners to renew; separately, any group with recent activity (a Teams message, a SharePoint file edit, an Outlook conversation, a Planner update, a SharePoint visit) is auto-renewed without anyone clicking anything. A group that is neither renewed nor active is soft-deleted — recoverable for 30 days, after which it is permanently gone. The two load-bearing dependencies: expiration needs human owners (ownerless groups get no renewal prompt and silently expire) and it explicitly excludes dynamic groups from the renewal engine.
Container sensitivity labels enforce container behavior, not file encryption. Sensitivity labels have two scopes: items (files and emails — where they can encrypt and watermark) and groups & sites (containers). A container label applied to a group/Team controls the container’s privacy (public vs private), whether guests can be members, whether unmanaged devices can access the connected SharePoint site (full access / web-only / blocked, via Conditional Access), the site’s external sharing scope, and the default sharing link type. A container label does not by itself encrypt the files inside the team — that is the item scope’s job, applied to documents. The same label can carry both scopes, but the container settings and the encryption settings are configured independently.
Guests are governed at two boundaries and re-attested over time. A container label gates guests at the group boundary (can a guest be added to this team at all). The tenant boundary — who may invite, which domains are allowed, what Conditional Access guests face — is governed separately through external collaboration and cross-tenant access settings. And because access granted is access that lingers, the lifecycle of each guest is governed by access reviews: a recurring campaign where owners (or named reviewers) re-attest each external member, and unreviewed or denied guests are auto-removed. Three layers — boundary, posture, lifecycle — that stack.
Soft-delete, hard-delete, and archive are three different retirements. When a team is “deleted” it is soft-deleted (the group goes to the deleted-items container, recoverable for 30 days, all workloads frozen). After 30 days it is hard-deleted (permanent). Archiving a team is different again: the team becomes read-only — members can read history but not post or edit — while the group and its data remain fully intact and instantly un-archivable. Choosing the right retirement (archive a finished-but-referenced project, soft-delete a mistake, let expiration soft-delete dormant ones) is a governance decision, not a technicality.
The vocabulary in one table
Pin down every moving part before the deep sections. The glossary repeats these for lookup; this table is the model side by side:
| Concept | One-line definition | Where it lives | Why it matters to governance |
|---|---|---|---|
| Microsoft 365 Group | Directory object (groupTypes: Unified) provisioning connected workloads |
Entra ID | The single object all five controls act on |
| Team | The Teams workload layered on a Microsoft 365 Group | Connected to the group | What users see; not the governance object |
Group.Unified setting |
Directory setting template holding naming + creation config | Entra ID directory settings | Where naming and creation control physically live |
| Naming policy | Prefix/suffix + blocked words on name/alias | Group.Unified values |
Consistency; admin-exempt gotcha |
| Expiration policy | Lifetime in days + renewal/soft-delete | M365 Groups lifecycle policy | Sprawl control; needs owners; excludes dynamic |
| Container label | Sensitivity label, group/site scope | Purview + group assignedLabels |
Privacy/guest/device/sharing enforcement |
| Label policy | Publishes labels to users; sets mandatory/default | Purview | Without it labels never appear on groups |
| Access review | Recurring re-attestation campaign | Entra ID Governance (P2) | Guest lifecycle; auto-removes stale access |
| External collaboration | Who can invite; allowed/blocked domains | Entra external identities | Guest invitation boundary |
| Ownerless group policy | Auto-nominates owners for groups with none | Microsoft 365 admin center | Keeps renewal working; accountability |
| Soft-delete / hard-delete | 30-day recoverable / permanent | Deleted items container | Recovery window vs permanence |
| Archive | Read-only retire, data intact | Teams admin / Graph | Retire-without-delete for finished work |
The naming policy: prefixes, suffixes, and blocked words
A naming policy is the cheapest, highest-visibility governance win — every new team’s name announces that governance exists. It does exactly two things, and understanding the mechanics prevents the classic rollout bugs.
What the policy actually transforms
The policy operates on two properties: displayName (the friendly name users see) and mailNickname (the email alias, used for the group’s SMTP address and SharePoint URL). The prefix/suffix string is a template made of fixed text and attribute tokens resolved from the creator’s Entra user object. The literal token [GroupName] represents whatever the user typed. A template of GRP_[Department]_[GroupName] typed by a Marketing user who enters “Campaign Planning” produces the display name GRP_Marketing_Campaign Planning and a sanitized alias.
The blocked-words list is a case-insensitive, comma-separated list (up to 5,000 entries, each up to 50 characters) that matches against the user-supplied portion only — not your own prefix. So blocking HR does not break a prefix that happens to contain those letters; it blocks a user from typing a name containing HR as a word fragment (the match is substring-based, so be deliberate — blocking HR also blocks “THREAD”).
The supported attribute tokens, and the behavior when an attribute is empty, are the details people get wrong:
| Token | Resolves from (creator’s user object) | Behavior if attribute is empty | Typical use |
|---|---|---|---|
[GroupName] |
The name the user typed (mandatory token) | N/A — it’s the user input | Always include exactly once |
[Department] |
department attribute |
Token removed; surrounding text remains | Departmental grouping |
[Company] |
companyName attribute |
Token removed | Multi-company tenant separation |
[Office] |
physicalDeliveryOfficeName |
Token removed | Site/office prefixing |
[StateOrProvince] |
state |
Token removed | Regional grouping |
[CountryOrRegion] |
country |
Token removed | Geo separation |
[Title] |
jobTitle |
Token removed | Rarely useful; high cardinality |
Fixed text (e.g. GRP_) |
Literal | Always present | Stable, searchable prefix |
The
[GroupName]trap.[GroupName]is the literal token for the user’s input. Forget it and every group collapses to the same static string — aGRP_Marketing_prefix with no user portion means every Marketing group is literally named “GRP_Marketing_”, and creation fails on the second one (duplicate alias). This is the single most common naming-policy rollout bug. Always include[GroupName]exactly once.
Prefix vs suffix, and length limits
You can place tokens before and after [GroupName]. A prefix is more useful for search and sort (everything groups together alphabetically); a suffix (e.g. [GroupName]_EXT for externally-shared teams) reads more naturally to users. The combined result must respect the platform limits — exceed them and creation fails with a length error.
| Constraint | Limit | Consequence of exceeding |
|---|---|---|
displayName total length |
256 characters | Creation rejected |
mailNickname (alias) total length |
64 characters | Creation rejected |
| Blocked-words list entries | 5,000 | Cannot add more |
| Each blocked word length | 50 characters | Entry rejected |
| Prefix + suffix combined fixed text | Reasonable (keep < ~50 chars) | Eats into user’s available length |
Configuring it
There is no first-class cmdlet — instantiate the Group.Unified template from a directory setting, then patch its values. (The cmdlets here use the beta Graph profile because directory-setting templates surface there.)
# Get (or create) the Group.Unified directory setting from its template
$template = Get-MgBetaDirectorySettingTemplate |
Where-Object DisplayName -eq "Group.Unified"
$setting = Get-MgBetaDirectorySetting |
Where-Object TemplateId -eq $template.Id
if (-not $setting) {
$values = $template.Values | ForEach-Object {
@{ Name = $_.Name; Value = $_.DefaultValue }
}
$setting = New-MgBetaDirectorySetting -TemplateId $template.Id -Values $values
}
# Apply the naming convention and the blocked-word list
$body = $setting.Values
($body | Where-Object Name -eq "PrefixSuffixNamingRequirement").Value =
"GRP_[Department]_[GroupName]"
($body | Where-Object Name -eq "CustomBlockedWordsList").Value =
"CEO,Payroll,Legal,Board,Confidential,Director,Executive,Finance"
Update-MgBetaDirectorySetting -DirectorySettingId $setting.Id -Values $body
Global Administrators, Partner Tier1/Tier2 Support, User Administrator, and Directory Writers roles are exempt from naming enforcement and blocked words. Always validate the policy by creating a group as a standard, non-admin user — admin testing will sail past the very rules you are trying to verify.
The directory-setting value names you will touch (the ones relevant to governance — the template has more):
Value name (Group.Unified) |
Type | Purpose | Example value |
|---|---|---|---|
PrefixSuffixNamingRequirement |
String | The naming template | GRP_[Department]_[GroupName] |
CustomBlockedWordsList |
String (CSV) | Blocked words (user portion) | CEO,Payroll,Legal |
EnableGroupCreation |
Boolean | Whether all users can create | false |
GroupCreationAllowedGroupId |
GUID | Security group allowed to create | <group object id> |
AllowGuestsToBeGroupOwner |
Boolean | Can guests own groups | false |
AllowGuestsToAccessGroups |
Boolean | Can guests access group resources | true |
GuestUsageGuidelinesUrl |
String | URL shown to guests | https://contoso.com/guest-policy |
UsageGuidelinesUrl |
String | “Group usage guidelines” link in clients | https://contoso.com/teams-policy |
EnableMSStandardBlockedWords |
Boolean | Microsoft’s profanity list (no custom edit) | true |
Expiration and renewal: bounding the lifecycle
Left alone, groups accumulate forever — every meeting, every short project, every experiment leaves a permanent team. The expiration policy is how you put a clock on them.
How the lifecycle actually runs
Set a lifetime in days (the canonical value is 180; the minimum is 30). The platform tracks each group’s expirationDateTime. As that date approaches, two things happen in parallel:
-
Activity-based auto-renewal. If the group had qualifying activity within the renewal window, its expiration is pushed forward automatically — no human action. Qualifying activity includes: a Teams channel message or visit, a SharePoint file view/edit, an Outlook group-mailbox conversation, a Yammer/Viva Engage post, and a Planner change. In practice this means active teams never expire — only genuinely dormant ones reach the renewal email, which is exactly the signal you want.
-
Owner renewal notifications. For groups without qualifying activity, the platform emails the group owners at intervals before expiry (typically at 30 days, 15 days, and 1 day out) asking them to renew with one click. Renewing resets the clock by another full lifetime.
A group that is neither active nor renewed by its owners is soft-deleted at expiry — recoverable for 30 days via the deleted-groups container, then permanently removed. The renewal notification intervals and what happens at each:
| Time before expiry | Platform action | Who is notified | What clears it |
|---|---|---|---|
| Continuously | Activity check | (none — automatic) | Any qualifying activity auto-renews |
| 30 days | First renewal email | Group owners | Owner clicks “Renew” or activity occurs |
| 15 days | Second renewal email | Group owners | Owner clicks “Renew” or activity occurs |
| 1 day | Final renewal email | Group owners | Owner clicks “Renew” or activity occurs |
| Expiry | Soft-delete | Owners notified of deletion | Restore within 30 days |
| Expiry + 30 days | Hard-delete (permanent) | — | Unrecoverable |
Scope it before you trust it
The policy’s scope (ManagedGroupTypes) is the most consequential setting. Start narrow.
ManagedGroupTypes |
What it governs | When to use | Risk |
|---|---|---|---|
None |
Nothing (policy effectively off) | Disable without deleting the policy | None |
Selected |
Only explicitly added groups | Pilot — scope to one security group first | Low; controlled blast radius |
All |
Every Microsoft 365 Group in the tenant | Steady state, after piloting and ownerless cleanup | High if owners/dynamic groups not handled |
# Pilot: 180-day lifetime, scoped to selected groups, renewal notices to a governance mailbox
Update-MgGroupLifecyclePolicy `
-GroupLifecyclePolicyId (Get-MgGroupLifecyclePolicy).Id `
-GroupLifetimeInDays 180 `
-ManagedGroupTypes "Selected" `
-AlternateNotificationEmails "groups-governance@contoso.com"
# If no policy exists yet, create it, then add pilot groups to its Selected scope
$policyId = (Get-MgGroupLifecyclePolicy).Id
$pilot = "11111111-1111-1111-1111-111111111111"
New-MgGroupLifecyclePolicyGroup -GroupLifecyclePolicyId $policyId `
-AdditionalProperties @{ "groupId" = $pilot }
Ownerless groups never get a renewal prompt and silently expire. This is why the ownerless-group cleanup (covered under drift) is not optional — it is a precondition for ever setting
ManagedGroupTypes = All. And dynamic Microsoft 365 Groups are excluded from the renewal engine entirely: a dynamic group with real SharePoint activity will still hit expiry because activity-based renewal does not apply to it, and a SCIM/dynamic group typically has no human owner to renew it. AuditmembershipRuleand owner count before widening scope, never after the first deletion wave.
The two hard constraints that cause the worst incidents, stated plainly:
| Expiration dependency | Why it matters | What breaks if ignored |
|---|---|---|
| At least one human owner | Renewal emails go to owners only | Ownerless groups expire and soft-delete with no warning to anyone |
| Assigned (not dynamic) membership | Activity-based auto-renewal only applies to assigned groups | Active dynamic teams still expire on schedule |
| Entra ID P1 for all members | Licensing requirement | Policy may not apply / compliance gap |
| Communication to owners | Owners must know the renewal mechanic | Panic tickets about “deleted” teams on the first wave |
Restricting who can create teams
By default, any user can create a Microsoft 365 Group (and therefore a Team, a Planner plan, an Outlook group, a SharePoint site). To gate that, set EnableGroupCreation to false and point GroupCreationAllowedGroupId at a security group whose members retain the right. This one setting governs creation across all surfaces simultaneously — there is, again, no Teams-only toggle.
# Restrict creation to members of a 'Team-Creators' security group
$allowed = Get-MgGroup -Filter "displayName eq 'Team-Creators'"
$body = $setting.Values
($body | Where-Object Name -eq "EnableGroupCreation").Value = "false"
($body | Where-Object Name -eq "GroupCreationAllowedGroupId").Value = $allowed.Id
Update-MgBetaDirectorySetting -DirectorySettingId $setting.Id -Values $body
The three creation-control postures
There is no single “right” answer — it is a trade-off between safety and self-service friction. The realistic options:
| Posture | EnableGroupCreation |
Who creates | Best for | Cost |
|---|---|---|---|---|
| Open self-service | true (default) |
Everyone | Tiny/low-risk tenants; max agility | Sprawl; no front-door governance |
| Restricted + request flow | false + allowed group |
A delegated set + a request workflow | Most enterprises | Build/run a request workflow |
| Template-driven | false + provisioning app |
A provisioning app/PnP solution | Mature orgs wanting consistent teams | Significant build investment |
| Fully locked (IT-only) | false, no broad allowed group |
IT only | Highly regulated; low collaboration tempo | High friction; shadow-IT risk |
Restricting creation does not stop users from needing a team — it stops them creating one ad hoc. Pair it with a request workflow (a Power Automate flow, a ServiceNow/Jira catalog item, or a Teams provisioning app like PnP Provisioning) so legitimate requests are fulfilled in hours, with the right label and owners applied at birth. Governance that only says “no” gets routed around with personal accounts, consumer apps, and shadow IT — the worst possible outcome.
What the restriction does and does not block — a common source of confusion:
| Action | Blocked by creation restriction? | Notes |
|---|---|---|
| Create a Team in Teams | Yes | The “Create team” path is hidden/blocked for non-members |
| Create an Outlook group | Yes | Same underlying group creation |
| Create a Planner plan (new group) | Yes | Planner backed by a new group is blocked |
| Create a SharePoint team site (group-connected) | Yes | Group-connected site creation is blocked |
| Create a communication SharePoint site | No | Not group-backed; governed by SharePoint settings |
| Be added to an existing team | No | Membership is separate from creation |
| Create a private/shared channel | No | Channels live inside an existing team |
| Self-service via approved request flow | No (by design) | The flow runs as a privileged account |
Container sensitivity labels: privacy, guests, devices, sharing
This is the richest control. A container sensitivity label applied to a Team/group enforces four families of behavior on the container and its connected SharePoint site. Understand each family, then author a small, opinionated set.
The four control families
| Control family | What it governs | Setting(s) | Values |
|---|---|---|---|
| Privacy | Public vs private group | Container privacy | Public, Private, or “let user decide” |
| External (guest) access | Whether guests can be members | Guest access on the container | Allow / Block guest membership |
| Unmanaged-device access | Access from non-compliant devices to the site | Conditional Access (via label) | Full / Limited web-only / Block |
| External sharing | Site’s external sharing scope + default link | SharePoint site sharing | Anyone / New+existing guests / Existing guests / Only people in org |
The privacy choice on the label closes a real gap: by default users can flip a team between public and private freely. A label can force privacy (e.g. a “Confidential” label forces Private) so a regulated team cannot be made public by an unaware user.
The guest control determines whether the group will accept external members at all. A “Highly Confidential — Internal Only” label that blocks guests means even an owner cannot add an external user — the platform refuses.
The unmanaged-device control routes through Conditional Access: the label sets a session policy so that access from a device that is not Intune-compliant or Entra hybrid-joined is either limited to web-only with no download/print/sync, or blocked entirely. This is how a container label enforces device posture without you authoring a separate CA policy per team.
The external-sharing control sets the connected SharePoint site’s sharing ceiling. SiteExternalSharingControlType accepts these values:
SiteExternalSharingControlType |
Meaning | Use for |
|---|---|---|
ExternalUserAndGuestSharing |
“Anyone” — anonymous/shareable links allowed | Rarely; only deliberately public content |
ExternalUserSharingOnly |
New and existing guests (authenticated) | Normal external collaboration |
ExistingExternalUserSharingOnly |
Only guests already in the directory | Tightened collaboration |
Disabled |
Only people in the organization | Confidential/internal-only containers |
Authoring a label
Connect to Purview PowerShell, create the label with the Site, UnifiedGroup content type, and configure container settings via AdvancedSettings plus the dedicated site parameters.
Connect-IPPSSession -UserPrincipalName admin@contoso.com
New-Label -Name "Confidential-Internal" `
-DisplayName "Confidential - Internal Only" `
-Tooltip "Private team, no guests, internal sharing, managed devices only" `
-ContentType "Site, UnifiedGroup"
# Guest and group-creation behaviors
Set-Label -Identity "Confidential-Internal" -AdvancedSettings @{
BlockGuestUserAccessOnGroupCreation = "true" # no guests can be added
AllowEmailFromGuestUsers = "false"
AllowAccessToGuestUsers = "false"
}
# Privacy + SharePoint site sharing posture
Set-Label -Identity "Confidential-Internal" `
-SiteAndGroupProtectionEnabled $true `
-SiteExternalSharingControlType "Disabled"
A worked four-label set covering the privacy/guest/device/sharing matrix — the goal is a decision a user makes in two seconds, so keep it to three or four:
| Label | Privacy | Guests | Unmanaged devices | External sharing | Typical content |
|---|---|---|---|---|---|
| Public | Public | Allowed | Full access | New + existing guests | Open, non-sensitive collaboration |
| General | Private (default) | Allowed | Full access | New + existing guests | Day-to-day project work |
| Confidential — Internal | Private (forced) | Blocked | Web-only (no download) | Only people in org | Regulated/sensitive internal data |
| Highly Confidential | Private (forced) | Blocked | Blocked | Only people in org | M&A, legal hold, crown-jewel data |
Keep the menu short. A label list of fifteen options causes mislabeling — users pick wrong or pick the default to escape the decision. Three or four labels covering the real matrix is the sweet spot. Long, granular label taxonomies are a classic over-engineering failure that reduces classification accuracy.
The Set-Label advanced settings most relevant to containers (there are more; these are the load-bearing ones):
| Advanced setting | Effect | Values |
|---|---|---|
BlockGuestUserAccessOnGroupCreation |
Prevent guests being added on creation | true / false |
AllowAccessToGuestUsers |
Whether guests can access at all | true / false |
AllowEmailFromGuestUsers |
Guests can email the group | true / false |
MembersCanShare |
Members may share the site externally | MemberShare / Disabled |
EnableGroupCreation (within container settings) |
Whether labeled containers can be created by users | true / false |
Publishing labels and enforcing them on teams
A label does nothing until a label policy publishes it to users and tenant-level container labeling is switched on. This sequencing trips up most rollouts.
Step 1 — Turn on container labeling at the tenant
Container sensitivity labeling is off by default. Until you enable it, labels will not appear on groups or sites at all, no matter how many you author. Sync labels into Entra and enable the SharePoint integration:
# Sync sensitivity labels into Entra ID so they're usable on containers
Execute-AzureAdLabelSync
# Enable SharePoint/OneDrive to honor sensitivity labels on sites
Set-SPOTenant -EnableAIPIntegration $true
Step 2 — Publish with a label policy (mandatory + default)
A label policy makes the labels visible and can make labeling mandatory at creation and supply a default label for users who would otherwise skip it.
New-LabelPolicy -Name "Container-Label-Policy" `
-Labels "Public","General","Confidential-Internal","Highly-Confidential" `
-ExchangeLocation "All"
# Make a label mandatory for groups and set a sensible default
Set-LabelPolicy -Identity "Container-Label-Policy" -AdvancedSettings @{
DefaultContainerLabel = (Get-Label -Identity "General").Guid
MandatoryLabelForGroup = "true"
}
The label-policy advanced settings that matter for containers:
| Label-policy setting | Effect | Recommendation |
|---|---|---|
MandatoryLabelForGroup |
Force a label choice when creating a group/team | true in regulated tenants |
DefaultContainerLabel |
Default label applied if user doesn’t choose | Set to your safest “General” |
DisableMandatoryInOutlook |
Exempt Outlook from mandatory item labeling | Container vs item nuance |
| Policy scope (users/groups) | Who sees these labels | Pilot to a group first |
Step 3 — Backfill existing teams
Teams created before labeling are unlabeled. Backfill them by patching the group’s assignedLabels via Graph:
$labelId = (Get-Label -Identity "General").Guid
$teams = Get-MgGroup -Filter "groupTypes/any(c:c eq 'Unified')" -All
foreach ($t in $teams) {
Update-MgGroup -GroupId $t.Id -AdditionalProperties @{
assignedLabels = @(@{ labelId = $labelId })
}
}
Backfill sets the floor going forward — it does not retroactively evict. Two propagation realities: (1) a privacy or guest change on a label can take time to propagate to the connected SharePoint site (not instantaneous), and (2) changing a label on an existing group does not remove guests already added under the old policy. So backfill must be paired with a one-time guest cleanup (the access-review and audit work below). Treat the label change as “from now on,” then clean up the existing state separately.
The propagation and retroactivity behaviors, so expectations are calibrated:
| Change | Propagates to SharePoint site? | Retroactive on existing state? | Operational implication |
|---|---|---|---|
| Apply label to existing group | Yes (asynchronously) | No — existing guests remain | Pair with guest cleanup |
| Change privacy on label | Eventually | No — doesn’t reshuffle membership | Don’t expect instant effect |
| Change external-sharing on label | Eventually | Existing shared links may persist | Audit existing links separately |
| Block guests on label | Future adds blocked | Existing guests stay | Run a guest review |
| Change unmanaged-device control | Via CA, near-real-time | Applies to next session | Sessions re-evaluate |
Guest access governance: invitation, posture, and lifecycle
Container labels gate guests at the group boundary. Guests at the tenant boundary, and over time, need three stacked controls.
Layer 1 — External collaboration and cross-tenant access (the invitation boundary)
Decide who may invite guests and which domains are allowed. Most tenants want member-or-admin invitation rights, never “anyone including guests,” and an allow-list (or block-list) of partner domains. The guest-invite settings:
| Setting | Options | Recommended | Why |
|---|---|---|---|
| Who can invite guests | Anyone / Members & admins / Admins & guest-inviter role / No one | Members & admins (or guest-inviter role) | Limit invitation sprawl |
| Guest user access level | Same as members / Limited / Restricted | Limited or Restricted | Guests shouldn’t enumerate the directory |
| Collaboration domain restrictions | Allow specified / Block specified | Allow-list partner domains | Prevent invites to arbitrary domains |
| Cross-tenant access (B2B) | Per-tenant inbound/outbound trust | Configure trusted partner tenants | Granular B2B trust, MFA pass-through |
These are configured in the Entra admin center under External Identities; cross-tenant access settings let you trust a partner tenant’s MFA and device claims so guests aren’t double-prompted. See Securing B2B Collaboration with Entra External ID: Cross-Tenant Access Settings and Custom Onboarding for the full model.
Layer 2 — Conditional Access for guests (the posture boundary)
Guests authenticate against their home tenant, so you cannot enroll or manage their device — device-compliance Conditional Access doesn’t apply the way it does for employees. Instead, target the All guest and external users user scope with a policy that requires MFA and uses session controls (sign-in frequency, no persistent browser). The realistic guest CA controls:
| CA control for guests | Works for guests? | Use |
|---|---|---|
| Require MFA | Yes | Always — baseline for any guest access |
| Require compliant device | No (can’t manage their device) | Use the container-label web-only control instead |
| Require hybrid-joined device | No | Same |
| Sign-in frequency / no persistent browser | Yes | Reduce standing session risk |
| Block legacy authentication | Yes | Always |
| Terms of use acceptance | Yes | Compliance/audit trail |
Layer 3 — Access reviews (the lifecycle boundary)
This is the control that actually removes stale guests. A recurring access review has owners (or named reviewers) re-attest each external member; with auto-apply and a default of Deny, inaction revokes access. Create one scoped to all Microsoft 365 Groups containing guests:
$params = @{
displayName = "Quarterly guest review - all M365 Groups"
descriptionForAdmins = "Owners re-attest external members each quarter"
scope = @{
"@odata.type" = "#microsoft.graph.accessReviewQueryScope"
query = "/groups?`$filter=groupTypes/any(c:c eq 'Unified')"
queryType = "MicrosoftGraph"
}
reviewers = @(@{ query = "./owners"; queryType = "MicrosoftGraph" })
settings = @{
recurrence = @{
pattern = @{ type = "absoluteMonthly"; interval = 3 }
range = @{ type = "noEnd"; startDate = "2026-06-01" }
}
defaultDecision = "Deny" # remove if no decision
defaultDecisionEnabled = $true
autoApplyDecisionsEnabled = $true
instanceDurationInDays = 14
}
}
New-MgIdentityGovernanceAccessReviewDefinition -BodyParameter $params
defaultDecision = "Deny"andautoApplyDecisionsEnabled = $truemust be set together, or the review becomes a quarterly box-ticking exercise that removes no one. The entire point of a review is that not responding revokes access. Give owners 14 days, add an escalation/fallback reviewer, and scope reviewers to./ownersso accountability sits with the people who actually know the guests.
The access-review settings that determine whether the review does anything:
| Setting | Effect | Governance-correct value |
|---|---|---|
defaultDecision |
Decision applied when no one reviews | Deny (revoke on inaction) |
autoApplyDecisionsEnabled |
Whether decisions are enforced automatically | true |
instanceDurationInDays |
How long reviewers have | 14 (balance urgency vs availability) |
reviewers |
Who attests | ./owners (+ fallback) |
recurrence |
Cadence | Quarterly for guests; monthly for crown jewels |
recommendationsEnabled |
Show usage-based recommendations | true (helps reviewers decide) |
Detecting drift: ownerless, unlabeled, dormant, orphaned
Governance is only real if you can prove it and catch erosion. Four queries cover the bulk of operational reporting.
Ownerless and under-owned groups
These break renewal and accountability. Every governed group should have at least two owners.
$risky = foreach ($g in Get-MgGroup -Filter "groupTypes/any(c:c eq 'Unified')" -All) {
$owners = Get-MgGroupOwner -GroupId $g.Id -All
if ($owners.Count -lt 2) {
[pscustomobject]@{
Group = $g.DisplayName
Owners = $owners.Count
Id = $g.Id
}
}
}
$risky | Sort-Object Owners | Export-Csv ./ownerless-groups.csv -NoTypeInformation
Microsoft 365 also ships a built-in ownerless groups policy (Microsoft 365 admin center) that automatically emails the most-active members of an ownerless group asking them to nominate themselves as owners. Enable it so the CSV above trends toward empty. Its key settings:
| Ownerless-group policy setting | Purpose | Recommended |
|---|---|---|
| Enable policy | Turn on auto-nomination emails | Yes |
| Max active members to email | How many candidates get the prompt | 2–3 |
| Allowed security group (who’s in scope) | Limit which groups the policy targets | Scope to governed groups |
| Number of weeks to send | How long to keep prompting | 4 |
| Require manager approval | Whether a manager must approve the new owner | Optional (adds rigor) |
Unlabeled groups (label drift)
Find Unified groups still missing a container label after backfill:
Get-MgGroup -Filter "groupTypes/any(c:c eq 'Unified')" -All `
-Property "id,displayName,assignedLabels" |
Where-Object { -not $_.AssignedLabels } |
Select-Object DisplayName, Id
Dormant teams (usage)
Last-activity and message-count data for dormant-team identification comes from the Microsoft 365 usage reports (Teams team activity, Groups activity) in the admin center or via the reports Graph endpoints. Reconcile dormant teams against expiration outcomes — a team that’s dormant but kept getting auto-renewed by a stray SharePoint visit is a candidate for manual archival or deletion.
Orphaned guests
Guests on teams that should have none (per their label), or guests whose inviting project is long finished. The access review removes them on cadence; an ad-hoc query finds them between reviews:
# Guests that are members of any Unified group (feed into review/cleanup)
$guests = Get-MgUser -Filter "userType eq 'Guest'" -All
foreach ($u in $guests) {
Get-MgUserMemberOf -UserId $u.Id -All |
Where-Object { $_.AdditionalProperties.groupTypes -contains "Unified" } |
ForEach-Object {
[pscustomobject]@{ Guest = $u.Mail; Group = $_.AdditionalProperties.displayName }
}
}
The drift signals and how to remediate each:
| Drift signal | Detect with | Remediate with | Cadence |
|---|---|---|---|
| Ownerless / under-owned | Owner-count query | Ownerless-group policy; assign owners | Weekly |
| Unlabeled group | assignedLabels empty query |
Backfill default label | Weekly until zero |
| Dormant team | Teams/Groups usage reports | Archive or delete; let expiration act | Monthly |
| Orphaned guest | Guest membership query | Access review auto-remove | Quarterly (review) |
| Public team holding sensitive data | Privacy + label mismatch query | Re-label; force private | Monthly |
| Duplicate-named teams | displayName grouping |
Merge/consolidate; delete dupes | Quarterly |
Archival and retirement: archive vs soft-delete vs hard-delete
Retirement is a governance decision with three distinct mechanisms — choosing wrong either loses data or clutters the tenant.
Archive when a team’s work is finished but still referenced (a completed project people occasionally search). Archiving makes the team read-only — members read history but can’t post or edit — while the group, SharePoint site, files, and channels stay fully intact and the team can be un-archived instantly. You can also set the SharePoint site to read-only at the same time.
# Archive a team (read-only); set SharePoint site read-only too
$teamId = (Get-MgGroup -Filter "displayName eq 'GRP_Eng_Project Phoenix'").Id
Invoke-MgArchiveTeam -TeamId $teamId `
-BodyParameter @{ shouldSetSpoSiteReadOnlyForMembers = $true }
Soft-delete when a team was a mistake or is genuinely no longer needed but you want a safety window — it’s recoverable for 30 days. Expiration produces soft-deletes automatically.
Hard-delete is what happens after the 30-day window, or via permanent removal of an already-soft-deleted group — unrecoverable. Restore within the window with Graph (the UI has no bulk path):
# Restore soft-deleted groups (within 30 days) matching a naming pattern
Get-MgDirectoryDeletedItemAsGroup -All |
Where-Object { $_.GroupTypes -contains "Unified" -and $_.DisplayName -like "GRP_Plant_*" } |
ForEach-Object { Restore-MgDirectoryDeletedItem -DirectoryObjectId $_.Id }
The retirement decision matrix:
| You want to… | Mechanism | Data state | Reversible? | Who initiates |
|---|---|---|---|---|
| Retire finished-but-referenced work | Archive | Read-only, fully intact | Instantly (un-archive) | Owner / admin |
| Retire a mistake with a safety net | Soft-delete | Frozen in deleted-items | 30 days | Owner / admin / expiration |
| Permanently remove | Hard-delete | Gone | No | Admin / 30-day timeout |
| Preserve for compliance/legal | Retention/hold (Purview) | Preserved regardless | Per retention policy | Compliance |
| Reduce noise without deleting | Hide from Teams / leave | Intact, hidden from rail | Yes | User |
Retention and legal hold (Microsoft Purview) override deletion: a group under a retention policy or eDiscovery hold won’t truly purge even when soft-deleted past 30 days — the content is preserved in place. This is the right behavior for regulated data but surprises admins who “deleted” a team and find its SharePoint content still discoverable. See Microsoft Purview Records Management: Retention Labels, Auto-Apply, Disposition Review, and Event-Based Holds for how retention interacts with the group lifecycle.
Sensitivity labels vs classic group classification
Before container sensitivity labels existed, Microsoft 365 Groups had classic classification — a flat list of free-text labels (Low, Medium, High Business Impact) set via the same Group.Unified directory setting (ClassificationList). It still works, but it is a label without teeth: it tags the group with a string and nothing enforces anything. Container sensitivity labels supersede it by binding the label to actual enforcement (privacy, guests, devices, sharing). The two should not coexist in steady state.
| Dimension | Classic classification | Container sensitivity label |
|---|---|---|
| Configured in | Group.Unified ClassificationList |
Microsoft Purview |
| Enforces privacy | No (string only) | Yes (can force Private) |
| Controls guest access | No | Yes (block/allow) |
| Controls unmanaged devices | No | Yes (via Conditional Access) |
| Controls external sharing | No | Yes (site sharing scope) |
| Encrypts files | No | Yes (item scope of same label) |
| Visible in Teams/SharePoint UI | Yes (as text) | Yes (as label, enforced) |
| License | Entra ID P1 | Purview Information Protection |
| Recommended today | No — migrate off | Yes |
Do not run both. If you previously set
ClassificationList, plan a migration: map each classic class to a container label, backfill, then clear the classification list so users see one taxonomy that actually enforces. Two parallel labeling schemes confuse users and split your reporting.
Architecture at a glance
Picture the whole governance control plane as a set of lenses focused on a single object at the center — the Microsoft 365 Group. Everything radiates from that object because every Team, mailbox, SharePoint site, Planner plan, and guest membership is a property of, or a workload connected to, that one group. There is no separate “Teams object” to govern; there is the group, and Teams is one face of it.
Trace a team’s life left to right through the control plane. At birth, two Entra ID directory settings intercept creation: the creation restriction (Group.Unified → EnableGroupCreation = false + an allowed security group) decides whether this user may create at all, and the naming policy (PrefixSuffixNamingRequirement + CustomBlockedWordsList) stamps the name and alias and rejects blocked words. If a label policy makes labeling mandatory, the user must also choose a container sensitivity label at this moment — and that single choice cascades into the connected SharePoint site as privacy (public/private), guest posture (allowed/blocked), unmanaged-device access (full / web-only / blocked, enforced through Conditional Access), and external sharing scope (Disabled … ExternalUserAndGuestSharing). One object, four enforced behaviors, set at birth from one label.
Through the team’s life, two more lenses operate continuously. The expiration policy (a lifetime in days on the group’s expirationDateTime) watches for activity: active teams auto-renew invisibly, dormant ones email their owners to renew, and the unrenewed are soft-deleted with a 30-day recovery window — which is why the policy depends on human owners and excludes dynamic groups. In parallel, guest governance stacks three controls on the same group: the invitation boundary (external collaboration / cross-tenant access), the posture boundary (Conditional Access requiring MFA for All guest and external users), and the lifecycle boundary (a recurring access review where owners re-attest each guest and inaction auto-revokes).
Finally, a drift-and-audit layer reads the object’s state — owner count, assignedLabels, last-activity from usage reports, guest membership — and feeds remediation: the ownerless-group policy nominates new owners, the label backfill closes classification gaps, and dormant teams are routed to archive (read-only, intact), soft-delete (recoverable), or hard-delete (permanent). The convergence point of the entire design is the same in every path: the control you want lives on the Microsoft 365 Group, not on “Teams.” Localize a governance need to a property of that object and you immediately know which directory setting, which label, or which policy configures it.
Real-world scenario
Nordhaven Manufacturing runs a 40,000-seat Microsoft 365 tenant: roughly 11,000 Microsoft 365 Groups after four years of open self-service Teams, heavy external collaboration with a supplier network across 60+ partner domains, and a regulated-data footprint (product designs, contracts, some PII) under ISO 27001 and customer-mandated controls. The collaboration ops team is six people; the identity team is four. An external audit flagged three findings: unclassified data in externally-shared teams, guests with multi-year standing access, and “no demonstrable group lifecycle.” Leadership gave them one quarter to remediate.
Under pressure, they made the classic mistake: they treated the findings as three independent fixes and rolled them all out the same week. They flipped expiration to ManagedGroupTypes = "All" with a 180-day lifetime tenant-wide, published a mandatory Confidential-Internal container label, and turned on the creation gate — all at once, with minimal communication.
Six months later, the consequences arrived in a single night. About 600 teams expired and soft-deleted simultaneously — including a cluster of plant-floor and supplier-coordination teams that had real, current SharePoint activity. Activity-based auto-renewal should have saved them, but it never fired: those teams had been provisioned by a SCIM connector into dynamic Microsoft 365 Groups, and dynamic groups are excluded from the renewal engine. Worse, their membership was rule-driven with no human owner, so no renewal email went anywhere. No owner, no dynamic-group renewal, no prompt — just deletion. The plant floor lost access to current work instructions on a Monday morning; the help desk took 300 tickets before 10am.
The breakthrough was recognizing this as one object’s lifecycle behaving exactly as designed against a membership model it doesn’t support. The fix had two parts. That night: recover inside the 30-day window with Graph rather than the UI (which has no bulk restore path) — Get-MgDirectoryDeletedItemAsGroup filtered to the GRP_Plant_* naming pattern, piped to Restore-MgDirectoryDeletedItem. All 600 came back in twenty minutes. The following week: stop trusting expiration to police dynamic groups. They moved every dynamic and SCIM-fed team out of the lifecycle scope (ManagedGroupTypes = "Selected", excluding those IDs) and governed those groups’ lifecycle through access reviews and the ownerless-group policy instead, while keeping expiration for the assigned-membership, owner-backed teams where it actually works.
The remediation then proceeded in the right order: creation gate first (with a ServiceNow request catalog so plant managers got teams in hours), then naming, then container labels with a backfill-plus-guest-cleanup, then expiration scoped only to owner-backed assigned groups, then quarterly guest access reviews with auto-apply and default Deny. The first guest review removed 1,400 stale external members — supplier contractors from finished projects. The audit findings closed. The durable lesson, written on the team’s wall: “Expiration is an owner-driven control. It only works where human owners and assigned membership exist. Audit membershipRule and owner count before widening scope — never after the first deletion wave.”
The incident as a timeline, because the order is the lesson:
| Time | Event | Action taken | Effect | What it should have been |
|---|---|---|---|---|
| Week 0 | Audit findings | Roll out all three controls at once, tenant-wide | Looks done | Pilot each on a scoped group first |
| Month 6, 02:00 | 600 teams soft-delete overnight | (automatic expiration) | Plant floor loses access | Scope expiration to owner-backed assigned groups only |
| Month 6, 08:00 | 300 help-desk tickets | Diagnose: dynamic groups, no owners, no renewal | Root cause found | Audit membershipRule + owners before All |
| Month 6, 08:20 | Recover | Get-MgDirectoryDeletedItemAsGroup → Restore-MgDirectoryDeletedItem |
All restored in 20 min | (correct emergency move) |
| Month 6, +1 week | Re-scope | ManagedGroupTypes=Selected, exclude dynamic/SCIM IDs |
Expiration safe | The actual fix |
| Month 6, +2 weeks | Sequence properly | Creation gate → naming → labels → expiration → guest reviews | Findings closing | The right rollout order |
| Month 7 | First guest review | Auto-apply, default Deny | 1,400 stale guests removed | The lifecycle control doing its job |
Advantages and disadvantages
Governing the Microsoft 365 Group as the single object both enables this whole control plane and creates the failure modes you must respect:
| Advantages (why governing the group works) | Disadvantages / risks (why it bites) |
|---|---|
| One object governs all workloads — naming/expiration/labels/creation apply to Teams, SharePoint, Outlook, Planner at once | The same coupling means a misconfigured control (e.g. expiration on dynamic groups) has wide blast radius |
| Container labels enforce privacy/guest/device/sharing from a single user choice at creation | Label changes propagate asynchronously and never retroactively evict existing guests/links |
| Expiration auto-renews active teams — only genuinely dormant ones need human attention | Expiration is owner-driven and excludes dynamic groups — silent deletion where owners/assigned membership are missing |
| Access reviews make inaction revoke access — guests are re-attested, not accumulated | Without defaultDecision=Deny+auto-apply, a review removes no one — a false sense of control |
| Naming/creation restriction govern every creation surface with one directory setting | Global Admins are exempt from naming/creation — admin testing produces false confidence |
| Native, built-in tooling (no third-party product) — Entra, Purview, Graph | Spread across four admin surfaces and two license tiers; requires cross-team coordination |
| Soft-delete + 30-day recovery + archive give graceful, reversible retirement | Retention/legal hold override deletion — “deleted” data can persist, surprising admins |
The model is right for any organization that adopted Teams (i.e. all of them) and needs collaboration to stay safe and legible at scale — it is the only approach that scales by policy rather than manual cleanup. It bites hardest where membership is dynamic/SCIM-fed (expiration breaks), where external collaboration is heavy (guest sprawl dominates and labels must be tight), and where teams roll out all controls at once without piloting — every disadvantage above is manageable, but only if you know it exists, which is the entire point of sequencing the rollout.
Hands-on lab
Stand up the core governance controls on a pilot scope, verify each as a non-admin would experience it, and tear down. Run in Microsoft Graph PowerShell + Purview PowerShell. This uses a Selected scope and a pilot security group throughout — nothing tenant-wide — so it is safe to run in a test/dev tenant.
Step 1 — Connect and create a pilot security group.
Connect-MgGraph -Scopes "Directory.ReadWrite.All","Group.ReadWrite.All","AccessReview.ReadWrite.All"
# A security group to scope creation rights AND a separate one to scope expiration
$creators = New-MgGroup -DisplayName "Team-Creators" -MailEnabled:$false `
-SecurityEnabled:$true -MailNickname "team-creators"
Expected: a group object with an Id. Note it.
Step 2 — Instantiate Group.Unified and apply a naming policy.
$template = Get-MgBetaDirectorySettingTemplate | Where-Object DisplayName -eq "Group.Unified"
$setting = Get-MgBetaDirectorySetting | Where-Object TemplateId -eq $template.Id
if (-not $setting) {
$values = $template.Values | ForEach-Object { @{ Name=$_.Name; Value=$_.DefaultValue } }
$setting = New-MgBetaDirectorySetting -TemplateId $template.Id -Values $values
}
$body = $setting.Values
($body | Where-Object Name -eq "PrefixSuffixNamingRequirement").Value = "GRP_[Department]_[GroupName]"
($body | Where-Object Name -eq "CustomBlockedWordsList").Value = "Payroll,CEO,Board"
Update-MgBetaDirectorySetting -DirectorySettingId $setting.Id -Values $body
Expected: no error. The setting now carries your naming template.
Step 3 — Restrict creation to the pilot group.
$body = (Get-MgBetaDirectorySetting | Where-Object TemplateId -eq $template.Id).Values
($body | Where-Object Name -eq "EnableGroupCreation").Value = "false"
($body | Where-Object Name -eq "GroupCreationAllowedGroupId").Value = $creators.Id
Update-MgBetaDirectorySetting -DirectorySettingId $setting.Id -Values $body
Expected: creation is now gated to Team-Creators members.
Step 4 — Configure an expiration policy scoped to Selected.
$existing = Get-MgGroupLifecyclePolicy
if (-not $existing) {
New-MgGroupLifecyclePolicy -GroupLifetimeInDays 180 -ManagedGroupTypes "Selected" `
-AlternateNotificationEmails "groups-governance@contoso.com"
} else {
Update-MgGroupLifecyclePolicy -GroupLifecyclePolicyId $existing.Id `
-GroupLifetimeInDays 180 -ManagedGroupTypes "Selected" `
-AlternateNotificationEmails "groups-governance@contoso.com"
}
Expected: a lifecycle policy with GroupLifetimeInDays = 180, ManagedGroupTypes = Selected.
Step 5 — Author and publish a container sensitivity label (Purview).
Connect-IPPSSession -UserPrincipalName admin@contoso.com
Execute-AzureAdLabelSync
New-Label -Name "Pilot-Confidential" -DisplayName "Pilot - Confidential" `
-Tooltip "Private, no guests, internal sharing" -ContentType "Site, UnifiedGroup"
Set-Label -Identity "Pilot-Confidential" -SiteAndGroupProtectionEnabled $true `
-SiteExternalSharingControlType "Disabled" `
-AdvancedSettings @{ BlockGuestUserAccessOnGroupCreation="true" }
New-LabelPolicy -Name "Pilot-Label-Policy" -Labels "Pilot-Confidential" -ExchangeLocation "All"
Expected: the label exists with ContentType including UnifiedGroup, and a policy publishes it.
Step 6 — Create a quarterly guest access review scoped to Unified groups.
$params = @{
displayName = "Pilot guest review"
scope = @{ "@odata.type"="#microsoft.graph.accessReviewQueryScope"
query="/groups?`$filter=groupTypes/any(c:c eq 'Unified')"; queryType="MicrosoftGraph" }
reviewers = @(@{ query="./owners"; queryType="MicrosoftGraph" })
settings = @{
recurrence = @{ pattern=@{ type="absoluteMonthly"; interval=3 }
range=@{ type="noEnd"; startDate="2026-06-01" } }
defaultDecision="Deny"; defaultDecisionEnabled=$true
autoApplyDecisionsEnabled=$true; instanceDurationInDays=14
}
}
New-MgIdentityGovernanceAccessReviewDefinition -BodyParameter $params
Expected: a review definition returns with a Status of NotStarted/InProgress.
Validation checklist. Each step maps to a control you can prove:
| Step | What you configured | How to verify (as the right principal) |
|---|---|---|
| 2 | Naming policy | As a non-admin in Team-Creators, create “test” → expect GRP_<dept>_test; try a name with “Payroll” → expect rejection |
| 3 | Creation restriction | Sign in as a user not in Team-Creators → “Create team” is blocked; a member can still create |
| 4 | Expiration | Add a pilot group to the policy, then Get-MgGroup -GroupId <id> -Property expirationDateTime is populated |
| 5 | Container label | Create a team → the label picker appears; pick the label → assignedLabels set; try to add a guest → blocked |
| 6 | Access review | Get-MgIdentityGovernanceAccessReviewDefinition shows it active, reviewers = owners |
Verify naming as a non-admin (the critical test):
# Run AS A STANDARD USER, not Global Admin (admins are exempt)
New-MgGroup -DisplayName "test" -GroupTypes "Unified" -MailEnabled:$true `
-MailNickname "test123" -SecurityEnabled:$false
# Expect the created group's displayName to be GRP_<your-dept>_test
Teardown.
# Re-open creation, clear naming, scope expiration to None, remove pilot artifacts
$body = (Get-MgBetaDirectorySetting | Where-Object TemplateId -eq $template.Id).Values
($body | Where-Object Name -eq "EnableGroupCreation").Value = "true"
($body | Where-Object Name -eq "PrefixSuffixNamingRequirement").Value = ""
($body | Where-Object Name -eq "CustomBlockedWordsList").Value = ""
Update-MgBetaDirectorySetting -DirectorySettingId $setting.Id -Values $body
Update-MgGroupLifecyclePolicy -GroupLifecyclePolicyId (Get-MgGroupLifecyclePolicy).Id -ManagedGroupTypes "None"
Remove-MgGroup -GroupId $creators.Id
Remove-LabelPolicy -Identity "Pilot-Label-Policy" -Confirm:$false
Remove-Label -Identity "Pilot-Confidential" -Confirm:$false
Cost note. Everything here is configuration on licenses you already pay for (Entra ID P1/P2, Purview) — there is no per-resource compute charge. The only “cost” is the license floor, which the lab assumes you have in a test tenant.
Common mistakes & troubleshooting
The recurring failures, as a scannable table you keep open during the rollout, then expanded for the ones that bite hardest.
| # | Symptom | Root cause | Confirm (exact cmd / portal path) | Fix |
|---|---|---|---|---|
| 1 | Every new group has the same name; creation fails on the second | [GroupName] token omitted from naming template |
Get-MgBetaDirectorySetting → inspect PrefixSuffixNamingRequirement |
Add [GroupName] exactly once |
| 2 | Naming policy “isn’t working” when admin tests it | Global Admin is exempt from naming/creation | Test as a non-admin user | Validate with a standard account, always |
| 3 | 600 teams expired overnight despite activity | Dynamic groups excluded from renewal; no owners | Check membershipRule populated + Get-MgGroupOwner count |
Scope expiration to assigned, owner-backed groups; govern dynamic via reviews |
| 4 | Sensitivity labels don’t appear on teams/sites | Container labeling not enabled at tenant | Get-SPOTenant → EnableAIPIntegration; was Execute-AzureAdLabelSync run? |
Set-SPOTenant -EnableAIPIntegration $true; Execute-AzureAdLabelSync |
| 5 | Label applied but guests still in the team | Label changes don’t retroactively evict | Compare assignedLabels vs Get-MgGroupMember guests |
Run a one-time guest cleanup / access review |
| 6 | Access review runs but removes no one | defaultDecision not Deny or auto-apply off |
Get-MgIdentityGovernanceAccessReviewDefinition → settings |
Set defaultDecision=Deny + autoApplyDecisionsEnabled=$true |
| 7 | Owners never see renewal emails | Group is ownerless (or notifications to wrong address) | Get-MgGroupOwner; check AlternateNotificationEmails |
Enable ownerless-group policy; set alternate emails |
| 8 | Creation restricted but users still make “sites” | Communication SharePoint sites aren’t group-backed | SharePoint admin → site creation settings | Govern SharePoint site creation separately |
| 9 | Users bypass the creation gate via personal accounts | “No” with no request path → shadow IT | Audit for external/personal collaboration | Pair restriction with a request workflow |
| 10 | Blocked word blocks legitimate names | Substring match (e.g. “HR” blocks “THREAD”) | Inspect CustomBlockedWordsList |
Choose words deliberately; test edge cases |
| 11 | Two labeling schemes confuse users | Classic ClassificationList + container labels both set |
Get-MgBetaDirectorySetting → ClassificationList |
Migrate to labels; clear classification list |
| 12 | “Deleted” team’s data still discoverable | Retention/legal hold overrides deletion | Purview → retention policies / eDiscovery holds | Expected — release hold if truly removing |
| 13 | Guest CA policy “requires compliant device” never works | Can’t manage guests’ devices | CA policy targeting guests with device-compliance grant | Require MFA + session controls; use label web-only control |
| 14 | Expiration set but expirationDateTime null on groups |
Group not in Selected scope (or None) |
Get-MgGroup -Property expirationDateTime |
Add group to lifecycle policy scope |
The expanded reasoning for the worst offenders:
1. Every new group collapses to the same name. Root cause: the [GroupName] token is missing from PrefixSuffixNamingRequirement, so the template has no slot for user input — every group is named the static prefix and the second creation fails on a duplicate alias. Confirm: read the setting value. Fix: ensure [GroupName] appears exactly once.
3. Mass overnight expiration despite real activity. Root cause: the teams are dynamic Microsoft 365 Groups (membership rule-driven), which are excluded from activity-based renewal, and being rule-driven they often have no human owner to receive a renewal prompt — so they expire silently even with current SharePoint activity. Confirm: membershipRule is populated and Get-MgGroupOwner returns zero. Fix: move dynamic/SCIM groups out of ManagedGroupTypes and govern their lifecycle through access reviews and the ownerless-group policy; keep expiration for assigned, owner-backed groups.
4. Labels invisible on teams. Root cause: container labeling is off at the tenant — labels exist in Purview but were never synced into Entra (Execute-AzureAdLabelSync) and/or SharePoint integration is disabled (EnableAIPIntegration). Confirm: Get-SPOTenant shows EnableAIPIntegration false. Fix: run the sync and enable the integration; allow propagation time.
6. Reviews that remove nobody. Root cause: the review’s defaultDecision is None/Approve or autoApplyDecisionsEnabled is false, so when reviewers don’t respond, nothing happens — the review is theater. Confirm: inspect the definition settings. Fix: defaultDecision = Deny and autoApplyDecisionsEnabled = $true together, with a fallback reviewer so one unresponsive owner doesn’t strand the campaign.
9. Users routing around the creation gate. Root cause: governance that only blocks, with no fast path to a legitimate team, pushes people to personal OneDrive, consumer chat, or email — strictly worse than a governed team. Confirm: rising external/personal-account collaboration in audit logs. Fix: pair every restriction with a self-service request workflow that delivers a correctly-labeled, owner-assigned team in hours.
Best practices
- Sequence the rollout: creation gate → naming → labels → expiration → guest reviews. Pilot each on a scoped security group before tenant-wide. They are one system; rolling them out together and untested is how 600 teams disappear overnight.
- Always validate naming and creation as a non-admin. Global Administrators are exempt; admin testing produces false confidence. A standard test account is the only honest verification.
- Include
[GroupName]exactly once in the naming template, and prefer a stable searchable prefix (GRP_) over a suffix for sort/search. - Keep the label menu to three or four opinionated labels covering the privacy/guest/device/sharing matrix. Long taxonomies cause mislabeling and reduce classification accuracy.
- Scope expiration to assigned, owner-backed groups only. Audit
membershipRuleand owner count before wideningManagedGroupTypes. Dynamic/SCIM groups need lifecycle governance from reviews, not expiration. - Enable the ownerless-group policy and enforce a two-owner minimum. Ownerless groups break renewal, accountability, and guest approval. This is a precondition for trusting expiration.
- Set
defaultDecision = Denyand auto-apply together on every access review. Inaction must revoke access, or the review is a quarterly box-ticking exercise. Add a fallback reviewer and a 14-day window. - Pair every creation/sharing restriction with a fast request path. Governance that only says “no” gets routed around with shadow IT — the worst outcome.
- Backfill labels as “the floor going forward,” then run a one-time guest/link cleanup. Label changes propagate asynchronously and never retroactively evict existing guests or links.
- Use container labels, not classic classification. Migrate any
ClassificationListto labels and clear it — one taxonomy that actually enforces. - Communicate the renewal mechanic loudly before the first expiration wave. A 30-day soft-delete is recoverable, but uninformed owners flood the help desk with “deleted team” panic.
- Codify directory settings, lifecycle, and label policies as infrastructure-as-code (Microsoft365DSC handles all of these resource types declaratively) and wire drift reports + access-review outcomes into your SIEM, so policy drift becomes an alert rather than a quarterly surprise.
Security notes
- Least-privilege admin roles. Naming/creation live in directory settings — manage them with Groups Administrator or a custom role, not blanket Global Admin. Access reviews need identity-governance roles; container labels need compliance roles. Separate these duties.
- Container labels are a primary data-loss control. A “Highly Confidential” label that forces Private, blocks guests, blocks unmanaged devices, and disables external sharing is how you keep crown-jewel data inside the boundary — treat label configuration with the same rigor as a firewall rule.
- Guests authenticate in their home tenant — you cannot manage their device. Require MFA via Conditional Access for
All guest and external users, use cross-tenant access to trust partner MFA, and rely on the container-label web-only control for unmanaged-device posture rather than device-compliance grants that don’t apply to guests. - Enforce the guest invitation boundary. Restrict who can invite (members/admins, not “anyone”), allow-list partner domains, and set guest access to limited so guests can’t enumerate your directory.
- Access reviews are a compliance control, not a convenience. Auto-apply + default Deny produces an auditable trail that inaction revoked access — exactly what an auditor wants to see. Wire outcomes to your SIEM.
- Retention/legal hold overrides deletion — by design. Regulated teams under hold preserve content even when “deleted.” Know which teams are held before you promise a hard-delete, and release holds only through the compliance process.
- Protect the request workflow’s privileged identity. A provisioning flow that creates teams runs as a privileged account that bypasses the creation restriction — secure it (managed identity, least scope, monitoring) as you would any privileged automation.
The security controls and what each prevents:
| Control | Mechanism | Prevents | Also enables |
|---|---|---|---|
| Container label (force private, block guests) | Purview label on group | Sensitive data going public / to guests | Consistent classification |
| Container label (web-only unmanaged) | Label → Conditional Access session | Download/exfil from unmanaged devices | BYOD-safe access |
External sharing scope Disabled |
Site sharing control on label | External oversharing of confidential sites | Internal-only collaboration |
| Guest invitation restriction | External collaboration settings | Uncontrolled guest sprawl | Allow-listed partner collaboration |
| Conditional Access for guests | CA All guest/external + MFA |
Unauthenticated/weak guest access | Trusted-tenant MFA pass-through |
| Access review (Deny + auto-apply) | Entra ID Governance | Standing stale guest access | Auditable re-attestation |
| Least-privilege admin roles | Groups Admin / custom roles | Over-broad governance admin rights | Separation of duties |
Cost & sizing
Governance here is licensing, not compute — there is no per-team resource bill. What drives cost is the license floor and the operational effort.
- Entra ID P1 (per governed member) is the floor for naming, expiration, and creation restriction. Entra ID P2 (or the standalone Microsoft Entra ID Governance SKU) is required for access reviews and lifecycle workflows. Microsoft Purview Information Protection (commonly in E3/E5) covers container labels. Most enterprises already hold these in an E3/E5 + Entra Suite stack; the real “cost” is confirming every governed member is licensed (frontline-worker SKUs may lack P1/P2).
- Operational effort is the dominant ongoing cost: the request-workflow build (Power Automate/ServiceNow), the quarterly review cycle, and drift-report automation. Budget engineering time, not cloud spend.
- Sizing the policy, not the infrastructure: there is no instance count to scale — these policies apply tenant-wide once enabled. “Sizing” means scoping (pilot → tenant-wide) and choosing the right lifetime (180 days is the common default; shorter for high-churn collaboration, longer for stable teams).
- Storage as an indirect cost: sprawl inflates SharePoint storage and backup footprint. Effective expiration and archival reduce storage cost — a real, if indirect, saving in large tenants.
The license/effort drivers:
| Driver | What it covers | Cost basis | Watch-out |
|---|---|---|---|
| Entra ID P1 | Naming, expiration, creation restriction | Per member (governed) | Frontline SKUs may lack it |
| Entra ID P2 / Governance | Access reviews, lifecycle workflows | Per member (reviewed) | Required for the guest lifecycle control |
| Purview Information Protection | Container sensitivity labels | Per E3/E5 entitlement | Confirm it’s in your SKU |
| Request workflow | Power Automate / ServiceNow build | Engineering time + connector licensing | Ongoing maintenance |
| Drift automation | Scheduled Graph runbooks + SIEM | Engineering time | Keep credentials least-privilege |
| SharePoint storage (indirect) | Sprawl footprint | Per-GB above quota | Expiration/archival reduces it |
Interview & exam questions
1. Why is “governing Teams” really “governing Microsoft 365 Groups”? Every Team is layered on a Microsoft 365 Group that owns the membership, mailbox, SharePoint site, and lifecycle properties. Naming, expiration, creation restriction, and labels all live on the group, so they govern Teams and every other connected workload (SharePoint, Outlook, Planner) simultaneously — there is deliberately no Teams-specific toggle for any of them.
2. Where does a group naming policy live and what are its two functions? In the Group.Unified directory setting template (no first-class cmdlet — you patch the template’s PrefixSuffixNamingRequirement and CustomBlockedWordsList). It stamps a deterministic prefix/suffix (fixed text + attribute tokens like [Department], plus the literal [GroupName] for user input) onto the display name and alias, and rejects names whose user-supplied portion contains a blocked word.
3. Why might a naming policy appear not to work when an admin tests it? Global Administrators (and a few other high-privilege roles) are exempt from naming and creation enforcement. Admin-account testing bypasses the very rules being verified, producing false confidence — always validate as a standard, non-admin user.
4. Explain the Microsoft 365 Groups expiration renewal mechanics and their two hard dependencies. A lifetime (days) is set; active groups auto-renew on qualifying activity (Teams/SharePoint/Outlook/Planner), dormant ones email owners to renew, and the unrenewed are soft-deleted (recoverable 30 days). The two dependencies: it needs human owners (ownerless groups get no prompt and silently expire) and it excludes dynamic groups from the renewal engine (a dynamic group expires even with activity).
5. What does a container sensitivity label control, and what does it not control? It controls container behavior: privacy (public/private), guest membership (allow/block), unmanaged-device access (full/web-only/blocked via Conditional Access), and the connected SharePoint site’s external-sharing scope and default link. It does not by itself encrypt the files inside the team — that’s the item scope of a label, applied to documents.
6. A user reports labels don’t appear when creating a team. What’s the most likely cause? Container labeling isn’t enabled at the tenant — the labels were never synced into Entra (Execute-AzureAdLabelSync) and/or SharePoint label integration is off (Set-SPOTenant -EnableAIPIntegration $true). Until both are on, labels don’t surface on groups/sites regardless of how many exist in Purview.
7. You applied a “no guests” label to an existing team but the guests are still there. Why? Label changes are not retroactive — applying or changing a container label blocks future guest additions but does not evict guests already present, and changes propagate to the SharePoint site asynchronously. Backfill sets the floor going forward; remove existing guests with a one-time cleanup or an access review.
8. How do you make an access review actually remove stale guests instead of being theater? Set defaultDecision = "Deny" and autoApplyDecisionsEnabled = $true together, so that inaction by reviewers auto-revokes access and the decision is enforced automatically. Add a fallback reviewer and a bounded duration (e.g. 14 days) so one unresponsive owner doesn’t strand the campaign.
9. Why can’t you require a compliant device for guests in Conditional Access, and what do you do instead? Guests authenticate in their home tenant, so you cannot enroll or manage their device — device-compliance grants don’t apply. Require MFA and use session controls (sign-in frequency, no persistent browser), and enforce unmanaged-device posture through the container label’s web-only control rather than a device-compliance grant.
10. Compare container sensitivity labels with classic group classification. Classic classification (ClassificationList in Group.Unified) is a free-text string that enforces nothing. Container sensitivity labels bind the label to real enforcement — privacy, guest, device, and sharing controls. Labels supersede classification; don’t run both (it splits the taxonomy and confuses users) — migrate to labels and clear the classification list.
11. What’s the difference between archiving, soft-deleting, and hard-deleting a team? Archive makes the team read-only with all data intact and instantly reversible (for finished-but-referenced work). Soft-delete moves it to the deleted-items container, recoverable for 30 days (a safety window; expiration produces these automatically). Hard-delete is permanent (after 30 days or explicit purge). Retention/legal hold overrides deletion — held content persists regardless.
12. In what order should you roll out the five controls, and why? Creation gate → naming → container labels → expiration → guest reviews, piloting each on a scoped group first. They are one system that interacts: expiration without owners orphans data; labels without a creation gate get bypassed by self-service; guest reviews without auto-apply remove no one. Rolling them out simultaneously and untested is how mass deletions and audit failures happen.
These map to MS-102 (Microsoft 365 Administrator) — manage Microsoft 365 Groups, governance, and information protection — and to identity-governance objectives in SC-300 (Identity and Access Administrator) — access reviews, entitlement management, external identities. Container labels and DLP touch SC-400 (Information Protection Administrator). A compact mapping:
| Question theme | Primary cert | Objective area |
|---|---|---|
| Groups lifecycle, naming, expiration | MS-102 | Manage M365 Groups & governance |
| Container sensitivity labels | SC-400 / MS-102 | Implement information protection |
| Access reviews, guest lifecycle | SC-300 | Plan & implement identity governance |
| External collaboration, B2B | SC-300 | Manage external identities |
| Conditional Access for guests | SC-300 | Implement Conditional Access |
| Archival, retention interplay | MS-102 / SC-400 | Records management & retention |
Quick check
- A team holding M&A documents was made public by an unaware user. Which single control would have forced it private at creation, and where is it configured?
- 600 dynamic, SCIM-fed teams with current SharePoint activity expired and soft-deleted overnight despite an expiration policy. Name the two reasons activity-based renewal didn’t save them.
- You published three sensitivity labels but none appear when users create teams. What two tenant-level actions did you most likely skip?
- A quarterly guest access review has run twice and removed zero guests. What two settings make a review actually revoke access?
- True or false: changing a container label to “block guests” immediately removes the guests already in the team.
Answers
- A container sensitivity label that forces Private privacy — configured in Microsoft Purview (Information Protection) and published via a label policy that makes labeling mandatory at creation. A label can force privacy so a regulated team cannot be made public by an unaware user.
- (a) Dynamic groups are excluded from the activity-based renewal engine — activity doesn’t auto-renew them. (b) Being rule-driven/SCIM-fed, they typically have no human owner, so no renewal email is sent to anyone. No renewal + no owner = silent expiration. Fix by scoping expiration to assigned, owner-backed groups and governing dynamic groups via access reviews.
- You skipped enabling container labeling at the tenant: syncing labels into Entra (
Execute-AzureAdLabelSync) and enabling SharePoint label integration (Set-SPOTenant -EnableAIPIntegration $true). Until both are on, labels don’t surface on groups/sites. defaultDecision = "Deny"(so inaction revokes) andautoApplyDecisionsEnabled = $true(so decisions are enforced automatically). Without both, the review removes no one.- False. Label changes are not retroactive — they block future guest additions but leave existing guests in place. Remove them with a one-time guest cleanup or an access review.
Glossary
- Microsoft 365 Group — the directory object (
groupTypescontainsUnified) that provisions and owns the connected workloads (Teams, Exchange mailbox, SharePoint site, Planner); the single object all governance controls act on. - Team — the Teams collaboration workload layered on a Microsoft 365 Group; not itself the governance object.
Group.Unifieddirectory setting — the Entra ID directory-setting template holding the naming policy, creation restriction, guest-owner rules, and usage-guidelines URLs.- Naming policy — prefix/suffix (fixed text + attribute tokens + the literal
[GroupName]) plus a blocked-words list, applied to a group’s display name and alias at creation/rename. - Blocked words list — a case-insensitive, comma-separated list (≤5,000 entries) matched against the user-supplied portion of a group name (substring match).
- Expiration policy — the Microsoft 365 Groups lifecycle policy assigning a lifetime in days; active groups auto-renew, dormant ones prompt owners, unrenewed ones soft-delete (30-day recovery).
ManagedGroupTypes— the expiration policy’s scope:None,Selected(explicit groups), orAll(every Unified group).- Activity-based renewal — automatic extension of a group’s expiration when it has qualifying activity (Teams/SharePoint/Outlook/Planner); excludes dynamic groups.
- Creation restriction —
EnableGroupCreation = false+GroupCreationAllowedGroupId(a security group), gating group/Team creation across all surfaces. - Container sensitivity label — a Purview sensitivity label with the group/site scope (
ContentTypeincludesUnifiedGroup/Site) that enforces privacy, guest access, unmanaged-device posture, and external sharing on the container. - Label policy — publishes labels to users and can set labeling mandatory at creation (
MandatoryLabelForGroup) and a default container label. assignedLabels— the group property holding the applied container label’s GUID; patched via Graph to backfill existing teams.SiteExternalSharingControlType— the label’s SharePoint external-sharing scope:ExternalUserAndGuestSharing,ExternalUserSharingOnly,ExistingExternalUserSharingOnly, orDisabled.- Access review — a recurring Entra ID Governance campaign re-attesting members/guests; with
defaultDecision = Deny+ auto-apply, inaction revokes access. - External collaboration settings — Entra controls for who may invite guests, allowed/blocked domains, and guest access level; the invitation boundary.
- Ownerless groups policy — a Microsoft 365 admin-center policy that emails active members of an ownerless group to nominate themselves as owners.
- Archive (a team) — making a team read-only with all data intact and instantly reversible; distinct from soft/hard delete.
- Soft-delete / hard-delete — soft-delete moves a group to the deleted-items container (recoverable 30 days); hard-delete is permanent.
- Classic classification — the legacy free-text
ClassificationListlabel on groups that enforces nothing; superseded by container sensitivity labels. - Microsoft365DSC — a PowerShell DSC project that manages these directory settings, lifecycle, and label policies declaratively as infrastructure-as-code.
Next steps
You can now govern the Microsoft 365 Group as the single object beneath every Team — naming, expiration, creation, labels, and guest lifecycle. Build outward:
- Next: Governing SharePoint and OneDrive External Sharing: Tenant vs Site Controls, Sensitivity Labels, and Access Reviews — the SharePoint side of every team’s site, where the container label and sharing controls overlap directly.
- Related: Sensitivity Labels in Microsoft Purview: Auto-Labeling, Encryption, Co-Authoring, and Container Inheritance — go deep on the labels themselves, including the item scope that encrypts the files inside a labeled team.
- Related: Building an Access Reviews Program in Entra ID: Recertifying Privileged Roles, Groups, and Guest Access at Scale — the full lifecycle program behind the guest review used here.
- Related: Securing B2B Collaboration with Entra External ID: Cross-Tenant Access Settings and Custom Onboarding — the invitation and cross-tenant trust boundary for the guests your teams collaborate with.
- Related: Designing Conditional Access at Scale: A Persona-Based Policy Framework with Authentication Context and Filters — the Conditional Access machinery that enforces the unmanaged-device control on your container labels.
- Related: Microsoft Purview Records Management: Retention Labels, Auto-Apply, Disposition Review, and Event-Based Holds — how retention and legal hold interact with (and override) the group lifecycle and deletion.