Loading...

Rehosting On-Prem Process Automation when migrating to Azure

Rehosting On-Prem Process Automation when migrating to Azure

Many enterprises seek to migrate on-premises IT infrastructure to cloud for cost optimization, scalability, and enhanced reliability. During modernization, key aspect is to transition automated processes from on-premises environments, where tasks are automated using scripts (PowerShell or Python) and tools like Windows Task Scheduler or System Center Service Management Automation (SMA).

This blog showcases successful transitions of customer automated processes to the cloud with Azure Automation, emphasizing script re-use and modernization through smart integrations with complementing Azure products. Using runbooks in PowerShell or Python, the platform supports PowerShell versions 5.1, and PowerShell 7.2. To learn more, click here.

 

Additionally, Azure Automation provides seamless certificate authentication with managed identity, eliminating the need to manage certificates and credentials while rehosting. Azure Automation safeguards the keys and passwords by wrapping the encryption key with the customer-managed key associated to key vault. Integration with Azure Monitor coupled with Automation’s native job logs equip the customers with advanced monitoring and error/failure management. Azure Automation platform efficiently manages long-running scripts in the cloud or on-premises with resource limits options with Hybrid runbook worker. Hybrid runbook worker also equips you to automate workloads off-Azure while utilizing the goodness of Azure Automation runbooks.

 

Rehosting on-premises operations with minimal effort covers scenarios listed below. Additional efforts involve modernizing scripts for cloud-native management of secrets, certificates, logging, and monitoring. –

  • State configuration management - Monitor state changes in the infrastructure and generate insights/alerts for subsequent actions.
  • Build, deploy and manage resources - Deploy virtual machines across a hybrid environment using runbooks. This is not entirely serverless and requires relatively higher manual effort in rehosting.
  • Periodic maintenance - to execute tasks that need to be performed at set timed intervals like
    1. purging stale data or reindex a SQL database.
    2. Checking for orphaned computer and users in Active Directory
    3. Windows Update notifications
  • Respond to alerts - Orchestrate a response when cost-based (e.g. VM cost consumption), system-based, service-based, and/or resource utilization alerts are generated.

Specifically, here are some of the scenarios of managing state configuration of M365 suite where our customer rehosted the on-premises PowerShell script to cloud with Azure Automation

 

Scenarios for State Configuration Management of M365 Suite

  1. User Permission & access control management
  2. Mailbox alerts configuration
  3. Configuring SharePoint sites availability
  4. Synchronizing Office 365 with internal applications

Example: Rehosting User Permission & access control management in M365 mailboxes

 

Here is how one of the customers rehosted a heavy monolithic PowerShell script to Azure. The objective of the job was to identify –

 

List of shared mailboxes --> list of permissions existing for these mailboxes --> users & groups mapped to the mailboxes --> list of permissions granted (& modified overtime) to these users/groups --> Final output with a view of Mailbox Id, Groups, Users, Permissions provided, Permissions modified (with timestamps).

 

1. Shared mailboxes credentials

 

 

########################################### # Get Shared Mailboxes ########################################### $forSharedMailboxes = @{ Properties = "GrantSendOnBehalfTo" RecipientTypeDetails = "SharedMailbox" ResultSize = "Unlimited" } $sharedMailboxes = Get-EXOMailbox @forSharedMailboxes

 

 

2. Obtain shared Mailbox permissions

 

 

########################################### # Get Shared Mailbox Permissions ########################################### $sharedMailboxesPermissions = foreach ($sharedMailbox in $sharedMailboxes) { # ------------------------------------------------------------------------------------------------------- # Get Send As Permissions # ------------------------------------------------------------------------------------------------------- try { $forTheSharedMailbox = @{ Identity = $sharedMailbox.Identity ResultSize = "Unlimited" } $recipientPermissions = @(Get-EXORecipientPermission @forTheSharedMailbox) $recipientPermissions = $recipientPermissions.Where({ $_.Trustee -ne "NT AUTHORITY\SELF" }) $recipientPermissions = $recipientPermissions.Where({ $_.Trustee -notlike "S-1-5-21*" }) if ($recipientPermissions) { foreach ($recipientPermission in $recipientPermissions) { [SharedMailboxPermission]@{ MailboxDisplayName = $sharedMailbox.DisplayName MailboxEmailAddresses = $sharedMailbox.EmailAddresses MailboxId = $sharedMailbox.Id MailboxUserPrincipalName = $sharedMailbox.UserPrincipalName Permission = $recipientPermission.AccessRights PermissionExchangeObject = $recipientPermission.Trustee } } } } catch { Write-Warning ("Getting send as permissions for $($sharedMailbox.Identity).") continue }

 

 

3. User & groups mapped to the mailboxes 

 

 

########################################### # Get Entra and Exchange User Objects ########################################### $forEntraAndExchangeUserObjects = @{ Connection = $forTheSharedMailboxGovernanceSite Identity = $entraAndExchangeUserObjectListRelativeUrl } $userObjectsList = Get-PnPList @forEntraAndExchangeUserObjects $fromTheEntraAndExchangeUserObjectsList = @{ Connection = $forTheSharedMailboxGovernanceSite List = $userObjectsList PageSize = 5000 } $userObjectsListItems = (Get-PnPListItem @fromTheEntraAndExchangeUserObjectsList).FieldValues ########################################### # Get Entra and Exchange Group Objects ########################################### $forEntraAndExchangeGroupObjects = @{ Connection = $forTheSharedMailboxGovernanceSite Identity = $entraAndExchangeGroupObjectListRelativeUrl } $groupObjectsList = Get-PnPList @forEntraAndExchangeGroupObjects $fromTheEntraAndExchangeGroupObjectsList = @{ Connection = $forTheSharedMailboxGovernanceSite List = $groupObjectsList PageSize = 5000 } $groupObjectsListItems = (Get-PnPListItem @fromTheEntraAndExchangeGroupObjectsList).FieldValues

 

 

4. List of permissions granted (& modified overtime) to these users/groups

 

 

# ---------------------------------------- # Get Full Access Permissions # ------------------------------------- try { $forTheSharedMailbox = @{ Identity = $sharedMailbox.Identity ResultSize = "Unlimited" } $mailboxPermissions = @(Get-EXOMailboxPermission @forTheSharedMailbox) $mailboxPermissions = $mailboxPermissions.Where({ $_.User -ne "NT AUTHORITY\SELF" }) $mailboxPermissions = $mailboxPermissions.Where({ $_.User -notlike "S-1-5-21*" }) if ($mailboxPermissions) { foreach ($mailboxPermission in $mailboxPermissions) { [SharedMailboxPermission]@{ MailboxDisplayName = $sharedMailbox.DisplayName MailboxEmailAddresses = $sharedMailbox.EmailAddresses MailboxId = $sharedMailbox.Id MailboxUserPrincipalName = $sharedMailbox.UserPrincipalName Permission = $mailboxPermission.AccessRights PermissionExchangeObject = $mailboxPermission.User } } } } catch { Write-Warning ("Getting full access permissions for $($sharedMailbox.Identity).") continue } # ------------------------------------------------------------------------------------------------------- # Get Send On Behalf Of Permissions # ------------------------------------------------------------------------------------------------------- $grantSendOnBehalfToPermissions = @($sharedMailbox.GrantSendOnBehalfTo) $grantSendOnBehalfToPermissions = $grantSendOnBehalfToPermissions.Where({ $_ -notlike "S-1-5-21*" }) if ($grantSendOnBehalfToPermissions) { foreach ($grantSendOnBehalfToPermission in $grantSendOnBehalfToPermissions) { [SharedMailboxPermission]@{ MailboxDisplayName = $sharedMailbox.DisplayName MailboxEmailAddresses = $sharedMailbox.EmailAddresses MailboxId = $sharedMailbox.Id MailboxUserPrincipalName = $sharedMailbox.UserPrincipalName Permission = "SendOnBehalfOf" PermissionExchangeObject = $grantSendOnBehalfToPermission } } } }

 

 

 

As the customer modernized from On-premises to Azure via Azure Automation, the following list captures the aspects that have to be updated. The changes were mostly an improvement in terms of experience offered by Azure Automation leveraging smart integrations with other Azure capabilities and little to no reliance on custom scripts.

  1. Setup Logging & Monitoring methods - In On prem setup, customers authored custom scripts for logging, which was no more needed with Azure Automation. Customers utilized in-portal Azure Monitor integration to forward logs to Azure monitor, quey logs, and set up alerts for insights.
  2. Handling certificate authentication Managed Identity based authentication provides improved means to store secrets and passwords without doing regular updates to code credentials. Azure Automation supports both PS script and in-built portal experience to configure Managed Identity
  3. Storing passwords and security keysKey Vault integration with Azure Automation helped the customers to transition this on-prem experience seamlessly. The sample PS script below is recommended to enable Key Vault integration.

 

 

Install-Module -Name Microsoft.PowerShell.SecretManagement -Repository PSGallery -Force Install-Module Az.KeyVault -Repository PSGallery -Force Import-Module Microsoft.PowerShell.SecretManagement Import-Module Az.KeyVault $VaultParameters = @{ AZKVaultName = $vaultName SubscriptionId = $subID } Register-SecretVault -Module Az.KeyVault -Name AzKV -VaultParameters $VaultParameters

 

 

 

If you are currently utilizing Azure Automation for rehosting such light weight environment agnostic operations from on-prem to cloud or want to know more details, please reach out to us on [email protected].

 

 

 

 

 

 

 

 

 

 

 

 

Published on:

Learn more
Azure Governance and Management Blog articles
Azure Governance and Management Blog articles

Azure Governance and Management Blog articles

Share post:

Related posts

Azure DocumentDB: A Fully Managed MongoDB-Compatible Database

Running MongoDB at scale eventually forces a trade-off: invest heavily in managing your own infrastructure or move to a managed service and ri...

5 hours ago

Azure SDK Release (February 2026)

Azure SDK releases every month. In this post, you'll find this month's highlights and release notes. The post Azure SDK Release (February 2026...

14 hours ago

Recovering dropped tables in Azure Databricks with UNDROP TABLE

Oops, Dropped the Wrong Table? What now? We’ve all been there: you’re cleaning up some old stuff in Databricks, run a quick DROP TABLE… and su...

22 hours ago

Azure Developer CLI (azd) – February 2026: JMESPath Queries & Deployment Slots

This post announces the February 2026 release of the Azure Developer CLI (`azd`). The post Azure Developer CLI (azd) – February 2026: JM...

1 day ago

Improved Python (PyPi/uvx) support in Azure MCP Server

Azure MCP Server now offers first-class Python support via PyPI and uvx, making it easier than ever for Python developers to integrate Azure i...

2 days ago

Power Automate: Get support for normalized schema import for data ingestion

Customers with existing data pipelines or data products in data mesh mostly want to stick to normalized, efficient forms such as star schema. ...

2 days ago

Power Automate: Export object-centric process mining data to Microsoft Fabric semantic model

Publishing to Microsoft Fabric breaks down data silos and amplifies the impact of your process insights across your organization. Instead of k...

2 days ago

Power Automate: Create and visualize custom KPIs in Process Intelligence Studio

Custom KPIs put your unique business priorities at the center of process analysis. While standard metrics provide valuable baseline insights, ...

2 days ago
Stay up to date with latest Microsoft Dynamics 365 and Power Platform news!
* Yes, I agree to the privacy policy