Azure Verified Modules (AVM) for Bicep is an initiative aimed at consolidating and setting standards for what a good Infrastructure-as-Code (IaC) module should look like. Modules that align with these standards are classified as AVMs and are available from their respective language-specific registries. Supported by Microsoft, AVM is intended to standardise and accelerate the deployment of Azure resources with Bicep and architectural patterns.
In this blog post, we will explore how to deploy a Logic App Standard using Azure Bicep Verified Modules.
How to Use Azure Bicep Verified Modules
The entire project open source is hosted on GitHub: https://github.com/Azure/bicep-registry-modules
There is also an official website available here: Azure Verified Modules for Bicep. However, their GitHub repository is essentially the most interesting part.
The Azure Bicep Verified Modules are hosted in a public repository, so you can easily use them across multiple projects. The modules are also versioned, so remember to upgrade them from time to time, especially if you want to use newer features.
Using them is straightforward. I use:
- Visual Studio Code
- Bicep extension
- Bicep Registry extension
Open a new .bicep file and start typing. IntelliSense will provide suggestions for public modules right out of the box. Below is an example where I typed “sto” and the IDE comes up with suggestions and a link to the documentation.

Deploy Logic App Standard Using Azure Bicep Verified Modules
The setup we’ll create is a fairly complete environment for a Logic App Standard, including Key Vault, Managed Identity, Storage Account, Log Analytics Workspace, and Application Insights.
Below is an architectural overview of the application landscape and release process:

Step 1: Create a Resource Group
We begin by creating a resource group and setting the target scope to the subscription level.
targetScope = 'subscription'
@description('Optional. The location to deploy resources to.')
param location string = deployment().location
resource appResourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: 'rg-avm-bicep'
location: location
}Step 2: Create the Hosting Plan (App Service Plan)
Next, we create the hosting plan or server farm:
module serverFarm 'br/public:avm/res/web/serverfarm:0.3.0' = {
scope: appResourceGroup
name: 'appfarm-logicapp01-${uniqueString(deployment().name, location)}'
params: {
name: 'appfarm-logicapp01'
kind: 'Elastic'
maximumElasticWorkerCount: 3
skuName: 'WS1'
}
}Step 3: Create a Managed Identity
We create a new User-Assigned Managed Identity to be used by the Logic App Standard:
module mgmtIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.0' = {
scope: appResourceGroup
name: 'mgmtidentity-${uniqueString(deployment().name, location)}'
params: {
name: 'Identity-Logicapp01'
}
}Step 4: Create the Storage Account and Key Vault
We create a Storage Account and a Key Vault. We will export the Storage Account connection string directly into the Key Vault as a secret for enhanced security.
Additionally, we’ll assign the Logic App’s Managed Identity access to read secrets from the Key Vault. If you don’t already have access to create Key Vault values by default, make sure to add yourself here, or the pipeline that executes this.
module keyvault 'br/public:avm/res/key-vault/vault:0.11.0' = {
scope: appResourceGroup
name: 'kv-${uniqueString(deployment().name, location)}'
params: {
name: 'keyvault01'
sku: 'standard'
roleAssignments: [
{ principalId: mgmtIdentity.outputs.principalId, roleDefinitionIdOrName: 'Key Vault Secrets User' }
{ principalId: '<your-principal-id>', roleDefinitionIdOrName: 'Key Vault Secrets User' } // Assign yourself access to Key Vault to create secrets (optional)
]
}
}
module storageAccount 'br/public:avm/res/storage/storage-account:0.14.3' = {
scope: appResourceGroup
name: 'stologicapp01-${uniqueString(deployment().name, location)}'
params: {
name: 'stologicapp01'
secretsExportConfiguration: { //this exports the connectionstring to a keyvault secret
keyVaultResourceId: keyvault.outputs.resourceId
connectionString1: 'stologicapp01-connectionstring'
}
networkAcls: {
defaultAction: 'Allow'
bypass: 'AzureServices'
}
publicNetworkAccess: 'Enabled'
}
}
Step 5: Create Log Analytics and Application Insights
We proceed to create a Log Analytics Workspace and an Application Insights instance:
module logAnalytics 'br/public:avm/res/operational-insights/workspace:0.9.0' = {
scope: appResourceGroup
name: 'log-webshop-${uniqueString(deployment().name, location)}'
params: {
name: 'loganaly01'
}
}
module appInsights 'br/public:avm/res/insights/component:0.4.2' = {
scope: appResourceGroup
name: 'appinsights-${uniqueString(deployment().name, location)}'
params: {
name: 'appinsights01'
workspaceResourceId: logAnalytics.outputs.resourceId
}
}Step 6: Create the Logic App Standard
Lastly, we create the Logic App:
module logicapp 'br/public:avm/res/web/site:0.11.1' = {
scope: appResourceGroup
name: 'las-logicapp01-${uniqueString(deployment().name, location)}'
params: {
name: 'las-webshop01'
kind: 'functionapp,workflowapp'
serverFarmResourceId: serverFarm.outputs.resourceId
appInsightResourceId: appInsights.outputs.resourceId
siteConfig: {
alwaysOn: true
netFrameworkVersion: 'v8.0'
}
managedIdentities: {
userAssignedResourceIds: [
mgmtIdentity.outputs.resourceId
]
}
keyVaultAccessIdentityResourceId: mgmtIdentity.outputs.resourceId
appSettingsKeyValuePairs: {
FUNCTIONS_EXTENSION_VERSION: '~4'
FUNCTIONS_WORKER_RUNTIME: 'dotnet'
WEBSITE_CONTENTSHARE: 'las-logicapp01'
APP_KIND: 'workflowApp'
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING: '@Microsoft.KeyVault(VaultName=${keyvault.outputs.name};SecretName=stologicapp01-connectionstring)'
}
}
}Bicep Logic App Module
Logic App Consumption has a separate module in Azure Bicep Verified Modules because, in Azure, it is actually a different resource. However, for Logic App Standard, there is no such different resource since it’s defined as a “site” with a specific kind: ‘functionapp,workflowapp’.
Currently, there is no separate module yet for Logic App Standard in Azure Bicep Verified Modules. However, this seems to be on the list of ongoing discussions. See this GitHub proposal: Azure-Verified-Modules Issue #647.
The current module is missing a bit of magic to populate the mandatory settings for Logic App automatically, which is actually present if you use this for Azure Functions.
Conclusion
Deploying a Logic App Standard with Azure Bicep Verified Modules is actually quite straightforward. It’s been a pleasant experience, and the modules are built on standards and best practices. I highly recommend everyone to follow this project and consider upgrading your deployment scripts to use these verified modules.
