Subchapter 8.11
references/iac-generation-rules.mdMarkdown7 KBView on GitHub
Rules for generating infrastructure code, Dockerfiles, security verification, and telemetry wiring.
For each service in services[]:
Sub-agent delegation: Use subagent-iac-gen.md template verbatim. Include full
prepare-plan.json,ScaffoldManifestinterface, and compute-target patterns. Self-review (Step 9) remains mandatory after sub-agent returns.
PostgreSQL wiring: Include firewall rule + extension allow-list (see subagent-iac-gen.md Step 6 if PostgreSQL in plan). ⛔ PostgreSQL config resources (e.g.,
require_secure_transport) must usesource: 'user-override'—'system-default'is read-only and ARM rejects it. ⛔ Do NOT createdatabases/postgreschild resource — it exists by default and ARM rejects duplicate creation. BuildKit Dockerfiles: GenerateDockerfile.azurefor ACR compatibility — see code-deployment-container-apps.md § BuildKit (opens in a new tab).
Env var completeness: Read
.env.example(or.env.sample,config.example) + config/settings files (PydanticSettings,@t3-oss/env-nextjs, Djangosettings.py) for each component to enumerate required env vars before generating IaC. Every env var with a placeholder value (notlocalhost) should map to either: (1) a Bicep parameter, (2) a KV secret reference, or (3) a hardcoded value derived from other resources (e.g., database connection string from the DB module output). ⛔ Container Apps: KVsecretRefentries must be gated behindisPlaceholder— Phase 1 =secrets: [], Phase 2 activates KV refs. See bicep-container-apps.md. Flag unmapped vars in selfReview as ⚠️ WARN. Missing vars cause container crash loops at deploy time.
⛔ Set
targetScope = 'subscription'inmain.bicep. Subscription-scope Bicep creates the resource group in IaC with all 5 AppOnboard tags (includingcreated-at). Do NOT use default resource-group scope — it requires imperativeaz group createwhich consistently misses tags. If the user lacks subscription-level permissions, the deploy phase handles fallback to RG-scope automatically.
⛔ Native module deploy strategy. If
prepare-plan.json.deployStrategyexists, read bicep-app-service.md § Native Module Deploy Strategy and apply the startup command + app settings to the App Service Bicep. ThedeployStrategy.startupCommandgoes intoappCommandLine, anddeployStrategy.requiredAppSettingsgoes intoappSettings[]. When nodeployStrategyexists, do NOT setappCommandLine— let Oryx use its default startup.
⛔ Include the 5 AppOnboard tags on every resource and module. See bicep-patterns.md § tags for Bicep code block or terraform-patterns.md § tags for HCL code block.
| Tag key | Value source |
|---|---|
app-onboard-skill | 'true' |
app-onboard-session-id | sessionId param |
created-at | ISO timestamp (scaffold populates, deploy may override) |
environment | naming.resourcePrefix |
deployed-by | context.json.azure.userDisplayName |
If extending existing IaC, MERGE with existing tags using union() / merge().
⛔ Do NOT generate
azure.yaml. Deploy viaaz deployment sub create. See pipeline-rules.md (opens in a new tab) § azure.yaml prohibition.
⛔ API version verification: Use versions from apiVersions input map. If a type is missing from the map, use the latest GA version from reference file examples — no -preview suffix. az bicep build catches invalid versions at compile time.
⛔ Resource property verification: Training data references deprecated properties. Known traps: Microsoft.CognitiveServices/accounts/deployments uses sku (name + capacity), NOT scaleSettings (deprecated) — omit raiPolicyName; Key Vault enablePurgeProtection — omit entirely (false rejected by ARM, true blocks cleanup). Fallback: az bicep build + what-if.
infra/main.bicep, main.parameters.json, modules/{service}.bicep per service.
.bicep files need LF, not CRLF — Bicep triple-quoted strings pass content literally to ARM, and \r bytes crash /bin/sh in containers. The validate subagent runs mcp_bicep_format_bicep_file (or bicep-format_bicep_file) post-generation to enforce this. If the formatter is unavailable, ensure files use LF manually.set -eu (POSIX). Do NOT use set -euo pipefail — Container Apps base images use /bin/sh (dash), not bash.packageManager field (e.g., pnpm@9.4.0). Never use @latest — major version drift breaks builds on older Node.js base images.⛔ Apply ALL patterns from bicep-patterns-security.md during generation — managed identity, SCM/FTP auth policies, KV secrets, least-privilege RBAC.
If prepare-plan.json.services[] has any entry with name containing “Container Apps” AND that component has no existing Dockerfile → ⛔ You MUST read dockerfile-generation.md and generate one. Skip if all Container Apps components already have Dockerfiles, or if no service targets Container Apps.
⛔ Read bicep-patterns-security.md (or terraform-patterns.md § Security Defaults) and verify ALL security patterns from Step 5. If deployment includes compute with MI ↔ resource RBAC, ⛔ read rbac-roles.md for GUID table. If a role is NOT in the table, check Azure built-in roles docs (opens in a new tab). Never guess GUIDs. Skip RBAC for SWA-only.
Tell the user which patterns were applied: managed identity, KV secrets, least-privilege RBAC, SCM/FTP auth policies, private endpoints.
If prepare-plan.json.instrumentation.appInsightsEnabled is true, add APPLICATIONINSIGHTS_CONNECTION_STRING as a plain app setting wired from the App Insights module output. The connection string is not a secret — no KV storage needed. For Container Apps: use a plain env var (not secretRef).