In the first part of this series, we cover some generalized PowerShell tips. In this article, we focus on how to use PowerShell to manage Microsoft 365. In addition, we consider how to use cloud services to manage PowerShell code, testing, security controls, and more.  The purpose of this article is to help those who write PowerShell scripts to see the bigger picture, beyond coding and into managing future use of their code.

Passwords, Secrets, and Certificates

Microsoft is steadily making changes to its Authentication mechanism to switch from insecure Basic Authentication (Exchange Online) to Modern Authentication (OAuth 2.0).  Administrators need to switch to more secure PowerShell connections for scripts, such as using certificates or using the secret PowerShell module for local credential storage, or using Azure Automation credentials, which are stored in a system-managed Azure Key Vault. Make sure to use either certificate-based authentication or Azure Automation Credentials, as these are more secure than locally stored passwords or clear text passwords stored in a script file.

Using Azure Automation store accounts requires the installation of the Az.Automation module, connecting to Azure and four lines of code:

install-module az.automation


$AutomationUserName = ''

$Password = ConvertTo-SecureString (Read-host 'Enter password to encrypt') -asplaintext -Force

$Credentials = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $AutomationUserName, $Password

New-AzureAutomationCredential -AutomationAccountName "AutomationAccount" -Name "AutomationCredentials" -Value $Credentials

For certificate-based authentication, most, but not all (SharePoint Online), Microsoft 365 PowerShell modules have an option to use certificates for authentication, Exchange Online Management v3, Security and Compliance Center, Microsoft Teams, SharePoint’s PNP module, and Microsoft Graph PowerShell SDK.  Certificate-based authentication is not hard to set up, but it does require a registered Azure App, the appropriate API permissions, and a local certificate that is referenced by the script and attached to the Azure App.  Once the certificate is in place, connecting to a valid workload can then happen.

Tip: If a script is run on a local server, ensure its security by locking down who has access to the file with file permissions, and this should be done irrespective of the authentication method.

Secrets Module resource link.

Certificate-based authentication resources for Exchange, Microsoft Graph, and SharePoint PNP.

Azure Automation credential management resource link.

Azure Automation

Start with this: stop using on-premises jump boxes or admin workstations.  Move your workloads to the cloud as Microsoft’s Azure Automation provides a scalable, verified solid foundation and is more secure than a workstation.  Azure Automation, with the right resources, can have a very small learning curve and has the potential to be a low-cost solution, depending on the usage. With access to many default PowerShell modules, Gallery modules, or your own modules imported into Azure, we can potentially automate numerous admin tasks. 

Azure Runbook: A service within Azure that allows an administrator to create automation tasks using languages such as PowerShell.

To be successful with Azure Automation, make sure to test your automation scripts with regular PowerShell before moving the task to Azure Automation, as PowerShell tools such as Visual Studio Code provide more debugging and feedback.  Once the script is ready for Automation testing, make sure to run the script by clicking on Start for the Runbook and check the loaded panel for errors, warnings, and logs (each pane could contain troubleshooting information) to see how the script performed.  Then once the script is ready and working, create and link a schedule that fits the task and monitor the logs present in the Runbook for the Automation.

With Automation, we manage data in Graph, Exchange Online, SharePoint, and Teams, to perform tasks such as reporting, notifications, and making changes to data within each of these workloads.  This is where testing comes in handy as access to these workloads, while controlled by Azure RBAC, can cause havoc if not implemented correctly. 

Azure Automation also supports certificate-based authentication.


GitHub – Your Script Repository

Change control for code is an important aspect of maintaining production-level scripts, and utilizing a web-based tool like GitHub can make this easier in terms of collaboration and change testing.  With GitHub, you can create projects that can directly correspond with an internal IT project, a group, or work from home project.  We can create landing pages, help pages, and more to assist in the collaboration process.

Why use GitHub?

  • Change control: Decide which features and code changes are released VIA Pull/Push requests.
  • Branching: Allow splits of code for stability checks or new versioning testing.
  • Access control: Take advantage of access controls and provide/block access to projects and codes depending on the need for the project.
  • Reporting: Create reports about changes made, who contributed, and more for each project.

Advantages of using GitHub

  • Most access is free
  • Repositories can be private, public, and shared (collaboration)
  • Desktop application and web access make for a good user experience
  • Integration exists for Visual Code Studio editor

Examples of good public script repositories: – Great set of PowerShell code to reference and utilize. – Microsoft’s official repository and source of their own PowerShell code samples. – A third-party resource for PowerShell scripts for managing Office 365.

Considerations / Recommendations

One key aspect of GitHub is determining what plan is needed by an organization or individual.  If there is a singular individual working on the project and there is no special collaboration needed, then the free version of GitHub is the right solution.  However, if an organization has a team that must collaborate on one or more projects, then either the Team or Enterprise edition should be chosen.  The key differentiator is that Enterprise has advanced features like System for Cross-domain Identity Management (SCIM) to control access to a GitHub organization, APIs for logging, more storage, more compute time for execution, as well as advanced compliance features like SOC1, SOC2, and FedRAMP (ATO).

QA Microsoft 365 Tenant

For administrators that manage a Microsoft 365 tenant, acquiring a development tenant in parallel is a good practice, and Microsoft provides a free signup link as described in this article.  What does this mean?  It means creating a duplicate tenant with the same licensing, features, etc., to mimic what is used in production. Some factors to consider with the creation of the test tenant include:

  • Budgeting and procurement: What budget and whose responsibility would it be to manage?
  • Determining which features to enable: Do all production features need to be tested in QA?
  • Source data: What will populate this environment?  Will it be a one-to-one copy of production, a scaled-down version, or anonymized data just for testing?
  • Change management: How will order be maintained when changes are made?  How can changes be reverted once made?
  • Domains: What vanity domains will be used for testing?

So, what does this type of tenant and its configuration have to do with PowerShell?  Simply put, this type of tenant allows administrators to try out PowerShell management against workloads in their tenant (Exchange, SharePoint, Teams, Graph and more) as well as automation scripts (Azure subscription required), credential storage, and other functions in a sandbox environment which does not affect their production users.  This can be crucial depending on the work that is being performed.  For example, if a script automates tasks for licensing, group assignment, or rights for an onboarding / offboarding process, running PowerShell can be more forgiving and cause fewer headaches. Thus, having a QA tenant, even from a PowerShell aspect, is a good idea.  Using this tenant, administrators can hone their PowerShell skills, tune scripts, and deliver solutions that would not cause production outages for their organization.

Controlling PowerShell access to tenant

Security and controlled access are important aspects of using scripting and automation tools in any environment, and this is also true for Microsoft 365.  Microsoft provides built-in protections and security controls with Azure AD Roles, which restricts what users can do based on roles and role groups they are assigned to.  Simply put, PowerShell should be allowed for administrators with the appropriate access, and non-admin users should be blocked from PowerShell:

Exchange Online: PowerShell access is enabled by default, though restricted to their own context.  To disable this access, use this as an example:

Set-User -Identity -RemotePowerShellEnabled $false

No configuration for the SharePoint Online PowerShell module is required as non-admins are blocked by default, as seen below in Figure 1 below.

Top Ten PowerShell Tips for Microsoft 365 Management: Part Two
Figure 1: End user attempts to access SharePoint via PowerShell, but fails.

Teams: Cannot be blocked – user has access to what they have been granted permissions to by either an administrator or Microsoft (default).

Microsoft Graph: Within a Conditional Access Policy, we can select the Microsoft Graph PowerShell app and set Access controls to Block non-admin users (figure 2).  This policy will block PowerShell access for users, but it will not block calls to the Graph API.  Any conditional policy that is created for this purpose should also exclude a break glass account to prevent lockout from the blocked resource.

Top Ten PowerShell Tips for Microsoft 365 Management: Part Two
 Figure 2: Available Cloud app in Conditional Access Policies.

AzureAD / MS Online: Scheduled for deprecation on June 2023.

Security and Compliance Center: Restricted via RBAC.  Regular users have access to Quarantine Message PowerShell cmdlets, but nothing else.

It is worth noting that regular users have restricted PowerShell access due to the Microsoft security model of roles and access granted.

Moving to the Cloud

When using PowerShell to manage cloud-based resources such as Microsoft 365, administrators should take advantage of these advanced tools that are also cloud-based as they provide scalability, stability, and security not found in on-premises systems.  If you are stuck using your on-premises resources to manage a cloud infrastructure, it is an opportune time to change that with the availability of tools and functions that are now available. Using GitHub, certificate-based authentication, and automation, you can increase the security and useability of PowerShell for an administrator.

About the Author

Damian Scoles

Damian Scoles is an eight-time Microsoft MVP, specializing in Exchange, Office 365 and PowerShell. He is currently based out of the Chicago area and started out managing Exchange 5.5 and Windows NT. He has worked with Office 365 since BPOS and has experience with Azure AD, Security and Compliance Admin Centers, and Exchange Online. Contributions to the community include helping on TechNet forums, creating PowerShell scripts that are located in the TechNet Gallery, writing detailed PowerShell / Office365 / Exchange blog articles (, tweets ( and creating PowerShell videos on YouTube ( He has written five PowerShell books and is actively working on the Microsoft 365 Security for IT Pros book as well.

Leave a Reply