Imagine packing for a trip — you only bring a swimsuit if you're headed somewhere sunny ☀️, and you leave the umbrella behind if it’s not the rainy season. In this exercise, we do the same — we only deploy certain Azure resources when the environment calls for them.
Let’s build it 💪
🧠 What We’re Learning
- How to use conditions in Bicep (
if (...)
) - When to deploy a storage account (for SQL auditing) only if the environment is Production
- How to control auditing settings based on environment
- Why conditional logic makes your infrastructure smarter and safer
🧱 Step 1: Base Template – SQL Server + Database
We started with a basic Bicep file called main.bicep
that creates:
- A SQL Server
- A SQL Database (because our teddy bear product needs somewhere to keep HR data)
Here’s what our starting parameters and variables looked like:
@description('The Azure region into which the resources should be deployed.')
param location string
@secure()
@description('SQL Server Admin Login')
param sqlServerAdministratorLogin string
@secure()
@description('SQL Server Admin Password')
param sqlServerAdministratorLoginPassword string
@description('Database SKU (Performance Tier)')
param sqlDatabaseSku object = {
name: 'Standard'
tier: 'Standard'
}
var sqlServerName = 'teddy${location}${uniqueString(resourceGroup().id)}'
var sqlDatabaseName = 'TeddyBear'
Then we defined two resources:
resource sqlServer 'Microsoft.Sql/servers@2024-05-01-preview' = { ... }
resource sqlDatabase 'Microsoft.Sql/servers/databases@2024-05-01-preview' = { ... }
✅ So far, this will always deploy a database server — no matter the environment.
⚙️ Step 2: Add Conditional Parameters & Logic
We added:
@description('The name of the environment. This must be Development or Production.')
@allowed(['Development', 'Production'])
param environmentName string = 'Development'
@description('The name of the audit storage account SKU.')
param auditStorageAccountSkuName string = 'Standard_LRS'
Then created two key variables:
var auditingEnabled = environmentName == 'Production'
var auditStorageAccountName = take('bearaudit${location}${uniqueString(resourceGroup().id)}', 24)
🚦 What’s Happening Here?
-
auditingEnabled
is a boolean —true
if we’re deploying to Production. -
take(...)
ensures our storage account name doesn’t go over the 24-character limit (because naming rules are picky 🧠)
🧳 Step 3: Conditionally Add a Storage Account
We only want to collect auditing data if we’re in a production environment.
resource auditStorageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = if (auditingEnabled) {
name: auditStorageAccountName
location: location
sku: {
name: auditStorageAccountSkuName
}
kind: 'StorageV2'
}
That little if (auditingEnabled)
is the magic. It’s like saying:
“Only pack this if we’re going on the important trip.”
🔍 Step 4: Add SQL Server Auditing
Now we wire the SQL Server to log data to that storage account — but only in Production.
resource sqlServerAudit 'Microsoft.Sql/servers/auditingSettings@2024-05-01-preview' = if (auditingEnabled) {
parent: sqlServer
name: 'default'
properties: {
state: 'Enabled'
storageEndpoint: environmentName == 'Production' ? auditStorageAccount.properties.primaryEndpoints.blob : ''
storageAccountAccessKey: environmentName == 'Production' ? auditStorageAccount.listKeys().keys[0].value : ''
}
}
Here we used the ternary operator (aka the ?:
symbol). Why?
Because even when a resource is conditionally deployed, Azure still checks every line. This avoids errors like:
“Hey, I don’t see that storage account you’re referencing” 🙃
🚀 Step 5: Deploy to Azure
We did the usual setup:
az bicep install && az bicep upgrade
az login
az group create --name BicepRG --location westus
Dev Deployment:
az deployment group create \
--resource-group BicepRG \
--name main \
--template-file main.bicep \
--parameters location=westus
We entered our SQL admin login + password when prompted.
💡 Since we didn’t set the environmentName
, it defaulted to Development.
👉 That means the storage account and auditing didn’t get deployed — exactly what we wanted!
🔁 Step 6: Redeploy for Production
Now let’s simulate a Production rollout:
az deployment group create \
--resource-group BicepRG \
--name main \
--template-file main.bicep \
--parameters environmentName=Production location=westus
💥 Boom. This time:
- We got the SQL Server
- A Storage Account for auditing
- Auditing enabled on the SQL Server
Just like switching a gear from “dry run” to “real world” 🧠
🔍 Step 7: Check the Results in Azure Portal
In the Azure Portal:
- Head to Resource Groups > BicepRG
- Select the SQL Server
- Go to Auditing
- You’ll see: ✅ State = Enabled ✅ Logging to the storage account
🧠 In Short
What We Did | Why It Matters |
---|---|
Used if () conditions in Bicep |
Smarter templates → Less waste in dev, more protection in prod |
Deployed SQL + DB to both envs | Core infrastructure stays consistent |
Only added auditing for prod | Less cost and clutter in dev |
Used ternary ? : logic |
Avoided reference errors in conditional deployments |
🎒 Takeaway
This pattern — using conditions — is super useful when:
- You're working with multiple environments
- You want flexibility without duplicating code
- You need governance (like logging or auditing) only in specific cases
Wanna follow my Azure learning journey?
Stick around — I’m sharing it all, wins and stumbles included 😄
You can find me on LinkedIn — drop me a message and just say hi 👋
Would love to hear what you're working on or learning!