Kali Linux

How to Enumerate Microsoft 365 Groups Using PowerShell and Python

Microsoft 365 Groups (also known as M365 Groups or Unified Groups) are at the heart of collaboration in Microsoft 365. They power Teams, Outlook Groups, SharePoint sites, Planner, and Yammer.

For IT admins and security researchers, it’s critical to be able to enumerate groups, review their metadata, and audit access. In this updated 2025 guide, we’ll show you how to:

  • List all Microsoft 365 Groups in your tenant
  • Retrieve key metadata (owners, members, visibility, mail, SharePoint URL, etc.)
  • Detect risks (ownerless groups, guest users, hidden memberships)
  • Export reports for compliance and governance

We’ll cover two modern approaches:

  • PowerShell with Microsoft Graph SDK → best for admins
  • Python with Microsoft Graph API → best for researchers & automation

Why Group Enumeration Matters in 2025

  • Security & Compliance → Spot ownerless or guest-heavy groups before they become a risk.
  • Governance → Identify inactive or duplicate groups for cleanup.
  • Visibility → Audit group lifecycles, ownership, and access patterns.
  • Modernization → Legacy APIs are deprecated; Graph API is now the standard.

1. Prerequisites

PowerShell (for Admins)

Install the Graph PowerShell SDK:

Install-Module Microsoft.Graph -Scope CurrentUser

Authenticate with MFA support:

Connect-MgGraph -Scopes "Group.Read.All","GroupMember.Read.All"

Python (for Researchers)

Install required packages:

pip install msgraph-core azure-identity

Register an Azure AD app with Group.Read.All and GroupMember.Read.All delegated permissions.

2. Enumerate Microsoft 365 Groups

PowerShell Example

Get-MgGroup -All |
Select-Object Id, DisplayName, Description, Visibility, Mail, CreatedDateTime

Python Example

from msgraph.core import GraphClient
from azure.identity import DeviceCodeCredential

# Authenticate (supports MFA)
credential = DeviceCodeCredential(client_id="YOUR-APP-ID")
client = GraphClient(credential=credential)

# Fetch groups with metadata
groups = client.get("/groups?$select=id,displayName,description,visibility,mail,createdDateTime")

for g in groups.json().get('value', []):
    print(f"{g['displayName']} ({g['visibility']}) - {g.get('mail')}")

3. Drill Down into Group Details

Owners & Members (PowerShell)

Get-MgGroupOwner -GroupId <GroupId>
Get-MgGroupMember -GroupId <GroupId>

Owners & Members (Python)

group_id = "<GROUP-ID>"
owners = client.get(f"/groups/{group_id}/owners")
members = client.get(f"/groups/{group_id}/members")

print("Owners:", [o["displayName"] for o in owners.json().get('value', [])])
print("Members:", [m["displayName"] for m in members.json().get('value', [])])

4. Identify Security Risks

Ownerless Groups

Get-MgGroup -All | Where-Object { -not (Get-MgGroupOwner -GroupId $_.Id) }

Groups with Guest Members (PowerShell)

Get-MgGroup -All | ForEach-Object {
    $guests = Get-MgGroupMember -GroupId $_.Id | Where-Object {$_.UserType -eq "Guest"}
    if ($guests) { Write-Output "$($_.DisplayName) has guest users" }
}

Groups with Guest Members (Python)

for g in groups.json().get('value', []):
    members = client.get(f"/groups/{g['id']}/members")
    if any(m.get("userType") == "Guest" for m in members.json().get('value', [])):
        print(f"Group {g['displayName']} contains guest members")

5. Export Reports

Export to CSV (PowerShell)

Get-MgGroup -All |
Select-Object DisplayName, Visibility, Mail, CreatedDateTime |
Export-Csv GroupsReport.csv -NoTypeInformation

Export to CSV (Python)

import csv

with open("groups_report.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["Name", "Visibility", "Mail"])
    for g in groups.json().get('value', []):
        writer.writerow([g['displayName'], g['visibility'], g.get('mail')])

6. Lifecycle & Governance (Advanced)

Apply Group Lifecycle Policy (PowerShell)

Add-MgGroupToLifecyclePolicy -GroupId <GroupId> -PolicyId <PolicyId>

Check Group Activity (Graph Reports API)

You can call:

/reports/getOffice365GroupsActivityDetail(period='D7')

to detect inactive groups.

Conclusion

Enumerating Microsoft 365 Groups is essential for security, compliance, and governance. Using PowerShell or Python with Microsoft Graph lets you quickly list groups, audit memberships, and detect risks like ownerless or guest-heavy groups. Always use an Azure AD app with the right permissions (Group.Read.All and GroupMember.Read.All) for secure and reliable access.

R K

Recent Posts

Install Python 3.7 on Ubuntu 18.04: apt and Source Build Methods

Python 3.7 was a significant release for the language. It introduced data classes, a decorator that automatically…

9 hours ago

Install Odoo 13 on Ubuntu 18.04: Python Venv and Nginx Guide

Odoo is a popular open-source suite of business applications. A single platform covers CRM, e-commerce, accounting,…

9 hours ago

Secure Apache with Let’s Encrypt on Ubuntu 18.04: Free SSL Guide

Let's Encrypt is a free, automated certificate authority run by the Internet Security Research Group…

9 hours ago

Install GCC on Ubuntu 18.04: C and C++ Compiler Setup Guide

GCC (GNU Compiler Collection) is a set of compilers and development libraries for C, C++, Fortran,…

9 hours ago

Install Python 3.8 on Ubuntu 18.04: apt and Source Build Methods

Python is one of the most widely used programming languages in the world. Its clean, readable…

9 hours ago

Install Tomcat 9 on Ubuntu 18.04: Systemd Service Setup Guide

Apache Tomcat is an open-source Java application server that implements the Java Servlet, JavaServer Pages, and…

1 day ago