Browse Tag

O365 Group

Get Office 365 Groups with Teams via PowerShell and the Microsoft Graph

Office 365 Groups are the backbone of a lot applications in Microsoft. The core principal is that an Office 365 Group is the security model that supports a Team. A good start to learn more about this is from the Microsoft documentation about the two.

Here is a more detailed image about how a Team is a workload that is supported by Office 365 Groups as the identity layer. This means that not all groups have an associated Team but all Teams are supported by a group.

Getting Groups with associated Teams

I had a client ask me recently to get a list of what groups have a Microsoft Teams chat connected vs Office 365 groups that don’t have a team connected. I have done this in the past using the method here on the TechCommunity. I then saw in some updated documentation that the beta Graph API includes a filterable property called resourceProvisioningOptions. The documentation can be found here. Filtering by this property is currently on the beta API so it is not recommended to utilize this in a production solution. 

Using the /groups Graph API we can retrieve all groups in the tenant that have a team. Any group that has a team has a resourceProvisioningOptions property that contains “Team”. 

  • Currently teams that were deleted may be included
  • This property can be changed but don’t do it
  • This also is populated for a group that has a Team added to it after the fact

One of the following permissions is required to call this API. To learn more, including how to choose permissions, see Permissions.

Permission type Permissions (from least to most privileged)
Delegated (work or school account) Group.Read.All, Group.ReadWrite.All
Delegated (personal Microsoft account) Not supported.
Application Group.Read.All, Group.ReadWrite.All

Here is the script and I will break it down below

#Enter scopes or app data - If a scope is entered it will used
#If scopes is empty it will check to run via app 
$scopes = 'Group.Read.All'

$appid = ''
$appsecret = ''
$appaaddomain = ''

#Graph URLs - uncomment one to run

#Get all groups
#$url = "https://graph.microsoft.com/v1.0/groups?`$filter=groupTypes/any(c:c eq 'Unified')&`$select=displayname,resourceProvisioningOptions"
#Get all groups with teams
$url = "https://graph.microsoft.com/beta/groups?`$filter=resourceProvisioningOptions/Any(x:x eq 'Team')"

#Establish connection
If($scopes.Length -gt 0){
    Connect-PnPOnline -Scopes "Group.Read.All"
} elseif($appid.Length -gt 0) {
    Connect-PnPOnline -AppId $appid -AppSecret $appsecret  -AADDomain $appaaddomain
} else {
    write-host 'Connection issue' -ForegroundColor Red
    exit
}

#Get token
$token = Get-PnPAccessToken

#Call graph
if($token){
    $response = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $token"}
} else {
    write-host 'Token issue' -ForegroundColor Red
    exit
}

#Parse data
if($response){
foreach($r in $response.value){ 
    if($r.resourceProvisioningOptions -eq 'Team'){
        write-host $r.displayname "is a Team enabled Group" -ForegroundColor Yellow
        #Do fancy stuff in here
    } else {
        write-host $r.displayname "is a regular O365 Group" -ForegroundColor Green
    }
}
} else {
    write-host 'Response issue' -ForegroundColor Red
}

Connecting to the Graph via PowerShell

To connect to the Graph via PowerShell I am using the PnP PowerShell module. SharePoint Patterns and Practices (PnP) contains a library of PowerShell commands (PnP PowerShell) that allows you to perform complex provisioning and artifact management actions towards SharePoint. The commands use CSOM and can work against both SharePoint Online as SharePoint On-Premises. Details about how to work with this module and its cmdlets can be found here.

The cmdlet that is used to connect is Connect-PnPOnline. This cmdlet can be used to connect to multiple entry points. When connecting to the Graph you can connect through Azure AD and declare permissions scopes with the -Scopes parameter or connect with app level permissions using the -AppId, -AppSecret, and -AADDomain parameters.

I have setup the script to handle either depending on what you enter at the top for the variables. Details for different types of permissions can be found here.

Calling the Graph via PowerShell

To call the Graph I am using the Invoke-RestMethod cmdlet to make the REST request. To handle the Graph call we need to pass along a bearer token. I am getting the token through the PnP cmdlet Get-PnPAccessToken. The data will then be returned as an object. You could convert the data into JSON to utilize it if necessary.

Along with the token we need to pass along the Graph Uri call. I have setup 2 different options to get the data. Swap the comment (#) tags for either $url line. 

Here is a breakdown of each option:

  • Get all groups which have Teams
    • This will return the filtered list of Groups
      • /v1.0/groups?$filter=groupTypes/any(c:c eq ‘Unified’)&`$select=displayname,resourceProvisioningOptions
  • Get all groups
    • This will return all groups and then go through all returned groups and perform an action for ones that have a connected Team
      • /beta/groups?$filter=resourceProvisioningOptions/Any(x:x eq ‘Team’)
      • Currently this only does a Write-Host but any business logic could be added here.

Make sure you copy and paste from the code block for proper formatting.

The best way to test Graph calls before working with them is through the Graph Explorer. I highly recommend this one!

Securing the app permissions

One idea that I did not put in here but would be a good idea if you wanted to set up a recurring solution around this would be to protect the app data through the Azure Key Vault.  Here are details on how this can be completed – 

Using Azure Key Vault with PowerShell – Part 1

More information about setting up an Azure AD app can be found here:

Interact with Graph and make O365 Groups with AzureFunctions PowerShell

View When You Deleted an Office 365 Group

group1

Introduction

The ability for soft-delete and restore of an Office 365 Group has recently been released. I put together some information about that in my previous post here. Before this restoration was possible, when you deleted an Office 365 Group it was fully gone. Now we have the ability to view Groups that have been deleted and restore them using PowerShell.

The ability to restore was a great but there was a small gap for me when the cmdlets were first rolled out:

  • You have 30 days to restore an Office 365 Group but you didn’t know when an Office 365 Group was deleted. 

This would make building any logic around things like notifications or reporting a challenge as we could not tell which Groups were about to expire. 

This has been resolved by Microsoft and we now have the ability to see the Deleted Date and Time of an Office 365 Group for the 30 days it is retained using PowerShell. 


What you need to know

  • You can only view the deletion date via PowerShell
  • You can only view the deletion date of Groups that are in the pending permanent delete state that stays around for 30 days

Prerequisites:

  • Azure AD PowerShell V2 – Preview 
    • The release of the cmdlets that support Office 365 Group recovery are now available only in the preview cmdlets. 
    • I am writing this using version 2.0.0.110

Viewing when an Office 365 Group was deleted

1 – Connect to Azure AD via PowerShell (ensure you connect to Preview)

Connect-AzureAD

2 – Review the Office 365 Groups that have been deleted and when they were deleted

This will sort the Groups by their DeletedDateTime

Get-AzureADMSDeletedGroup | Sort-Object DeletedDateTime | Format-Table DisplayNAme, DeletedDateTime, Description, Visibility, Mail, ID

You are now good to go build something fancy like:

  • Build a report for admins to notify them weekly what Groups are being permanently deleted
  • Build a single page app to surface deleted Groups and allow users to recover them using an Azure Function