Skip to content
The Lazy Administrator
  • Home
  • Disclaimer
  • Contact
  • About Me
  • Search Icon

The Lazy Administrator

Finding ways to do the most work with the least effort possible

Connect to Exchange Online PowerShell with an Azure Managed Identity

Connect to Exchange Online PowerShell with an Azure Managed Identity

September 9, 2022 Brad Wyatt Comments 5 comments

Table of Contents

  • What You Will Need
  • Create the Managed Identity, Permissions, and Runbook
    • Connect to Azure
    • Create a Resource Group
    • Create the Automation Account
    • Install the Module
    • Create System Identity
    • Get Service Principal Information
    • Connect to Graph
    • Assign the Exchange Administrator Role
  • Creating the Runbook
  • Sources

Recently the Exchange Online Module v2 came out with support for connecting to Exchange Online via a managed identity. The module has several parameters:

  1. ManagedIdentity
  2. ManagedIdentityAccountId
  3. Organization

When using the ManagedIdentity parameter you must also call the Organization parameter which is the initial, or ‘.onmicrosoft’ domain.

What You Will Need

  • PowerShell
  • Az PowerShell Module (install-module az)
  • The Microsoft Graph SDK (install-module Microsoft.Graph

Create the Managed Identity, Permissions, and Runbook

Connect to Azure

First thing we must do is connect to Azure using the Az module. Open a PowerShell window and run

Connect-AzAccount

Create a Resource Group

After we are connected we need to create a Resource Group to house everything. In my example I will create a new Resource Group in the Central US region.

$rgname = "rg-exchangeautomation"
$location = "centralus"
New-AzResourceGroup -Name $rgname -Location $location

Create the Automation Account

Next, we need to create the Automation Account that runs the runbooks. In my example I will place the Account in the Resource Group I created above, and call the account ‘exchangeautoaccount’

$accountName = 'exchangeautoaccount'
$rgName = 'rg-exchangeautomation'
$location = 'centralus'
New-AzAutomationAccount -Name $accountName -ResourceGroupName $rgName -Location $location

Install the Module

Next, we need to install the module into the automation account. I tried doing it manually and it didn’t seem to work properly. Note: You will need the preview version of the module which the latest preview version today is 2.0.6 preview7. You can always check here for the latest.

$accountName = 'exchangeautoaccount'
$rgName = 'rg-exchangeautomation'
$Name = 'ExchangeOnlineManagement'
$Version = '2.0.6-Preview7'
New-AzAutomationModule -AutomationAccountName $accountName -ResourceGroupName $rgName -Name $Name -ContentLinkUri "https://www.powershellgallery.com/api/v2/package/$Name/$Version"

Very Important! Verify that the correct version got installed. Go to your automation account > modules and verify ExchangeOnlineManagement is the correct version! If you are not on the correct version you may see an error similar to:

The role assigned to application ad423d0-dc5-4a6-a66a-20213fc7 isn't supported in this scenario. Please check online documentation for assigning correct Directory Roles to Azure AD Application for EXO App-Only Authentication.

Create System Identity

Next, we need to create/enable a system identity for our automation account to use. Using the name of our automation account from earlier, we can use PowerShell to enable it.

$accountName = 'exchangeautoaccount'
$rgName = 'rg-exchangeautomation'
Set-AzAutomationAccount -Name $accountName -ResourceGroupName $rgName -AssignSystemIdentity

Get Service Principal Information

Next, we need to get the Service Principal Information for our managed identity. Take note of the ID value (not the AppID). We will use it later.

$accountName = 'exchangeautoaccount'
Get-AzADServicePrincipal -DisplayName $accountName

Connect to Graph

Next, we need to connect to Graph using the SDK. Make sure to specify the tenant using the TenantID parameter.

Connect-MgGraph -TenantId '6438bc9-49-4c9851-fc45dc1f'

Assign Permissions to our Managed Identity

Using the ID we got earlier, we now will assign the proper permissions to our Managed Identity.

$MIAppID = 'f892abbd-c511-44e1-8ee4-89b70a5790f9'
$params = @{
    ServicePrincipalId = $MIAppID # managed identity object id
    PrincipalId = $MIAppID # managed identity object id
    ResourceId = (Get-MgServicePrincipal -Filter "AppId eq '00000002-0000-0ff1-ce00-000000000000'").id # Exchange online
    AppRoleId = "dc50a0fb-09a3-484d-be87-e023b12c6440" # Exchange.ManageAsApp
}
New-MgServicePrincipalAppRoleAssignedTo @params

Assign the Exchange Administrator Role

Lastly, we need to assign the role Exchange Administrator to the managed identity.

$MIAppID = 'f892abbd-c511-44e1-8ee4-89b70a5790f9'
$roleId = (Get-MgRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq 'Exchange Administrator'").id
New-MgRoleManagementDirectoryRoleAssignment -PrincipalId $MIAppID -RoleDefinitionId 29232cdf-9323-42fd-ade2-1d097af3e4de -DirectoryScopeId "/"

Creating the Runbook

Now in the Azure Portal I will go to my Resource Group and select my Automation Account. From there I will create a PowerShell runbook. IMPORTANT! When selecting a runtime version, select 5.1. I tried PSCore and it could never import the ExchangeOnlineManagement module. This may be fix is future versions.

Using Get-AcceptedDomain as a test, we can now see if we are able to use the managed identity that is tied to the automation account to connect to exchange online via PowerShell. My Runbook has the following code

$organization = "bwya77.onmicrosoft.com"
Connect-ExchangeOnline -ManagedIdentity -Organization $organization
Get-AcceptedDomain | Format-Table -AutoSize

Sources

HUGE shout out to onprem.wtf where I was able to read their article to understand how everything works. I spent quite a bit of time trying to find how to use the preview module’s parameters. How to connect to Exchange Online powershell with a managed identity | onprem.wtf

Brad Wyatt
Brad Wyatt

My name is Bradley Wyatt; I am a 5x Microsoft Most Valuable Professional (MVP) in Microsoft Azure and Microsoft 365. I have given talks at many different conferences, user groups, and companies throughout the United States, ranging from PowerShell to DevOps Security best practices, and I am the 2022 North American Outstanding Contribution to the Microsoft Community winner.


Azure, PowerShell
Automation, Azure, Graph, Managed Identity, PowerShell, Runbook, SDK

Post navigation

PREVIOUS
Creating a Microsoft 365 Automated Off-boarding Process with SharePoint, Graph API, and PowerShell
NEXT
Block Outdated Operating Systems with Microsoft Defender for Cloud Apps (Cloud App Security)

5 thoughts on “Connect to Exchange Online PowerShell with an Azure Managed Identity”

  1. Aleix says:
    April 12, 2023 at 2:49 am

    So cool, thank you very much!
    On the other hand, how did you get this pretty terminal?

    Thanks.

    Reply
    1. Brad Wyatt says:
      April 24, 2023 at 3:44 pm

      I am using iterm (mac) for my terminal but the using OhMyPosh for the theme
      This is my PS Profile: Set-PoshPrompt jblab_2021

      Reply
  2. Dat says:
    May 2, 2023 at 10:28 pm

    I was wondering you’re creating runbook in PowerShell 5.1 runtime because ExchangeOnlineManagement module does not work in 7.1 or 7.2 runtime.

    I’m having trouble getting Connect-AzAccount to work in 5.1. I would use 7.1 or 7.2 but I need to use Exchange Online in my script so I need to stick with 5.1.

    I’m trying to avoid using Connect-AzureAD because it is scheduled for deprecation.

    My objective is to pull users from an Azure AD group and just make changes to their mailbox base on conditions

    Reply
    1. Dat says:
      May 5, 2023 at 10:52 am

      Sorry about this, please delete this post. I forgot to add the correct module runtime version, 5.1, for the Az.Account module. Stupid me!

      Reply
  3. Steve Allison says:
    June 1, 2023 at 9:42 am

    Thanks for the write-up, come notes I have made:

    Under “ASSIGN THE EXCHANGE ADMINISTRATOR ROLE”
    You fetch the roleid for Exchange Administrator, place it into a variable, and then you don’t use the variable.

    Under “CONNECT TO GRAPH”
    There is an assumption that you have the scopes needed. I had to add
    -Scopes “RoleManagement.ReadWrite.Directory”
    in order to make the necessary change

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Subscribe

Email


Categories

  • Active Directory (8)
  • AI (3)
  • API (1)
  • AutoPilot (2)
  • Azure (15)
  • Bicep (4)
  • Connectwise (1)
  • Defender for Cloud Apps (1)
  • Delegated Admin (1)
  • DevOps (6)
  • Graph (6)
  • Intune (15)
  • LabTech (1)
  • Microsoft Teams (6)
  • Office 365 (19)
  • Permissions (2)
  • PowerShell (50)
  • Security (1)
  • SharePoint (3)
  • Skype for Business (1)
  • Terraform (1)
  • Uncategorized (2)
  • Yammer (1)

Recent Comments

  • Kristopher Gates on Getting Started with GitHub Copilot in the CLI
  • MD SHARIQUE AKHTAR on Modern Active Directory – An update to PSHTML-AD-Report
  • TommyBoich on How The ConnectWise Manage API Handles Pagination with PowerShell
  • LOTTERY 365 LOGIN on Windows LAPS Management, Configuration and Troubleshooting Using Microsoft Intune
  • SPRUNKI PHASE 6 on Get a New Computer’s Auto Pilot Hash Without Going Through the Out of Box Experience (OOBE)

1,739,509 People Reached

© 2025   All Rights Reserved.