Bicep Expert Assistant
Expert guidance for Azure Bicep infrastructure-as-code development, including best practices, resource type discovery, schema retrieval, and Azure Verified Modules.
Core Capabilities
This skill provides four main functions equivalent to the Bicep MCP Server:
- Best Practices - Comprehensive Bicep authoring guidelines
- Resource Type Discovery - List Azure resource types with API versions
- Schema Retrieval - Get detailed schemas for resource types
- AVM Metadata - Azure Verified Modules information
Instructions
When User Asks About Bicep Best Practices
Provide guidance from the comprehensive best practices below. Focus on the specific area they're asking about (parameters, variables, resources, modules, naming, security, etc.).
When User Needs Resource Types for a Provider
Run the helper script to list resource types:
# PowerShell
./scripts/get-resource-types.ps1 -Provider "Microsoft.Storage"
# Bash
./scripts/get-resource-types.sh "Microsoft.Storage"
Or use Azure CLI directly:
az provider show --namespace Microsoft.Storage --query "resourceTypes[].{Type:resourceType,ApiVersions:apiVersions[0]}" -o table
When User Needs a Resource Schema
Use Bicep CLI to get the schema:
bicep build-params --stdout <<< "param resourceType string = 'Microsoft.Storage/storageAccounts@2023-05-01'"
Or reference the helper script in scripts/get-resource-schema.ps1
When User Asks About Azure Verified Modules
Provide AVM guidance and help them find appropriate modules from the Bicep Public Registry.
Bicep Best Practices Reference
Parameters
Use descriptive names: Parameters should have clear, meaningful names that indicate their purpose
// Good param storageAccountName string param enableHttpsTrafficOnly bool = true // Avoid param san string param flag boolProvide descriptions: Always add
@description()decorator@description('The name of the storage account. Must be globally unique.') param storageAccountName stringSet safe defaults: Default values should be secure and cost-effective
@description('The SKU for the storage account') @allowed(['Standard_LRS', 'Standard_GRS', 'Standard_ZRS', 'Premium_LRS']) param storageAccountSku string = 'Standard_LRS'Use constraints wisely: Apply
@minLength(),@maxLength(),@minValue(),@maxValue()@minLength(3) @maxLength(24) param storageAccountName stringUse
@allowedsparingly: Overly restrictive lists block valid deployments as Azure adds new SKUsSecure sensitive parameters: Use
@secure()for secrets@secure() param adminPassword string
Variables
Use for computed values: Variables simplify complex expressions
var storageAccountName = '${prefix}${uniqueString(resourceGroup().id)}'Use for repeated values: Define once, use multiple times
var commonTags = { environment: environment project: projectName deployedBy: 'Bicep' }Typed variables (Bicep 0.26+): Add types for clarity
var instanceCount int = environment == 'prod' ? 5 : 2
Resources
Use symbolic names without 'name' suffix:
// Good resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = { // Avoid resource storageAccountName 'Microsoft.Storage/storageAccounts@2023-05-01' = {Use latest stable API versions: Check for the most recent stable API version
Leverage implicit dependencies: Bicep automatically handles dependencies when you reference resources
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = { name: storageAccountName // ... } resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = { parent: storageAccount // Implicit dependency name: 'default' }Use
existingkeyword for references:resource existingVnet 'Microsoft.Network/virtualNetworks@2023-09-01' existing = { name: vnetName }
Child Resources
Use nested declaration (preferred):
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = { name: storageAccountName // ... resource blobService 'blobServices' = { name: 'default' } }Or use parent property:
resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = { parent: storageAccount name: 'default' }
Modules
Use modules for reusability: Break large templates into focused modules
module storageModule 'modules/storage.bicep' = { name: 'storageDeployment' params: { storageAccountName: storageAccountName location: location } }Use Azure Verified Modules: Leverage pre-built, tested modules from the Bicep Registry
module storage 'br/public:avm/res/storage/storage-account:0.9.0' = { name: 'storageDeployment' params: { name: storageAccountName location: location } }Version your modules: Always pin to specific versions
Naming Conventions
- Use camelCase for parameters, variables, and symbolic names
- Use
uniqueString()for unique names:var storageAccountName = 'st${uniqueString(resourceGroup().id)}' - Add prefixes for context: Include environment, project, or region prefixes
- Follow Azure naming constraints: Check character limits and allowed characters
Outputs
Expose essential values: Output what consumers need
output storageAccountId string = storageAccount.id output primaryEndpoints object = storageAccount.properties.primaryEndpointsNever output secrets: Use Key Vault references instead
// WRONG - Never do this output connectionString string = storageAccount.listKeys().keys[0].value
Security Best Practices
- Use managed identities instead of credentials where possible
- Enable HTTPS/TLS for all services
- Use private endpoints for sensitive resources
- Apply least privilege with RBAC assignments
- Enable diagnostic logging and monitoring
- Use Key Vault for secrets management
- Enable encryption at rest and in transit
Code Organization
File structure:
project/ ├── main.bicep # Entry point ├── main.bicepparam # Parameters file ├── modules/ │ ├── networking.bicep │ ├── storage.bicep │ └── compute.bicep └── tests/ └── main.tests.bicepOrder of elements in files:
- Target scope (if not resourceGroup)
- Parameters
- Variables
- Resources
- Modules
- Outputs
Comments: Use
//for single-line,/* */for multi-line
Azure Verified Modules (AVM)
What is AVM?
Azure Verified Modules are pre-built, tested Bicep modules maintained by Microsoft that follow best practices and the Well-Architected Framework.
Using AVM Modules
// Reference from Bicep Public Registry
module storage 'br/public:avm/res/storage/storage-account:0.9.0' = {
name: 'storageDeployment'
params: {
name: 'mystorageaccount'
location: location
}
}
Finding AVM Modules
- Browse: https://azure.github.io/Azure-Verified-Modules/indexes/bicep/
- GitHub: https://github.com/Azure/bicep-registry-modules
- Registry:
mcr.microsoft.comfor container images
Module Types
- Resource Modules (
avm/res/): Single Azure resource with all configurations - Pattern Modules (
avm/ptn/): Multi-resource patterns for common scenarios - Utility Modules (
avm/utl/): Helper types and functions
Common Resource Type Examples
Storage Account
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageAccountName
location: location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
accessTier: 'Hot'
supportsHttpsTrafficOnly: true
minimumTls }
}
Virtual Network
resource vnet 'Microsoft.Network/virtualNetworks@2023-09-01' = {
name: vnetName
location: location
properties: {
addressSpace: {
addressPrefixes: ['10.0.0.0/16']
}
subnets: [
{
name: 'default'
properties: {
addressPrefix: '10.0.1.0/24'
}
}
]
}
}
Key Vault
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
name: keyVaultName
location: location
properties: {
tenantId: subscription().tenantId
sku: {
family: 'A'
name: 'standard'
}
enableRbacAuthorization: true
enableSoftDelete: true
softDeleteRetentionInDays: 90
}
}
When to Use This Skill
- Writing or reviewing Bicep templates
- Looking up Azure resource types and API versions
- Finding the correct schema for a resource type
- Using Azure Verified Modules
- Applying Bicep best practices
- Deploying Azure infrastructure with IaC
Keywords
bicep, azure, arm, infrastructure as code, iac, resource manager, deployment, template, module, avm, azure verified modules, resource type, schema, api version, storage account, virtual network, key vault, best practices