Manage Multiple Office 365 Tenants from PowerShell

o365-logo1Yep, another PowerShell themed post.

This is something I cobbled together a few years back, never thought it was worth sharing, but sitting here this evening with nothing much to do decided to write it up.

At it’s core it is not much more than a method of automating entering credentials to your various Office 365 ‘Clients’. I say ‘’clients” because I do not know if that is the correct terminology. If you are the Partner of Record or even if you are supporting more than one tenant on 365 this may be useful to you.

First, in PowerShell ISE we can define some functions.

function connect
{
Import-Module MSOnline
$pwd = Read-Host -AsSecureString -Prompt "Enter Password for Client $clientName"
$cred = New-Object System.Management.Automation.PSCredential($username,$pwd)
Connect-MSolService -credential $cred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri
https://ps.outlook.com/powershell/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Write-Output "Connected to Office 365 & Exchange"
}

function disconnect
{
Remove-Module MSOnline
Get-PSSession | Remove-PSSession
}

function connect
These are pretty straight forward, with Connect, connecting us to 365 and Disconnect removing all of our current sessions.

Next we can set our credentials for our various tenants.

# Client A
$clientAName = "Company A"
$clientAUserName = "userAAdmin@companyA.onMicrosoft.com"

# Client B

$clientBName = "Company B"
$clientBUserName = "
userBAdmin@companyB.onMicrosoft.com"

credentials

Again, reasonably straight forward, we have defined the usernames for our two tenants.

Next we have a small menu to build.

function menu
{
Write-Host "Office 365 Management Connect to PowerShell"
Write-Host ""
Write-Host "Enter Client ID.."
Write-Host ""
Write-Host "1. Client A"
Write-Host "2. Client B"
Write-Host "D. Disconnect"
Write-Host "0. Quit"
$client = Read-Host
if (($client) -eq "1")
{
$clientName = $clientAName
$userName = $clientAUserName
Connect
}
if (($client) -eq "2")
{
$clientName = $clientBName
$userName = $clientBUserName
Connect
}
if (($client) -eq "d")
{
Disconnect
}
}

Menu

menu The menu will give us the option of choosing Client A  (1) or Client B (2) it then prompts us for the password for that account and connects us to Office 365.

Of course you can keep adding more clients and expand the menu to include the additional Clients.

Save it as something memorable, like 365.ps1 and fire it up.

365 poSh

Not ground breaking by any means, but something i find useful.

Following some useful comments below from Mark Watson, i created this today for using Delegated Admin Credentials.

Import-Module MSOnline
Write-Output "Enter Office 365 Credentials.."
$cred = Get-Credential
Connect-MSolService -credential $cred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Write-Output "Connected to Office 365 & Exchange"
$clients = Get-MSOLPartnerContract
$clientObj = @()
$clientNum = 0
foreach ( $client in $clients )
{
$clO = New-Object System.Object
$clO | Add-Member -Type NoteProperty -Name "Number" -Value $clientNum
$clO | Add-Member -Type NoteProperty -Name "ClientName" -Value $client.Name
$clO | Add-Member -Type NoteProperty -Name "TenantID" -Value $client.TenantID
$clO | Add-Member -Type NoteProperty -Name "DomainName" -Value $client.DefaultDomainName
$clientObj += $clO
$clientNum++
}
$clientObj | ft -AutoSize
$clientChoice = Read-Host -Prompt "Select Your Client"
$clientTenant = $clientObj[$clientChoice]
$TenantId = $clientTenant.TenantID.Guid
$Global:TenantID = $TenantId.Guid
$Domain = Get-MsolDomain -TenantId $TenantId | Where {$_.IsInitial -eq $true}
$ConnectionURL = “https://ps.outlook.com/powershell-liveid?DelegatedOrg=” + $clientTenant.DomainName
$ConnectionURL
$s = New-PSSession -ConnectionUri $ConnectionURL -Credential $Cred -Authentication Basic -ConfigurationName Microsoft.Exchange -AllowRedirection
Import-PSSession $s -AllowClobber

DelegatedAdmin

Once the script finished the $tenantID variable is loaded with your chosen clients TenantID Guid.

About Robert Pearman
Robert Pearman is a UK based Small Business Server enthusiast. He has been working within the SMB IT Industry for what feels like forever. Robert likes Piña colada and taking walks in the rain, on occasion he also enjoys writing about Small Business Technology like Windows Server Essentials or more recently writing PowerShell Scripts. If you're in trouble, and you can find him, maybe you can ask him a question.

14 Responses to Manage Multiple Office 365 Tenants from PowerShell

  1. David says:

    Nice script. It will be very handy. Thank you.

    I do get a warning when running the script. Its because userBAdmin@companyB.onMicrosoft.com needs quotation marks:

    $clientBUserName = “userBAdmin@companyB.onMicrosoft.com”

  2. Mark Watson says:

    Nice share, we did something similar but opted to use our delegated admin rights coupled with the TenantID, we supply the Org Name and build the connection from there. Doing it this way means you don’t need to lookup/remember the clients admin credentials, you just use yours.

    $TenantId=(Get-MsolPartnerContract | ?{$_.Name -eq $OrgName}).TenantId
    $Domain = Get-MsolDomain -TenantId $TenantId | Where {$_.IsInitial -eq $true}
    $ConnectionURL = “https://outlook.Office365.com/powershell-liveid?DelegatedOrg=” + $Domain.Name
    $s = New-PSSession -ConnectionUri $ConnectionURL -Credential $Credential -Authentication Basic -ConfigurationName Microsoft.Exchange -AllowRedirection
    $Output = Import-PSSession $s -AllowClobber

    • $clients = Get-MSOLPartnerContract
      $clientObj = @()
      $clientNum = 0
      foreach ( $client in $clients )
      {
      $clO = New-Object System.Object
      $clO | Add-Member -Type NoteProperty -Name "Number" -Value $clientNum
      $clO | Add-Member -Type NoteProperty -Name "ClientName" -Value $client.Name
      $clO | Add-Member -Type NoteProperty -Name "TenantID" -Value $client.TenantID
      $clO | Add-Member -Type NoteProperty -Name "DomainName" -Value $client.DefaultDomainName
      $clientObj += $clO
      $clientNum++
      }
      $clientObj
      $clientChoice = Read-Host -Prompt "Select Your Client"
      $clientObj[$clientChoice]

      How about this?

    • Matthew T. Montgomery says:

      I tried this modification but the script just continues to run with no output.

    • Matthew T. Montgomery says:

      I am trying to use this mod so we can continue to use our credentials but it doesn’t seem to work. when I connect using my credentials and perform a get-msoluser or get-mailbox, both cmdlets report my own domain for my MSP credentials. Never the remove client even though I select an option. I run the $client variable and like I mentioned in another post, it seems like it automatically defaults to the very last entry on my list of 39 entries. I would really love to manag our tenants properly with PowerShell but so far none of these work and I have no idea why.

      • Is each set of credentials defined as a unique variable?

      • Matthew T. Montgomery says:

        Robert,

        Do you mean am I using the very first script where he built a menu and has client A with this admin logon and client B with this admin logon? If so, no… Although that is the only one that is working as I would like it to. I was really hoping to take advantage of the delegated admin rights but the connection context is different as I have mentioned in a different reply below.

  3. Matthew T. Montgomery says:

    Hello, I have been using your script to manage our tenants. Something I have noticed is when it provides us our list of tenants. I enter a number, say “30”. It uses my delegated credentials and connects to that tenant. However, when i try to run commands for that tenant like get-msoluser, it is listing my organizations people and not the tenant. If I do get-mailbox, it is the tenant, however the wrong tenant. It automatically for some reason defaults to the very last tenant on the list. Something is wrong with this script. Has nobody else experienced this?

  4. Matthew T. Montgomery says:

    Please someone get back to me. I am having issues with your scripts and we are an MSP with many clients and these would be so helpful if they worked like we thought they would. If I use the script at the very top of the page where you specify the respective admin account for each tenant (which would take forever btw), it works perfectly. If I do get-msoluser or get-mailbox, both report users in the tenant I want to work in. The dynamic scripts below don’t seem to do that where I use my partner credentials. It seems to connect to Office 365 with my MSP domain but connects to Exchange as the tenant, however it is the wrong tenant, it seems to pick the very last one in the msolpartercontract list. I am very close but something just isn’t quite right. I really hope someone can guide me in the right direction here. Thanks a million.

Leave a reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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

%d bloggers like this: