Modules Retiring, Cmdlets Changing, and Parameters Disappearing
The common saying, “If it works, don’t fix it,” isn’t strictly true in the world of cloud computing. For business processes depending on PowerShell scripts and modules, not proactively maintaining code can quickly become an issue because of the changes Microsoft makes to modules and cmdlets. That is, unless organizations have no problem with automated jobs breaking, usually creating an unpleasant surprise on the first day of the following month.
In this article, related to the presentation of the same name held at the wonderful The Experts Conference 2023, I discuss some of the challenges administrators might encounter with PowerShell scripts. Also, I provide some guidance and point out a few tools that can assist with rewriting or refactoring code, i.e., updating code while keeping its external functionality. With this, I mean the way the code needs to be called is preserved, such as keeping parameters identical.
Awareness
A complicating factor for maintenance is that some organizations are unaware of all the dependencies hidden in their infrastructure. For example, a significant number of third-party solutions still exist that rely on PowerShell scripts and modules. And those dependencies have end dates.
Here are a few statements overheard from customers:
- Partner X implemented a task that facilitates provisioning and licensing. I expect they keep us informed when we need to do something.
- I read PowerShell module X will be deprecated on date Y. Do we need to do something?
- We have a set of PowerShell scripts to support administrative tasks; where do we start?
Rather than wait until the final weeks before Microsoft deprecates a PowerShell module or lean back when Microsoft postpones deprecation, I cannot emphasize enough that you should adopt a proactive stance. Staying current applies not only to technology and, in this case, PowerShell modules but also to knowledge and skills. For example, the number of administrators knowledgeable about the Microsoft Graph PowerShell SDK is minimal. At the same time, it has been written on the wall for a few years that both the Microsoft Online Services and Azure AD modules are heading for the exit.
Motivation to Track Change
So, what creates the need for administrators to review existing scripts and tools? In my experience, apart from optimization and adjustments to accommodate changes in other business processes, two main drivers exist:
- Security. A recent example is the deprecation of Basic Authentication in Exchange Online. This step required administrators to review their scripts and tools to detect any usage of Basic Authentication and to update them by implementing Modern Authentication.
Another example is using certificate-based authentication over passphrases (secrets) and saved credentials or Microsoft 365 starting to require TLS 1.2 at some point. In some cases, changes like this lead to implementing changes on the client side. - Lifecycle. PowerShell modules are subject to a lifecycle. So, keeping an eye out for changes to those modules that might impact your organization, such as their lifecycle, is of the utmost importance. Current examples are the Microsoft Online Services and AzureAD modules, both due for final retirement on 30 March 2024.
In addition, modules might be incompatible with the underlying operating system or newer PowerShell versions. For example, the AzureAD and Microsoft Commerce modules are unsupported on PowerShell v7, creating a dilemma if you want to use PowerShell v7 features such as pipeline parallelization. Yes, you can import it in compatibility mode using Import-Module with the UseWindowsPowerShell switch, but this quickly leads to unexpected issues.
Module Housekeeping
To keep modules updated on the local client or server, several scripts available in the community might assist with this task. Connect-Office365Services contains helper functions for reporting and updating a fixed set of well-known Office365 workload-related PowerShell modules. After loading the script in your current session or through the PowerShell profile by dot-sourcing it ([PS]>. .\Connect-Office365Services.ps1), use Report-Office365Modules to report on modules that are candidates for updating, or use Update-Office365Modules to update them. Note that to check and install Preview modules, you need to specify the AllowPrerelease switch. Alternatively, use the script to assist with updating modules published by Tony Redmond: UpdateOffice365PowerShellModules.ps1.
When it comes to scripts that are running as part of an Azure Function or Azure Runbook, those also have dependencies. This means the same review process applies to that code as well. Just be aware the method of updating modules in Azure is slightly different, as described here.
Exchange Online
The Exchange Online Management module version 3 (v3) module is the current version for managing Exchange Online through PowerShell. The GA version of the v2 module is still around but not recommended. Not only does it depend on the client WinRM for PowerShell Remoting, which needs to have Basic Authentication enabled, but v2 also stopped receiving updates since September 2022. In the continuous change that happens in Microsoft 365, that sounds like a lifetime. A fun fact is that the v3 module originally started as a v2 Preview module, which previously blocked organizations with a “no preview in production” policy from using it.
A simplified sample of updating existing Exchange code, which can also be part of a script you used against Exchange on-premises, is shown below. Here, commands in scripts used to connect to Exchange need to be revised to use modern authentication, which involves specifying the tenant and application ID generated by the application registered in Entra ID for this purpose, together with the certificate or secret configured as potential authentication methods with the registered application. Also, Exchange-related commands such as Get-Mailbox might be replaced with the REST-based Get-EXOMailbox and some additional code changes to benefit from performance benefits over the REST-backed Get-Mailbox cmdlet.
Remote PowerShell | Exchange Online Management v3 |
New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<fqdn>/PowerShell/ -Authentication Kerberos -Credential $Credential | Import-PSSession Connect-ExchangeOnline –Credential .. | Connect-ExchangeOnline –Organization ..onmicrosoft.com –AppId .. –CertificateThumbprint .. |
Get-Mailbox | Get-EXOMailbox. |
Entra ID
The challenge with the modules used for managing Entra ID is like managing Exchange Online but with a twist. For Entra ID, two old modules are available: Microsoft Online Services (MSOnline) and AzureAD. The first has been around since the dawn of Office 365’s predecessor, Business Productivity Online Suite (BPOS). The latter saw daylight in 2016, being a PowerShell manageable PowerShell module (MSOnline used to require installation) and changes in the API in Office 365. Since AzureAD never offered full feature parity compared to MSOnline, both are still around. Many scripts, products, and documentation – even written by Microsoft – still refer to these modules. Even Microsoft Support still hands out instructions based on MSOnline and AzureAD modules. These scripts and instructions will become inaccurate and non-functioning soon.
The days of these modules are numbered, because the underlying library and API used to interface with Entra ID will be retired. The actual date for retirement is now set to March 30, 2024, after Microsoft postponed this a few times to grant vendors and organizations more time to make the necessary changes. The licensing API used by cmdlets in these modules to assign Office 365 licenses already retired on September 30, 2023.
Microsoft Platform Migration Planning and Consolidation
Simplify migration planning, overcome migration challenges, and finish projects faster while minimizing the costs, risks and disruptions to users.
Embrace the Graph
Instead of MSOnline and AzureAD, Microsoft is nudging organizations and vendors to embrace the Microsoft Graph PowerShell SDK, a set of PowerShell modules that offers cmdlets to talk to Microsoft Graph. But where the MSOnline and AzureAD modules offered ‘blanket’ permissions in the Entra ID space, Graph requires more granular specification permissions. Administrators might need to learn about concepts they might be unfamiliar with, such as permission scopes or when to use advanced queries. Also, there is the separation of endpoints for Graph when talking to the regular endpoint (v1) for productivity usage or the beta one, which offers the latest developments but is not for production usage.
Similar to updating code for Exchange Online with modern authentication, the same principle applies to MSOnline and AzureAD scripts and tools. Here, statements need to be updated to the Microsoft Graph PowerShell SDK, which communicates with Microsoft Graph instead of the to-be-deprecated Azure Active Directory Authentication Library (ADAL) and Azure AD Graph API used by both modules.
To complicate things a bit, The Microsoft Graph PowerShell SDK recently split its module in two (V1.0 or production and beta), and both endpoints got their own module. This created a minor hurdle for administrators already using the PowerShell Graph SDK, as they had to review their code. My point is, it also shows that when you finally have moved to using the PowerShell Graph SDK, you will still face the same challenges once in a while.
Guidance and Tools
Reading the above, one might think this is a matter of a simple find-replace operation. This could be true for smaller repositories, but a more methodological approach would be preferred when dealing with an extensive set of scripts and tools.
An approach for reviewing Exchange-related code is using a script I originally developed to check scripts for usage of Basic Authentication, Analyze-ExoScript. It compares the commands contained in the Exchange Online Management module against one or more scripts. For this, it leverages something called the Abstract Syntax Tree to interpret code, allowing you to do intelligent things like outputting Exchange-only commands, showing where Connect-ExchangeOnline is used in combination with the Credentials parameter, or indicating where REST-based commands could be considered for performance reasons. I wrote about this process here.
Microsoft only provides global guidance for converting scripts based on MSOnline and AzureAD to PowerShell Graph SDK. Luckily, the community did not sit still. A Microsoft employee, Merill Fernando, a principal PM for Entra, developed an online Graph PowerShell Conversion Analyzer. This website can be used to assist in converting MSOnline and AzureAD commands to their Microsoft Graph PowerShell SDK counterparts by copying and pasting code. As a bonus, the analysis contains the scope permissions required to perform the related Microsoft Graph PowerShell SDK cmdlet.
Where the conversion analyzer is suitable for one-offs due to its interactive nature, the PowerShell Azure Migration Advisor, or just PSAzureMigrationAdvisor, can analyze a set of scripts, similar to the Exchange analyze script mentioned earlier. The PSAzureMigrationAdvisor is a PowerShell module that must be installed on a workstation. Then, you can have it analyze scripts, for example,
Get-ChildItem C:\ADScripts | Read-AzScriptFile. This command outputs the scripts processed, which line contains what MSOnline or AzureAD command and what its counterpart is (figure 1). This provides an indication of how big the ‘problem’ is, but also can function as a checklist that can be helpful when updating larger repositories with a team of people.
The Promise of AI
Can ChatGPT or Copilot for GitHub not play any role in this conversion exercise? The answer is “it depends.” First, there is a yes because, like the analysis tools, Copilot can help you quickly analyze scripts and create an initial draft of the conversion. Then there is a no because the output AI produces still needs code review and testing by an intelligent human and might require some debugging. This is because sometimes AI makes mistakes. An example of this is a simple equation $var eq ‘string,’ which was brought up by ChatGPT when asked to produce PowerShell code, but since “eq” is not a PowerShell operator (-eq is), the code will not work. However, the development of AI does not stand still, so having periodic looks at these AI solutions is recommended. And, of course, the effect of learning a new skill is absent when you let AI perform this task.
Conclusion
You might think that maintaining scripts and processes utilizing PowerShell is a lot of work. And truth be told, it can be. Like “real developers,” administrators should plan and perform code review cycles to accommodate changes in modules and interfaces their code depends on. Having a good overview of scripts and tools and their dependencies and connectivity might accelerate the job of code reviews and help spot the consequences of external changes.
Administrators, please take a proactive stance regarding your code and anticipate future changes; update scripts and tools when you can, not when you must, and time and resources become scarce.
Extremely valuable. Thank you, Michel. The time has come to try persuading Infrastructure and Security colleagues to grant granular permissions allowing Graph scripts to run.