But a Better Choice is Plain Old PowerShell

Announced in message center notification MC289245 (Oct 4, 2021, Microsoft 365 roadmap item 82708), the ability to invoke an Azure Cloud Shell session from the Teams admin center is now available in tenants. Apparently, the idea is to allow Teams administrators to perform tasks using cmdlets in the Microsoft Teams PowerShell module without having to install anything on a workstation. As discussed below, Cloud Shell can certainly run the Teams cmdlets, but the limitations imposed by the implementation are such that I don’t recommend using this approach unless you absolutely must.

Running the Cloud Shell

To start a new Cloud Shell session, click the shell icon in the browser bar. A pane opens beneath the admin center, connects to Azure, and creates a cloud drive. Behind the scenes, Azure creates a new PowerShell Core instance running on a Linux virtual machine on a Hyper-V host. In many respects, things haven’t moved on much since Vasil Michev investigated Cloud Shell three years ago.

Once connected to a shell session, you can run the Connect-MicrosoftTeams cmdlet to connect to Teams and load the cmdlets from the module. After loading the module, you can run its cmdlets (Figure 1).

Running PowerShell in a Cloud Shell session from the Teams admin center
Figure 1: Running PowerShell in a Cloud Shell session from the Teams admin center

Not Just the Teams Admin Center

The same functionality is available if you start a Cloud Shell session from the Microsoft 365 admin center. In other words, the news is not that you can start Cloud Shell from the Teams admin center. Rather, it’s that Microsoft has done the engineering to make the Teams cmdlets available to Cloud Shell, no matter from where you create a Cloud Shell session. I was able to run Teams cmdlets in Cloud Shell from the Microsoft 365 admin center, Azure portal, Teams admin center, and the Azure mobile app for iOS (I wouldn’t recommend the latter).

Azure Subscription Required

Before being able to connect to Cloud Shell from the Teams admin center, you must sign in with an account connected to an Azure subscription. The reason is that Cloud Shell sessions use Azure storage for the Linux virtual machine and to hold temporary data and store uploaded scripts. The subscription covers the use of Azure storage.

The need for an account to have a subscription isn’t an issue if you use the same account for both subscription management and Teams administration, which is very possible in a small tenant. In larger tenants, you must assign a suitable Azure role for a subscription to all accounts that you want to perform administrative actions involving that subscription.

Typically, I assign the Azure coordinator role to the accounts used for tenant administration as that’s enough to use resources (like storage) linked to the subscription. You might find that a Azure different role (such as Co-Administrator) suits your circumstances better. Figure 2 shows accounts holding the Contributor role for a subscription in the Azure admin center.

Azure subscription role assignments
Figure 2: Azure subscription role assignments

Connecting to Teams

After satisfying the Azure requirements, we can connect to Teams. Microsoft’s documentation for Teams PowerShell says that you can run the Connect-MicrosoftTeams cmdlet without any parameters. Here’s what happens:

PS /home/global> Connect-MicrosoftTeams
WARNING: Interactive authentication is not supported in this session. Using parameter '-Identity' instead.

Account   Environment Tenant                               TenantId
-------   ----------- ------                               --------
MSI@50342 AzureCloud  a562313f-14fc-43a2-9a7a-d2e27f4f3478 a562313f-14fc-43a2-9a7a-d2e27f4f3478

Note that the account used is MSI@50342 rather than the account signed into the Teams admin center. This is a form of pseudo account used by Cloud Shell when it inherits authentication from a console like the Teams admin center. However, the cmdlets which came from the Skype for Business Online Connector (retired in February 2021) that are now included in the Teams module use a different endpoint and authentication mechanism. The net effect is that if you attempt to run these cmdlets, you get a 404 error:

PS /home/global> Get-CsTeamsMeetingPolicy
Get-CsTeamsMeetingPolicy: The remote server returned an error: (404) Not Found.
PS /home/global> Get-CsTeamsMessagingPolicy
Get-CsTeamsMessagingPolicy: The remote server returned an error: (404) Not Found.

Everything works if you sign into Teams with credentials for a specific account unless it uses multi-factor authentication. The problem with multi-factor authentication is that Cloud Shell runs in a terminal window, so there’s no way to display the interactive signin dialog. You can use basic authentication to sign into an account, and once connected, both the new and old (Skype) cmdlets run perfectly. Tenants should secure all administrator accounts with multi-factor authentication, so I don’t recommend this approach.

PS /home/global> $O365Cred = Get-Credential

PowerShell credential request
Enter your credentials.
User: Admin@office365itpros.com
Password for user Admin@office365itpros.com: ************

PS /home/global> connect-microsoftteams -Credential $O365Cred

Account                             Environment Tenant                               TenantId
-------                             ----------- ------                               --------
Admin@office365itpros.com           AzureCloud  as62313f-14fc-43a2-9a7a-d2e27f4f3478 as62313f-14fc-43a2-9a7a-d2e27f4f3478

PS /home/global> Get-CsTeamsFeedbackPolicy

Identity                  : Global
UserInitiatedMode         : Enabled
ReceiveSurveysMode        : EnabledUserOverride
AllowScreenshotCollection : False
AllowEmailCollection      : False
AllowLogCollection        : False

The solution and recommended approach is to use device authentication to sign into Teams. This method generates a unique identifier to input into a web page.

PS /home/global> Connect-MicrosoftTeams -UseDeviceAuthentication

To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code C5BQJLUJ8 to authenticate.

After inputting the code, you’re asked which account to sign in with and then to confirm that you want to use a Microsoft Graph app called MS Teams PowerShell Cmdlets (Figure 3).

Confirming sign-in to the Teams PowerShell app
Figure 3: Confirming sign-in to the Teams PowerShell app

For more information about how Microsoft Graph apps use device authentication, read this blog by Lee Ford.

Running PowerShell in the Cloud Shell

After you’ve connected using a suitable account, you can run any of the cmdlets included in the latest version of the Microsoft Teams PowerShell module (2.6.0 at the time of writing). You can also upload scripts from a workstation to Azure to allow them to run in Cloud Shell. Figure 4 shows the result of running a simple script to report the display name of Teams users with Get-CsOnlineUser.

Uploading and running a script in Cloud Shell
Figure 4: Uploading and running a script in Cloud Shell

Scripts uploaded to run in Cloud Shell run without a hitch if you limit them to Teams cmdlets and basic PowerShell commands like ForEach-Object, Select-Object, and Where-Object. However, you can hit problems if you don’t spell out command names fully. For example, it’s common to use Sort instead of Sort-Object in commands like:

Get-Team | Sort DisplayName

Cloud Shell protests if you run the command:

Get-Team | Sort DisplayName
/usr/bin/sort: cannot read: displayname: No such file or directory

This kind of hitch underlines the point that Cloud Shell is not the same as running PowerShell as you might normally do. It’s a separate environment with its own quirks and requirements, and if you expect to use it in production, you need to write code with Cloud Shell in mind.

Apart from making sure that basic syntax is correct, things become more complicated when you need to use cmdlets from other modules. Teams relies upon multiple components drawn from across the Microsoft 365 ecosystem and the harsh fact of administrative life is that for administrators to get work done, they often need to use cmdlets from other modules such as SharePoint Online or the Microsoft Graph SDK for PowerShell.

For instance, I couldn’t make Azure AD work in Cloud Shell from either the Teams admin center or Microsoft 365 admin center. A note in GitHub explains that Cloud Shell has a special function to override the default Connect-AzureAD function to avoid the need for users to re-enter credentials. Perhaps this is where the problem lies.

On the upside, you can connect to Exchange Online PowerShell using Remote PowerShell (which means that none of the REST cmdlets like Get-ExoMailbox are available). This works for Cloud Shell when invoked from either the Microsoft 365 admin center (Figure 5) or Teams admin center.

Running Exchange cmdlets from a Cloud Shell session created from the Microsoft 365 admin center
Figure 5: Running Exchange cmdlets from a Cloud Shell session created from the Microsoft 365 admin center

Overall, the need to be certain that all the modules used by scripts or to perform interactive tasks is a limiting factor for Cloud Shell.

Graph Access

Cloud Shell supports Graph API calls using the Invoke-RestMethod or Invoke-WebRequest cmdlets, so this is also a viable method to access and process data where modules don’t work as expected. Figure 6 shows the use of the editor in Cloud Shell to modify a script which uses a Graph API call with the results of the script in the terminal window.

Editing a script in Cloud Shel
Figure 6: Editing a script in Cloud Shell

Too Many Limitations for Comfort

No doubt some will delight in Cloud Shell and use it in a very productive manner. However, Cloud Shell just doesn’t work for me. Messing around with modules in the hope that they will all work doesn’t seem like an effective way to work when I have a perfectly acceptable environment between standard PowerShell sessions and Visual Studio Code (for development). Everything works. All modules load. Commands run. Muscle memory overcomes any flaws that exist in how the setup functions. I doubt I will ever use Cloud Shell much, if at all. But that’s no reason for you not to try it out and make your own mind up.

About the Author

Tony Redmond

Tony Redmond has written thousands of articles about Microsoft technology since 1996. He is the lead author for the Office 365 for IT Pros eBook, the only book covering Office 365 that is updated monthly to keep pace with change in the cloud. Apart from contributing to Practical365.com, Tony also writes at Office365itpros.com to support the development of the eBook. He has been a Microsoft MVP since 2004.

Comments

  1. Garry Williams

    I waited with bated breath for this feature to come to M365 (particularly for Teams management), only to be dismayed by these limitations when it arrived. Excellent roundup Tony – many thanks.

  2. Mike

    To me Cloud Shell is one of those “nice to have” things. It’s handy to do something quick, or on a new machine or a colleague’s machine where you don’t have all the modules installed already.

    1. Avatar photo
      Tony Redmond

      True. But how long does it take to download and install a couple of modules? (Rhetorical question).

Leave a Reply