Running Office365 Powershell scripts cross tenant

When you manage multiple tenants or have a Microsoft Partner account to manage a lot of tenants it often gets annoying having to redeploy the same scripts to each tenant over and over. You can try using the MSOL commands but most of the times the scripts you are trying to run are Exchange, Skype for business, or Teams scripts, and you’re not able to run these just by using the Azure Active Directory Module for PowerShell.

The great thing is that Microsoft actually has a perfect solution for this by using your partner credentials cross tenant. You can change the session URL to match the specific client you are trying to manage, this means you can deploy scripts across all clients with relative ease when using the following scripts.

To get started on this, I’ll demonstrate how to get all mailbox sizes across your multiple tenants.
First, we’ll have to connect to Office365 by using the MSOL Microsoft Azure Active Directory Module for Windows PowerShell

connect-msolservice
$clients = Get-MsolPartnerContract -All

When we’re connected, our client list is filled in $clients. This means we can loop trough each client and perform actions for them. In our case we’ll simply be gathering information, but you could also change settings such as disabling clutter, or enabling other functionality.

foreach ($client in $clients) {
$ClientDomain = Get-MsolDomain -TenantId $client.TenantId | Where-Object {$_.IsInitial -eq $true}
    Write-host "Logging into portal for $($client.Name)"
    $DelegatedOrgURL = "https://ps.outlook.com/powershell-liveid?DelegatedOrg=" + $ClientDomain.Name
    $ExchangeOnlineSession = New-PSSession -ConnectionUri $DelegatedOrgURL -Credential $credential -Authentication Basic -ConfigurationName Microsoft.Exchange -AllowRedirection
    Import-PSSession -Session $ExchangeOnlineSession -AllowClobber -DisableNameChecking

Now that we’re connected to the Exchange PowerShell session for this client we can run whaterver Exchange commands we’d like. in our case, getting the mailboxes and respective size:

Get-Mailbox | Get-MailboxStatistics | Select-Object DisplayName, IsArchiveMailbox, ItemCount, TotalItemSize | format-table

When we’ve performed our commands, we do need to destroy our session as PowerShell sessions on Office365 can be rate limited.

Remove-PSSession $ExchangeOnlineSession
}

See that final curly bracket? With that one we close our for-each loop, Simply put we’re telling PowerShell that the loop is over, and it can continue with the next client in the list. If we put all of this together our script will look like this:

$credential = Get-Credential
connect-msolservice -Credential $credential
$clients = Get-MsolPartnerContract -All
foreach ($client in $clients) {
    $ClientDomain = Get-MsolDomain -TenantId $client.TenantId | Where-Object {$_.IsInitial -eq $true}
    Write-host "Logging into portal for $($client.Name)"
    $DelegatedOrgURL = "https://ps.outlook.com/powershell-liveid?DelegatedOrg=" + $ClientDomain.Name
    $ExchangeOnlineSession = New-PSSession -ConnectionUri $DelegatedOrgURL -Credential $credential -Authentication Basic -ConfigurationName Microsoft.Exchange -AllowRedirection
    Import-PSSession -Session $ExchangeOnlineSession -AllowClobber -DisableNameChecking
    Get-Mailbox | Get-MailboxStatistics | Select-Object DisplayName, IsArchiveMailbox, ItemCount, TotalItemSize | format-table
    Remove-PSSession $ExchangeOnlineSession
}

So that’s it. you can easily replace the command for something as disabling clutter, focused inbox, enable auditing, etc. The great thing is that by combining this with an Azure Function gives your the ability to automatically apply your preffered settings to all clients. Happy PowerShelling!

Recent Articles

The return of CyberDrain CTF

CyberDrain CTF returns! (and so do I!)

It’s been since september that I actually picked up a digital pen equivalent and wrote anything down. This was due to me being busy with life but also my side projects like CIPP. I’m trying to get back into the game of scripting and blogging about these scripts. There’s still so much to automate and so little time, right? ;)

Monitoring with PowerShell: Monitoring Acronis Backups

Intro

This is a monitoring script requested via Reddit, One of the reddit r/msp users wondered how they can monitor Acronis a little bit easier. I jumped on this because it happened pretty much at the same time that I was asked to speak at the Acronis CyberSummit so it kinda made sense to script this so I have something to demonstrate at my session there.

Monitoring with PowerShell: Monitoring VSS Snapshots

Intro

Wow! It’s been a while since I’ve blogged. I’ve just been so swamped with CIPP that I’ve just let the blogging go entirely. It’s a shame because I think out of all my hobbies it’s one I enjoy the most. It’s always nice helping others achieve their scripting target. I even got a couple of LinkedIn questions asking if I was done with blogging but I’m not. Writing always gives me some more piece of mind so I’ll try to catch up again. I know I’ve said that before but this time I’ll follow through. I’m sitting down right now and scheduling the release of 5 blogs in one go. No more whining and no more waiting.