Microsoft Unified Tenant Configuration Management

UTCM Controls and Manages Microsoft 365 Tenant Configurations

In late January, Microsoft launched the preview of Unified Tenant Configuration Management (UTCM), a solution to track and manage configuration settings for a set of Microsoft 365 workloads. In effect, UTCM is a Microsoft-engineered version of Microsoft Desired State Configuration (DSC) using much the same principles but different technology. The current UTCM implementation is through a set of Microsoft Graph APIs accessed via the beta endpoint. Because the public interface of UTCM is the Graph, interactions can be via any interface that supports that Graph. Here, I use V2.34 of the Microsoft Graph PowerShell SDK.

The target for UTCM is configuration management for Microsoft 365 and associated workloads. Currently, the workloads supported by UTCM are Exchange Online, Entra, Purview, Teams, Intune, and Defender. Unsurprisingly given the weak state of Graph support for SharePoint Online management, control over SharePoint Online and OneDrive for Business configurations is not yet supported. It will be interesting to see how the solution develops in terms of scope, if Microsoft delivers a UX for UTCM (perhaps in the Purview portal), and licensing.

I don’t intend to go into UTCM in-depth and don’t pretend to cover every detail here. Instead, this is a UTCM introduction for Microsoft 365 tenant administrators based on what I discovered when I setup UTCM for a tenant. To go further, you’ll need to spend some time reviewing the documentation and figuring out what resources need to be monitored in your tenant.

UTCM Basics

UTCM is built around a set of objects accessed through Graph APIs:

Resource types: UTCM supports over 300 workload resource types to monitor. A resource type is something like an Entra administrative unit (microsoft.entra.administrativeUnit), so monitoring that resource might mean checking for the creation of new administrative units and deletions or changes to existing administrative units. The full set of monitor resource types and their properties are defined in the monitor schema.

Snapshots are UTCM captures of defined parts (monitored entities) of the current tenant configuration. A snapshot is a point in time baseline that can be used to compute configuration drift, or the changes that have occurred in monitored entities since UTCM took the snapshot Configuration Jobs

Configuration Monitor jobs run every six hours to compare monitored resources and snapshots (you cannot change this frequency now, but Microsoft says that you’ll be able to do so in the future).

Each time a monitor job runs, it creates a configuration drift record if the job detects any changes based on the monitor definition. UTCM keeps the drift records until an administrator reviews the change to figure out what to do (“resolution”). For example, resolved changes might be captured in a new baseline snapshot.

Drift records are kept for 30 days after resolution and then permanently deleted. Up to 30 monitor jobs can be active in a tenant. Collectively, UTCM can keep track of up to 800 resources daily (because monitor jobs run every six hours, each resource consumes four of this quota).

UTCM Configuration

Tenant configuration uses an Entra enterprise app to access information to monitor within a tenant. For now, each tenant must configure the UTCM app. When UTCM is generally available, it’s likely that this step will be automated. For now, to configure the app, you need to create a service principal and assign permissions. To create the service principal, run the New-MgServicePrincipal cmdlet:

New-MgServicePrincipal -AppId '03b07b79-c5bc-4b5e-9bfa-13acf4a99998'

DisplayName                             Id                                   AppId  
------------                            --                                   ----- 
Unified Tenant Configuration Management 64226bcd-ed40-4701-b92c-41e445ee2ac6 03b07b79-c5bc-4b5e-9bfa-13acf4a99998

Interestingly, the service principal created for the UTCM app holds the set of application permissions required for monitoring. Out of the box, the documentation uses Policy.Read.All and User.ReadWrite.All as examples. I don’t know why the full-blown User.ReadWrite.All permission is used instead of the more restricted User.ReadBasic.All. It doesn’t seem like an application to manage policy information for Microsoft 365 workloads should need to read the full set of properties for user accounts or update user account properties. Perhaps this is a permission overreach by the UTCM developers that’s happens regularly in other apps. In any case, here’s how to add the required permissions:

[array]$AppPermissions = @('User.ReadWrite.All', 'Policy.Read.All')
# Get Graph app details
$GraphApp = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'"
# Define the target
$TargetId = (Get-MgServicePrincipal -filter "displayname eq 'Unified Tenant Configuration Management'").id
# Loop through each permission and assign it to the target
ForEach ($Permission in $AppPermissions) {
   $Role = $GraphApp.AppRoles | Where-Object {$_.Value -eq $Permission}
   $AppRoleAssignment = @{}
   $AppRoleAssignment.Add("PrincipalId",$TargetId)
   $AppRoleAssignment.Add("ResourceId",$GraphApp.Id)
   $AppRoleAssignment.Add("AppRoleId", $Role.Id)
   # Assign Graph permission
   Try {
     New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $TargetId -BodyParameter $AppRoleAssignment -ErrorAction Stop
   } Catch {
      Write-Host ("Unable to assign {0} permission to app" -f $Permission)
   }
}

After creating the service principal and assigning the permissions, the result should be an enterprise app with the two configured application permissions as shown in Figure 1.

UTCM enterprise app and its permissions.
Figure 1: UTCM enterprise app and its permissions

A critical point is that you must also assign the required permissions and/or roles to the UTCM service principal to allow UTCM to access information when its monitor jobs run. For example, to monitor Exchange Online resources, the service principal must be granted either the Global Reader (to read) or Exchange administrator (read-write) role. In addition, the UTCM app must hold the Exchange.ManageAsApp permission for the Office 365 Exchange Online app (see the code in this article).

Permissions to Work with UTCM

A new ConfigurationMonitoring.ReadWrite.All permission is required to work with the UTCM Graph APIs. With that permission, a signed in session can run Graph requests to interact with UTCM.

The documentation says that “any privileged role” is also required for interactive delegated access and points to the page listing Entra built-in roles. What I think Microsoft means is that the administrative role required by the signed-in user during an interactive session depends on what data is being accessed. Some trial and error might be needed to find exactly what’s required.

UTCM Snapshots

There’s no doubt that a Microsoft 365 tenant manages many different settings across workloads. The number and different types of settings makes it almost impossible for humans to be sure that no one makes a change to an important setting, like adjusting a retention policy. Let’s go through the steps of creating a simple monitor to check that no one messes with the Exchange Online CAS mailbox policy for enterprise mailboxes. First, create a snapshot of the current CAS mailbox plan:

$Uri = "https://graph.microsoft.com/beta/admin/configurationManagement/configurationSnapshots/createSnapshot"

$RequestBody = @"
{
    "displayName": "CAS Mailbox Plan snapshot",
    "description": "This is a snapshot created via the Graph API for CAS Mailbox Plans",
    "resources": [
        "microsoft.exchange.casMailboxPlan"
    ]
}
"@

$NewSnapShot = Invoke-MgGraphRequest -Uri $Uri -Method Post -Body $RequestBody

$NewSnapshot

Name                           Value
----                           -----
@odata.context                 https://graph.microsoft.com/beta/$metadata#microsoft.graph.configurationSnapshotJob
completedDateTime              01/01/0001 00:00:00
resourceLocation
id                             88349df9-52f7-4d47-91af-bd944e7af5a5
createdDateTime                30/01/2026 11:32:48
displayName                    CAS Mailbox Plan snapshot
createdBy                      {[user, System.Collections.Hashtable], [application, System.Collections.Hashtable]}
status                         notStarted
description                    This is a snapshot created via the Graph API for CAS Mailbox Plans
resources                      {microsoft.exchange.casMailboxPlan}
tenantId                       22e90715-3da6-4a78-9ec6-b3282389492b

Creating a Configuration Monitor

To create a configuration monitor, create a request body containing details of the resource for UTCM to monitor and the properties to monitor. The request is then posted to the configurationMonitors endpoint:

$Uri = "https://graph.microsoft.com/beta/admin/configurationManagement/configurationMonitors"

$RequestBody = @"
{
    "displayName": "Exchange Online monitor",
    "description": "This is an Exchange Online UTCM monitor created via the Graph API. The monitor covers the CAS Mailbox Plan resource",
    "baseline":
    {
        "displayName": "Exchange Online Monitor 1",
        "description": "Exchange Online Monitor for CAS mailbox plan",
        "resources": [
        {
            "displayName": "casMailboxPlan",
            "resourceType": "microsoft.exchange.casMailboxPlan",
            "properties": {
                "Identity": "ExchangeOnlineEnterprise-3ba414b9-c3ea-4a9e-bad0-59e39e1173de",
                "DisplayName": "ExchangeOnlineEnterprise-3ba414b9-c3ea-4a9e-bad0-59e39e1173de",
                "ImapEnabled": false,
                "OwaMailboxPolicy": "OwaMailboxPolicy-Default",
                "PopEnabled": false,
                "ActiveSyncEnabled": true,
                "Ensure":"Present"
            }
        }
    ]
}
"@

$NewMonitor = Invoke-MgGraphRequest -Uri $Uri -Method POST -Body $RequestBody

The documentation includes an example showing how to monitor three Exchange Online resources (shared mailbox, mail contact, and accepted domain). In the case of Exchange, most of the monitorable properties are those that can be set using well-known cmdlets like Set-Mailbox and Set-CasMailbox. However, something like license assignments for shared mailboxes cannot be monitored.

To check the newly created monitor, fetch its details using the configurationMonitors API by filtering with the display name of the monitor (captured when created in the $NewMonitor variable):

#Find individual monitor
$Uri = ("https://graph.microsoft.com/beta/admin/configurationManagement/configurationMonitors/?`$filter=displayName eq '{0}'" -f $NewMonitor.displayName)
Invoke-MgGraphRequest -Uri $Uri -Method Get

# Find all Monitors

$uri = "https://graph.microsoft.com/beta/admin/configurationManagement/configurationMonitors/"
$Data = Invoke-MgGraphRequest -Uri $Uri -Method Get -OutputType PsObject | Select-Object -ExpandProperty Value

id                         : 04d76e5c-b565-41fb-9fe3-8a89d3de364b
displayName                : Exchange Online monitor
description                : This is an Exchange Online UTCM monitor created via the Graph API. The monitor covers the
                             CAS Mailbox Plan resource
tenantId                   : 22e90715-3da6-4a78-9ec6-b3282389492b
status                     : active
monitorRunFrequencyInHours : 6
mode                       : monitorOnly
createdDateTime            : 30/01/2026 11:22:46
lastModifiedDateTime       : 30/01/2026 11:22:46
runAsUTCMServicePrincipal  : True
inactivationReason         :
createdBy                  : @{user=; application=}
runningOnBehalfOf          : @{user=; application=}
lastModifiedBy             : @{user=; application=}
parameters                 :

Checking Monitoring Jobs

The monitor status is active, so it’s in the queue for UTCM to run according to its fixed six-hourly schedule. After at least six hours elapses, we can check monitoring results to detect if any job reports drifts against the baseline snapshot. Here’s how to select the latest job record that reports some drift:

$Uri = ("https://graph.microsoft.com/beta/admin/configurationManagement/configurationMonitoringResults/?`$filter=MonitorId eq '{0}' and driftsCount gt 0" -f $NewMonitor.Id)
[array]$MonitorJobs = Invoke-MgGraphRequest -Uri $Uri -Method Get -OutputType PsObject | Select-Object -ExpandProperty Value | Sort-Object {$_.runCompletionDateTime -as [datetime]} -Descending

$MonitorJob = $MonitorJobs[0]

id                    : a62eb467-165b-4e04-adfd-840e428b951d
monitorId             : 04d76e5c-b565-41fb-9fe3-8a89d3de364b
tenantId              : 22e90715-3da6-4a78-9ec6-b3282389492b
runInitiationDateTime : 02/02/2026 12:00:55
runCompletionDateTime : 02/02/2026 12:01:05
runStatus             : successful
driftsCount           : 1
driftsFixed           : 0
runType               : monitor

After confirming that some drift in the monitored properties exists, retrieve the drift records found by the configuration monitor by querying the configurationDrifts endpoint:

$Uri = ("https://graph.microsoft.com/beta/admin/configurationManagement/configurationDrifts/?`$filter=monitorId eq '{0}'" -f $MonitorJob.MonitorId)
[array]$DriftRecords = Invoke-MgGraphRequest -Uri $uri -Method GET -OutputType PSObject | Select-Object -ExpandProperty Value

$DriftRecords[0]

id                          : c8ff1df8-0f15-4738-b4c0-70db6a02a602
monitorId                   : 04d76e5c-b565-41fb-9fe3-8a89d3de364b
tenantId                    : 22e90715-3da6-4a78-9ec6-b3282389492b
resourceType                : microsoft.exchange.casMailboxPlan
baselineResourceDisplayName : casMailboxPlan
firstReportedDateTime       : 30/01/2026 12:01:05
status                      : active
resourceInstanceIdentifier  : @{Identity=ExchangeOnlineEnterprise-3ba414b9-c3ea-4a9e-bad0-59e39e1173de}
driftedProperties           : {@{propertyName=PopEnabled; currentValue=True; desiredValue=False},@{propertyName=DisplayName; currentValue=ExchangeOnlineEnterprise; desiredValue=ExchangeOnlineEnterprise-3ba414b9-c3ea-4a9e-bad0-59e39e1173de},
@{propertyName=ImapEnabled; currentValue=True; desiredValue=False}}

The information about the changes made to monitored properties is in the DriftedProperties property, so here’s what we see. Someone has changed the value for the PopEnabled and ImapEnabled settings from False to True:

$DriftRecords[0].DriftedProperties

propertyName             currentValue                                                  desiredValue
------------             ------------                                                  ------------
PopEnabled                       True                                                         False
DisplayName  ExchangeOnlineEnterprise ExchangeOnlineEnterprise-3ba414b9-c3ea-4a9e-bad0-59e39e1173de
ImapEnabled                      True                                                         False

Notice that there’s no mention of who made the change. To find that information, you’ll probably have to review audit records around the time when the change happens. You can narrow the change down to a six-hour period by finding the first drift record to highlight a change, which happened between that time and the previous monitoring job,

There’s no API available to resolve a drift. At this point, the appropriate method appears to be that administrators decide whether the change made to a configuration is acceptable. If it is, they should create a new snapshot. This action removes all drift records and monitoring results because those objects no longer apply. If the change is unacceptable, administrators can reverse it. Following the change, UTCM will no longer create drift records.

In the future, Microsoft will deliver a more sophisticated mechanism to resolve configuration drifts, but that’s what we have for now.

A Welcome Start

UTCM is an incomplete solution, but there’s enough structure and fundamentals in place to imagine the potential of the software. I think UTCM will be popular with Microsoft 365 tenants, subject of course to licensing and cost. Those wanting to move from DSC should read the Microsoft365DSC blog, where the topic is already being discussed.

If you want to look outside Microsoft, there are ISV products available, like CoreView Configuration Manager for Microsoft 365. The nice thing about the arrival of UTCM is that anyone working in this space needs to raise their game, and that’s goodness.


Make sure that you’re not surprised about changes that appear inside Microsoft 365 applications by subscribing to the Office 365 for IT Pros eBook. Our monthly updates make sure that our subscribers stay informed.

One Reply to “Microsoft Unified Tenant Configuration Management”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.