Azure Resource Lock Auditor
Daily, the flow checks that critical Azure resources (production resource groups, key data stores) carry the required CanNotDelete/ReadOnly locks via Azure Resource Manager, records any missing locks to Dataverse, alerts the platform team in Teams, and optionally re-applies a default lock. Prevents accidental deletion of protected resources.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
This flow enforces Azure resource-lock hygiene. On a daily schedule it inspects every resource group in a subscription through Azure Resource Manager (ARM), flags any group that does not carry a management lock, records each unprotected group as a finding in Dataverse, alerts the platform team in Microsoft Teams, and can optionally re-apply a default lock (auto-remediation, off by default).
Why it matters: A missing CanNotDelete lock on a production resource group is a deletion waiting to happen. A daily audit — with an optional one-switch remediation — closes that gap before someone fat-fingers a delete.
As-built note: Azure Resource Manager has no first-class Power Automate connector action wired up in this environment, so ARM is called with the built-in HTTP action using `ActiveDirectoryOAuth` — the sanctioned connector-first exception for non-connectorized REST APIs (§4b case 2). Dataverse and Teams use their standard connector actions. The flow ships Off; going live requires only authorizing the two connections and populating the eight environment variables.
Use Case
A platform / cloud-governance team mandates delete-locks on protected resources and wants continuous, automated verification that they are present — plus an optional break-glass switch to re-apply a default lock on anything found unprotected. Audience: IT Admins, Operations.
Flow Architecture
Recurrence
Recurrence (Daily)Runs the audit once per day
Initialize Correlation Id
Initialize variableguid() to trace this run across the findings log and the Teams alert
Initialize Required Lock Level
Initialize variableLock level to enforce, from flowlibs_RequiredLockLevel
Initialize Arm Base Url
Initialize variableARM endpoint, from flowlibs_ArmBaseUrl (sovereign-cloud portable)
Initialize Subscription Id
Initialize variableSubscription to audit, from flowlibs_AzureSubscriptionId
Initialize Locks Api Version
Initialize variableARM Management Locks API version (2016-09-01)
Initialize Rg Api Version
Initialize variableARM Resource Groups API version (2021-04-01)
Initialize Auto Reapply Lock
Initialize variable"false" by default; set "true" to enable auto-remediation
Initialize Findings Count
Initialize variable (Integer)Counter of unprotected resource groups
Initialize Unprotected Html
Initialize variableAccumulates an HTML <li> list for the Teams alert
HTTP List Resource Groups
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_AzureSubscriptionId | String | <configure> | Subscription to audit |
| flowlibs_AzureTenantId | String | <your-tenant-id> | AAD tenant for the ARM OAuth token |
| flowlibs_AzureClientId | String | <configure> | App registration (client) ID for ARM auth |
| flowlibs_AzureClientSecret | String | <configure> | App registration client secret — supply at go-live; never inline |
| flowlibs_ArmBaseUrl | String | https://management.azure.com | ARM endpoint; change for sovereign clouds. Audience = this + / |
| flowlibs_RequiredLockLevel | String | CanNotDelete | Lock level to enforce (CanNotDelete or ReadOnly) |
| flowlibs_TeamsGroupId | String | <your-team-id> | Target Teams team/group for the alert |
| flowlibs_TeamsChannelId | String | <your-channel-id> | Target Teams channel for the alert |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Microsoft Dataverse | shared_commondataserviceforapps | CreateRecord |
| Microsoft Teams | shared_teams | PostMessageToConversation |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Scope the audit
- Point flowlibs_AzureSubscriptionId at the target subscription. To audit several, clone the flow or wrap the two HTTP calls in a Foreach over a subscription list.
- Lock level by tier
- Set flowlibs_RequiredLockLevel to ReadOnly for stricter groups, or branch on RG tags to require different levels per tier.
- Enable auto-remediation
- Set varAutoReapplyLock to "true" (and grant the SP locks/write) to have the flow PUT a default lock on any unprotected RG.
- Approval before apply
- Insert an Approvals StartAndWaitForAnApproval before HTTP Apply Default Lock to gate remediation.
- Resource-level locks
- Extend the ARM calls to enumerate key data stores (storage accounts, SQL) and check their locks, not just resource groups.
- Coverage report
- Add a weekly summary reading the findings table for a % protected metric.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01No-lock gate (per RG)
True when no locks match the current resource group.
EXPR.02Lock-scope match (Filter array where)
Keeps locks whose scope id is at or under the current RG.
EXPR.03ARM list-RGs URI
Builds the ARM resource-groups list endpoint.
EXPR.04OAuth audience
Derives the OAuth audience from the ARM base URL.
EXPR.05Re-apply lock URI
Builds the PUT endpoint for re-applying a default lock to the RG.
EXPR.06Findings alert gate
True when at least one unprotected RG was found.
Customize & download
Generate a ready-to-import copy of this solution with your environment-variable values baked in — available on Base, Pro, or Team.
Upgrade to customize
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.