Exchange Online PowerShell from Linux with Docker

These steps allow you to connect to Exchange Online using PowerShell inside a Docker container from a Linux host. in my example I am connecting to Exchange Online from Ubuntu 21.04. For the Docker container image I am using the official Azure PowerShell container from Microsoft (mcr.microsoft.com/azure-powershell).

The account I am using to administer Exchange Online has 2FA authentication enabled. Due to this I am using the -Device authentication flag with Connect-ExchangeOnline

Update – 2022/05/07

At some point in the last few months, the original steps I published stopped working due to an SSL error:

PS /> Connect-ExchangeOnline -Device

----------------------------------------------------------------------------
The module allows access to all existing remote PowerShell (V1) cmdlets in addition to the 9 new, faster, and more reliable cmdlets.

.......

To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXX to authenticate.

pwsh: symbol lookup error: /opt/microsoft/powershell/7/libmi.so: undefined symbol: SSL_library_init

I have updated the below steps which resolve this problem. Installing the PSWSMan module and launching a new PowerShell session resolved the problem.

Container Setup

Start the container which will give you a PowerShell session:

docker run \
  --rm \
  -it mcr.microsoft.com/azure-powershell

It should look like this:

me@h4cktop ~ $ docker run \
  --rm \
  -it mcr.microsoft.com/azure-powershell
PowerShell 7.1.3
Copyright (c) Microsoft Corporation.

https://aka.ms/powershell
Type 'help' to get help.

PS />

Alternatively, if you will be reusing the container in future and don’t want to reinstall PSWSMan and the Exchange Online modules, create a container and attach to it:

docker container create -i -t \
  --name powershell \
  mcr.microsoft.com/azure-powershell
docker container start --attach -i powershell

Next the PSWSMan module needs to be installed into the container. After installing the module a new PowerShell session needs to be started; without starting a new PowerShell session you will not be able to connect due to an SSL error.

Install-Module -Name PSWSMan -Force
Install-WSMan
pwsh

Next the PSWSMan and ExchangeOnlineManagement module needs to be installed inside the container:

Install-Module -Name ExchangeOnlineManagement -Force

The container should be setup and ready to connect to Exchange Online.

Exchange Online Connection

Now you can simply connect to Exchange Online using device authentication:

Connect-ExchangeOnline -Device

When you run the cmdlet you will be provided with an authentication code and a link to visit to enter the authentication code, as an example:

PS /> Connect-ExchangeOnline -Device
.....

To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code 1234567XXX to authenticate.

Once you visit the link and authenticate/enter the code you should get a message in the web browser:

Exchange REST API Powershell Authentication Success

Wait for a few seconds and the PowerShell session should then be authenticated. Once authenticated you should get a message for “Creating implicit remoting module”:

 Creating implicit remoting module ...
        Getting command information from remote session ... 150 commands received
        [ooooooooooooooooooooooooooooooooooooooooooooooooooooooo]
        00:00:20 remaining.

The end result should look like this once authenticated:

PS /> Connect-ExchangeOnline -Device

----------------------------------------------------------------------------
The module allows access to all existing remote PowerShell (V1) cmdlets in addition to the 9 new, faster, and more reliable cmdlets.

|--------------------------------------------------------------------------|
|    Old Cmdlets                    |    New/Reliable/Faster Cmdlets       |
|--------------------------------------------------------------------------|
|    Get-CASMailbox                 |    Get-EXOCASMailbox                 |
|    Get-Mailbox                    |    Get-EXOMailbox                    |
|    Get-MailboxFolderPermission    |    Get-EXOMailboxFolderPermission    |
|    Get-MailboxFolderStatistics    |    Get-EXOMailboxFolderStatistics    |
|    Get-MailboxPermission          |    Get-EXOMailboxPermission          |
|    Get-MailboxStatistics          |    Get-EXOMailboxStatistics          |
|    Get-MobileDeviceStatistics     |    Get-EXOMobileDeviceStatistics     |
|    Get-Recipient                  |    Get-EXORecipient                  |
|    Get-RecipientPermission        |    Get-EXORecipientPermission        |
|--------------------------------------------------------------------------|

To get additional information, run: Get-Help Connect-ExchangeOnline or check https://aka.ms/exops-docs

Send your product improvement suggestions and feedback to exocmdletpreview@service.microsoft.com. For issues related to the module, contact Microsoft support. Don't use the feedback alias for problems or support issues.
----------------------------------------------------------------------------

To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code 1234567XXX to authenticate.
PS />

You should now be able to run the Exchange Online cmdlets. As an example:

PS /> Get-EXOMailbox
ExternalDirectoryObjectId : xxxxxxxx-e4e9-42bd-b2b7-xxxxxxxx
UserPrincipalName         : xxxxxxxx@gbe0.com
Alias                     : xxxxxxxx
DisplayName               : xxxxxxxx
EmailAddresses            : {smtp:xxxxxxxx@gbe0.com}
PrimarySmtpAddress        : xxxxxxxx@gbe0.com
RecipientType             : UserMailbox
RecipientTypeDetails      : SharedMailbox
Identity                  : xxxxxxxx
Id                        : xxxxxxxx
ExchangeVersion           : 0.20 (15.0.0.0)
Name                      : xxxxxxxx
DistinguishedName         : CN=xxxxxxxx,OU=xxxxxxxx.onmicrosoft.com,OU=Microsoft Exchange Hosted Organizations,DC=xxxxxxxx,DC=PROD,DC=OUTLOOK,DC=COM
OrganizationId            : xxxxxxxx.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xxxxxxxx.onmicrosoft.com - xxxxxxxx.PROD.OUTLOOK.COM/ConfigurationUnits/xxxxxxxx.onmicrosoft.com/Configuration
Guid                      : xxxxxxxx-249d-42a3-9384-xxxxxxxx

In my case, I needed to enable DKIM for a newly added domain:

PS /> New-DkimSigningConfig -DomainName xxxxx.com -Enabled $true -KeySize 2048
PS /> Get-DkimSigningConfig xxxxx.com | Select-Object Selector1CNAME, Selector2CNAME | fl

Selector1CNAME : selector1-xxxxx-com._domainkey.xxxxx.onmicrosoft.com
Selector2CNAME : selector2-xxxxx-com._domainkey.xxxxx.onmicrosoft.com


PS />

Potential Issues

While trying to get this work from other steps I found online I ran into a bunch of problems.

Unable to open a web page using xdg-open

On the first attempt at connecting using Connect-ExchangeOnline I was getting an error that xdg-open couldn’t be used:

Error Acquiring Token:
Unable to open a web page using xdg-open. See inner exception for details. Possible causes for this error are: xdg-open is not installed or it cannot find a way to open an url - make sure you can open a web page by invoking from a terminal: xdg-open https://www.bing.com
New-ExoPSSession: /root/.local/share/powershell/Modules/ExchangeOnlineManagement/2.0.4/netCore/ExchangeOnlineManagement.psm1:475
Line |
 475 |  … PSSession = New-ExoPSSession -ExchangeEnvironmentName $ExchangeEnviro …
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | One or more errors occurred. (Unable to open a web page using xdg-open. See inner exception for details. Possible causes for this error are: xdg-open is not installed or it cannot find a way to open an url - make sure you can open a web page by invoking
     | from a terminal: xdg-open https://www.bing.com )

This error was fixed by adding the -Device flag to Connect-ExchangeOnline.

WSMan client library was found

The next problem I ran into using the microsoft/powershell container was that I managed to install the ExchangeOnline module and authenticate in my browser. After I authenticated, the Powershell session then gave this exception:

To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code 1234567XXX to authenticate.
Exception: /root/.local/share/powershell/Modules/ExchangeOnlineManagement/2.0.4/netCore/ExchangeOnlineManagement.psm1:475
Line |
 475 |  …             $PSSession = New-ExoPSSession -ExchangeEnvironmentName $E …
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | This parameter set requires WSMan, and no supported WSMan client library was found. WSMan is either not installed or unavailable for this system.

The fix for this was to use the mcr.microsoft.com/azure-powershell container instead.

2 thoughts on “Exchange Online PowerShell from Linux with Docker

    1. Do you have more information about what you are trying to do? It’s possible the steps I provided no longer work; I will review them later and update if required.

Leave a Reply

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