Installation

Install with CLI Recommended
gh skills-hub install azure-enterprise-infra-planner

Don't have the extension? Run gh extension install samueltauil/skills-hub first.

Download and extract to your repository:

.github/skills/azure-enterprise-infra-planner/

Extract the ZIP to .github/skills/ in your repo. The folder name must match azure-enterprise-infra-planner for Copilot to auto-discover it.

Skill Files (35)

SKILL.md 3.9 KB
---
name: azure-enterprise-infra-planner
description: "Architect and provision enterprise Azure infrastructure from workload descriptions. For cloud architects and platform engineers planning networking, identity, security, compliance, and multi-resource topologies with WAF alignment. Generates Bicep or Terraform directly (no azd). WHEN: 'plan Azure infrastructure', 'architect Azure landing zone', 'design hub-spoke network', 'plan multi-region DR topology', 'set up VNets firewalls and private endpoints', 'subscription-scope Bicep deployment'. PREFER azure-prepare FOR app-centric workflows."
license: MIT
metadata:
  author: Microsoft
  version: "1.0.1"
---

# Azure Enterprise Infra Planner

## When to Use This Skill

Activate this skill when user wants to:
- Plan enterprise Azure infrastructure from a workload or architecture description
- Architect a landing zone, hub-spoke network, or multi-region topology
- Design networking infrastructure: VNets, subnets, firewalls, private endpoints, VPN gateways
- Plan identity, RBAC, and compliance-driven infrastructure
- Generate Bicep or Terraform for subscription-scope or multi-resource-group deployments
- Plan disaster recovery, failover, or cross-region high-availability topologies

## Quick Reference

| Property | Details |
|---|---|
| MCP tools | `get_azure_bestpractices_get`, `wellarchitectedframework_serviceguide_get`, `microsoft_docs_fetch`, `microsoft_docs_search`, `bicepschema_get` |
| CLI commands | `az deployment group create`, `az bicep build`, `az resource list`, `terraform init`, `terraform plan`, `terraform validate`, `terraform apply` |
| Output schema | [plan-schema.md](references/plan-schema.md) |
| Key references | [research.md](references/research.md), [resources/](references/resources/README.md), [waf-checklist.md](references/waf-checklist.md), [constraints/](references/constraints/README.md) |

## Workflow

Read [workflow.md](references/workflow.md) for detailed step-by-step instructions, including MCP tool usage, CLI commands, and decision points. Follow the phases in order, ensuring all key gates are passed before proceeding to the next phase.

| Phase | Action | Key Gate |
|-------|--------|----------|
| 1 | Research β€” WAF Tools | All MCP tool calls complete |
| 2 | Research β€” Refine & Lookup | Resource list approved by user |
| 3 | Plan Generation | Plan JSON written to disk |
| 4 | Verification | All checks pass, user approves |
| 5 | IaC Generation | `meta.status` = `approved` |
| 6 | Deployment | User confirms destructive actions |

## MCP Tools

| Tool | Purpose |
|------|---------|
| `get_azure_bestpractices_get` | Azure best practices for code generation, operations, and deployment |
| `wellarchitectedframework_serviceguide_get` | WAF service guide for a specific Azure service |
| `microsoft_docs_search` | Search Microsoft Learn for relevant documentation chunks |
| `microsoft_docs_fetch` | Fetch full content of a Microsoft Learn page by URL |
| `bicepschema_get` | Bicep schema definition for any Azure resource type (latest API version) |

## Error Handling

| Error | Cause | Fix |
|---|---|---|
| MCP tool error or not available | Tool call timeout, connection error, or tool doesn't exist | Retry once; fall back to reference files and notify user if unresolved |
| Plan approval missing | `meta.status` is not `approved` | Stop and prompt user for approval before IaC generation or deployment |
| IaC validation failure | `az bicep build` or `terraform validate` returns errors | Fix the generated code and re-validate; notify user if unresolved |
| Pairing constraint violation | Incompatible SKU or resource combination | Fix in plan before proceeding to IaC generation |
| Infra plan or IaC files not found | Files written to wrong location or not created | Verify files exist at `<project-root>/.azure/` and `<project-root>/infra/`; if missing, re-create the files by following [workflow.md](references/workflow.md) exactly |
references/
bicep-generation.md 3.5 KB
# Bicep Generation

Generate Bicep IaC files from the approved infrastructure plan.

> Important: All Bicep files must be created under `<project-root>/infra/`. Never place `.bicep` files in the project root or in `.azure/`.

## File Structure

Generate files under `<project-root>/infra/`:

```
infra/
β”œβ”€β”€ main.bicep              # Orchestrator β€” deploys all modules
β”œβ”€β”€ main.bicepparam         # Parameter values
└── modules/
    β”œβ”€β”€ storage.bicep        # One module per resource or logical group
    β”œβ”€β”€ compute.bicep
    β”œβ”€β”€ networking.bicep
    └── monitoring.bicep
```

## Generation Steps

1. Create `infra/` directory β€” create `<project-root>/infra/` and `<project-root>/infra/modules/` directories. All files in subsequent steps go here.
2. Read plan β€” load `<project-root>/.azure/infrastructure-plan.json`, verify `meta.status === "approved"`
3. Fetch Bicep schemas β€” for each resource in the plan, use a sub-agent to call `bicepschema_get` with `resource-type` set to the ARM type from the relevant [resources/](resources/README.md) category file (e.g., `Microsoft.ContainerService/managedClusters`). Instruct the sub-agent: "Return the full property structure for {ARM type}: required properties, allowed values, child resources. ≀500 tokens." Use this output β€” not training data β€” to generate correct resource definitions.

> The schema tool returns only the schema for the exact type requested. Sub-resource types (e.g., `Microsoft.Network/virtualNetworks/subnets`) return a smaller, focused schema but miss parent-level properties (e.g., VNet `encryption` lives on the parent, not the subnet sub-resource). Strategy:
> - Start with sub-resource types when validating child resources β€” smaller responses (~25KB vs ~95KB), easier to summarize
> - Fetch the parent type separately when you need parent-level properties (encryption, tags, SKU) β€” delegate to a sub-agent with specific property extraction instructions to manage the large response

4. Generate modules β€” group resources by category; one `.bicep` file per group under `infra/modules/`. Use the schema from step 3 for property names, allowed values, and required fields.
5. Generate main.bicep β€” write `infra/main.bicep` that imports all modules and passes parameters
6. Generate parameters β€” create `infra/main.bicepparam` with environment-specific values

## Bicep Conventions

- Use `@description()` decorators on all parameters
- Use `@secure()` for secrets and connection strings
- Choose `targetScope` in `main.bicep` based on the deployment plan:
  - For single resource group deployments, set `targetScope = 'resourceGroup'` and deploy with `az deployment group create`.
  - For subscription-scope deployments (for example, resources across multiple resource groups or subscription-level resources), set `targetScope = 'subscription'` and deploy with `az deployment sub create`.
- Use `existing` keyword for referencing pre-existing resources
- Output resource IDs and endpoints needed by other resources
- Use `dependsOn` only when implicit dependencies are insufficient

## Parameter File Format

```bicep
using './main.bicep'

param location = 'eastus'
param environmentName = 'prod'
param workloadName = 'datapipeline'
```

## Multi-Environment

For multi-environment plans, generate one parameter file per environment:

```txt
infra/
β”œβ”€β”€ main.bicep
β”œβ”€β”€ main.dev.bicepparam
β”œβ”€β”€ main.staging.bicepparam
└── main.prod.bicepparam
```

## Validation Before Deployment

Run `az bicep build --file infra/main.bicep` to validate syntax before deploying.
deployment.md 3.7 KB
# Deployment Execution

Execute infrastructure deployment after plan approval and IaC generation.

## Status Gate

Before executing any deployment command, verify:

```txt
meta.status === "approved"
```

If status is not `approved`, stop and inform the user. Do not manually change the status.

## Pre-Deployment Checklist

1. Plan approved β€” `meta.status` is `approved`
2. IaC generated β€” Bicep or Terraform files exist in `<project-root>/infra/`
3. Azure context confirmed β€” subscription and resource group selected
4. User confirmation β€” explicit "yes, deploy" from the user
5. Syntax validated β€” `az bicep build` or `terraform validate` passed

## Bicep Deployment

Scope selection: use resource-group scope when your template deploys into an existing resource group. Use subscription scope when your template creates resource groups or other subscription-level resources (policies, role assignments, etc.).

```bash
# Validate first (applies to both scopes)
az bicep build --file infra/main.bicep
```

Choose the command based on the `targetScope` set in `main.bicep` (see [bicep-generation.md](bicep-generation.md) Bicep Conventions):

| `targetScope` | When to use | Command |
|---|---|---|
| `resourceGroup` (default) | All resources in one resource group | `az deployment group create` |
| `subscription` | Resources span multiple resource groups, or includes subscription-level resources (policy, RBAC, resource group creation) | `az deployment sub create` |

### Resource Group Scope

```bash
# What-if preview
az deployment group create \
  --resource-group <resource-group-name> \
  --template-file infra/main.bicep \
  --parameters infra/main.bicepparam \
  --what-if

# Deploy
az deployment group create \
  --resource-group <resource-group-name> \
  --template-file infra/main.bicep \
  --parameters infra/main.bicepparam \
  --name <deployment-name>
```

PowerShell:
```powershell
az deployment group create `
  --resource-group <resource-group-name> `
  --template-file infra/main.bicep `
  --parameters infra/main.bicepparam `
  --name <deployment-name>
```

### Subscription Scope

```bash
# What-if preview
az deployment sub create \
  --location <location> \
  --template-file infra/main.bicep \
  --parameters infra/main.bicepparam \
  --what-if

# Deploy
az deployment sub create \
  --location <location> \
  --template-file infra/main.bicep \
  --parameters infra/main.bicepparam \
  --name <deployment-name>
```

PowerShell:
```powershell
az deployment sub create `
  --location <location> `
  --template-file infra/main.bicep `
  --parameters infra/main.bicepparam `
  --name <deployment-name>
```

## Terraform Deployment

```bash
cd infra

# Initialize
terraform init

# Preview changes
terraform plan -var-file=prod.tfvars -out=tfplan

# Apply (requires confirmation)
terraform apply tfplan
```

PowerShell:
```powershell
Set-Location infra
terraform init
terraform plan -var-file=prod.tfvars -out=tfplan
terraform apply tfplan
```

## Post-Deployment

After successful deployment:

1. Update status β€” set `meta.status` to `deployed` in `<project-root>/.azure/infrastructure-plan.json`
2. Verify resources β€” list resources in the target resource group using Azure CLI: `az resource list -g <resource-group-name> -o table`
3. Report to user β€” list deployed resources, endpoints, and any follow-up actions

## Error Handling

| Error | Action |
|-------|--------|
| Authentication failure | Run `az login` and retry |
| Quota exceeded | Check limits with `mcp_azure_mcp_quota`, select different SKU or region |
| Name conflict | Resource name already taken; append unique suffix or choose new name |
| Region unavailable | Service not available in chosen region; select alternative |
| Validation failure | Fix IaC syntax errors before retrying deployment |
pairing-checks.md 3.7 KB
# Property & Pairing Checks

Cross-check each new resource's properties against every already-written resource it connects to. Only run the checks relevant to this resource's type. Consult the resource file's Pairing Constraints section for type-specific rules.

## SKU Compatibility

| # | Check | Fix |
|---|-------|-----|
| 1 | Public IP SKU matches Load Balancer SKU (both Standard or both Basic) | Align to Standard (Basic retiring Sep 2025) |
| 2 | Application Gateway v1/v2 on separate subnets; v2 if zone redundancy, autoscaling, or Key Vault integration needed | Upgrade to v2 or split subnets |
| 3 | VPN Gateway SKU supports required features (BGP, IPv6, coexistence) β€” not Basic if any advanced feature is needed | Upgrade SKU |
| 4 | App Service Plan SKU meets feature requirements (VNet integration β‰₯ Basic, slots β‰₯ Standard, isolation β‰₯ IsolatedV2) | Upgrade plan SKU |
| 5 | Redis Cache tier supports required features (VNet injection = Premium, clustering = Premium/Enterprise) | Upgrade tier |

## Subnet & Network Conflicts

| # | Check | Fix |
|---|-------|-----|
| 1 | No already-written service with exclusive subnet requirements shares the same subnet as this resource | Assign a separate subnet |
| 2 | Subnet delegation matches service requirement β€” delegated for App Service/Container Apps Workload Profiles; NOT delegated for AKS, Consumption-only Container Apps | Fix delegation setting |
| 3 | App Service VNet Integration subnet β‰  App Service Private Endpoint subnet | Split into two subnets |
| 4 | Subnet CIDR size meets minimum (/26 for Firewall/Bastion, /27 for Gateway/Container Apps WP, /23 for Container Apps Consumption) | Expand CIDR |
| 5 | GatewaySubnet has no NSG; AzureBastionSubnet has an NSG | Add or remove NSG resource |

## Storage Pairing

| # | Check | Fix |
|---|-------|-----|
| 1 | Functions storage account uses `StorageV2` or `Storage` kind (not BlobStorage/BlockBlob/FileStorage) | Change `kind` to `StorageV2` |
| 2 | Functions on Consumption plan do not reference network-secured storage | Remove network rules or upgrade to Premium plan |
| 3 | Zone-redundant Functions use ZRS storage (not LRS/GRS) | Change storage SKU to `Standard_ZRS` |
| 4 | VM boot diagnostics storage is not Premium or ZRS | Use `Standard_LRS` or `Standard_GRS` |

## Cosmos DB

| # | Check | Fix |
|---|-------|-----|
| 1 | Multi-region writes + Strong consistency not configured together | Switch to Session consistency or single-region writes |
| 2 | Serverless accounts are single-region only, no shared-throughput databases | Remove multi-region config or switch to provisioned throughput |

## Key Vault & CMK

| # | Check | Fix |
|---|-------|-----|
| 1 | Any service using CMK has its Key Vault with `enableSoftDelete: true` and `enablePurgeProtection: true` | Add properties to Key Vault (or fix the already-written Key Vault entry) |
| 2 | CMK at storage creation uses user-assigned managed identity (not system-assigned) | Add a user-assigned identity resource before this resource |

## SQL Database

| # | Check | Fix |
|---|-------|-----|
| 1 | Zone redundancy not configured on Basic/Standard DTU tiers | Upgrade to Premium, Business Critical, or GP vCore |
| 2 | Hyperscale zone-redundant elastic pools use ZRS/GZRS backup storage | Set backup storage redundancy |

## AKS Networking

| # | Check | Fix |
|---|-------|-----|
| 1 | Pod CIDR does not overlap with cluster subnet, peered VNets, or gateway ranges already in the plan | Adjust CIDR |
| 2 | Reserved CIDR ranges (169.254.0.0/16, 172.30.0.0/16, 172.31.0.0/16, 192.0.2.0/24) not used | Change to allowed range |
| 3 | CNI Overlay not combined with VM availability sets, virtual nodes, or DCsv2 VMs | Switch CNI plugin or VM series |
plan-schema.md 3.1 KB
# Infrastructure Plan JSON Schema

The infrastructure plan is written to `<project-root>/.azure/infrastructure-plan.json`. This document describes the schema.

## Top-Level Structure

```json
{
  "meta": { ... },
  "inputs": { ... },
  "plan": { ... }
}
```

## `meta` (required)

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `planId` | string | Yes | Unique identifier (e.g., `plan-1`) |
| `generatedAt` | string | Yes | ISO 8601 timestamp |
| `version` | string | Yes | Schema version (e.g., `0.1-draft`) |
| `status` | string | Yes | Lifecycle state: `draft`, `approved`, `deployed` |

## `inputs` (required)

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `userGoal` | string | Yes | User's stated objective or workload description, matches user query exactly |
| `subGoals` | string[] | No | Inferred architectural constraints and priorities derived from the user's request and research phase. Examples: `"Cost-optimized: user chose defaults, avoid premium networking"`, `"Security-first: encrypt all data, use managed identity"`, `"Minimal complexity: single region, no VNet"`. These help evaluators understand intentional tradeoffs. Should be short list of 0-3 points. |

## `plan` (required)

### `plan.resources[]` (required)

Each element represents one Azure resource, include resource groups:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Logical resource name (CAF-compliant) |
| `type` | string | Yes | ARM resource type (e.g., `Microsoft.Storage/storageAccounts`) |
| `subtype` | string | No | Exact subtype (e.g., `Blob Storage`, `Azure Function`) |
| `location` | string | Yes | Azure region (e.g., `eastus`) |
| `sku` | string | Yes | SKU tier (e.g., `Standard_LRS`, `Consumption`) |
| `properties` | object | No | Resource-specific properties |
| `reasoning` | object | Yes | See Reasoning below |
| `dependencies` | string[] | Yes | Names of resources this depends on (empty if none) |
| `dependencyReasoning` | string | No | Why these dependencies exist |
| `references` | array | Yes | `[{ "title": "...", "url": "..." }]` links to Azure docs |

### `plan.resources[].reasoning` (required)

| Field | Type | Description |
|-------|------|-------------|
| `whyChosen` | string | Justification referencing WAF pillars (see [research.md](research.md)) or requirements |
| `alternativesConsidered` | string[] | Other options evaluated |
| `tradeoffs` | string | Key tradeoffs in this choice |

### `plan.overallReasoning` (required)

| Field | Type | Description |
|-------|------|-------------|
| `summary` | string | Overall architecture rationale |
| `tradeoffs` | string | Top-level tradeoffs and gaps |

### Other `plan` fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `validation` | string | Yes | Deployment coherence statement |
| `architecturePrinciples` | string[] | Yes | Guiding principles (e.g., `Highly available`, `Secure`) |
| `references` | array | Yes | Architecture-level doc links |

## Example

See [sample_infrastructure_plan.json](./sample_infrastructure_plan.json) for a complete example.
research.md 4.2 KB
# Research Phase

Research is sequential: identify resources β†’ call WAF tools β†’ refine β†’ load resource files.

## Input Analysis

| Scenario | Action |
|----------|--------|
| Repository | Scan `package.json`, `requirements.txt`, `Dockerfile`, `*.csproj` for runtime/dependencies. |
| User requirements | Clarify workload purpose, traffic, data storage, security, budget. |
| Multi-environment | Ask about dev/staging/prod sizing differences. |

## Step 1 β€” Identify Core Resources and Sub-Goals

From the user's description, list the core Azure services (compute, data, networking, messaging). Also derive sub-goals β€” implicit constraints to include in `inputs.subGoals`:
- "assume all defaults" β†’ `"Cost-optimized: consumption/serverless tiers, minimal complexity"`
- production system β†’ `"Production-grade: zone redundancy, private networking, managed identity"`

## Step 2 β€” WAF Tool Calls

> Mandatory: Call WAF MCP tools before reading local resource files. Complete this step before proceeding.

1. Call `get_azure_bestpractices` with `resource: "general"`, `action: "all"` for baseline guidance.
2. Call `wellarchitectedframework_serviceguide_get` with `service: "<name>"` for each core service (in parallel). Examples: `"Container Apps"`, `"Cosmos DB"`, `"App Service"`, `"Event Grid"`, `"Key Vault"`.
3. The tool returns a markdown URL. Use a sub-agent to fetch and summarize in ≀500 tokens, focusing on: additional resources needed, required properties for security/reliability, key design decisions.
4. Collect all WAF findings: missing resources, property hardening, architecture patterns.

## Step 3 β€” Resource Refinement

> Mandatory: Walk through the WAF checklist and document what was added or intentionally omitted.

Walk through every concern in the [WAF cross-cutting checklist](waf-checklist.md) and add missing resources or harden properties. For each checklist item, either add the resource/property or document the intentional omission in `overallReasoning.tradeoffs` and `inputs.subGoals`. Present the refinement summary to the user before proceeding to Step 4.

## Step 4 β€” Resource Lookup via Tools

> Mandatory: Complete this step for every resource before generating the plan. WAF tools (Step 2) provide architecture guidance but do not provide ARM types, naming rules, or pairing constraints. This step fills those gaps. Read [resources/README.md](resources/README.md) to identify which category files contain the resources you need, then load only those category files.

For each resource identified in Steps 1-3:

1. Look up the resource in the relevant [resources/](resources/README.md) category file (e.g., `resources/compute-infra.md` for AKS, `resources/data-analytics.md` for Cosmos DB) to get its ARM type, API version, and CAF prefix. Read the index in `resources/README.md` to find the right category file.
2. Use a sub-agent to call `microsoft_docs_fetch` with the naming rules URL from the resource category file. Instruct the sub-agent: "Extract naming rules for {service}: min/max length, allowed characters, uniqueness scope. ≀200 tokens." Fall back to `microsoft_docs_search` with `"<resource-name> naming rules"` only if the URL is missing or returns an error.
3. Read pairing constraints for the resource from the matching [constraints/](constraints/README.md) category file (e.g., `constraints/networking-core.md` for VNet, `constraints/security.md` for Key Vault). Each category file is <2K tokens β€” read the whole file for all resources in that category.

   Use the [constraints/README.md](constraints/README.md) index to find the right category file for each resource name.

> Important: Only load the category files you need. For a plan with AKS + Cosmos DB + VNet + Key Vault, you'd load 4 constraint files and 4 resource files (~5,500 tokens total) instead of the full catalog (~21,600 tokens).

From the tool results, verify:

1. Type β€” Correct `Microsoft.*` resource type and API version
2. SKU β€” Available in target region, appropriate for workload
3. Region β€” Service available, data residency met
4. Name β€” CAF-compliant naming constraints
5. Dependencies β€” All prerequisites identified and ordered
6. Properties β€” Required properties per resource schema
7. Alternatives β€” At least one alternative with tradeoff documented
sample_infrastructure_plan.json 22.5 KB
{
  "meta": {
    "planId": "plan-1",
    "generatedAt": "2026-03-13T05:48:18.788Z",
    "version": "0.1-draft",
    "status": "draft"
  },
  "inputs": {
    "userGoal": "Provision an event-driven data processing pipeline using ACA with Pub/Sub integration, connect to Azure Event Grid, and output results to Cosmos DB.",
    "subGoals": [
      "Cost-optimized: user chose defaults β€” consumption/serverless tiers, minimal complexity",
      "Minimal complexity: single region (eastus), no VNet, no private endpoints",
      "Security baseline: managed identity for service-to-service auth, RBAC over keys, Key Vault for secrets"
    ]
  },
  "plan": {
    "resources": [
      {
        "name": "rg-datapipeline-dev-001",
        "type": "Microsoft.Resources/resourceGroups",
        "location": "eastus",
        "sku": "N/A",
        "properties": {},
        "reasoning": {
          "whyChosen": "Logical container for all pipeline resources. Single resource group simplifies management for a cost-optimized, single-environment deployment.",
          "alternativesConsidered": [
            "Multiple resource groups per service type"
          ],
          "tradeoffs": "Single resource group reduces governance granularity but simplifies RBAC and lifecycle management for a dev/default workload."
        },
        "dependencies": [],
        "dependencyReasoning": "No dependencies β€” resource group is the top-level container.",
        "references": [
          {
            "title": "Resource group overview",
            "url": "https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal"
          }
        ]
      },
      {
        "name": "log-datapipeline-dev-001",
        "type": "Microsoft.OperationalInsights/workspaces",
        "location": "eastus",
        "sku": "PerGB2018",
        "properties": {
          "retentionInDays": 30,
          "publicNetworkAccessForIngestion": "Enabled",
          "publicNetworkAccessForQuery": "Enabled"
        },
        "reasoning": {
          "whyChosen": "Required by Container Apps Environment for log aggregation (WAF Operational Excellence). PerGB2018 is the recommended default pay-as-you-go tier. Provides centralized monitoring across all pipeline resources.",
          "alternativesConsidered": [
            "Azure Monitor (no workspace) β€” insufficient for CAE requirement",
            "Free tier β€” 500 MB/day limit too restrictive"
          ],
          "tradeoffs": "Pay-as-you-go pricing; 30-day retention keeps costs minimal. Public network access enabled per cost-optimized sub-goal (no VNet)."
        },
        "dependencies": [
          "rg-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Must be created inside the resource group before the Container Apps Environment references it.",
        "references": [
          {
            "title": "Log Analytics overview",
            "url": "https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview"
          },
          {
            "title": "Bicep resource reference (2025-02-01)",
            "url": "https://learn.microsoft.com/azure/templates/microsoft.operationalinsights/workspaces?pivots=deployment-language-bicep"
          }
        ]
      },
      {
        "name": "id-datapipeline-dev-001",
        "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
        "location": "eastus",
        "sku": "N/A",
        "properties": {},
        "reasoning": {
          "whyChosen": "WAF Security pillar: managed identity for service-to-service auth eliminates credential management. Shared identity assigned to the Container App for accessing Event Grid (publish/subscribe) and Cosmos DB (data read/write). Best practices mandate managed identity over key-based auth.",
          "alternativesConsidered": [
            "System-assigned managed identity per resource β€” harder to pre-assign RBAC roles in IaC",
            "Connection strings/keys β€” violates security best practices"
          ],
          "tradeoffs": "Single shared identity simplifies RBAC but provides less granular isolation than per-resource identities."
        },
        "dependencies": [
          "rg-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Must exist before role assignments and before the Container App references it.",
        "references": [
          {
            "title": "Managed identities overview",
            "url": "https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview"
          },
          {
            "title": "Bicep resource reference (2024-11-30)",
            "url": "https://learn.microsoft.com/azure/templates/microsoft.managedidentity/userassignedidentities?pivots=deployment-language-bicep"
          }
        ]
      },
      {
        "name": "kv-datapipeline-dev-001",
        "type": "Microsoft.KeyVault/vaults",
        "location": "eastus",
        "sku": "standard",
        "properties": {
          "enableRbacAuthorization": true,
          "enableSoftDelete": true,
          "enablePurgeProtection": true,
          "softDeleteRetentionInDays": 90,
          "tenantId": "<tenant-id>",
          "sku": {
            "name": "standard",
            "family": "A"
          }
        },
        "reasoning": {
          "whyChosen": "WAF Security pillar: centralized secrets management for any connection strings, certificates, or API keys the pipeline may need. RBAC authorization preferred over access policies per best practices. Soft delete and purge protection enabled per WAF checklist.",
          "alternativesConsidered": [
            "No Key Vault, rely solely on managed identity β€” insufficient if any third-party secrets are needed",
            "Premium SKU with HSM β€” overkill for cost-optimized defaults"
          ],
          "tradeoffs": "Standard SKU provides software-protected keys which is sufficient for non-HSM workloads. Purge protection prevents accidental permanent deletion but makes cleanup harder during dev."
        },
        "dependencies": [
          "rg-datapipeline-dev-001",
          "id-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Needs resource group. Managed identity referenced for RBAC role assignments on the vault.",
        "references": [
          {
            "title": "Key Vault overview",
            "url": "https://learn.microsoft.com/azure/key-vault/general/overview"
          },
          {
            "title": "Bicep resource reference (2024-11-01)",
            "url": "https://learn.microsoft.com/azure/templates/microsoft.keyvault/vaults?pivots=deployment-language-bicep"
          }
        ]
      },
      {
        "name": "cae-datapipeline-dev-001",
        "type": "Microsoft.App/managedEnvironments",
        "location": "eastus",
        "sku": "Consumption",
        "properties": {
          "appLogsConfiguration": {
            "destination": "log-analytics",
            "logAnalyticsConfiguration": {
              "customerId": "<customer-id>",
              "sharedKey": "<shared-key>"
            }
          },
          "workloadProfiles": [
            {
              "workloadProfileType": "Consumption",
              "name": "Consumption"
            }
          ],
          "zoneRedundant": false,
          "peerAuthentication": {
            "mtls": {
              "enabled": true
            }
          }
        },
        "reasoning": {
          "whyChosen": "Required hosting environment for Container Apps. Consumption workload profile provides serverless auto-scaling (including scale-to-zero) aligned with cost-optimized defaults. Dapr integration for pub/sub is configured at the environment level. mTLS enabled for service-to-service security per WAF guidance.",
          "alternativesConsidered": [
            "Dedicated workload profiles (D4/E4) β€” unnecessary cost for defaults",
            "AKS β€” more operational overhead, overkill for this workload",
            "Azure Functions β€” less flexible for custom container workloads"
          ],
          "tradeoffs": "Consumption-only environment lacks UDR support, NAT Gateway egress, and private endpoints. Zone redundancy disabled to minimize cost. These are acceptable per cost-optimized sub-goal."
        },
        "dependencies": [
          "rg-datapipeline-dev-001",
          "log-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Log Analytics workspace must exist first β€” environment requires customerId and sharedKey for log aggregation.",
        "references": [
          {
            "title": "Container Apps environments overview",
            "url": "https://learn.microsoft.com/azure/container-apps/environment"
          },
          {
            "title": "Bicep resource reference (2025-01-01)",
            "url": "https://learn.microsoft.com/azure/templates/microsoft.app/managedenvironments?pivots=deployment-language-bicep"
          },
          {
            "title": "Workload profiles overview",
            "url": "https://learn.microsoft.com/azure/container-apps/workload-profiles-overview"
          }
        ]
      },
      {
        "name": "evgt-datapipeline-dev-001",
        "type": "Microsoft.EventGrid/topics",
        "location": "eastus",
        "sku": "Basic",
        "properties": {
          "inputSchema": "CloudEventSchemaV1_0",
          "publicNetworkAccess": "Enabled",
          "disableLocalAuth": true,
          "identity": {
            "type": "SystemAssigned"
          }
        },
        "reasoning": {
          "whyChosen": "Azure Event Grid provides serverless event routing with native CloudEvents support, ideal for the event-driven pipeline. Basic SKU sufficient for standard event routing without private endpoints. CloudEvents v1.0 schema chosen for interoperability with Dapr pub/sub. Local auth disabled per WAF Security hardening β€” managed identity used instead.",
          "alternativesConsidered": [
            "Event Hubs β€” higher throughput but more complex and costly for event routing",
            "Service Bus β€” better for ordered/transactional messaging, overkill for event-driven pipeline",
            "Premium SKU β€” adds private endpoints, unnecessary per cost-optimized sub-goal"
          ],
          "tradeoffs": "Basic SKU lacks private endpoint support. Public network access enabled per cost-optimized sub-goal. System-assigned identity used for dead-letter and delivery authentication."
        },
        "dependencies": [
          "rg-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Only requires the resource group. Event subscription to the Container App is configured after both resources exist.",
        "references": [
          {
            "title": "Event Grid overview",
            "url": "https://learn.microsoft.com/azure/event-grid/overview"
          },
          {
            "title": "Bicep resource reference (2025-02-15)",
            "url": "https://learn.microsoft.com/azure/templates/microsoft.eventgrid/topics?pivots=deployment-language-bicep"
          },
          {
            "title": "Event Grid security and authentication",
            "url": "https://learn.microsoft.com/azure/event-grid/security-authentication"
          }
        ]
      },
      {
        "name": "cosmos-datapipeline-dev-001",
        "type": "Microsoft.DocumentDB/databaseAccounts",
        "subtype": "NoSQL (SQL API)",
        "location": "eastus",
        "sku": "Serverless",
        "properties": {
          "kind": "GlobalDocumentDB",
          "databaseAccountOfferType": "Standard",
          "capabilities": [
            {
              "name": "EnableServerless"
            }
          ],
          "consistencyPolicy": {
            "defaultConsistencyLevel": "Session"
          },
          "locations": [
            {
              "locationName": "eastus",
              "failoverPriority": 0,
              "isZoneRedundant": false
            }
          ],
          "enableAutomaticFailover": false,
          "enableMultipleWriteLocations": false,
          "publicNetworkAccess": "Enabled",
          "disableLocalAuth": true
        },
        "reasoning": {
          "whyChosen": "Cosmos DB NoSQL API with Serverless capacity mode is ideal for event-driven workloads with variable/unpredictable traffic β€” pay only per RU consumed with no minimum throughput. Session consistency balances performance and correctness. Local auth disabled per WAF Security β€” RBAC with managed identity used for data plane access.",
          "alternativesConsidered": [
            "Provisioned throughput (autoscale) β€” unnecessary cost for defaults/dev workload",
            "Azure SQL β€” relational model less suited for flexible event data schemas",
            "Azure Table Storage β€” limited query capabilities compared to Cosmos DB"
          ],
          "tradeoffs": "Serverless is single-region only, no multi-region writes, no shared-throughput databases. No zone redundancy. Acceptable for cost-optimized defaults. Public network access enabled (no VNet per sub-goal)."
        },
        "dependencies": [
          "rg-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Only requires the resource group. The Container App will reference the Cosmos DB endpoint via managed identity.",
        "references": [
          {
            "title": "Cosmos DB overview",
            "url": "https://learn.microsoft.com/azure/cosmos-db/introduction"
          },
          {
            "title": "Bicep resource reference (2025-04-15)",
            "url": "https://learn.microsoft.com/azure/templates/microsoft.documentdb/databaseaccounts?pivots=deployment-language-bicep"
          },
          {
            "title": "Serverless capacity mode",
            "url": "https://learn.microsoft.com/azure/cosmos-db/serverless"
          },
          {
            "title": "Consistency levels",
            "url": "https://learn.microsoft.com/azure/cosmos-db/consistency-levels"
          }
        ]
      },
      {
        "name": "cosmos-datapipeline-dev-001/pipeline-db",
        "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
        "location": "eastus",
        "sku": "N/A",
        "properties": {
          "resource": {
            "id": "pipeline-db"
          }
        },
        "reasoning": {
          "whyChosen": "SQL Database container for the NoSQL API. Required parent resource for Cosmos DB containers that store pipeline output data.",
          "alternativesConsidered": [
            "MongoDB API database β€” SQL/NoSQL API is simpler and more widely supported"
          ],
          "tradeoffs": "Serverless accounts do not support shared-throughput databases β€” throughput is per-container only."
        },
        "dependencies": [
          "cosmos-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Child resource β€” Cosmos DB account must exist first.",
        "references": [
          {
            "title": "Cosmos DB SQL databases",
            "url": "https://learn.microsoft.com/azure/cosmos-db/nosql/how-to-create-database"
          }
        ]
      },
      {
        "name": "cosmos-datapipeline-dev-001/pipeline-db/processed-events",
        "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
        "location": "eastus",
        "sku": "N/A",
        "properties": {
          "resource": {
            "id": "processed-events",
            "partitionKey": {
              "paths": [
                "/partitionKey"
              ],
              "kind": "Hash",
              "version": 2
            }
          }
        },
        "reasoning": {
          "whyChosen": "Container to store processed event results from the data pipeline. Partition key on /partitionKey allows flexible partitioning strategy. Hash v2 provides better distribution.",
          "alternativesConsidered": [
            "Multiple containers per event type β€” premature optimization for defaults"
          ],
          "tradeoffs": "Single container with generic partition key; production workloads should optimize partition key based on actual query patterns."
        },
        "dependencies": [
          "cosmos-datapipeline-dev-001/pipeline-db"
        ],
        "dependencyReasoning": "Child resource β€” SQL Database must exist first.",
        "references": [
          {
            "title": "Cosmos DB containers",
            "url": "https://learn.microsoft.com/azure/cosmos-db/nosql/how-to-create-container"
          },
          {
            "title": "Partitioning overview",
            "url": "https://learn.microsoft.com/azure/cosmos-db/partitioning-overview"
          }
        ]
      },
      {
        "name": "ca-processor-dev-001",
        "type": "Microsoft.App/containerApps",
        "location": "eastus",
        "sku": "Consumption",
        "properties": {
          "environmentId": "<environment-resource-id>",
          "identity": {
            "type": "UserAssigned",
            "userAssignedIdentities": {
              "<managed-identity-resource-id>": {}
            }
          },
          "configuration": {
            "dapr": {
              "enabled": true,
              "appId": "processor",
              "appPort": 8080,
              "appProtocol": "http"
            },
            "ingress": {
              "external": false,
              "targetPort": 8080,
              "transport": "auto"
            },
            "activeRevisionsMode": "Single",
            "secrets": []
          },
          "template": {
            "containers": [
              {
                "name": "processor",
                "image": "mcr.microsoft.com/k8se/quickstart:latest",
                "resources": {
                  "cpu": 0.5,
                  "memory": "1Gi"
                }
              }
            ],
            "scale": {
              "minReplicas": 0,
              "maxReplicas": 10
            }
          }
        },
        "reasoning": {
          "whyChosen": "Container App hosts the data processing workload. Dapr sidecar enabled for pub/sub integration with Event Grid β€” Dapr abstracts messaging infrastructure. Scale-to-zero with max 10 replicas provides cost-efficient auto-scaling for event-driven processing. 0.5 CPU / 1Gi memory is a valid consumption-tier combination. Internal ingress only (no public access) since events arrive via Dapr/Event Grid subscription. User-assigned managed identity for Cosmos DB and Event Grid access.",
          "alternativesConsidered": [
            "Azure Functions with Event Grid trigger β€” less flexible for custom containers",
            "AKS pod β€” more operational overhead",
            "Multiple Container Apps per processing stage β€” premature for defaults"
          ],
          "tradeoffs": "Placeholder quickstart image β€” must be replaced with actual processing container. Scale-to-zero means cold start latency on first event. Single revision mode simplifies management but prevents blue-green deployments."
        },
        "dependencies": [
          "cae-datapipeline-dev-001",
          "id-datapipeline-dev-001",
          "evgt-datapipeline-dev-001",
          "cosmos-datapipeline-dev-001"
        ],
        "dependencyReasoning": "Requires environment (hosting), managed identity (auth), Event Grid topic (event source), and Cosmos DB account (output destination) to be provisioned first.",
        "references": [
          {
            "title": "Container Apps overview",
            "url": "https://learn.microsoft.com/azure/container-apps/overview"
          },
          {
            "title": "Bicep resource reference (2025-01-01)",
            "url": "https://learn.microsoft.com/azure/templates/microsoft.app/containerapps?pivots=deployment-language-bicep"
          },
          {
            "title": "Dapr integration in Container Apps",
            "url": "https://learn.microsoft.com/azure/container-apps/dapr-overview"
          },
          {
            "title": "Container Apps scaling",
            "url": "https://learn.microsoft.com/azure/container-apps/scale-app"
          }
        ]
      }
    ],
    "overallReasoning": {
      "summary": "This plan provisions a serverless, event-driven data processing pipeline on Azure Container Apps. Events are published to an Event Grid Topic (CloudEvents schema), routed via Dapr pub/sub to a Container App processor, and results are written to Cosmos DB (Serverless, NoSQL API). The architecture uses Consumption-tier compute, serverless database, and Basic event routing to minimize cost. A user-assigned managed identity provides secure, keyless service-to-service authentication. Log Analytics provides centralized monitoring, and Key Vault is included for any secrets management needs.",
      "tradeoffs": "Cost-optimized defaults omit: VNet/private endpoints (public network access on all resources), zone redundancy, multi-region failover, and dedicated workload profiles. These should be addressed when moving to production. Serverless Cosmos DB is single-region only. Basic Event Grid SKU lacks private endpoints. No Application Insights component is included β€” add for production observability. Placeholder container image must be replaced with actual processing logic."
    },
    "validation": "All resources deploy to eastus in a single resource group. Container Apps Environment requires Log Analytics (dependency ordered). Container App references the environment, managed identity, and connects to Event Grid and Cosmos DB via Dapr/SDK using managed identity RBAC. Cosmos DB serverless is single-region with Session consistency (no conflict with multi-region constraints). Event Grid Basic SKU with CloudEvents schema is compatible with Dapr pub/sub. CPU/memory combination (0.5/1Gi) is valid for Consumption tier. No subnet delegation conflicts (no VNet). Key Vault has soft delete and purge protection enabled per WAF requirements.",
    "architecturePrinciples": [
      "Event-driven: loosely coupled components communicating via Event Grid and Dapr pub/sub",
      "Serverless-first: Consumption-tier Container Apps and Serverless Cosmos DB for cost efficiency",
      "Secure by default: managed identity, RBAC, local auth disabled, mTLS between services",
      "Observable: centralized logging via Log Analytics with Container Apps Environment integration",
      "Infrastructure as Code: all resources defined declaratively for reproducible deployments"
    ],
    "references": [
      {
        "title": "Event-driven architecture on Azure",
        "url": "https://learn.microsoft.com/azure/architecture/guide/architecture-styles/event-driven"
      },
      {
        "title": "Container Apps with Dapr",
        "url": "https://learn.microsoft.com/azure/container-apps/dapr-overview"
      },
      {
        "title": "Azure Well-Architected Framework",
        "url": "https://learn.microsoft.com/azure/well-architected/"
      }
    ]
  }
}
terraform-generation.md 2.6 KB
# Terraform Generation

Generate Terraform IaC files from the approved infrastructure plan.

## File Structure

Generate files under `<project-root>/infra/`:

```
infra/
β”œβ”€β”€ main.tf                 # Root module β€” calls child modules
β”œβ”€β”€ variables.tf            # Input variable declarations
β”œβ”€β”€ outputs.tf              # Output values
β”œβ”€β”€ terraform.tfvars        # Default variable values
β”œβ”€β”€ providers.tf            # Provider configuration
β”œβ”€β”€ backend.tf              # State backend configuration
└── modules/
    β”œβ”€β”€ storage/
    β”‚   β”œβ”€β”€ main.tf
    β”‚   β”œβ”€β”€ variables.tf
    β”‚   └── outputs.tf
    β”œβ”€β”€ compute/
    β”‚   β”œβ”€β”€ main.tf
    β”‚   β”œβ”€β”€ variables.tf
    β”‚   └── outputs.tf
    └── networking/
        β”œβ”€β”€ main.tf
        β”œβ”€β”€ variables.tf
        └── outputs.tf
```

## Generation Steps

1. Create `infra/` directory β€” create `<project-root>/infra/` and `<project-root>/infra/modules/` directories. All files in subsequent steps go here.
2. Read plan β€” load `<project-root>/.azure/infrastructure-plan.json`, verify `meta.status === "approved"`
3. Generate providers.tf β€” write `infra/providers.tf` to configure `azurerm` provider with required features
4. Generate modules β€” group resources by category; one module per group under `infra/modules/`
5. Generate root main.tf β€” write `infra/main.tf` that calls all modules, wire outputs to inputs
6. Generate variables.tf β€” write `infra/variables.tf` with all configurable parameters
7. Generate terraform.tfvars β€” write `infra/terraform.tfvars` with default values from the plan
8. Generate backend.tf β€” write `infra/backend.tf` for Azure Storage backend remote state

## Terraform Conventions

- Use `azurerm` provider (latest stable version)
- Set `features {}` block in provider configuration
- Use `variable` blocks with `description`, `type`, and `default` where appropriate
- Use `locals` for computed values and naming patterns
- Use `depends_on` only when implicit dependencies are insufficient
- Tag all resources with `environment`, `workload`, and `managed-by = "terraform"`

## Provider Configuration

```hcl
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}

provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
}
```

## Multi-Environment

For multi-environment plans, generate one `.tfvars` file per environment:

```
infra/
β”œβ”€β”€ main.tf
β”œβ”€β”€ variables.tf
β”œβ”€β”€ dev.tfvars
β”œβ”€β”€ staging.tfvars
└── prod.tfvars
```

Deploy with: `terraform apply -var-file=prod.tfvars`

## Validation Before Deployment

Run `terraform validate` and `terraform plan` to verify before applying.
verification.md 1.6 KB
# Resource Verification

Run these checks immediately after writing each resource to `plan.resources[]`. Fix issues in-place before moving to the next resource. Load the relevant category file from [resources/](resources/README.md) for naming constraints, valid SKUs, and pairing rules.

## 1. Name Checks

| # | Check | Fix |
|---|-------|-----|
| 1 | Follows CAF pattern from resource file Identity/Naming section | Rewrite using correct abbreviation |
| 2 | Length within min/max for type | Truncate or restructure |
| 3 | Only allowed characters for type | Strip disallowed characters |
| 4 | Globally-unique names avoid collisions | Add distinguishing suffix |
| 5 | Required subnet names exact (`AzureFirewallSubnet`, `GatewaySubnet`, `AzureBastionSubnet`) | Use exact required string |
| 6 | Function Apps sharing Storage diverge within first 32 chars | Rename or separate storage |
| 7 | AKS `MC_{rg}_{cluster}_{region}` ≀ 80 chars | Shorten names |

## 2. Dependency Checks

| # | Check | Fix |
|---|-------|-----|
| 1 | Every `dependencies` entry references an existing resource name in the plan | Add missing resource or remove stale ref |
| 2 | Implicit dependencies are explicit (subnet→VNet, App Service→Plan) | Add missing entries |
| 3 | No circular dependencies | Break weaker edge |

## 3. Property & Pairing Checks

Cross-check against every already-written connected resource. Consult the resource file's Pairing Constraints section and [pairing-checks.md](pairing-checks.md) for full rules covering: SKU compatibility, subnet/network conflicts, storage pairing, Cosmos DB, Key Vault/CMK, SQL Database, and AKS networking.
waf-checklist.md 1.8 KB
# WAF Cross-Cutting Checklist

Walk through every row and decide if resources or properties are needed.

| Concern | Question | Resources / Properties to Add |
|---------|----------|-------------------------------|
| Identity | How do services authenticate to each other? | Managed identity (`Microsoft.ManagedIdentity/userAssignedIdentities`), RBAC role assignments |
| Secrets | Are there connection strings, API keys, credentials? | Key Vault (`Microsoft.KeyVault/vaults`) with `enableRbacAuthorization: true`, `enableSoftDelete: true`, `enablePurgeProtection: true` |
| Monitoring | How will operators observe the system? | Application Insights for compute resources, Log Analytics workspace, diagnostic settings per data resource |
| Network | Should resources have public endpoints? | Production β†’ VNet + private endpoints, `publicNetworkAccess: "Disabled"`. Cost-optimized β†’ document omission as tradeoff. |
| Encryption | Is data encrypted at rest and in transit? | `httpsOnly: true`, `minTlsVersion: "1.2"`, Key Vault for CMK |
| Resilience | Single points of failure? | `zoneRedundant: true` on supported SKUs. Cost-optimized β†’ document as tradeoff. |
| Auth hardening | Can local/key-based auth be disabled? | `disableLocalAuth: true` on Event Grid, Service Bus, Storage |
| Tagging | Resources tagged for cost tracking? | Tags on every resource |

## Common Additions

Most workloads should include these unless sub-goals justify omission:

- Key Vault β€” secrets, certificates, CMK
- Managed Identity β€” prefer over keys for service-to-service auth
- Application Insights β€” for App Service, Functions, Container Apps, AKS
- Log Analytics β€” centralized log aggregation
- Diagnostic Settings β€” wire Cosmos DB, SQL, Storage to Log Analytics

If you intentionally skip a concern (e.g., no VNet for cost reasons), document it in `overallReasoning.tradeoffs` and `inputs.subGoals`.
workflow.md 4.5 KB
# Workflow β€” Azure Enterprise Infra Planner

## Rules

1. Research before planning β€” call `mcp_azure_mcp_get_azure_bestpractices` and `mcp_azure_mcp_wellarchitectedframework` MCP tools before reading local resource files or generating a plan. See [research.md](research.md) Step 2.
2. Plan before IaC β€” generate `<project-root>/.azure/infrastructure-plan.json` before any IaC so we can map the plan to generated code and ensure alignment.
3. Get approval β€” plan status must be `approved` before deployment.
4. User chooses IaC format β€” Bicep or Terraform; ask if not specified.
5. Destructive actions require explicit confirmation.

> Complete each phase fully before starting the next. Phases are sequential, not parallel.

## Phase 1: Research β€” WAF Tools
Call MCP tools to gather best practices and WAF guidance. See [research.md](research.md) Steps 1-2.
- Call `get_azure_bestpractices` once (direct call β€” small response)
- Call `wellarchitectedframework_serviceguide_get` for each core service (direct parallel calls β€” small responses, returns URLs only)
- Use sub-agents to fetch and summarize each WAF guide URL (large responses β€” 20-60KB each)

Gate: All WAF tool calls complete and summarized before proceeding.

## Phase 2: Research β€” Refine & Lookup

Look up resources before generating the plan. The [resources/](resources/README.md) directory contains ARM types, API versions, CAF prefixes, naming rule URLs, and region categories that MCP tools do not provide.

Apply WAF findings, then look up every resource in local reference files. See [research.md](research.md) Steps 3-4.
- Walk through [waf-checklist.md](waf-checklist.md) β€” add missing resources, document omissions
- Read [resources/README.md](resources/README.md) to identify which category files to load, then read only the relevant category files (e.g., `resources/compute-infra.md` for AKS, `resources/security.md` for Key Vault)
- For each resource: use sub-agents to fetch naming rules via `microsoft_docs_fetch` using URLs from the resource category files
- For each resource: read pairing constraints from the matching [constraints/](constraints/README.md) category file (e.g., `constraints/networking-core.md` for VNet)

Gate: Every resource has an ARM type, naming rules, and pairing constraints checked. Present the preliminary resource list to the user with brief justifications and wait for approval before proceeding.

## Phase 3: Plan Generation
Build `<project-root>/.azure/infrastructure-plan.json` using the schema in [plan-schema.md](plan-schema.md). Set `meta.status` to `draft`.

Gate: Plan JSON written to disk before proceeding.

## Phase 4: Verification
Run a full verification pass on the generated plan. See [verification.md](verification.md) and [pairing-checks.md](pairing-checks.md).
- Check goal coverage β€” does every user requirement map to a resource?
- Check dependency completeness β€” every `dependencies[]` entry resolves
- Check pairing constraints β€” SKU compatibility, subnet conflicts, storage pairing
- Fix issues in-place in the plan JSON

Gate: All verification checks pass. Present plan to user and wait for approval before proceeding.

## Phase 5: IaC Generation
Generate Bicep or Terraform from the approved plan. Refer to [bicep-generation.md](bicep-generation.md) for Bicep or [terraform-generation.md](terraform-generation.md) for Terraform.

Gate: `meta.status` must be `approved` before generating any IaC files.

## Phase 6: Deployment
Execute deployment commands. See [deployment.md](deployment.md).
- Confirm subscription and resource group with user
- Select the correct deployment scope based on `targetScope` in `main.bicep` (resource group, subscription, management group, or tenant)
- Run `az bicep build` to validate, then execute the matching scope command (`az deployment group create`, `az deployment sub create`, etc.) or `terraform apply`

Gate: `meta.status` must be `approved`. Destructive actions require explicit user confirmation.

## Status Lifecycle

`draft` β†’ `approved` β†’ `deployed`

## Outputs

| Artifact | Location |
|----------|----------|
| Infrastructure Plan | `<project-root>/.azure/infrastructure-plan.json` |
| Bicep files | `<project-root>/infra/main.bicep`, `<project-root>/infra/modules/*.bicep` |
| Terraform files | `<project-root>/infra/main.tf`, `<project-root>/infra/modules/**/*.tf` |

Before writing any `.bicep` or `.tf` files:
1. Create the `infra/` directory at `<project-root>/infra/`
2. Create `infra/modules/` for child modules
3. Write `main.bicep` (or `main.tf`) inside `infra/`, not in the project root or `.azure/`

references/constraints/
README.md 1.3 KB
# Pairing Constraints Index

Load only the files matching resources identified in Phase 1.

| Sub-Category | File | Resources |
|-------------|------|-----------|
| AI & ML | [ai-ml.md](ai-ml.md) | AI Search, Cognitive Services, ML Workspace |
| Compute (PaaS) | [compute-apps.md](compute-apps.md) | App Service, ASP, Function App, Container App, CAE, ACR, Static Web App |
| Compute (IaaS) | [compute-infra.md](compute-infra.md) | AKS, VM, VMSS, Availability Set, Managed Disk |
| Data (Relational) | [data-relational.md](data-relational.md) | SQL Server, SQL Database, MySQL, PostgreSQL |
| Data (Analytics) | [data-analytics.md](data-analytics.md) | Cosmos DB, Redis, Storage, Data Factory, Synapse |
| Messaging | [messaging.md](messaging.md) | Event Grid, Event Hub, Service Bus |
| Monitoring | [monitoring.md](monitoring.md) | App Insights, Log Analytics |
| Networking (Core) | [networking-core.md](networking-core.md) | VNet, Subnet, NSG, Route Table, NIC, Public IP, NAT Gateway |
| Networking (Traffic) | [networking-traffic.md](networking-traffic.md) | App Gateway, Front Door, LB, APIM |
| Networking (Connectivity) | [networking-connectivity.md](networking-connectivity.md) | Bastion, Firewall, VPN GW, DNS, Private DNS, PE |
| Security | [security.md](security.md) | Key Vault, Managed Identity |
ai-ml.md 3.3 KB
# AI & ML Pairing Constraints

### AI Search

| Paired With | Constraint |
|-------------|------------|
| **Cognitive Services (AI Enrichment)** | For AI enrichment pipelines (skillsets), attach a Cognitive Services account. Must be `kind: 'CognitiveServices'` or `kind: 'AIServices'` and in the same region as the search service. |
| **Storage Account (Indexers)** | Indexer data sources support Blob, Table, and File storage. Storage must be accessible (same VNet or public). For managed identity access, assign `Storage Blob Data Reader` role. |
| **Cosmos DB (Indexers)** | Indexer data source for Cosmos DB. Requires connection string or managed identity with `Cosmos DB Account Reader Role`. |
| **SQL Database (Indexers)** | Indexer data source. Requires change tracking enabled on the source table. |
| **Private Endpoints** | When `publicNetworkAccess: 'Disabled'`, create shared private link resources for outbound connections to data sources. |
| **Managed Identity** | Assign system or user-assigned identity for secure connections to data sources. Use RBAC instead of connection strings. |
| **Semantic Search** | Requires `semanticSearch` property set to `free` or `standard`. Available on `basic` and above SKUs. |

### Cognitive Services

| Paired With | Constraint |
|-------------|------------|
| **Azure OpenAI Deployments** | When `kind: 'OpenAI'` or `kind: 'AIServices'`, create model deployments as child resource `accounts/deployments`. |
| **Microsoft Entra ID Auth** | Requires `customSubDomainName` to be set. Without it, only API key auth works. |
| **Private Endpoint** | Requires `customSubDomainName`. Set `publicNetworkAccess: 'Disabled'` and configure private DNS zone. |
| **Key Vault (CMK)** | When using customer-managed keys, Key Vault must have soft-delete and purge protection enabled. Set `encryption.keySource: 'Microsoft.KeyVault'`. |
| **Storage Account** | When using `userOwnedStorage`, the storage account must be in the same region. Required for certain features (e.g., batch translation). |
| **AI Foundry Hub** | When `kind: 'AIServices'` with `allowProjectManagement: true`, can manage Foundry projects as child resources (`accounts/projects`). |
| **VNet Integration** | Configure `networkAcls` with `defaultAction: 'Deny'` and add virtual network rules. Set `bypass: 'AzureServices'` to allow trusted Azure services. |

### ML Workspace

| Paired With | Constraint |
|-------------|------------|
| **Storage Account** | Must be linked via `properties.storageAccount`. Cannot change after creation. Use `StorageV2` kind with standard SKU. |
| **Key Vault** | Must be linked via `properties.keyVault`. Cannot change after creation. Requires soft-delete enabled. |
| **Application Insights** | Linked via `properties.applicationInsights`. Should use workspace-based App Insights (backed by Log Analytics). |
| **Container Registry** | Optional but recommended for custom environments. Linked via `properties.containerRegistry`. |
| **Hub workspace (kind=Project)** | Must set `properties.hubResourceId` to the parent Hub's ARM resource ID. The Project inherits the Hub's linked resources. |
| **VNet Integration** | When `managedNetwork.isolationMode` is `AllowOnlyApprovedOutbound`, must configure outbound rules for all dependent services. |
compute-apps.md 7.9 KB
# Compute (PaaS) Pairing Constraints

### App Service

| Paired With | Constraint |
|-------------|------------|
| **App Service Plan** | Must be in the same region. Linux apps need Linux plan (`reserved: true`). Windows apps need Windows plan. |
| **Deployment Slots** | Only available on Standard or higher plan tiers. Free and Basic do not support slots. |
| **VNet Integration** | Requires Basic or higher plan tier. Subnet must be delegated to `Microsoft.Web/serverFarms`. VNet integration subnet must be a different subnet than any Private Endpoint subnet. |
| **Private Endpoints** | Requires Basic or higher plan tier. Not available on Free or Shared tiers. |
| **Custom Domain** | Requires Shared (D1) or higher tier for custom domains. Free tier only supports `*.azurewebsites.net`. Managed certificates require Basic or higher. |
| **Application Insights** | Set `APPLICATIONINSIGHTS_CONNECTION_STRING` in app settings. |
| **Key Vault References** | Use `@Microsoft.KeyVault(SecretUri=...)` in app settings. Requires managed identity with Key Vault access. |
| **Managed Identity** | Enable `identity.type: 'SystemAssigned'` or `'UserAssigned'` for passwordless auth to other Azure resources. |

### App Service Plan

| Paired With | Constraint |
|-------------|------------|
| **Function App** | Consumption (`Y1`) and Flex (`FC1`) plans cannot be shared with web apps. EP plans can host both functions and web apps. |
| **Linux Apps** | Linux plan (`reserved: true`) cannot host Windows apps and vice versa. |
| **Zone Redundancy** | Requires Premium v3 (`P1v3`+) or Isolated v2. Minimum 3 instances. |
| **Deployment Slots** | Slots share plan capacity. Standard+ tier required. Slots are not available on Free/Basic. |
| **Auto-scale** | Not available on Free/Shared/Basic. Standard+ required for manual scale, auto-scale. |
| **VNet Integration** | Requires Basic or higher. Subnet must be delegated to `Microsoft.Web/serverFarms`. Minimum subnet size /28 (or /26 for multi-plan subnet join). VNet integration subnet must be a different subnet than any Private Endpoint subnet. |
| **Private Endpoints** | Requires Basic tier or higher. Not available on Free or Shared tiers. |
| **Isolated Compute** | Dedicated single-tenant compute requires IsolatedV2 (`I1v2`+) tier. |
| **Free/Shared Tiers** | Free (`F1`) and Shared (`D1`) use shared compute with no VNet integration, no private endpoints, no deployment slots, no Always On, and no auto-scale. Managed Identity is available but limited. |

### Container App

| Paired With | Constraint |
|-------------|------------|
| **Container Apps Environment** | Must reference `environmentId`. Environment must exist in the same region. |
| **VNet** | VNet integration is configured on the **Environment**, not the individual app. Environment needs a dedicated subnet with minimum /23 prefix for Consumption-only environments or /27 for workload profiles environments. |
| **Container Registry** | Requires registry credentials in `configuration.registries[]` or managed identity-based pull. |
| **Dapr** | Enable via `configuration.dapr.enabled: true`. Dapr components are configured on the Environment. |
| **CPU/Memory** | CPU and memory must follow valid combinations: 0.25 cores/0.5Gi, 0.5/1Gi, 1/2Gi, 2/4Gi, 4/8Gi (consumption). |
| **Scale Rules** | KEDA-based scale rules reference secrets by name β€” secrets must be defined in `configuration.secrets[]`. |

### Container Apps Environment

| Paired With | Constraint |
|-------------|------------|
| **Container App** | Container Apps reference the environment via `properties.environmentId`. Apps and environment must be in the same region. |
| **Log Analytics Workspace** | Provide `customerId` and `sharedKey` in `appLogsConfiguration`. Workspace must exist before the environment. |
| **VNet / Subnet** | Subnet must have a minimum /23 prefix for Consumption-only environments or /27 for workload profiles environments. Subnet must be dedicated to the Container Apps Environment (no other resources). Workload Profiles: subnet must be delegated to `Microsoft.App/environments`. Consumption-only: subnet MUST NOT be delegated to any service. |
| **Zone Redundancy** | Requires VNet integration. Zone-redundant environments need a /23 subnet in a region with availability zones. |
| **Internal Environment** | When `internal: true`, no public endpoint is created. Requires custom DNS or Private DNS Zone and a VNet with connectivity to clients. |
| **Workload Profiles** | At least one `Consumption` profile must be defined when using workload profiles. Dedicated profiles require `minimumCount` and `maximumCount`. |
| **Workload Profiles vs Consumption-only** | UDR support, NAT Gateway egress, private endpoints, and remote gateway peering are only available with Workload Profiles environments β€” not Consumption-only. |
| **Network Immutability** | Network type (Workload Profiles vs Consumption-only) is immutable after creation. Cannot change between environment types. |
| **IPv6** | IPv6 is not supported for either Workload Profiles or Consumption-only environments. |
| **VNet Move** | VNet-integrated environments cannot be moved to a different resource group or subscription while in use. |

### Container Registry

| Paired With | Constraint |
|-------------|------------|
| **AKS** | AKS needs `acrPull` role assignment on the registry. Use managed identity (attach via `az aks update --attach-acr`). |
| **Container App** | Reference in `configuration.registries[]`. Use managed identity or admin credentials. |
| **ML Workspace** | Referenced as `containerRegistry` property. Used for custom training/inference images. |
| **Private Endpoint** | Premium SKU required. Set `publicNetworkAccess: 'Disabled'`. |
| **Geo-Replication** | Premium SKU required. Configure via child `replications` resource. |
| **CMK** | Premium SKU required. Needs user-assigned identity with Key Vault access. |

### Function App

| Paired With | Constraint |
|-------------|------------|
| **Storage Account** | Must use `StorageV2` or `Storage` kind. `BlobStorage`, `BlockBlobStorage`, `FileStorage` not supported (need Queue + Table). |
| **Storage (Consumption)** | Consumption plan cannot use VNet-secured storage. Only Premium/Dedicated support VNet-restricted storage. |
| **Storage (ZRS)** | Zone-redundant functions require `Standard_ZRS` storage SKU. |
| **App Service Plan** | Plan must be in the same region. Linux functions need Linux plan (`reserved: true`). |
| **VNet Integration** | Requires Premium (EP) or Dedicated plan. Consumption does not support VNet integration (use Flex Consumption). |
| **Application Insights** | Set `APPINSIGHTS_INSTRUMENTATIONKEY` or `APPLICATIONINSIGHTS_CONNECTION_STRING` in app settings. |
| **Key Vault References** | App settings can use `@Microsoft.KeyVault(SecretUri=...)` syntax. Requires managed identity with Key Vault access. |

### Static Web App

| Paired With | Constraint |
|-------------|------------|
| **GitHub Repository** | Provide `repositoryUrl`, `branch`, and `repositoryToken`. A GitHub Actions workflow is auto-created in the repo. |
| **Azure DevOps** | Set `provider: 'DevOps'`. Provide `repositoryUrl` and `branch`. Pipeline is configured separately. |
| **Azure Functions (managed)** | API location in `buildProperties.apiLocation` deploys a managed Functions backend. Limited to HTTP triggers, C#, JavaScript, Python, Java. |
| **Linked Backend** | Use `linkedBackends` child resource to connect an existing Function App, Container App, or App Service as the API backend. Standard SKU required. |
| **Private Endpoint** | Only available with `Standard` SKU. Set up a Private Endpoint to restrict access to the static web app. |
| **Custom Domain** | Custom domains are child resources. Require DNS CNAME or TXT validation. Free SSL certificates are auto-provisioned. |
| **Enterprise-Grade CDN** | `Standard` SKU only. Enables Azure Front Door integration for advanced caching and edge capabilities. |
compute-infra.md 4.5 KB
# Compute (IaaS) Pairing Constraints

### AKS Cluster

| Paired With | Constraint |
|-------------|------------|
| **VNet / Subnet** | With Azure CNI, subnet must have enough IPs for nodes + pods (30 pods/node default Γ— node count). Subnet cannot have other delegations. Reserved CIDR ranges cannot be used: `169.254.0.0/16`, `172.30.0.0/16`, `172.31.0.0/16`, `192.0.2.0/24`. |
| **Pod CIDR** | Pod CIDR must not overlap with cluster subnet, peered VNets, ExpressRoute, or VPN address spaces. Overlapping causes SNAT/routing issues. |
| **kubenet** | Kubenet uses NAT β€” subnet only needs IPs for nodes. Less IP pressure but no direct pod-to-VNet connectivity. Kubenet is retiring March 2028 β€” migrate to CNI Overlay. Not supported by Application Gateway for Containers. |
| **CNI Overlay** | CNI Overlay does not support VM availability sets (must use VMSS-based node pools), virtual nodes, or DCsv2-series VMs (use DCasv5/DCadsv5 instead). |
| **Dual-stack CNI Overlay** | IPv4+IPv6 dual-stack disables Azure/Calico network policies, NAT gateway, and virtual nodes. |
| **Key Vault** | Enable `azureKeyvaultSecretsProvider` addon. Use `enableRbacAuthorization: true` on Key Vault with managed identity. |
| **Container Registry** | Attach ACR via `acrPull` role assignment on cluster identity, or use `imagePullSecrets`. |
| **Log Analytics** | Enable `omsagent` addon with `config.logAnalyticsWorkspaceResourceID` pointing to workspace. |
| **Load Balancer** | AKS creates a managed Standard LB by default (`loadBalancerSku: 'standard'`). |
| **System Pool** | At least one agent pool must have `mode: 'System'`. System pools run critical pods (CoreDNS, tunnelfront). |

### Availability Set

| Paired With | Constraint |
|-------------|------------|
| **Virtual Machine** | VMs must be in the same resource group. Set `vm.properties.availabilitySet.id`. |
| **Availability Zones** | Cannot combine with zones β€” availability zones supersede availability sets for zone-redundant architectures. |
| **Managed Disks** | `sku.name` must be `Aligned` when VMs use managed disks. |
| **VM Scale Set** | A VM cannot be in both an availability set and a VMSS. |

### Managed Disk

| Paired With | Constraint |
|-------------|------------|
| **Virtual Machine** | Attach via `storageProfile.osDisk` or `storageProfile.dataDisks`. Disk must be in same region. |
| **Availability Zone** | `PremiumV2_LRS` and `UltraSSD_LRS` require zone specification. |
| **Premium SSD v2** | Cannot be used as OS disk (data disks only). Does not support host caching (`ReadOnly`/`ReadWrite` unavailable). Requires zonal VM deployment. Cannot mix with other storage types on SQL Server VMs. |
| **Key Vault (CMK)** | Requires a Disk Encryption Set pointing to Key Vault key. Key Vault must have purge protection enabled. |

### Virtual Machine

| Paired With | Constraint |
|-------------|------------|
| **NIC** | At least one NIC required via `networkProfile.networkInterfaces`. NIC must be in the same region. |
| **Availability Set** | Cannot combine with `virtualMachineScaleSet` or availability zones. Set `availabilitySet.id`. |
| **Availability Zone** | Cannot combine with availability sets. Set `zones: ['1']` (string array). |
| **Managed Disk (Premium SSD)** | Not all VM sizes support Premium storage β€” check size docs for compatibility. |
| **Managed Disk (UltraSSD)** | Requires `additionalCapabilities.ultraSSDEnabled: true`. Cannot enable on a running VM β€” requires stop/deallocate first. |
| **Managed Disk (Premium SSD v2)** | Premium SSD v2 cannot be used as OS disk (data disks only). Does not support host caching (ReadOnly/ReadWrite unavailable). Requires zonal VM deployment. Cannot mix Premium SSD v2 with other storage types on SQL Server VMs. |
| **Dedicated Host** | Cannot specify both `host` and `hostGroup`. |
| **Boot Diagnostics Storage** | Cannot use Premium or ZRS storage. Use `Standard_LRS` or `Standard_GRS`. |
| **CNI Overlay (AKS)** | DCsv2-series VMs are not supported with Azure CNI Overlay. Use DCasv5/DCadsv5 for confidential computing. |

### VM Scale Set

| Paired With | Constraint |
|-------------|------------|
| **Subnet** | Network interfaces defined inline in `virtualMachineProfile.networkProfile`. Subnet must be in same region. |
| **Load Balancer** | Reference backend pool ID in NIC IP configuration. |
| **Orchestration Mode** | `Flexible` is the modern default. `Uniform` requires `upgradePolicy`. |
| **Availability Zone** | Set `zones: ['1', '2', '3']` for zone distribution. Cannot combine with availability sets. |
data-analytics.md 6.4 KB
# Data (Analytics) Pairing Constraints

### Cosmos DB

| Paired With | Constraint |
|-------------|------------|
| **Multi-region writes** | `consistencyPolicy.defaultConsistencyLevel` cannot be `Strong` when `enableMultipleWriteLocations: true`. |
| **Strong consistency** | Strong consistency with regions >5000 miles apart is blocked by default (requires support ticket to enable). Strong and Bounded Staleness reads cost 2Γ— RU/s compared to Session/Consistent Prefix/Eventual. |
| **Serverless** | Cannot combine `EnableServerless` capability with multi-region writes or analytical store. Serverless is single-region only β€” cannot add regions. No shared throughput databases. Cannot provision throughput (auto-managed; settings return error). Merge partitions not available for serverless accounts. |
| **Free tier** | Only one free-tier account per subscription. Cannot combine with multi-region writes. |
| **VNet** | Set `isVirtualNetworkFilterEnabled: true` and configure `virtualNetworkRules[]` with subnet IDs. Subnets need `Microsoft.AzureCosmosDB` service endpoint. |
| **Private Endpoint** | Set `publicNetworkAccess: 'Disabled'` when using private endpoints exclusively. One Private DNS Zone record per DNS name β€” multiple private endpoints in different regions need separate Private DNS Zones. |
| **Key Vault (CMK)** | Requires `keyVaultKeyUri` in encryption config. Key Vault must be in same region. |
| **Merge Partitions** | Not available for serverless or multi-region write accounts. Single-region provisioned throughput only. |

### Redis Cache

| Paired With | Constraint |
|-------------|------------|
| **VNet** | Only Premium SKU supports VNet injection via `subnetId`. Basic/Standard use firewall rules only. |
| **VNet + Private Endpoint** | VNet injection and private endpoint are mutually exclusive β€” cannot use both on the same cache. |
| **Private Endpoint** | Available for Basic, Standard, Premium, and Enterprise tiers. Set `publicNetworkAccess: 'Disabled'` when using private endpoints. Premium with clustering supports max 1 private link; non-clustered supports up to 100. |
| **Clustering** | Only Premium SKU supports `shardCount`. Basic and Standard are single-node/two-node only. |
| **Persistence** | Only Premium SKU supports RDB/AOF persistence. Requires a storage account for RDB exports. |
| **Geo-replication** | Only Premium SKU. Primary and secondary must be Premium with same shard count. Passive geo-replication with private endpoints requires unlinking geo-replication first, adding private link, then re-linking. |
| **Zones** | Zone redundancy requires Premium SKU with multiple replicas. |
| **Tier Scaling** | Cannot scale down tiers (Enterprise β†’ lower, Premium β†’ Standard/Basic, Standard β†’ Basic). Cannot scale between Enterprise and Enterprise Flash, or from Basic/Standard/Premium to Enterprise/Flash β€” must create a new cache. |
| **Enterprise/Flash** | Firewall rules and `publicNetworkAccess` flag are not available on Enterprise/Enterprise Flash tiers. |
| **Azure Lighthouse** | Azure Lighthouse + VNet injection is not supported. Use private links instead. |

### Storage Account

| Paired With | Constraint |
|-------------|------------|
| **Azure Functions** | Must use `StorageV2` or `Storage` kind. `BlobStorage`, `BlockBlobStorage`, `FileStorage` not supported (missing Queue/Table). |
| **Functions (Consumption plan)** | Cannot use network-secured storage (VNet rules). Only Premium/Dedicated plans support VNet-restricted storage. |
| **Functions (zone-redundant)** | Must use ZRS SKU (`Standard_ZRS`). LRS/GRS not sufficient. |
| **VM Boot Diagnostics** | Cannot use Premium storage or ZRS. Use `Standard_LRS` or `Standard_GRS`. Managed boot diagnostics (no storage account required) is also available. |
| **CMK Encryption** | Key Vault must have `enableSoftDelete: true` AND `enablePurgeProtection: true`. |
| **CMK at creation** | Requires user-assigned managed identity (system-assigned only works for existing accounts). |
| **Geo-redundant failover** | Certain features (SFTP, NFS 3.0, etc.) block GRS/GZRS failover. |

### Data Factory

| Paired With | Constraint |
|-------------|------------|
| **Storage Account** | Linked service requires `Storage Blob Data Contributor` role on the storage account for the ADF managed identity. For ADLS Gen2, also requires `Storage Blob Data Reader` at minimum. |
| **Key Vault** | For CMK encryption, Key Vault must have `enableSoftDelete: true` and `enablePurgeProtection: true`. ADF managed identity needs `Key Vault Crypto Service Encryption User` role or equivalent access policy. |
| **Managed VNet** | When `managedVirtualNetworks` is configured, all outbound connections must use managed private endpoints (`factories/managedVirtualNetworks/managedPrivateEndpoints`). |
| **Private Endpoint** | When `publicNetworkAccess: 'Disabled'`, must create private endpoint to `dataFactory` sub-resource for studio access and pipeline connectivity. |
| **Purview** | Requires Microsoft Purview instance resource ID. ADF managed identity must have `Data Curator` role in Purview. |
| **Integration Runtime** | Self-hosted IR requires network line-of-sight to on-premises sources. Azure IR regional choice affects data residency. |

### Synapse Workspace

| Paired With | Constraint |
|-------------|------------|
| **ADLS Gen2 Storage Account** | **Required.** Storage account must have `isHnsEnabled: true` (hierarchical namespace / Data Lake Storage Gen2) and `kind: 'StorageV2'`. Synapse managed identity needs `Storage Blob Data Contributor` role on the storage account. |
| **Key Vault** | For CMK encryption, Key Vault must have `enableSoftDelete: true` and `enablePurgeProtection: true`. Synapse managed identity needs `Get`, `Unwrap Key`, and `Wrap Key` permissions. |
| **Managed VNet** | When `managedVirtualNetwork: 'default'`, all outbound connections require managed private endpoints. Set at creation time β€” cannot be changed after. |
| **Private Endpoint** | When `publicNetworkAccess: 'Disabled'`, create private endpoints for sub-resources: `Dev` (Studio), `Sql` (dedicated SQL), `SqlOnDemand` (serverless SQL). |
| **Purview** | Requires Microsoft Purview resource ID. Synapse managed identity needs appropriate Purview roles. |
| **VNet (compute subnet)** | `virtualNetworkProfile.computeSubnetId` must reference an existing subnet. The subnet must be delegated to `Microsoft.Synapse/workspaces` if required by the deployment model. |
data-relational.md 5.0 KB
# Data (Relational) Pairing Constraints

### SQL Server

| Paired With | Constraint |
|-------------|------------|
| **SQL Database** | Databases are child resources β€” must reference this server as parent. |
| **Key Vault (TDE)** | Key Vault must have `enablePurgeProtection: true`. Must be in same Azure AD tenant. Server needs GET, WRAP KEY, UNWRAP KEY permissions on key. TDE protector setup fails if Key Vault soft-delete and purge-protection are not both enabled. |
| **Virtual Network** | Use `Microsoft.Sql/servers/virtualNetworkRules` to restrict access to specific subnets. Subnets need `Microsoft.Sql` service endpoint. |
| **Private Endpoint** | Set `publicNetworkAccess: 'Disabled'` when using private endpoints exclusively. |
| **Elastic Pool** | Databases using elastic pools reference `elasticPoolId` β€” server must host both pool and databases. Hyperscale elastic pools cannot be created from non-Hyperscale pools. |
| **Failover Group** | Both primary and secondary servers must exist. Databases to be replicated must belong to the primary server. Failover group from zone-redundant to non-zone-redundant Hyperscale elastic pool fails silently (geo-secondary shows "Seeding 0%"). |

### SQL Database

| Paired With | Constraint |
|-------------|------------|
| **SQL Server** | Must be deployed as child of the parent SQL Server. Location must match. |
| **Elastic Pool** | `elasticPoolId` must reference a pool on the same server. Cannot set `sku` when using elastic pool (it inherits pool SKU). |
| **Zone Redundancy** | Only available in `GeneralPurpose`, `BusinessCritical`, and `Hyperscale` tiers. Not available in DTU tiers. General Purpose zone redundancy is only available in selected regions. Hyperscale zone redundancy can only be set at creation β€” cannot modify after provisioning; must recreate via copy/restore/geo-replica. |
| **Serverless** | Only available in `GeneralPurpose` tier. SKU name uses `GP_S_Gen5_*` pattern. |
| **Hyperscale** | Reverse migration from Hyperscale to General Purpose is supported within 45 days of the original migration. Databases originally created as Hyperscale cannot reverse migrate. |
| **Hyperscale Elastic Pool** | Cannot be created from a non-Hyperscale pool. Cannot be converted to non-Hyperscale (one-way only). Named replicas cannot be added to Hyperscale elastic pools (`UnsupportedReplicationOperation`). Zone-redundant Hyperscale elastic pools require databases with ZRS/GZRS backup storage β€” cannot add LRS-backed databases. |
| **Failover Group** | Failover group from zone-redundant to non-zone-redundant Hyperscale elastic pool fails silently (geo-secondary shows "Seeding 0%"). |
| **Backup Redundancy** | `GeoZone` only available in select regions. `Local` not available in all regions. |

### MySQL Flexible Server

| Paired With | Constraint |
|-------------|------------|
| **VNet (private access)** | Requires a dedicated subnet delegated to `Microsoft.DBforMySQL/flexibleServers`. Subnet must have no other resources. |
| **Private DNS Zone** | For VNet-integrated (private access) servers, use the zone name `{name}.mysql.database.azure.com` (not `privatelink.*`). The `privatelink.mysql.database.azure.com` zone is used for Private Endpoint connectivity only. Provide `privateDnsZoneResourceId` and the DNS zone must be linked to the VNet. |
| **High Availability** | `ZoneRedundant` HA requires `GeneralPurpose` or `MemoryOptimized` tier. Not available with `Burstable`. |
| **Geo-Redundant Backup** | Must be enabled at server creation time. Cannot be changed after creation. Not available in all regions. |
| **Storage Auto-Grow** | Storage can only grow, never shrink. Enabled by default. |
| **Read Replicas** | Source server must have `backup.backupRetentionDays` > 1. Replica count limit: up to 10 replicas. |
| **Key Vault (CMK)** | Customer-managed keys require user-assigned managed identity and Key Vault with purge protection enabled. |

### PostgreSQL Flexible Server

| Paired With | Constraint |
|-------------|------------|
| **VNet (private access)** | Requires a dedicated subnet delegated to `Microsoft.DBforPostgreSQL/flexibleServers`. Subnet must have no other resources. |
| **Private DNS Zone** | For VNet-integrated (private access) servers, use the zone name `{name}.postgres.database.azure.com` (not `privatelink.*`). The `privatelink.postgres.database.azure.com` zone is used for Private Endpoint connectivity only. Provide `privateDnsZoneArmResourceId` and the DNS zone must be linked to the VNet. |
| **High Availability** | `ZoneRedundant` HA requires `GeneralPurpose` or `MemoryOptimized` tier. Not available with `Burstable`. |
| **Geo-Redundant Backup** | Not available in all regions. Cannot be enabled with VNet-integrated (private access) servers in some configurations. |
| **Storage Auto-Grow** | Storage can only grow, never shrink. Minimum increase is based on current size. |
| **Key Vault (CMK)** | Customer-managed keys require user-assigned managed identity and Key Vault with purge protection enabled. |
messaging.md 2.5 KB
# Messaging Pairing Constraints

### Event Grid Topic

| Paired With | Constraint |
|-------------|------------|
| **Event Subscriptions** | Subscriptions are child resources. Delivery endpoints include: Webhook, Azure Function, Event Hub, Service Bus Queue/Topic, Storage Queue, Hybrid Connection. |
| **Private Endpoint** | Only available with `Premium` SKU. Set `publicNetworkAccess: 'Disabled'` when using private endpoints exclusively. |
| **Managed Identity** | Required for dead-letter destinations and delivery to Azure resources that require authentication (Event Hub, Service Bus, Storage). |
| **Function App** | Use Event Grid trigger binding. Subscription endpoint type is `AzureFunction`. Function must have Event Grid extension registered. |
| **Event Hub** | Subscription endpoint type is `EventHub`. Provide the Event Hub resource ID. Requires managed identity or connection string. |
| **Storage Queue** | Subscription endpoint type is `StorageQueue`. Provide storage account ID and queue name. |
| **Dead Letter** | Dead-letter destination must be a Storage blob container. Requires managed identity or storage key for access. |

### Event Hub

| Paired With | Constraint |
|-------------|------------|
| **VNet** | Standard, Premium, and Dedicated SKUs support VNet service endpoints and private endpoints. |
| **Zone Redundancy** | Available in Standard (with β‰₯4 TU recommended) and Premium. |
| **Kafka** | Kafka protocol support available in Standard and Premium only (not Basic). |
| **Capture** | Event capture to Storage/Data Lake available in Standard and Premium only. |
| **Consumer Groups** | Basic: 1 consumer group. Standard: 20. Premium: 100. Dedicated: 1,000. |
| **Retention** | Basic: 1 day. Standard: 1–7 days. Premium: up to 90 days. |
| **Function App** | Event Hub trigger uses connection string or managed identity. Set `EventHubConnection` in app settings. |

### Service Bus

| Paired With | Constraint |
|-------------|------------|
| **Topics** | Only Standard and Premium SKUs support topics and subscriptions. Basic supports queues only. |
| **VNet** | Only Premium SKU supports VNet service endpoints and private endpoints. |
| **Zone Redundancy** | Only Premium SKU supports zone redundancy. |
| **Partitioning** | Premium messaging partitions cannot be changed after creation. |
| **Message Size** | Basic/Standard: max 256 KB. Premium: max 100 MB. Plan accordingly for large payloads. |
| **Function App** | Service Bus trigger uses connection string or managed identity. Set `ServiceBusConnection` in app settings. |
monitoring.md 1.8 KB
# Monitoring Pairing Constraints

### Application Insights

| Paired With | Constraint |
|-------------|------------|
| **Log Analytics** | Workspace-based App Insights (recommended) requires `WorkspaceResourceId`. Classic (standalone) is being phased out. |
| **Function App** | Set `APPLICATIONINSIGHTS_CONNECTION_STRING` or `APPINSIGHTS_INSTRUMENTATIONKEY` in function app settings. |
| **App Service** | Set `APPLICATIONINSIGHTS_CONNECTION_STRING` in app settings. Enable auto-instrumentation for supported runtimes. |
| **AKS** | Use Container Insights (different from App Insights) for cluster-level monitoring. App Insights used for application-level telemetry. |
| **Private Link** | Use Azure Monitor Private Link Scope (AMPLS) to restrict ingestion/query to private networks. |
| **Retention** | If workspace-based, retention is governed by the Log Analytics workspace. Component-level retention acts as an override. |

### Log Analytics

| Paired With | Constraint |
|-------------|------------|
| **Application Insights** | App Insights `WorkspaceResourceId` must reference this workspace. Both should be in the same region for optimal performance. |
| **AKS (Container Insights)** | AKS `omsagent` addon references workspace via `logAnalyticsWorkspaceResourceID`. |
| **Diagnostic Settings** | Multiple resources can send diagnostics to the same workspace. Configure via `Microsoft.Insights/diagnosticSettings` on each resource. |
| **Retention** | Free tier is limited to 7-day retention. PerGB2018 supports 30–730 days. Archive tier available for longer retention. |
| **Private Link** | Use Azure Monitor Private Link Scope (AMPLS) for private ingestion/query. A workspace can be linked to up to 100 AMPLS resources (a VNet can connect to only one AMPLS). |
networking-connectivity.md 6.1 KB
# Networking (Connectivity) Pairing Constraints

### Azure Bastion

| Paired With | Constraint |
|-------------|------------|
| **VNet** | Requires a subnet named exactly `AzureBastionSubnet` with minimum /26 prefix. |
| **Developer SKU** | Does NOT require `AzureBastionSubnet` or public IP. Deploys as shared infrastructure. Only connects to VMs in the same VNet. |
| **Public IP** | Requires Standard SKU public IP with Static allocation. |
| **NSG** | NSG on `AzureBastionSubnet` requires mandatory inbound (HTTPS 443 from Internet, GatewayManager 443) and outbound rules (see [Bastion NSG docs](https://learn.microsoft.com/azure/bastion/bastion-nsg)). |
| **VMs** | Target VMs must be in the same VNet as Bastion (or peered VNets with Standard/Premium SKU). |

### Azure Firewall

| Paired With | Constraint |
|-------------|------------|
| **VNet** | Requires a subnet named exactly `AzureFirewallSubnet` with minimum /26 prefix. |
| **Basic Tier** | Additionally requires `AzureFirewallManagementSubnet` with /26 minimum and its own public IP. |
| **Public IP** | Requires Standard SKU public IP with Static allocation. |
| **Firewall Policy** | Cannot use both `firewallPolicy.id` and classic rule collections simultaneously. Policy tier must match or exceed firewall tier. |
| **Zones** | In zone-redundant mode, all associated public IPs must also be zone-redundant (Standard SKU). |
| **Virtual WAN** | `AZFW_Hub` SKU name must reference `virtualHub.id` instead of `ipConfigurations`. |

### VPN Gateway

| Paired With | Constraint |
|-------------|------------|
| **VNet** | Requires a subnet named exactly `GatewaySubnet` with minimum /27 prefix. Use /26+ for 16 ExpressRoute circuits or for ExpressRoute/VPN coexistence. |
| **Public IP** | Basic VPN SKU requires Basic public IP. VpnGw1+ requires Standard public IP. |
| **Active-Active** | Requires 2 public IPs and 2 IP configurations. Only supported with VpnGw1+. |
| **Zone-Redundant** | Must use `AZ` SKU variant (e.g., `VpnGw1AZ`). Requires Standard SKU public IPs. AZ SKU cannot be downgraded to non-AZ (one-way migration only). |
| **ExpressRoute** | Can coexist with VPN gateway on the same `GatewaySubnet` (requires /27 or larger). Not supported with Basic SKU. Route-based VPN required. |
| **PolicyBased** | Limited to 1 S2S tunnel, no P2S, no VNet-to-VNet. Use `RouteBased` for most scenarios. |
| **Basic SKU** | Basic VPN Gateway does not support BGP, IPv6, RADIUS authentication, IKEv2 P2S, or ExpressRoute coexistence. Max 10 S2S tunnels. |
| **GatewaySubnet UDR** | Do not apply UDR with `0.0.0.0/0` next hop on GatewaySubnet. ExpressRoute gateways require management controller access β€” this route breaks it. |
| **GatewaySubnet BGP** | BGP route propagation must remain enabled on GatewaySubnet. Disabling causes the gateway to become non-functional. |
| **DNS Private Resolver** | DNS Private Resolver in a VNet with an ExpressRoute gateway and wildcard forwarding rules can cause management connectivity problems. |

### DNS Zone

| Paired With | Constraint |
|-------------|------------|
| **Domain Registrar** | NS records from `properties.nameServers` must be configured at your domain registrar to delegate the domain to Azure DNS. |
| **App Service** | Create a CNAME record pointing to `{app-name}.azurewebsites.net` for custom domains. Add a TXT verification record. |
| **Front Door** | Create a CNAME record pointing to the Front Door endpoint. Add a `_dnsauth` TXT record for domain validation. |
| **Application Gateway** | Create an A record pointing to the Application Gateway public IP, or a CNAME to the public IP DNS name. |
| **Traffic Manager** | Create a CNAME record pointing to the Traffic Manager profile `{name}.trafficmanager.net`. |
| **Child Zones** | Delegate subdomains by creating NS records in the parent zone pointing to the child zone's Azure name servers. |

### Private DNS Zone

| Paired With | Constraint |
|-------------|------------|
| **Virtual Network** | Must create a `virtualNetworkLinks` child resource to link the DNS zone to each VNet that needs resolution. |
| **Private Endpoint** | Use a `privateDnsZoneGroups` child on the Private Endpoint to auto-register A records, or manually create A record sets. One DNS record per DNS name β€” multiple private endpoints in different regions need separate Private DNS Zones. |
| **VNet Link (auto-registration)** | Only one Private DNS Zone with `registrationEnabled: true` can be linked per VNet. Auto-registration creates DNS records for VMs in the VNet. |
| **Hub-Spoke VNet** | Link the Private DNS Zone to the hub VNet. Spoke VNets resolve via hub DNS forwarder or VNet link. |
| **PostgreSQL Flexible Server** | For Private Endpoint access, zone name is `privatelink.postgres.database.azure.com`. For VNet-integrated (private access) servers, the zone name is `{name}.postgres.database.azure.com` (not `privatelink.*`). Referenced via `properties.network.privateDnsZoneArmResourceId`. |
| **MySQL Flexible Server** | For Private Endpoint access, zone name is `privatelink.mysql.database.azure.com`. For VNet-integrated (private access) servers, the zone name is `{name}.mysql.database.azure.com` (not `privatelink.*`). Referenced via `properties.network.privateDnsZoneResourceId`. |

### Private Endpoint

| Paired With | Constraint |
|-------------|------------|
| **Subnet** | The subnet must not have NSG rules that block private endpoint traffic. Subnet must have `privateEndpointNetworkPolicies` set to `Disabled` (default) for network policies to be bypassed. |
| **Private DNS Zone** | Create a `Microsoft.Network/privateDnsZones/virtualNetworkLinks` to link the DNS zone to the VNet. Create an A record or use a private DNS zone group to auto-register DNS. |
| **Private DNS Zone Group** | Use `privateEndpoint/privateDnsZoneGroups` child resource to auto-register DNS records in the Private DNS Zone. |
| **Key Vault** | Group ID: `vault`. DNS zone: `privatelink.vaultcore.azure.net`. |
| **Storage Account** | Group IDs: `blob`, `file`, `queue`, `table`, `web`, `dfs`. Each requires its own PE and DNS zone. |
| **SQL Server** | Group ID: `sqlServer`. DNS zone: `privatelink.database.windows.net`. |
| **Container Registry** | Group ID: `registry`. DNS zone: `privatelink.azurecr.io`. |
networking-core.md 7.1 KB
# Networking (Core) Pairing Constraints

### Virtual Network

| Paired With | Constraint |
|-------------|------------|
| **Subnets** | Address prefixes of all subnets must fall within the VNet address space. Subnet CIDRs cannot overlap. |
| **VNet Peering** | Peered VNets cannot have overlapping address spaces. |
| **Azure Firewall** | Requires a subnet named exactly `AzureFirewallSubnet` with minimum /26 prefix. |
| **Azure Bastion** | Requires a subnet named exactly `AzureBastionSubnet` with minimum /26 prefix (recommended /26). |
| **VPN Gateway** | Requires a subnet named exactly `GatewaySubnet` with minimum /27 prefix (recommended /27). |
| **Application Gateway** | Requires a dedicated subnet (no mandatory name, but must not contain other resource types). |
| **AKS** | AKS subnet must have enough IP addresses for nodes + pods. With Azure CNI, each node reserves IPs for max pods. |

### Subnet

| Paired With | Constraint |
|-------------|------------|
| **NSG** | Cannot attach NSG to `GatewaySubnet` β€” NSGs are not supported for either VPN or ExpressRoute gateways. NSG on `AzureBastionSubnet` requires specific required rules. |
| **Delegations** | A subnet can only be delegated to one service. Delegated subnets cannot host other resource types. |
| **Service Endpoints** | Must match the service being accessed (e.g., `Microsoft.Sql` for SQL Server VNet rules). |
| **Private Endpoints** | Set `privateEndpointNetworkPolicies: 'Enabled'` to apply NSG/route table to private endpoints (default is `Disabled`). |
| **AKS** | AKS subnet needs enough IPs for all nodes + pods. Cannot be delegated or have conflicting service endpoints. |
| **Application Gateway** | Dedicated subnet required β€” cannot coexist with other resources except other App Gateways. Cannot mix v1 and v2 App Gateway SKUs on the same subnet. |
| **Azure Firewall** | Subnet must be named `AzureFirewallSubnet`, minimum /26. Cannot have other resources. |
| **App Service VNet Integration** | Subnet must be delegated to `Microsoft.Web/serverFarms`. Minimum size /28 (or /26 for multi-plan subnet join). This subnet must be different from any subnet used for App Service Private Endpoints. |
| **GatewaySubnet UDR** | Do not apply UDR with `0.0.0.0/0` next hop on `GatewaySubnet`. ExpressRoute gateways require management controller access. BGP route propagation must remain enabled on `GatewaySubnet`. |

### NSG

| Paired With | Constraint |
|-------------|------------|
| **GatewaySubnet** | NSGs are not supported on `GatewaySubnet`. Associating an NSG may cause VPN and ExpressRoute gateways to stop functioning. |
| **AzureBastionSubnet** | NSG on Bastion subnet requires specific inbound/outbound rules (see [Azure Bastion NSG](https://learn.microsoft.com/azure/bastion/bastion-nsg)). |
| **Application Gateway** | NSG on App Gateway subnet must allow `GatewayManager` service tag on ports `65200–65535` (v2) and health probe traffic. |
| **Load Balancer** | Must allow `AzureLoadBalancer` service tag for health probes. Standard LB requires NSG β€” it is secure by default and blocks inbound traffic without an NSG. |
| **Virtual Network** | NSG is associated to subnets, not directly to VNets. Each subnet can have at most one NSG. |

### Route Table

| Paired With | Constraint |
|-------------|------------|
| **Subnet** | Route table is associated on the subnet side: set `subnet.properties.routeTable.id` to the route table resource ID. Each subnet can have at most one route table. |
| **Azure Firewall** | For forced tunneling, create a default route (`0.0.0.0/0`) with `nextHopType: 'VirtualAppliance'` pointing to the firewall private IP. |
| **VPN Gateway** | Set `disableBgpRoutePropagation: true` to prevent BGP routes from overriding UDRs on the subnet. |
| **GatewaySubnet** | UDRs on `GatewaySubnet` have restrictions β€” cannot use `0.0.0.0/0` route pointing to a virtual appliance. |
| **AKS** | AKS subnets with UDRs require careful route design. Must allow traffic to Azure management APIs. `kubenet` and `Azure CNI` have different routing requirements. |
| **Virtual Appliance** | `nextHopIpAddress` must be a reachable private IP in the same VNet or a peered VNet. The appliance NIC must have `enableIPForwarding: true`. |

### Network Interface

| Paired With | Constraint |
|-------------|------------|
| **Virtual Machine** | Each VM requires at least one NIC. NIC must be in the same region and subscription as the VM. |
| **Subnet** | NIC must reference a subnet. The subnet determines the VNet, NSG, and route table that apply. |
| **NSG** | NSG can be associated at the NIC level or at the subnet level (or both). NIC-level NSG is evaluated after subnet-level NSG. |
| **Public IP** | Public IP and NIC must be in the same region. When associated with a Load Balancer, Public IP SKU must match the LB SKU (Basic with Basic, Standard with Standard). |
| **Load Balancer** | NIC IP configuration can reference `loadBalancerBackendAddressPools` and `loadBalancerInboundNatRules`. Load balancer and NIC must be in the same VNet. |
| **Accelerated Networking** | Not all VM sizes support accelerated networking. Must verify VM size compatibility. |
| **VM Scale Set** | NICs for VMSS instances are managed by the scale set β€” do not create standalone NICs for VMSS. |
| **Application Gateway** | NIC IP configuration can reference `applicationGatewayBackendAddressPools`. |

### Public IP

| Paired With | Constraint |
|-------------|------------|
| **Standard SKU** | Must use `Static` allocation method. `Dynamic` only works with Basic SKU. |
| **Load Balancer** | Public IP SKU must match Load Balancer SKU (Standard ↔ Standard, Basic ↔ Basic). |
| **Application Gateway** | Standard_v2 App Gateway requires Standard SKU public IP with Static allocation. |
| **Azure Bastion** | Requires Standard SKU with Static allocation. |
| **VPN Gateway** | Basic VPN Gateway SKU requires Basic public IP. Standard+ gateway SKUs require Standard public IP. |
| **Azure Firewall** | Requires Standard SKU with Static allocation. |
| **Zones** | Standard SKU is zone-redundant by default. Specify `zones` only to pin to specific zone(s). |

### NAT Gateway

| Paired With | Constraint |
|-------------|------------|
| **Subnet** | NAT Gateway is associated on the subnet side: set `subnet.properties.natGateway.id` to the NAT Gateway resource ID. A subnet can have at most one NAT Gateway. |
| **Public IP** | Public IP must use `Standard` SKU and `Static` allocation. Public IP and NAT Gateway must be in the same region. |
| **Public IP Prefix** | Public IP prefix must use `Standard` SKU. Provides contiguous outbound IPs. |
| **Availability Zones** | NAT Gateway can be zonal (pinned to one zone) or non-zonal. Public IPs must match the same zone or be zone-redundant. |
| **Load Balancer** | NAT Gateway takes precedence over outbound rules of a Standard Load Balancer when both are on the same subnet. |
| **VPN Gateway / ExpressRoute** | `GatewaySubnet` does not support NAT Gateway association. |
| **Azure Firewall** | NAT Gateway can be associated with the `AzureFirewallSubnet` for deterministic outbound IPs in SNAT scenarios. |
networking-traffic.md 4.6 KB
# Networking (Traffic) Pairing Constraints

### Application Gateway

| Paired With | Constraint |
|-------------|------------|
| **Subnet** | Requires a dedicated subnet β€” no other resources allowed in the subnet (except other App Gateways). Cannot mix v1 and v2 SKUs on the same subnet β€” separate subnets required for each. |
| **Public IP** | v2 SKU requires Standard SKU public IP with Static allocation. |
| **NSG** | NSG on App Gateway subnet must allow `GatewayManager` service tag on ports `65200–65535` (v2) or `65503–65534` (v1). |
| **WAF** | WAF configuration only available with `WAF_v2` or `WAF_Large`/`WAF_Medium` SKUs. WAF v2 cannot disable request buffering β€” chunked file transfer requires path-rule workaround. |
| **Zones** | v2 supports availability zones. Specify `zones: ['1','2','3']` for zone-redundant deployment. |
| **Key Vault** | For SSL certificates, use `sslCertificates[].properties.keyVaultSecretId` to reference Key Vault certificates. User-assigned managed identity required. |
| **v1 Limitations** | v1 does not support: autoscaling, zone redundancy, Key Vault integration, mTLS, Private Link, WAF custom rules, or header rewrite. Must use v2 for these features. v1 SKUs are being retired April 2026. |
| **Private-only (no public IP)** | Requires `EnableApplicationGatewayNetworkIsolation` feature registration. Only available with `Standard_v2` or `WAF_v2`. |
| **Global VNet Peering** | Backend via private endpoint across global VNet peering causes traffic to be dropped β€” results in unhealthy backend status. |
| **kubenet (AKS)** | Kubenet is not supported by Application Gateway for Containers. Must use CNI or CNI Overlay. |

### Front Door

| Paired With | Constraint |
|-------------|------------|
| **Origins (backends)** | Origins are defined in child `originGroups/origins`. Supported origin types: App Service, Storage, Application Gateway, Public IP, custom hostname. |
| **Private Link Origins** | Only available with `Premium_AzureFrontDoor` SKU. Enable private origin connections to App Service, Storage, Internal Load Balancer, etc. |
| **WAF Policy** | WAF policies are separate `Microsoft.Network/FrontDoorWebApplicationFirewallPolicies` resources. Linked via security policy child resource on the profile. |
| **Custom Domains** | Custom domains are child resources of the profile. Require DNS CNAME/TXT validation and certificate (managed or custom). |
| **Application Gateway** | Front Door in front of App Gateway: use App Gateway public IP as origin. Set `X-Azure-FDID` header restriction on App Gateway to accept only Front Door traffic. |
| **App Service** | Restrict App Service to Front Door traffic using access restrictions with `AzureFrontDoor.Backend` service tag and `X-Azure-FDID` header check. |

### Load Balancer

| Paired With | Constraint |
|-------------|------------|
| **Public IP** | Public IP SKU must match LB SKU. Basic LB requires Basic public IP; Standard LB requires Standard public IP. No cross-SKU mixing. |
| **Standard SKU** | Backend pool VMs must be in the same VNet. No VMs from different VNets. Standard LB blocks outbound traffic by default β€” requires explicit outbound rules, NAT gateway, or instance-level public IPs. Standard LB requires an NSG (secure by default; inbound traffic blocked without NSG). |
| **Basic SKU** | Backend pool VMs must be in the same availability set or VMSS. |
| **Availability Zones** | Standard SKU is zone-redundant by default. Frontend IPs inherit zone from public IP. |
| **VMs / VMSS** | VMs in backend pool cannot have both Basic and Standard LBs simultaneously. |
| **Outbound Rules** | Only Standard SKU supports outbound rules. Basic SKU has implicit outbound. |

### API Management

| Paired With | Constraint |
|-------------|------------|
| **VNet (External)** | Only available with `Developer`, `Premium`, or `Isolated` SKU. Subnet must be dedicated with an NSG allowing APIM management traffic. |
| **VNet (Internal)** | Same as External but no public gateway endpoint. Requires Private DNS or custom DNS for resolution. |
| **Application Gateway** | Common pattern: App Gateway in front of Internal-mode APIM. App Gateway uses the APIM private IP as backend. |
| **Key Vault** | Named values and certificates can reference Key Vault secrets. Requires managed identity with `Key Vault Secrets User` role. |
| **Application Insights** | Set `properties.customProperties` with `Microsoft.WindowsAzure.ApiManagement.Gateway.Protocols.Server.Http2` and logger resource for diagnostics. |
| **NSG (VNet mode)** | Subnet NSG must allow: inbound on ports 3443 (management), 80/443 (client); outbound to Azure Storage, SQL, Event Hub, and other dependencies. |
security.md 2.4 KB
# Security Pairing Constraints

### Key Vault

| Paired With | Constraint |
|-------------|------------|
| **Storage Account (CMK)** | Must have `enableSoftDelete: true` AND `enablePurgeProtection: true`. |
| **Storage Account (CMK at creation)** | Storage must use user-assigned managed identity β€” system-assigned only works for existing accounts. |
| **SQL Server (TDE)** | Must enable `enablePurgeProtection`. Key Vault and SQL Server must be in the same Azure AD tenant. |
| **AKS (secrets)** | Use `enableRbacAuthorization: true` with Azure RBAC for secrets access. AKS needs `azureKeyvaultSecretsProvider` addon. |
| **Disk Encryption** | Must set `enabledForDiskEncryption: true`. Premium SKU required for HSM-protected keys. |
| **Private Endpoint** | Set `publicNetworkAccess: 'Disabled'` and `networkAcls.defaultAction: 'Deny'` when using private endpoints. |
| **CMK Firewall** | When any Azure service uses CMK from Key Vault, the Key Vault firewall must enable "Allow trusted Microsoft services to bypass this firewall" β€” unless using private endpoints to Key Vault. |
| **CMK Key Type** | Key must be RSA or RSA-HSM, 2048/3072/4096-bit. Other key types are not supported for customer-managed keys. |
| **CMK Cross-Tenant** | Key Vault and consuming service must be in the same Azure AD tenant. Cross-tenant CMK requires separate configuration. |

### Managed Identity

| Paired With | Constraint |
|-------------|------------|
| **Any Resource (identity assignment)** | Reference the identity resource ID in the resource's `identity.userAssignedIdentities` object as `{ '${managedIdentity.id}': {} }`. |
| **Key Vault (CMK)** | Storage accounts using CMK at creation require a user-assigned identity β€” system-assigned only works for existing accounts. |
| **Container Registry (ACR pull)** | Assign `AcrPull` role to the identity's `principalId`. Reference the identity in the pulling resource (AKS, Container App, etc.). |
| **AKS (workload identity)** | Create a federated identity credential on the managed identity. Map it to a Kubernetes service account via OIDC issuer. |
| **Role Assignments** | Use `properties.principalId` with `principalType: 'ServicePrincipal'` in `Microsoft.Authorization/roleAssignments`. |
| **Function App / App Service** | Set `identity.type` to `'UserAssigned'` and reference the identity resource ID. Use for Key Vault references, storage access, etc. |
references/resources/
README.md 1.7 KB
# Resource Reference Index

Load only the files matching resources identified in Phase 1.

## Region Categories

Resources fall into region-scoped or global categories. Check individual files for details.

## Globally-Unique Names

Some resources require globally unique names (e.g., Storage Accounts, Key Vaults). See individual category files.

## Shared ARM Types

Resources share the `Microsoft.*` ARM type namespace. Each file documents the relevant ARM types and documentation URLs.

| Sub-Category | File | Resources |
|-------------|------|-----------|
| AI & ML | [ai-ml.md](ai-ml.md) | AI Search, Cognitive Services, ML Workspace |
| Compute (PaaS) | [compute-apps.md](compute-apps.md) | App Service, ASP, Function App, Container App, CAE, ACR, Static Web App |
| Compute (IaaS) | [compute-infra.md](compute-infra.md) | AKS, VM, VMSS, Availability Set, Managed Disk |
| Data (Relational) | [data-relational.md](data-relational.md) | SQL Server, SQL Database, MySQL, PostgreSQL |
| Data (Analytics) | [data-analytics.md](data-analytics.md) | Cosmos DB, Redis, Storage, Data Factory, Synapse |
| Messaging | [messaging.md](messaging.md) | Event Grid, Event Hub, Service Bus |
| Monitoring | [monitoring.md](monitoring.md) | App Insights, Log Analytics |
| Networking (Core) | [networking-core.md](networking-core.md) | VNet, Subnet, NSG, Route Table, NIC, Public IP, NAT Gateway |
| Networking (Traffic) | [networking-traffic.md](networking-traffic.md) | App Gateway, Front Door, LB, APIM |
| Networking (Connectivity) | [networking-connectivity.md](networking-connectivity.md) | Bastion, Firewall, VPN GW, DNS, Private DNS, PE |
| Security | [security.md](security.md) | Key Vault, Managed Identity |
ai-ml.md 2.1 KB
# AI & ML Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| Cognitive Services | `Microsoft.CognitiveServices/accounts` | `2025-06-01` | varies by kind | Resource group | Mainstream |
| ML Workspace | `Microsoft.MachineLearningServices/workspaces` | `2025-06-01` | `mlw`/`hub`/`proj` | Resource group | Mainstream |
| AI Search | `Microsoft.Search/searchServices` | `2025-05-01` | `srch` | Global | Mainstream |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| Cognitive Services | [2025-06-01](https://learn.microsoft.com/azure/templates/microsoft.cognitiveservices/accounts?pivots=deployment-language-bicep) | [Custom subdomain names](https://learn.microsoft.com/azure/ai-services/cognitive-services-custom-subdomains) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcognitiveservices) | [All API versions](https://learn.microsoft.com/azure/templates/microsoft.cognitiveservices/allversions) |
| ML Workspace | [2025-06-01](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/workspaces?pivots=deployment-language-bicep) | [ML Services](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/allversions) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftmachinelearningservices) | [All API versions](https://learn.microsoft.com/azure/templates/microsoft.machinelearningservices/allversions) |
| AI Search | [2025-05-01](https://learn.microsoft.com/azure/templates/microsoft.search/searchservices?pivots=deployment-language-bicep) | [Service limits](https://learn.microsoft.com/azure/search/search-limits-quotas-capacity) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftsearch) | [All API versions](https://learn.microsoft.com/azure/templates/microsoft.search/allversions) |
compute-apps.md 4.0 KB
# Compute (PaaS) Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| App Service | `Microsoft.Web/sites` | `2024-11-01` | `app` | Global | Mainstream |
| App Service Plan | `Microsoft.Web/serverfarms` | `2024-11-01` | `asp` | Resource group | Mainstream |
| Container App | `Microsoft.App/containerApps` | `2025-01-01` | `ca` | Environment | Strategic |
| Container Apps Environment | `Microsoft.App/managedEnvironments` | `2025-01-01` | `cae` | Resource group | Strategic |
| Container Registry | `Microsoft.ContainerRegistry/registries` | `2025-04-01` | `cr` | Global | Mainstream |
| Function App | `Microsoft.Web/sites` | `2024-11-01` | `func` | Global | Mainstream |
| Static Web App | `Microsoft.Web/staticSites` | `2024-11-01` | `stapp` | Resource group | Mainstream |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| App Service | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.web/sites?pivots=deployment-language-bicep) | [App Service overview](https://learn.microsoft.com/azure/app-service/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftweb) | [Hosting plans](https://learn.microsoft.com/azure/app-service/overview-hosting-plans) |
| App Service Plan | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.web/serverfarms?pivots=deployment-language-bicep) | [Plan overview](https://learn.microsoft.com/azure/app-service/overview-hosting-plans) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftweb) | [Pricing](https://azure.microsoft.com/en-us/pricing/details/app-service/linux) |
| Container App | [2025-01-01](https://learn.microsoft.com/azure/templates/microsoft.app/containerapps?pivots=deployment-language-bicep) | [Container Apps overview](https://learn.microsoft.com/azure/container-apps/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftapp) | [Environments](https://learn.microsoft.com/azure/container-apps/environment) |
| Container Apps Environment | [2025-01-01](https://learn.microsoft.com/azure/templates/microsoft.app/managedenvironments?pivots=deployment-language-bicep) | [Environments overview](https://learn.microsoft.com/azure/container-apps/environment) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftapp) | [Workload profiles](https://learn.microsoft.com/azure/container-apps/workload-profiles-overview) |
| Container Registry | [2025-04-01](https://learn.microsoft.com/azure/templates/microsoft.containerregistry/registries?pivots=deployment-language-bicep) | [ACR overview](https://learn.microsoft.com/azure/container-registry/container-registry-intro) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcontainerregistry) | [SKU tiers](https://learn.microsoft.com/azure/container-registry/container-registry-skus) |
| Function App | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.web/sites?pivots=deployment-language-bicep) | [Functions overview](https://learn.microsoft.com/azure/azure-functions/functions-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftweb) | [Hosting plans](https://learn.microsoft.com/azure/azure-functions/functions-scale) |
| Static Web App | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.web/staticsites?pivots=deployment-language-bicep) | [Static Web Apps overview](https://learn.microsoft.com/azure/static-web-apps/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftweb) | [Hosting plans](https://learn.microsoft.com/azure/static-web-apps/plans) |
compute-infra.md 2.8 KB
# Compute (IaaS) Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| AKS Cluster | `Microsoft.ContainerService/managedClusters` | `2025-05-01` | `aks` | Resource group | Foundational |
| Availability Set | `Microsoft.Compute/availabilitySets` | `2024-11-01` | `avail` | Resource group | Foundational |
| Managed Disk | `Microsoft.Compute/disks` | `2025-01-02` | `osdisk`/`disk` | Resource group | Foundational |
| Virtual Machine | `Microsoft.Compute/virtualMachines` | `2024-11-01` | `vm` | Resource group | Foundational |
| VM Scale Set | `Microsoft.Compute/virtualMachineScaleSets` | `2024-11-01` | `vmss` | Resource group | Foundational |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| AKS Cluster | [2025-05-01](https://learn.microsoft.com/azure/templates/microsoft.containerservice/managedclusters?pivots=deployment-language-bicep) | [AKS overview](https://learn.microsoft.com/azure/aks/intro-kubernetes) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcontainerservice) | [Networking concepts](https://learn.microsoft.com/azure/aks/concepts-network) |
| Availability Set | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.compute/availabilitysets?pivots=deployment-language-bicep) | [Overview](https://learn.microsoft.com/azure/virtual-machines/availability-set-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcompute) | β€” |
| Managed Disk | [2025-01-02](https://learn.microsoft.com/azure/templates/microsoft.compute/disks?pivots=deployment-language-bicep) | [Managed disks overview](https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcompute) | β€” |
| Virtual Machine | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.compute/virtualmachines?pivots=deployment-language-bicep) | [VMs overview](https://learn.microsoft.com/azure/virtual-machines/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcompute) | [VM sizes](https://learn.microsoft.com/azure/virtual-machines/sizes/overview) |
| VM Scale Set | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.compute/virtualmachinescalesets?pivots=deployment-language-bicep) | [VMSS overview](https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcompute) | β€” |
data-analytics.md 3.0 KB
# Data (Analytics) Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| Cosmos DB | `Microsoft.DocumentDB/databaseAccounts` | `2025-04-15` | `cosmos` | Global | Foundational |
| Data Factory | `Microsoft.DataFactory/factories` | `2018-06-01` | `adf` | Global | Mainstream |
| Redis Cache | `Microsoft.Cache/redis` | `2024-11-01` | `redis` | Global | Mainstream |
| Storage Account | `Microsoft.Storage/storageAccounts` | `2025-01-01` | `st` | Global | Foundational |
| Synapse Workspace | `Microsoft.Synapse/workspaces` | `2021-06-01` | `synw` | Global | Strategic |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| Cosmos DB | [2025-04-15](https://learn.microsoft.com/azure/templates/microsoft.documentdb/databaseaccounts?pivots=deployment-language-bicep) | [Cosmos DB overview](https://learn.microsoft.com/azure/cosmos-db/introduction) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftdocumentdb) | [Consistency levels](https://learn.microsoft.com/azure/cosmos-db/consistency-levels) |
| Data Factory | [2018-06-01](https://learn.microsoft.com/azure/templates/microsoft.datafactory/factories?pivots=deployment-language-bicep) | [ADF overview](https://learn.microsoft.com/azure/data-factory/introduction) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftdatafactory) | [ADF naming rules](https://learn.microsoft.com/azure/data-factory/naming-rules) |
| Redis Cache | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.cache/redis?pivots=deployment-language-bicep) | [Redis overview](https://learn.microsoft.com/azure/azure-cache-for-redis/cache-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcache) | [Service tiers](https://learn.microsoft.com/azure/azure-cache-for-redis/cache-overview#service-tiers) |
| Storage Account | [2025-01-01](https://learn.microsoft.com/azure/templates/microsoft.storage/storageaccounts?pivots=deployment-language-bicep) | [Storage overview](https://learn.microsoft.com/azure/storage/common/storage-account-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftstorage) | [Storage redundancy](https://learn.microsoft.com/azure/storage/common/storage-redundancy) |
| Synapse Workspace | [2021-06-01](https://learn.microsoft.com/azure/templates/microsoft.synapse/workspaces?pivots=deployment-language-bicep) | [Synapse overview](https://learn.microsoft.com/azure/synapse-analytics/overview-what-is) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftsynapse) | [All API versions](https://learn.microsoft.com/azure/templates/microsoft.synapse/allversions) |
data-relational.md 2.6 KB
# Data (Relational) Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| SQL Server | `Microsoft.Sql/servers` | `2023-08-01` | `sql` | Global | Foundational |
| SQL Database | `Microsoft.Sql/servers/databases` | `2023-08-01` | `sqldb` | Parent server | Foundational |
| MySQL Flexible Server | `Microsoft.DBforMySQL/flexibleServers` | `2023-12-30` | `mysql` | Global | Mainstream |
| PostgreSQL Flexible Server | `Microsoft.DBforPostgreSQL/flexibleServers` | `2024-08-01` | `psql` | Global | Mainstream |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| SQL Server | [2023-08-01](https://learn.microsoft.com/azure/templates/microsoft.sql/servers?pivots=deployment-language-bicep) | [SQL Server overview](https://learn.microsoft.com/azure/azure-sql/database/sql-database-paas-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftsql) | [TDE with Key Vault](https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-overview) |
| SQL Database | [2023-08-01](https://learn.microsoft.com/azure/templates/microsoft.sql/servers/databases?pivots=deployment-language-bicep) | [SQL Database overview](https://learn.microsoft.com/azure/azure-sql/database/sql-database-paas-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftsql) | [DTU vs vCore](https://learn.microsoft.com/azure/azure-sql/database/purchasing-models) |
| MySQL Flexible Server | [2023-12-30](https://learn.microsoft.com/azure/templates/microsoft.dbformysql/flexibleservers?pivots=deployment-language-bicep) | [MySQL overview](https://learn.microsoft.com/azure/mysql/flexible-server/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftdbformysql) | [Compute and storage](https://learn.microsoft.com/azure/mysql/flexible-server/concepts-compute-storage) |
| PostgreSQL Flexible Server | [2024-08-01](https://learn.microsoft.com/azure/templates/microsoft.dbforpostgresql/flexibleservers?pivots=deployment-language-bicep) | [PostgreSQL overview](https://learn.microsoft.com/azure/postgresql/flexible-server/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftdbforpostgresql) | [Compute and storage](https://learn.microsoft.com/azure/postgresql/flexible-server/concepts-compute-storage) |
messaging.md 2.0 KB
# Messaging Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| Event Grid Topic | `Microsoft.EventGrid/topics` | `2025-02-15` | `evgt` | Region | Mainstream |
| Event Hub | `Microsoft.EventHub/namespaces` | `2024-01-01` | `evhns` | Global | Foundational |
| Service Bus | `Microsoft.ServiceBus/namespaces` | `2024-01-01` | `sbns` | Global | Foundational |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| Event Grid Topic | [2025-02-15](https://learn.microsoft.com/azure/templates/microsoft.eventgrid/topics?pivots=deployment-language-bicep) | [Event Grid overview](https://learn.microsoft.com/azure/event-grid/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsofteventgrid) | [Security and auth](https://learn.microsoft.com/azure/event-grid/security-authentication) |
| Event Hub | [2024-01-01](https://learn.microsoft.com/azure/templates/microsoft.eventhub/namespaces?pivots=deployment-language-bicep) | [Event Hubs overview](https://learn.microsoft.com/azure/event-hubs/event-hubs-about) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsofteventhub) | [Event Hubs tiers](https://learn.microsoft.com/azure/event-hubs/event-hubs-quotas) |
| Service Bus | [2024-01-01](https://learn.microsoft.com/azure/templates/microsoft.servicebus/namespaces?pivots=deployment-language-bicep) | [Service Bus overview](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-messaging-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftservicebus) | [Service Bus tiers](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-premium-messaging) |
monitoring.md 1.5 KB
# Monitoring Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| Application Insights | `Microsoft.Insights/components` | `2020-02-02` | `appi` | Resource group | Mainstream |
| Log Analytics | `Microsoft.OperationalInsights/workspaces` | `2025-02-01` | `log` | Resource group | Mainstream |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| Application Insights | [2020-02-02](https://learn.microsoft.com/azure/templates/microsoft.insights/components?pivots=deployment-language-bicep) | [App Insights overview](https://learn.microsoft.com/azure/azure-monitor/app/app-insights-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftinsights) | [Workspace-based](https://learn.microsoft.com/azure/azure-monitor/app/convert-classic-resource) |
| Log Analytics | [2025-02-01](https://learn.microsoft.com/azure/templates/microsoft.operationalinsights/workspaces?pivots=deployment-language-bicep) | [Log Analytics overview](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftoperationalinsights) | [Pricing](https://learn.microsoft.com/azure/azure-monitor/logs/cost-logs) |
networking-connectivity.md 3.6 KB
# Networking (Connectivity) Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| Azure Bastion | `Microsoft.Network/bastionHosts` | `2024-07-01` | `bas` | Resource group | Mainstream |
| Azure Firewall | `Microsoft.Network/azureFirewalls` | `2024-07-01` | `afw` | Resource group | Mainstream |
| DNS Zone | `Microsoft.Network/dnsZones` | `2018-05-01` | *(domain)* | Resource group | Foundational |
| VPN Gateway | `Microsoft.Network/virtualNetworkGateways` | `2024-07-01` | `vpng` | Resource group | Foundational |
| Private DNS Zone | `Microsoft.Network/privateDnsZones` | `2024-06-01` | *(domain)* | Resource group | Foundational |
| Private Endpoint | `Microsoft.Network/privateEndpoints` | `2024-07-01` | `pep` | Resource group | Foundational |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| Azure Bastion | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/bastionhosts?pivots=deployment-language-bicep) | [Bastion overview](https://learn.microsoft.com/azure/bastion/bastion-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Configuration settings](https://learn.microsoft.com/azure/bastion/configuration-settings) |
| Azure Firewall | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/azurefirewalls?pivots=deployment-language-bicep) | [Firewall overview](https://learn.microsoft.com/azure/firewall/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [SKU comparison](https://learn.microsoft.com/azure/firewall/choose-firewall-sku) |
| DNS Zone | [2018-05-01](https://learn.microsoft.com/azure/templates/microsoft.network/dnszones?pivots=deployment-language-bicep) | [Azure DNS overview](https://learn.microsoft.com/azure/dns/dns-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Delegate a domain](https://learn.microsoft.com/azure/dns/dns-delegate-domain-azure-dns) |
| VPN Gateway | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/virtualnetworkgateways?pivots=deployment-language-bicep) | [VPN Gateway overview](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpngateways) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Gateway SKUs](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsku) |
| Private DNS Zone | [2024-06-01](https://learn.microsoft.com/azure/templates/microsoft.network/privatednszones?pivots=deployment-language-bicep) | [Private DNS overview](https://learn.microsoft.com/azure/dns/private-dns-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [PE DNS config](https://learn.microsoft.com/azure/private-link/private-endpoint-dns) |
| Private Endpoint | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/privateendpoints?pivots=deployment-language-bicep) | [PE overview](https://learn.microsoft.com/azure/private-link/private-endpoint-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [DNS zone values](https://learn.microsoft.com/azure/private-link/private-endpoint-dns) |
networking-core.md 4.3 KB
# Networking (Core) Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| Virtual Network | `Microsoft.Network/virtualNetworks` | `2024-07-01` | `vnet` | Resource group | Foundational |
| Subnet | `Microsoft.Network/virtualNetworks/subnets` | `2024-07-01` | `snet` | Parent VNet | Foundational |
| NSG | `Microsoft.Network/networkSecurityGroups` | `2024-07-01` | `nsg` | Resource group | Foundational |
| Route Table | `Microsoft.Network/routeTables` | `2024-07-01` | `rt` | Resource group | Foundational |
| Network Interface | `Microsoft.Network/networkInterfaces` | `2024-07-01` | `nic` | Resource group | Foundational |
| Public IP | `Microsoft.Network/publicIPAddresses` | `2024-07-01` | `pip` | Resource group | Foundational |
| NAT Gateway | `Microsoft.Network/natGateways` | `2024-07-01` | `ng` | Resource group | Foundational |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| Virtual Network | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/virtualnetworks?pivots=deployment-language-bicep) | [VNet overview](https://learn.microsoft.com/azure/virtual-network/virtual-networks-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [VNet planning](https://learn.microsoft.com/azure/virtual-network/virtual-network-vnet-plan-design-arm) |
| Subnet | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/virtualnetworks/subnets?pivots=deployment-language-bicep) | [Subnets](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-subnet) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Subnet delegation](https://learn.microsoft.com/azure/virtual-network/subnet-delegation-overview) |
| NSG | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/networksecuritygroups?pivots=deployment-language-bicep) | [NSG overview](https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Security rules](https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works) |
| Route Table | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/routetables?pivots=deployment-language-bicep) | [Traffic routing](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Forced tunneling](https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-forced-tunneling-rm) |
| Network Interface | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/networkinterfaces?pivots=deployment-language-bicep) | [NIC overview](https://learn.microsoft.com/azure/virtual-network/virtual-network-network-interface) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Accelerated networking](https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview) |
| Public IP | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/publicipaddresses?pivots=deployment-language-bicep) | [Public IP overview](https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Basic SKU retirement](https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-basic-upgrade-guidance) |
| NAT Gateway | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/natgateways?pivots=deployment-language-bicep) | [NAT Gateway overview](https://learn.microsoft.com/azure/nat-gateway/nat-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Availability zones](https://learn.microsoft.com/azure/nat-gateway/nat-availability-zones) |
networking-traffic.md 2.6 KB
# Networking (Traffic) Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| API Management | `Microsoft.ApiManagement/service` | `2024-05-01` | `apim` | Global | Mainstream |
| Application Gateway | `Microsoft.Network/applicationGateways` | `2024-07-01` | `agw` | Resource group | Foundational |
| Front Door | `Microsoft.Cdn/profiles` | `2025-06-01` | `afd` | Resource group | Foundational |
| Load Balancer | `Microsoft.Network/loadBalancers` | `2024-07-01` | `lbi`/`lbe` | Resource group | Foundational |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| API Management | [2024-05-01](https://learn.microsoft.com/azure/templates/microsoft.apimanagement/service?pivots=deployment-language-bicep) | [APIM overview](https://learn.microsoft.com/azure/api-management/api-management-key-concepts) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftapimanagement) | [VNet integration](https://learn.microsoft.com/azure/api-management/virtual-network-concepts) |
| Application Gateway | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/applicationgateways?pivots=deployment-language-bicep) | [App Gateway overview](https://learn.microsoft.com/azure/application-gateway/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [v2 features](https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant) |
| Front Door | [2025-06-01](https://learn.microsoft.com/azure/templates/microsoft.cdn/profiles?pivots=deployment-language-bicep) | [Front Door overview](https://learn.microsoft.com/azure/frontdoor/front-door-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftcdn) | [Routing architecture](https://learn.microsoft.com/azure/frontdoor/front-door-routing-architecture) |
| Load Balancer | [2024-07-01](https://learn.microsoft.com/azure/templates/microsoft.network/loadbalancers?pivots=deployment-language-bicep) | [LB overview](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftnetwork) | [Standard LB](https://learn.microsoft.com/azure/load-balancer/load-balancer-standard-overview) |
security.md 1.5 KB
# Security Resources

| Resource | ARM Type | API Version | CAF Prefix | Naming Scope | Region |
|----------|----------|-------------|------------|--------------|--------|
| Key Vault | `Microsoft.KeyVault/vaults` | `2024-11-01` | `kv` | Global | Foundational |
| Managed Identity | `Microsoft.ManagedIdentity/userAssignedIdentities` | `2024-11-30` | `id` | Resource group | Foundational |

## Documentation

| Resource | Bicep Reference | Service Overview | Naming Rules | Additional |
|----------|----------------|------------------|--------------|------------|
| Key Vault | [2024-11-01](https://learn.microsoft.com/azure/templates/microsoft.keyvault/vaults?pivots=deployment-language-bicep) | [Key Vault overview](https://learn.microsoft.com/azure/key-vault/general/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftkeyvault) | [Soft-delete](https://learn.microsoft.com/azure/key-vault/general/soft-delete-overview) |
| Managed Identity | [2024-11-30](https://learn.microsoft.com/azure/templates/microsoft.managedidentity/userassignedidentities?pivots=deployment-language-bicep) | [Managed identities](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview) | [Naming rules](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-name-rules#microsoftmanagedidentity) | [Workload identity federation](https://learn.microsoft.com/entra/workload-id/workload-identity-federation) |

License (MIT)

View full license text
MIT License

Copyright 2025 (c) Microsoft Corporation.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.