**UTILITY SKILL** — Reusable Azure Bicep patterns: hub-spoke, private endpoints, diagnostics, AVM composition. WHEN: "hub-spoke Bicep", "private endpoint module", "diagnostic settings", "AVM Bicep composition". USE FOR: Bicep template design, hub-spoke networking, private endpoint patterns, AVM modules. DO NOT USE FOR: Terraform code (use terraform-patterns), architecture decisions (use azure-adr), troubleshooting, diagram generation (use drawio).
Scanned 5/27/2026
Install via CLI
openskills install jonathan-vella/azure-agentic-infraops---
name: azure-bicep-patterns
description: '**UTILITY SKILL** — Reusable Azure Bicep patterns: hub-spoke, private endpoints, diagnostics, AVM composition. WHEN: "hub-spoke Bicep", "private endpoint module", "diagnostic settings", "AVM Bicep composition". USE FOR: Bicep template design, hub-spoke networking, private endpoint patterns, AVM modules. DO NOT USE FOR: Terraform code (use terraform-patterns), architecture decisions (use azure-adr), troubleshooting, diagram generation (use drawio).'
compatibility: Requires Azure CLI with Bicep extension
---
# Azure Bicep Patterns Skill
Reusable infrastructure patterns for Azure Bicep templates. Complements
`iac-bicep-best-practices.instructions.md` (style) and `azure-defaults` skill (naming, tags, regions).
> **Canonical sources** — the security baseline, AVM-first mandate, naming
> conventions, required tags, and unique-suffix rule live in
> [`azure-defaults/SKILL.md`](../azure-defaults/SKILL.md) and
> [`iac-policy-compliance.md`](../../instructions/references/iac-policy-compliance.md).
> This skill restates the rules tersely below for IaC-output convenience
> only; in conflict, the canonical sources win.
## Quick Reference
| Pattern | When to Use | Reference |
| ------------------------ | ------------------------------------------------ | ---------------------------------------------------------------------- |
| Hub-Spoke Networking | Multi-workload environments with shared services | [hub-spoke-pattern](references/hub-spoke-pattern.md) |
| Private Endpoint Wiring | Any PaaS service requiring private connectivity | [private-endpoint-pattern](references/private-endpoint-pattern.md) |
| Diagnostic Settings | Every deployed resource (mandatory) | [common-patterns](references/common-patterns.md) |
| Conditional Deployment | Optional resources controlled by parameters | [common-patterns](references/common-patterns.md) |
| Module Composition | Breaking main.bicep into reusable modules | [common-patterns](references/common-patterns.md) |
| Managed Identity Binding | Any service-to-service authentication | [common-patterns](references/common-patterns.md) |
| Budget & Cost Monitoring | Every deployment (mandatory) | [budget-pattern](references/budget-pattern.md) |
| What-If / AVM Pitfalls | Pre-deployment validation & AVM gotchas | [avm-pitfalls](references/avm-pitfalls.md) |
| Batch Bicep Formatting | After generating/editing the Bicep tree | `npm run format:bicep -- infra/bicep/{project}` (wraps `bicep format`) |
## Canonical Example — Module Interface
Every Bicep module in this repo follows the same input/output contract:
- **Inputs (required)**: `name`, `location`, `tags`, `logAnalyticsWorkspaceName`
- **Outputs (required)**: `resourceId`, `resourceName`, `principalId` (use `.?principalId ?? ''` so modules without managed identity still expose the output)
Full code sample and rationale: [`references/module-interface.md`](references/module-interface.md).
## Steps
Applying a pattern in a Bicep template:
1. **Identify the pattern** — match your need to a row in [Quick Reference](#quick-reference) (hub-spoke, private endpoint, diagnostics, conditional, identity, budget)
2. **Load the reference** — read the linked `references/*.md` for the chosen pattern; do not load all at once
3. **Compose the module** — follow the Module Interface contract above (`name`/`location`/`tags`/`logAnalyticsWorkspaceName` in; `resourceId`/`resourceName`/`principalId` out)
4. **Pin AVM versions to the latest stable** — at plan time, query MCR (`https://mcr.microsoft.com/v2/bicep/avm/res/{path}/tags/list`) and pin the highest non-prerelease semver; never reuse a version from training data, a prior project, or `references/avm-modules.md`. Stale pins require a `pin_policy.mode = "exception"` block in `04-iac-contract.json` (see `azure-defaults` skill). Enforced by `npm run validate:avm-versions:freeze`.
5. **Add diagnostics + budget** — every deployed resource gets a diagnostic setting; every deployment gets a budget with 80%/100%/120% forecast alerts
6. **What-if before deploy** — run `az deployment group what-if` and review for unexpected deletes, SKU downgrades, or auth changes
7. **Validate** — `bicep build` + `bicep lint` + `npm run validate:iac-security-baseline`
## Rules
- **Hub-Spoke**: Hub holds shared infra; spokes peer to hub only; NSGs per subnet
- **Private Endpoints**: Always wire PE + DNS Zone Group + DNS Zone; see group ID table in reference
- **Diagnostics**: `categoryGroup: 'allLogs'` + `AllMetrics`; pass workspace **name** not ID
- **Conditional**: `bool` params with defaults; guard outputs with ternary
- **Identity**: `guid()` for idempotent role names; `principalType: 'ServicePrincipal'`; scope narrowly
- **Budget**: 3 forecast thresholds (80%/100%/120%); amount and emails MUST be parameters
- **What-If**: Run before every deploy; watch for unexpected deletes and SKU downgrades
- **AVM**: ALWAYS pin to the **latest published stable version** (resolve at plan time via MCR `tags/list`); wrap modules to override defaults; verify outputs in README. Stale pins require a `pin_policy` exception block — see `azure-defaults` skill.
- **AVM Version Source of Truth**: MCR tag listing (`mcr.microsoft.com/v2/bicep/{module}/tags/list`) is authoritative.
Helpers and doc tables are NOT — they go stale. Validator: `npm run validate:avm-versions`.
## Gotchas
- **AVM output shapes vary across modules** — Different AVM modules expose different
outputs. Always check the module README before referencing outputs.
- **Tag merging in AVM modules** — Some AVM modules merge tags internally.
Verify deployed tags include all required policy tags after deployment.
- **What-If red flags** — Watch for unexpected deletes, SKU downgrades,
public access changes, authentication mode changes, or identity removal.
Always run what-if before deploy.
- **MCR version discovery** — When AVM version helpers are incomplete,
query `mcr.microsoft.com/v2/bicep/{module}/tags/list` for authoritative
published versions.
- **Cross-RG module `scope:` ARM ID split indexes** — Splitting a full
resource ID (`/subscriptions/{sub}/resourceGroups/{rg}/providers/...`)
on `/` yields `['', 'subscriptions', '{sub}', 'resourceGroups', '{rg}', ...]`.
Subscription is at **index 2**, RG name is at **index 4**. Use:
`scope: resourceGroup(split(resId, '/')[2], split(resId, '/')[4])`.
Indexes `[1]`/`[3]` are the literals `'subscriptions'`/`'resourceGroups'`
and only fail at `az deployment ... validate` time.
- **AVM `insights/metric-alert:0.4.1+` requires `criteria.allof[].name`** —
Each entry in `criteria.allOf[]` needs a `name` field; omission passes
`bicep build` but fails `az deployment ... validate`:
```bicep
allOf: [{
name: 'HighCpu' // REQUIRED
metricName: 'Percentage CPU'
operator: 'GreaterThan'
threshold: 80
timeAggregation: 'Average'
}]
```
- **`bicep build` poisons tree-hash folders** — Running `bicep build main.bicep`
emits `main.json` next to the source. If the folder is hashed by
`validate-iac-handoff.mjs`, that compiled output drifts the hash. The
validator now excludes `<stem>.json` siblings of `<stem>.bicep`, but if
you must build manually inside a handoff tree, `rm -f main.json`
immediately after.
## Reference Index
| File | Content |
| --------------------------------------------------------------------- | --------------------------------------------------------------------- |
| [hub-spoke-pattern.md](references/hub-spoke-pattern.md) | Hub-spoke VNet orchestration with peering |
| [private-endpoint-pattern.md](references/private-endpoint-pattern.md) | PE wiring + DNS zone groups + group ID table |
| [common-patterns.md](references/common-patterns.md) | Diagnostics, conditional deploy, module composition, managed identity |
| [budget-pattern.md](references/budget-pattern.md) | Consumption budget, forecast alerts, anomaly detection |
| [avm-pitfalls.md](references/avm-pitfalls.md) | What-if interpretation, AVM gotchas, learn more links |
| [module-interface.md](references/module-interface.md) | Canonical module input/output contract |
## Learn More
| Topic | How to Find |
| -------------------- | ---------------------------------------------------------------------------------------------------- |
| AVM module catalog | `mcp_azure-mcp_documentation` — `command: "microsoft_docs_search"`, `query: "Azure Verified Modules registry Bicep"` |
| Resource type schema | `mcp_azure-mcp_documentation` — `command: "microsoft_docs_search"`, `query: "{resource-type} Bicep template reference"` |
No comments yet. Be the first to comment!