Time for an Update

A Microsoft 365 Tenant-to-Tenant migration can be a daunting task. As more apps and features become available, the list of things to keep track of when planning a migration grows. I strongly believe that the key to any project – particularly migration projects – lies in strong preparation and planning.

Some time ago, I published a PowerShell script to help admins prepare for Microsoft 365 Tenant to Tenant Migrations. The script gathers key data from a Microsoft 365 tenant to generate an Excel report containing key data for consideration during the migration planning process. The feedback on this script was very positive and many people had their own suggestions of items that should be included.

The feedback provided through GitHub or within the article comments has highlighted some areas to include in the assessment script. Taking this on board, I have now published Version 2 of the Tenant-to-Tenant Migration Assessment on GitHub.

What’s New?

While the fundamentals of the script haven’t changed, there are some key improvements and additions to be aware of:

  • A new Power BI template that can be used to summarize core areas.
  • The entire script has been updated to use the Microsoft Graph PowerShell SDK, allowing for better performance and scalability.
  • Addition of the following optional areas in the output:
    • SharePoint Document Libraries
    • SharePoint Lists
    • Planner Plans
  • Addition of the user’s directory sync status in the output.

Prepare the Environment

Preparing and running the script is like the process for Version 1 of the Tenant Assessment. The files for the assessment are available from GitHub here. To prepare to run the script, download all files to the folder C:\TenantAssessment on a local machine. The following files are used:

  • Perform-TenantAssessment.ps1 – This PowerShell script runs the assessment and generates the output file.
  • Prepare-TenantAssessment.ps1 – This PowerShell script creates the app registration in the Entra tenant and generates a self-signed certificate for authentication.
  • TenantAssessment-Report.pbit – This Power BI template imports data from the output file and visualizes key data.
  • TenantAssessment-Template.xlsx – This is the Excel template used to create the output file.

To prepare the tenant and generate the authentication certificate, run the script Prepare-TenantAssessment.ps1, as shown in Figure 1.

Tenant-to-Tenant Migration Assessment
Figure 1: Running the preparation script

The script performs the following tasks to prepare the environment for the assessment:

  • Authenticates to the Microsoft Graph using the PowerShell SDK (prompting the user for credentials).
  • Creates a new app registration with the permissions shown in Figure 2 below.
  • Adds the app service principal to the “Global Reader” and “Exchange Administrator” roles. If the roles are not activated yet, the script will activate them.
  • Generate a new self-signed certificate and store it in the user’s certificate store on the workstation
  • Upload the certificate to the app registration for use when authenticating.
  • Outputs the Tenant ID, Client ID, and Certificate Thumbprint to the screen.
  • Opens the application consent page in a browser to allow consent for the application permissions (as per Figure 2). Alternatively, the permissions can be consented from the app registration page of the Entra admin center. This consent must be granted by a Global Administrator account.
Tenant-to-Tenant Migration Assessment
Figure 2: Granting consent for the required permissions

It’s important to understand that this app requires a high level of permissions, a level that attackers would love to gain to enumerate data in the tenant. The app registration should be treated as a highly privileged account and protected with Conditional Access and/or deleted after you have run the assessment. The high level of permissions is required to gather the data butit it shouldn’t be left in place and unprotected.

Running the Assessment Script

As with the previous version of the script, version 2 requires the “TenantID”, “ClientID” and “CertificateThumbprint” parameters. These values are displayed as the output of the preparation script shown above in Figure 1. There are also several optional parameters which will gather additional information:

  • IncludeGroupMembership – This parameter includes a report of the members of each group.
  • IncludeMailboxPermissions – This parameter includes a report of all mailbox permission assignments.
  • IncludeDocumentLibraries – This parameter includes a report of all Document Libraries in the SharePoint environment.*
  • IncludeLists – This parameter includes a report of all lists in the SharePoint environment (Excluding Document Libraries).
  • IncludePlans – This parameter includes a report of all Planner plans in the tenant.

*Note, for non-English tenants, the filters in the code need to be updated to reflect the name of the “Documents” library in your tenant

The script uses only these PowerShell modules:

  • Microsoft.Graph to perform the data gathering
  • ImportExcel to create the output file
  • ExchangeOnlineManagement to connect to Exchange Online to get information that is not exposed via the Graph API

The example command shown in Figure 3 runs the script with all optional parameters enabled and the Client ID, Tenant ID, and Certificate Thumbprint passed as variables as shown in Figure 3:

.\Perform-TenantAssessment.ps1 -clientId $clientid -tenantId $tenantID -certificateThumbprint $Thumbprint -IncludePlans -IncludeGroupMembership -IncludeMailboxPermissions -IncludeDocumentLibraries -IncludeLists
Tenant-to-Tenant Migration Assessment
Figure 3: Running the assessment script will write progress to the screen

Note: Adding all optional parameters can increase the time required to run the script significantly, particularly in larger environments. Progress is displayed throughout to allow the administrator to know what’s happening.

When the script finishes, it generates a report in the folder C:\TenantAssessment named TenantAssessment.xlsx. Many of the tabs in the report are similar to the output from Version 1 of the assessment, so I won’t repeat them here. The new tabs generated by using the optional parameters are:

  • Mailbox Permissions: This tab lists each assigned mailbox permission in Exchange Online.
  • Group Membership: This tab lists every group membership present in Microsoft Entra ID.
  • Document Libraries: This tab lists every Document Library present in SharePoint Online.
  • Lists: This tab lists every SharePoint list (excluding Document Libraries) present in SharePoint Online.
  • Planner Plans: This tab lists every Planner plan present in Microsoft 365 Groups.

Using the Power BI Template

With the output file generated, opening the Power BI Template “TenantAssessment-Report.pbit” will connect to the output file (located in C:\TenantAssessment) and import the data. After a few seconds, the report will load and present four pages: “User Overview”, “Exchange Overview”, “SharePoint Overview” and “Teams Overview”.

User Overview Page

The User Overview page in the Power BI report displays high-level statistics about the user accounts in the tenant. From this page, it’s easy to see data sizes for each component of a user account and see how they relate to each other as seen in Figure 4.

Microsoft 365 Tenant-to-Tenant Migration Assessment Version 2
Figure 4: The User Overview report page

Each report page also contains two buttons on the left to filter results to only items which have the “migrate” column in the report set to “TRUE”. By default, all items have migrate set to “TRUE” but as you work through the migration plan, any objects not being migrated can be set to “FALSE” and they will be excluded from this view by clicking the “Show Migrating” button.

Exchange Overview

The Exchange Overview page (Figure 5) shows the details of the Exchange-related objects in the assessment such as counts and sizes of each mailbox type. The sliders at the top of the page allow for quickly identifying mailboxes of each type by size, for example, locating particularly large mailboxes that may take more time to synchronize data.

Microsoft 365 Tenant-to-Tenant Migration Assessment Version 2
Figure 5: The Exchange Overview report page

SharePoint Overview

The SharePoint Overview page (Figure 6) shows the data sizes within SharePoint (not including SharePoint sites linked to Teams), and the associated site types and activity. It also provides details on the 10 largest OneDrive and SharePoint sites and the most active sites. This information is useful when targeting priority areas for the business during a migration.

Microsoft 365 Tenant-to-Tenant Migration Assessment Version 2
Figure 6: The SharePoint Overview report page

Teams Overview

Finally, the Teams Overview page (Figure 7) shows the details of Teams data sizes, counts of private and shared channels, and lists the largest Teams, Teams with most private channels and Teams with most Shared channels. Private and Shared channels require extra consideration during a migration, so this information supports planning for migration and estimating timeframes of data transfers.

Microsoft 365 Tenant-to-Tenant Migration Assessment Version 2
Figure 7: Teams Overview report page

Summary

When I created the initial tenant assessment script, I included what was (at the time) the most important aspects of a tenant-to-tenant migration for Microsoft 365. Extending the assessment out to these additional areas will help when it comes to planning migrations and the Power BI template allows for a summarized view of the key areas that impact migration planning.

One consistent piece of feedback I received in the previous version was that this information isn’t just useful in a migration context. Sometimes admins just need to get a view of what is in their tenant and the information provided can absolutely help in that scenario too.

As with the previous version, the feedback from the community is key to determining what version 3 might look like. I encourage people to share what they have found useful and maybe even add and share some features of their own through GitHub. Having a solid assessment is the first step to success in a migration project, and hopefully, this tool will help people to prepare and minimize late nights and weekends trying to get everything working in the new environment.

About the Author

Sean McAvinue

Sean McAvinue is a Microsoft MVP in Office Development and has been working with Microsoft Technologies for more than 10 years. As Modern Workplace Practice Lead at Ergo Group, he helps customers with planning, deploying and maximizing the many benefits of Microsoft 365 with a focus on security and automation. With a passion for creative problem solving, he enjoys developing solutions for business requirements by leveraging new technologies or by extending the built-in functionality with automation. Blogs frequently at https://seanmcavinue.net and loves sharing and collaborating with the community. To reach out to Sean, you can find him on Twitter at @sean_mcavinue

Comments

  1. Bryan Hughes

    The Real Person!

    Author Bryan Hughes acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    The Real Person!

    Author Bryan Hughes acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    This constantly gets stuck on Task 9 downloading App info.

  2. Jitendra Bhagwat

    The Real Person!

    Author Jitendra Bhagwat acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    The Real Person!

    Author Jitendra Bhagwat acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    Hi,
    Trying to run .\Prepare-TenanatAssessment.ps1 and getting following error; any pointers why it must be happening?
    Thank you!
    *************************************
    PS C:\TenantAssessment> .\Prepare-TenantAssessment.ps1
    Provisioning Entra App Registration for Tenant Migration Assessment Tool
    get-mgcontext : The term ‘get-mgcontext’ is not recognized as the name of a cmdlet, function, script file, or operable program.
    Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:\TenantAssessment\Prepare-TenantAssessment.ps1:73 char:12
    + $Context = get-mgcontext
    + ~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (get-mgcontext:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Error connecting to Microsoft Graph:
    The term ‘Connect-MgGraph’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling o
    f the name, or if a path was included, verify that the path is correct and try again.
    Try again…
    Error connecting to Microsoft Graph:
    The term ‘Connect-MgGraph’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling o
    f the name, or if a path was included, verify that the path is correct and try again.
    Try again…
    Error connecting to Microsoft Graph:
    The term ‘Connect-MgGraph’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling o
    f the name, or if a path was included, verify that the path is correct and try again.
    Try again…
    Error connecting to Microsoft Graph:
    The term ‘Connect-MgGraph’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling o
    f the name, or if a path was included, verify that the path is correct and try again.
    Try again…
    *****************************

    1. Avatar photo
      Tony Redmond

      If Connect-MgGraph isn’t recognized as a cmdlet, you haven’t installed the Microsoft Graph PowerShell SDK on your PC.

  3. Ryan Perry

    The Real Person!

    Author Ryan Perry acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    The Real Person!

    Author Ryan Perry acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    Hi Sean,

    Greate content, and solid code repo. Noted there is very little in here related to Power Platform. MSFT Docs indicate the presence of a TenantToTenant-MigratePowerAppEnvironment cmdlet, but docs are sparse. Can you shed any light on it?

  4. Thierry

    The Real Person!

    Author Thierry acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    The Real Person!

    Author Thierry acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    Hi Sean,

    I tried your scripts on a large tenant (10k users, 7k Teams, …) I’ve got some errors during the execution :

    | An error occurred while sending the request.
    InvalidOperation: C:\temp\temp\Perform-TenantAssessment.ps1:231
    Line |
    231 | $teamgroup | Add-Member -MemberType NoteProperty -Name “URL” -Val …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | Cannot index into a null array.
    | Invalid request Status: 400 (BadRequest) ErrorCode: invalidRequest Date: 2024-08-09T09:33:03 Headers: Cache-Control : max-age=0, private Vary : Accept-Encoding
    | Strict-Transport-Security : max-age=31536000 request-id : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxclient-request-id : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    | x-ms-ags-diagnostic : {“ServerInfo”:{“DataCenter”:”Italy North”,”Slice”:”E”,”Ring”:”3″,”ScaleUnit”:”000″,”RoleInstance”:”MI1PEPF0000031C”}} Date : Fri, 09 Aug 2024
    | 09:33:02 GMT
    InvalidOperation: C:\temp\temp\Perform-TenantAssessment.ps1:231
    Line |
    231 | $teamgroup | Add-Member -MemberType NoteProperty -Name “URL” -Val …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | Cannot index into a null array.
    InvalidOperation: C:\temp\temp\Perform-TenantAssessment.ps1:885
    Line |
    885 | $user.OneDriveSizeGB = (((($OneDrive | ? { $_.’Owner Prin …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | Method invocation failed because [System.Object[]] does not contain a method named ‘op_Division’.

    But after 7 hours, the script has finished.

    When I tried to open the Excel file, I’ve got an error: “We found a problem with some content in TenantAssessment.xlsx … After the repair, I’ve been able to consult the results. But when I tried to open the PowerBi Report, I’ve got a new error concerning the DisplayName in Teams table because it contains duplicate values.

    Thanks for your great job, and thanks for your help.
    Thierry

  5. Mark R

    The Real Person!

    Author Mark R acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    The Real Person!

    Author Mark R acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    I’ve been trying to run against my MS CDX demo tenants.

    I’ve found the powerbi report will not load unless I create a shared mailbox and a resource – the table lacks headers when there is no data, and this causes an error. I suspect this would rarely be a problem with a real tenant.

    More importantly, I am not getting any data from the fields below, even though it exists.

    targetobjectID
    targetUPN
    TargetMail
    MailboxItemCount
    MailboxSizeGB
    OneDriveSizeGB
    OneDriveFileCount

    Admin is assigned to the App.

    PowerShell 7.7.4
    Version Name
    2.0.2.182 AzureAD
    3.5.1 ExchangeOnlineManagement
    2.21.1 Microsoft.Graph
    7.8.9 ImportExcel

    sure how to check MSAL.PS version

    1. Sean Mcavinue

      Hey Mark,
      I expect the data not showing is because names are concealed in reports, could you check you are allowing names to be shown in reports in the tenant? On the shared mailboxes, that is a bug which I will resolve soon. Without shared mailboxes that page does show up blank.

      1. Mark

        The Real Person!

        Author Mark acts as a real person and verified as not a bot.
        Passed all tests against spam bots. Anti-Spam by CleanTalk.

        The Real Person!

        Author Mark acts as a real person and verified as not a bot.
        Passed all tests against spam bots. Anti-Spam by CleanTalk.

        Thanks, that did the trick!

  6. Tristan

    The Real Person!

    Author Tristan acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    The Real Person!

    Author Tristan acts as a real person and verified as not a bot.
    Passed all tests against spam bots. Anti-Spam by CleanTalk.

    Scripts works well, great work and thanks Sean! Note that it only worked when i ran it with PS V7 (Exchange Online connection error when tested on PS version 5). Also the Assessment outputs to C:\TenantAssessment rather than C:\Temp\TenantAssessment.

    1. Mark

      The Real Person!

      Author Mark acts as a real person and verified as not a bot.
      Passed all tests against spam bots. Anti-Spam by CleanTalk.

      The Real Person!

      Author Mark acts as a real person and verified as not a bot.
      Passed all tests against spam bots. Anti-Spam by CleanTalk.

      Thanks, that did the trick!

  7. PS

    Getting below when running assessment in PSv5. Tried running the Connect-ExchangeOnline and get below –

    Error connecting to Exchange Online…Exiting…
    Press Enter to continue…:
    PS C:\temp\Assessment> Connect-ExchangeOnline -Certificate $Certificate -AppID $clientid -Organization ($orgdetails.verifieddomains | ? { $_.isinitial -eq “true” }).name -ShowBanner:$false
    Function Get-DeviceComplianceSummaryReport cannot be created because function capacity 4096 has been exceeded for this scope.
    At C:\Program Files\WindowsPowerShell\Modules\ExchangeOnlineManagement\3.5.1\netFramework\ExchangeOnlineManagement.psm1:766 char:21
    + throw $_.Exception;
    + ~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (Get-DeviceComplianceSummaryReport:String) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : FunctionOverflow

    Found that using PSv7 works to avoid the above error but now getting below –

    InvalidOperation: C:\TEMP\Assessment\Perform-TenantAssessment.ps1:885
    Line |
    885 | $user.OneDriveSizeGB = (((($OneDrive | ? { $_.’Owner Prin …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | Method invocation failed because [System.Object[]] does not contain a method named ‘op_Division’.
    PS C:\TEMP\Assessment>

    1. Sean McAvinue

      H,
      What version of the Exchange Online Management module are you using?

      1. PS

        Hi Sean
        Thanks for the followup.

        3.5.1 ExchangeOnlineManagement PSGallery

        When using PS v7.4.2, I am not getting the “ExchangeOnline exiting” error which I was getting with PS v5.1, but now the script stops at below error as mentioned in my last post.

        Line |
        885 | $user.OneDriveSizeGB = (((($OneDrive | ? { $_.’Owner Prin …
        | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        | Method invocation failed because [System.Object[]] does not contain a method named ‘op_Division’.

        Regards

        1. Sean McAvinue

          Ok, I have seen this before when a null value is returned for a user in the OneDrive report exported. I will add logic to suppress this error but the export should still work fine?

  8. PS

    Hi
    Script fails with “Error connecting to Exchange Online…Exiting…” The same issue also happens with older v1 script.

  9. Justin

    Getting Error connecting to Exchange Online…Exiting… even though I have the most up to date version of Exchange Online Management PowerShell module (version 3.5.1)

    1. Sean Mcavinue

      The best thing to do in this case is to open the code and try to connect using the same logic interactivity to see where it’s failing.

  10. Jakke

    the script is running great, but the SharePoint Site URL is staying empty for me

  11. Lance Lingerfelt

    Awesome Script to assess migration items. I have done many T2T migration projects and this helps simplify the assessment process immensely! Thanks for the script!

    1. Sean Mcavinue

      You’re welcome! Glad it’s helped!

  12. Kryste O

    It’s really nice to have the PowerBI reporting template. Appreciate it!

  13. Amol G

    Can i know that Tenant ID and Client ID requires of Source or Destination environment?

  14. Mathieu Ait Azzouzene

    This is a really great tool! Thx a lot for your commitment to the community!
    The only caveat is, and this is just a personal opinio, you used the powershell SDK instead of the invoke powershell cmd let. I got fed up with those modules becoming deprecated every few years, and lots of customers don’t want to install such things (for bad reasons I admit). Rest API is so easy for people like us, and way more reliable, that the PS SDK is just an obstacle to scalability.

    1. Avatar photo
      Tony Redmond

      I guess the issue is which development environment should someone use: SDK or Graph API? My response is that professional developers should use the Graph APIs and tenant administrators should use the SDK (because it’s easier). I don’t think the SDK is an obstacle to scalability. There are some features (like JSON batching) that can’t be done with the SDK cmdlets, but generally, the cmdlets are as fast as Graph API requests because they are Graph API requests…

    2. Sean McAvinue

      The original version used direct Graph API calls without the SDK but I feel that the SDK is a much easier way for tenant admins of all skill levels to understand the code and adapt / learn from it. The audience for this tool is not limited to people with knowledge of the API (while I recommend all tenant admins familiarise themselves with it).

  15. Joe

    I’m getting the same error. I’ve both updated and reinstalled the ExchangeOnlineManagement module version 3.4.0, still will not connect to Exchange Online.

  16. Benoit

    It seems to be an issue with the connection to exchange online
    Error connecting to Exchange online …. Exiting ….

    1. Sean McAvinue

      The most likely issue is that you don’t have the latest version of the Exchange Online Management PowerShell module.

  17. Justin

    Hi there

    I’m busy investigate this for my company and something else to possibly add to the list is the Devops portal (Dev.azure.com), as I believe this is tied to the tenant.

Leave a Reply