Powershell for Office 365 Delegated Admins

At Axiom IT, we manage close to a hundred Office 365 tenants. Occasionally, we need to run a set of Powershell commands against each tenant, for example, when conducting a licensing audit. As you can imagine, doing this individually on each tenant would be a very time consuming exercise. Luckily, PowerShell provides us with a way to manage our partner Office 365 tenancies using a single delegated administrator account.

In my work, there are typically two scenarios I need to deal with. The first scenario is Office 365 administration. This is the easier of the two, as all Office 365 cmdlets have a TenantId parameter we can use to specify which tenant we are working on.

The second, slightly more complex scenario, is managing Exchange Online. If you’ve worked with PowerShell and Exchange Online you will know that cmdlets must be imported to the local PowerShell session using Import-Session before any Exchange Online cmdlets can be run. An imported session only applies to a single tenant which means if we are working on multiple delegated admin tenancies we can’t use the TenantId parameter because Exchange Online cmdlets don’t know include it. Instead, we must re-import the cmdlets for each tenant.  Don’t worry if you’re feeling confused at this point, it’s all very simple.


Scenario 1 – Manage Office 365

Let’s start with the easy scenario – Office 365 Administration. For simplicity, lets assume we need a list of users from each of our tenants.

First, we need to connect to Office 365 using our delegated admin account. Next, we run the Get-MsolPartnerContract which returns a list of contracts (aka tenants). We then want to pipe the results to a For-Each cmdlet which loops us through each of the tenants allowing us to run our cmdlets. Take a look at the code below.

Scenario 2 – Manage Exchange Online

Now, for the slightly more complex scenario. As I mentioned earlier, to connect to Exchange Online we must import the cmdlets using Import-Session. This has to be done for each tenant and we must ensure that the session is removed before importing another if we want to avoid hitting the session limit.

As in our previous example, we’ll get started using the Get-MsolPartnerContract to return a list of tenants. We then loop the results using For-Each, only this time we must capture the tenant prefix and store it in a variable. Using the tenant prefix, we build a connection uri specific to the tenant using the DelegatedOrg parameter and pass it to the New-PSSession cmdlet to indicate which delegated tenant we are connecting to. Make sure the -AllowClobber parameter is included to ensure the cmdlets are overwritten on each import. Leaving this out will cause errors.

Now we’re connected to Exchange Online and can run any of the cmdlets we need to. Once we’re done the final step is to call Remove-PSSession which kills the current session, preventing us from hitting the 3 session limit. Code sample below.

So there you have it, a simple way to run powershell against all of your delegated admin tenants with a single script. A few examples where this comes in handy are:

  • Adding your own domain as a safe sender
  • Enabling archiving
  • Enabling litigation hold for all Exchange Plan 2 license holders
  • Checking for syndication licenses (aka Telstra in Australia)

Got a question? Tweet me on @tasgray


Manage Office 365 tenants with Windows PowerShell for Delegated Access Permissions (DAP) partners

Connect to Exchange Online tenants with remote Windows PowerShell for Delegated Access Permissions (DAP) partners