Group descriptions are easy to skip when groups are created, and a year later nobody knows what SG-App-Prod-RW-02 is for. Filling them in one group at a time in the Entra admin center is slow, so I do it in bulk with Microsoft Graph PowerShell and a CSV file. The steps below cover finding the groups with no description, filling them in from a CSV, and checking the result.

Applies to: Microsoft Entra ID (formerly Azure AD) security groups and Microsoft 365 groups, using Microsoft Graph PowerShell SDK v2.

The old AzureAD module (Connect-AzureAD / Set-AzureADGroup) is retired and no longer works. Everything below uses the Microsoft Graph PowerShell SDK.

Prerequisites

  • Microsoft Graph PowerShell installed: Install-Module Microsoft.Graph -Scope CurrentUser
  • The Groups Administrator role (or higher)
  • The delegated permission Group.ReadWrite.All, granted when you connect

Step 1: Export the groups that have no description

Start from what's missing rather than writing the CSV by hand:

Connect-MgGraph -Scopes "Group.ReadWrite.All"

Get-MgGroup -All -Property Id, DisplayName, Description, OnPremisesSyncEnabled, MailEnabled, SecurityEnabled, GroupTypes |
  Where-Object { [string]::IsNullOrWhiteSpace($_.Description) } |
  Select-Object @{n='groupobjectid';e={$_.Id}}, DisplayName,
                @{n='description';e={''}}, OnPremisesSyncEnabled, MailEnabled |
  Export-Csv C:\temp\groups.csv -NoTypeInformation -Encoding UTF8

Open groups.csv in Excel and fill in the description column. Delete the rows you don't want to change.

Bulk Group Description

The script only needs the groupobjectid and description columns:

groupobjectid,description
f8f3b56e-56b1-49c0-b8ec-a061e6c9ac07,Read/write access to the Finance share
a7013eb0-1973-4232-ad73-a7d9ac0968ba,Licence group: Microsoft 365 E3 for HR

Step 2: Update the descriptions

This version skips groups Graph can't change (see the next section) and logs every result:

$rows = Import-Csv C:\temp\groups.csv
$log  = foreach ($row in $rows) {
    if ($row.OnPremisesSyncEnabled -eq 'True') {
        [pscustomobject]@{ Id = $row.groupobjectid; Result = 'Skipped: synced from on-premises AD' }
        continue
    }
    try {
        Update-MgGroup -GroupId $row.groupobjectid -Description $row.description -ErrorAction Stop
        [pscustomobject]@{ Id = $row.groupobjectid; Result = 'Updated' }
    }
    catch {
        [pscustomobject]@{ Id = $row.groupobjectid; Result = "Failed: $($_.Exception.Message)" }
    }
}
$log | Export-Csv C:\temp\groups-result.csv -NoTypeInformation
$log | Group-Object Result | Select-Object Name, Count

The simplest version, if your CSV only contains cloud-only groups:

Import-Csv C:\temp\groups.csv | ForEach-Object {
    Update-MgGroup -GroupId $_.groupobjectid -Description $_.description
}

Step 3: Verify

Import-Csv C:\temp\groups.csv | ForEach-Object {
    Get-MgGroup -GroupId $_.groupobjectid -Property DisplayName, Description |
      Select-Object DisplayName, Description
}

Groups you can't update this way

Group type Why it fails Where to change it
Synced from on-premises AD (OnPremisesSyncEnabled = True) On-premises AD is the source of truth, so Entra ID treats the group as read-only On-premises: Set-ADGroup -Identity <name> -Description "<text>", then wait for the next Entra Connect sync
Distribution lists and mail-enabled security groups Graph doesn't allow updating these group types Exchange Online admin center or Exchange Online PowerShell

Not sure which type a group is? See types of groups in Microsoft 365.

Using group names in the CSV instead of IDs

If your CSV has display names instead of object IDs, look up each ID first. Display names don't have to be unique, so the script skips any name that matches more than one group:

Import-Csv C:\temp\groups-by-name.csv | ForEach-Object {
    $name  = $_.displayname -replace "'", "''"
    $match = @(Get-MgGroup -Filter "displayName eq '$name'")
    if ($match.Count -eq 1) { Update-MgGroup -GroupId $match[0].Id -Description $_.description }
    else { Write-Warning "$($_.displayname): $($match.Count) matches, skipped" }
}

Related