Skip to content

Step 5 — Infra-as-Code Gen

Generated by 06b-Bicep CodeGen agent | 2025-07-13

⬅️ Previous📑 IndexNext ➡️
Implementation PlanDemo IndexDeployment Summary

📁 Code Location: Bicep templates repository folder

infra/bicep/nordic-fresh-foods/
├── main.bicep # Main orchestration — uniqueSuffix, phased deployment
├── main.bicepparam # Production parameters
├── main.dev.bicepparam # Development parameters
├── deploy.ps1 # PowerShell deployment script (5 phases)
└── modules/
├── budget.bicep # Consumption budget + forecast alerts
├── compute.bicep # App Service Plan + App Service + RBAC + Autoscale
├── dns.bicep # Private DNS Zones (SQL, Blob, KV) + VNet links
├── keyvault.bicep # Key Vault + PE + diagnostics
├── monitoring.bicep # Log Analytics + Application Insights
├── network.bicep # VNet + Subnets + NSGs (AVM)
├── sql.bicep # SQL Server + Database + PE
└── storage.bicep # Storage Account + containers + PE
CheckResultDetails
bicep build0 errors, ⚠️ 34 warnings (BCP318 conditional modules, BCP321 nullable MI outputs, no-hardcoded-env-urls DNS)
bicep lint0 errors
bicep-lint-subagent✅ PASS0 errors, 34 warnings (all acceptable)
bicep-review-subagent✅ APPROVED❌ NEEDS_REVISION → all must_fix items resolved, re-validated
FindingSeverityDescriptionResolution
H2HIGHNSGs used raw Bicep instead of AVMReplaced with br/public:avm/res/network/network-security-group:0.5.2
H3HIGHNSG names missing project identifierUpdated to nsg-${projectName}-{role}-${environment}
H4HIGHdeploy.ps1 missing ARM token validationAdded az account get-access-token check
H5HIGHdeploy.ps1 wildcard in deployment name queryTrack phase-2 name explicitly via $phase2DeploymentName
M3MEDIUMftpsState set to FtpsOnlyChanged to Disabled per security baseline
M6MEDIUMHardcoded technical contact email in deploy.ps1Parameterized as $TechnicalContact
H1HIGH (FP)dailyQuotaGb type — reviewer claimed int but BCP036 confirmed null | stringNo change needed — string is correct
M2MEDIUM (FP)availabilityZone: -1 questioned — build confirmed int worksNo change needed
FindingSeverityDescriptionRationale
M1MEDIUMSQL missing diagnosticSettingsAVM SQL Server module does not support diagnosticSettings parameter (build error confirmed)
M4MEDIUMStandard_LRS in prodImplementation plan specifies Standard_LRS; aligns with cost-optimized architecture
M5MEDIUMBudget startDate resets on each deployutcNow() in param default is acceptable pattern; deployer can override
M7MEDIUMPE subnet network policiesEnabled is correct GA behavior for API 2024-01-01
L1-L5LOWHealth probe, log retention, blob diagnostics, autoscale ceiling, dev KV accessNon-blocking; addressable in subsequent iteration
ResourceAVM ModuleModule File
Virtual Networkbr/public:avm/res/network/virtual-network:0.7.2network.bicep
NSG (App)br/public:avm/res/network/network-security-group:0.5.2network.bicep
NSG (Data)br/public:avm/res/network/network-security-group:0.5.2network.bicep
NSG (PE)br/public:avm/res/network/network-security-group:0.5.2network.bicep
Log Analytics Workspacebr/public:avm/res/operational-insights/workspace:0.15.0monitoring.bicep
Application Insightsbr/public:avm/res/insights/component:0.7.1monitoring.bicep
Key Vaultbr/public:avm/res/key-vault/vault:0.13.3keyvault.bicep
Private DNS Zones (×3)br/public:avm/res/network/private-dns-zone:0.8.1dns.bicep
SQL Server + Databasebr/public:avm/res/sql/server:0.21.1sql.bicep
Storage Accountbr/public:avm/res/storage/storage-account:0.32.0storage.bicep
App Service Planbr/public:avm/res/web/serverfarm:0.7.0compute.bicep
App Servicebr/public:avm/res/web/site:0.22.0compute.bicep
Private Endpoints (×3)br/public:avm/res/network/private-endpoint:0.12.0keyvault/sql/storage.bicep
Consumption BudgetRaw Bicep (Microsoft.Consumption/budgets)budget.bicep
graph TD
    MAIN["main.bicep"] --> NET["network.bicep"]
    MAIN --> MON["monitoring.bicep"]
    MAIN --> DNS["dns.bicep"]
    MAIN --> KV["keyvault.bicep"]
    MAIN --> SQL["sql.bicep"]
    MAIN --> ST["storage.bicep"]
    MAIN --> COMP["compute.bicep"]
    MAIN --> BUD["budget.bicep"]

    NET --> VN["🌐 VNet + Subnets"]
    NET --> NSG["🛡️ NSGs (×3)"]
    MON --> LAW["📊 Log Analytics"]
    MON --> AI["📈 App Insights"]
    DNS --> PDNS["🔗 DNS Zones (×3)"]
    KV --> KVR["🔐 Key Vault + PE"]
    SQL --> SQLR["💾 SQL Server + DB + PE"]
    ST --> STR["📦 Storage + PE"]
    COMP --> ASP["⚙️ App Service Plan"]
    COMP --> APP["💻 App Service"]
    COMP --> RBAC["🔑 RBAC Assignments"]
    COMP --> AUTO["📏 Autoscale"]
    BUD --> BUDR["💰 Budget + Alerts"]
Terminal window
cd infra/bicep/nordic-fresh-foods
./deploy.ps1 -ResourceGroup "rg-nordic-fresh-foods-prod" -Environment "prod"

Deploys in 5 phases with approval gates between each phase.

Terminal window
cd infra/bicep/nordic-fresh-foods
./deploy.ps1 -ResourceGroup "rg-nordic-fresh-foods-dev" -Environment "dev"

Single-pass deployment (no private endpoints, reduced SKUs).

Terminal window
./deploy.ps1 -ResourceGroup "rg-nordic-fresh-foods-prod" -Environment "prod" -WhatIf
Terminal window
./deploy.ps1 -ResourceGroup "rg-nordic-fresh-foods-prod" -Environment "prod" -StartFromPhase 3

Supported phases: 1 (Foundation), 2 (Observability), 3 (Security), 4 (Data), 5 (Compute)

Terminal window
az deployment group create \
--resource-group "rg-nordic-fresh-foods-prod" \
--template-file main.bicep \
--parameters main.bicepparam \
--parameters phase=foundation
PhaseNameResourcesApprox. Time
1FoundationVNet, Subnets, NSGs~2 min
2ObservabilityLog Analytics, App Insights~3 min
3SecurityKey Vault, DNS Zones, KV PE~5 min
4DataSQL Server, Database, Storage, PEs~8 min
5ComputeApp Service Plan, App Service, Budget, RBAC, Autoscale~5 min
  • Replace <replace-with-sql-admin-group-object-id> in parameter files
  • Replace <replace-with-sql-admin-group-name> in parameter files
  • Replace <replace-with-budget-contact-email> in parameter files
  • Replace <replace-with-technical-contact> in parameter files
  • Verify Azure AD group exists for SQL admin
  • Confirm subscription 00858ffc-dded-4f0f-8bbf-e17fff0d47d9 is targeted
NoteImpactReference
Unique suffix via uniqueString(resourceGroup().id)All resource names (KV, Storage, SQL, App)main.bicep
11 mandatory tags (9 governance Deny + 2 baseline)All resources — Azure Policy enforcedmain.bicep var tags
Azure AD-only SQL authNo SQL password management; MI-based accesssql.bicep
Phased deployment with @allowed phase parameterSupports incremental rollout and re-entrymain.bicep
Private endpoints conditional on enablePrivateEndpointsProd: full PE isolation; Dev: public accessall PE modules
FTPS disabled on App ServiceSecurity baseline — no FTP attack surfacecompute.bicep
Budget alerts at 80%/100%/120% forecast + 90% actualCost governance with anomaly detectionbudget.bicep
var uniqueSuffix = uniqueString(resourceGroup().id)
// Example: kv-nff-prod-ab1c → 24-char limit respected via take()

All 21 Azure Policy assignments from 04-governance-constraints.json have been mapped and satisfied:

  • 9 Deny-policy tags: Applied via var tags in main.bicep, inherited by all modules
  • Azure AD-only SQL auth: azureADOnlyAuthentication: true in sql.bicep
  • Tag inheritance (Modify): 4 tags auto-inherited from resource group
  • MFA for write operations: Enforced at Azure AD level (not IaC-scoped)

Implementation reference generated from Bicep templates.