Installation

Install with CLI Recommended
gh skills-hub install azure-validate

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

Download and extract to your repository:

.github/skills/azure-validate/

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

Skill Files (17)

SKILL.md 3.5 KB
---
name: azure-validate
description: "Pre-deployment validation for Azure readiness. Run deep checks on configuration, infrastructure (Bicep or Terraform), RBAC role assignments, managed identity permissions, and prerequisites before deploying. WHEN: validate my app, check deployment readiness, run preflight checks, verify configuration, check if ready to deploy, validate azure.yaml, validate Bicep, test before deploying, troubleshoot deployment errors, validate Azure Functions, validate function app, validate serverless deployment, verify RBAC roles, check role assignments, review managed identity permissions, what-if analysis."
license: MIT
metadata:
  author: Microsoft
  version: "1.0.3"
---

# Azure Validate

> **AUTHORITATIVE GUIDANCE** — Follow these instructions exactly. This supersedes prior training.

> **⛔ STOP — PREREQUISITE CHECK REQUIRED**
>
> Before proceeding, verify this prerequisite is met:
>
> **azure-prepare** was invoked and completed → `.azure/deployment-plan.md` exists with status `Approved` or later
>
> If the plan is missing, **STOP IMMEDIATELY** and invoke **azure-prepare** first.
>
> The complete workflow ensures success:
>
> `azure-prepare` → `azure-validate` → `azure-deploy`

## Triggers

- Check if app is ready to deploy
- Validate azure.yaml or Bicep
- Run preflight checks
- Troubleshoot deployment errors

## Rules

1. Run after azure-prepare, before azure-deploy
2. All checks must pass—do not deploy with failures
3. ⛔ **Destructive actions require `ask_user`** — [global-rules](references/global-rules.md)

## Steps

| # | Action | Reference |
|---|--------|-----------|
| 1 | **Load Plan** — Read `.azure/deployment-plan.md` for recipe and configuration. If missing → run azure-prepare first | `.azure/deployment-plan.md` |
| 2 | **Add Validation Steps** — Copy recipe "Validation Steps" to `.azure/deployment-plan.md` as children of "All validation checks pass" | [recipes/README.md](references/recipes/README.md), `.azure/deployment-plan.md` |
| 3 | **Run Validation** — Execute recipe-specific validation commands | [recipes/README.md](references/recipes/README.md) |
| 4 | **Build Verification** — Build the project and fix any errors before proceeding | See recipe |
| 5 | **Static Role Verification** — Review Bicep/Terraform for correct RBAC role assignments in code | [role-verification.md](references/role-verification.md) |
| 6 | **Record Proof** — Populate **Section 7: Validation Proof** with commands run and results | `.azure/deployment-plan.md` |
| 7 | **Resolve Errors** — Fix failures before proceeding | See recipe's `errors.md` |
| 8 | **Update Status** — Only after ALL checks pass, set status to `Validated` | `.azure/deployment-plan.md` |
| 9 | **Deploy** — Invoke **azure-deploy** skill | — |
> **⛔ VALIDATION AUTHORITY**
>
> This skill is the **ONLY** authorized way to set plan status to `Validated`. You MUST:
> 1. Run actual validation commands (azd provision --preview, bicep build, terraform validate, etc.)
> 2. Populate **Section 7: Validation Proof** with the commands you ran and their results
> 3. Only then set status to `Validated`
>
> Do NOT set status to `Validated` without running checks and recording proof.

---

> **⚠️ MANDATORY NEXT STEP — DO NOT SKIP**
>
> After ALL validations pass, you **MUST** invoke **azure-deploy** to execute the deployment. Do NOT attempt to run `azd up`, `azd deploy`, or any deployment commands directly. Let azure-deploy handle execution.
>
> If any validation failed, fix the issues and re-run azure-validate before proceeding.
references/
aspire-functions-secrets.md 3.6 KB
# Aspire + Azure Functions: Secret Storage Validation

> ⚠️ **Pre-provisioning check** — Run this BEFORE `azd provision`.

## When This Applies

This check is required when **all** of these are true:

| Condition | How to detect |
|-----------|--------------|
| .NET Aspire project | `*.AppHost.csproj` exists or `Aspire.Hosting` package reference |
| Azure Functions component | `AddAzureFunctionsProject` call in `AppHost.cs` or `Program.cs` |
| Identity-based storage | `WithHostStorage` call (Aspire default) |

## Detection

Search for `AddAzureFunctionsProject` in the AppHost source file(s):

```bash
grep -rn "AddAzureFunctionsProject" . --include="*.cs"
```

**PowerShell:**
```powershell
Get-ChildItem -Recurse -Filter "*.cs" | Select-String "AddAzureFunctionsProject" -List
```

If found, check whether `AzureWebJobsSecretStorageType` is already configured in those same file(s):

```bash
# Check only the AppHost file(s) that contain AddAzureFunctionsProject
find . -name "*.cs" -path "*AppHost*" -print0 | xargs -0 grep -l "AddAzureFunctionsProject" 2>/dev/null | xargs grep -l "AzureWebJobsSecretStorageType"
```

**PowerShell:**
```powershell
Get-ChildItem -Recurse -Filter "*.cs" |
  Where-Object { $_.FullName -match "AppHost" } |
  Select-String "AddAzureFunctionsProject" -List |
  ForEach-Object { Select-String "AzureWebJobsSecretStorageType" -Path $_.Path }
```

**If `AddAzureFunctionsProject` is present but `AzureWebJobsSecretStorageType` is NOT configured in the same file → fix is required.**

## Fix

Add `.WithEnvironment("AzureWebJobsSecretStorageType", "Files")` to the Azure Functions project builder chain in the AppHost source file that contains the `AddAzureFunctionsProject` call (often `Program.cs` in the `*.AppHost` project).

### Before

```csharp
var functions = builder.AddAzureFunctionsProject<Projects.MyFunctions>("functions")
    .WithHostStorage(storage)
    .WithReference(queues);
```

### After

```csharp
var functions = builder.AddAzureFunctionsProject<Projects.MyFunctions>("functions")
    .WithHostStorage(storage)
    .WithEnvironment("AzureWebJobsSecretStorageType", "Files")
    .WithReference(queues);
```

> 💡 **Tip:** Place `.WithEnvironment(...)` immediately after `.WithHostStorage(...)` for clarity.

## Why This Is Required

Azure Functions needs storage for managing host secrets/keys (function keys, host keys, master key). By default, it stores them as blobs in the `AzureWebJobsStorage` account.

When Aspire configures identity-based storage access (via `WithHostStorage`), it sets URI-based environment variables like `AzureWebJobsStorage__blobServiceUri` instead of a connection string. The Functions runtime's secret manager does **not** support these identity-based URIs — it requires either a connection string or SAS token.

Setting `AzureWebJobsSecretStorageType=Files` switches the Functions host to file-system-based key storage, bypassing the blob storage dependency for secrets.

## Error Without This Setting

```
System.InvalidOperationException: Secret initialization from Blob storage failed
due to missing both an Azure Storage connection string and a SAS connection URI.
For Blob Storage, please provide at least one of these.
```

## When This Check Does NOT Apply

| Scenario | Why |
|----------|-----|
| Aspire project without Azure Functions | No Functions secret manager involved |
| Standalone Azure Functions (not Aspire) | Uses connection string by default |
| Functions with explicit connection string | `AzureWebJobsStorage` is a full connection string, not identity-based |
| `AzureWebJobsSecretStorageType` already set | Configuration is already present |
global-rules.md 1.2 KB
# Global Rules

> **MANDATORY** — These rules apply to ALL skills. Violations are unacceptable.

## Rule 1: Destructive Actions Require User Confirmation

⛔ **ALWAYS use `ask_user`** before ANY destructive action.

### What is Destructive?

| Category | Examples |
|----------|----------|
| **Delete** | `az group delete`, `azd down`, `rm -rf`, delete resource |
| **Overwrite** | Replace existing files, overwrite config, reset settings |
| **Irreversible** | Purge Key Vault, delete storage account, drop database |
| **Cost Impact** | Provision expensive resources, scale up significantly |
| **Security** | Expose secrets, change access policies, modify RBAC |

### How to Confirm

```
ask_user(
  question: "This will permanently delete resource group 'rg-myapp'. Continue?",
  choices: ["Yes, delete it", "No, cancel"]
)
```

### No Exceptions

- Do NOT assume user wants to delete/overwrite
- Do NOT proceed based on "the user asked to deploy" (deploy ≠ delete old)
- Do NOT batch destructive actions without individual confirmation

---

## Rule 2: Never Assume Subscription or Location

⛔ **ALWAYS use `ask_user`** to confirm:
- Azure subscription (show actual name and ID)
- Azure region/location
policy-validation.md 1.5 KB
# Azure Policy Validation

## How to Validate Policies

### 1. Get Subscription ID

Retrieve your current Azure subscription ID:

```bash
az account show --query id -o tsv
```

### 2. Validate Policies

Call the Azure MCP Policy tool to retrieve policies for your subscription:

```
mcp_azure_mcp_policy(command: "list", parameters: { subscription_id: "<subscription-id>" })
```

Replace `<subscription-id>` with the actual subscription ID obtained from step 1.

## Review Policy Compliance

When validating Azure policies for your subscription:

- **Check for policy violations** — Identify any resources or configurations that don't comply with assigned policies
- **Verify organizational compliance** — Ensure the planned deployment meets all organizational policy requirements
- **Address policy conflicts** — Resolve any policy issues before proceeding to deployment

## Common Policy Issues

| Issue | Resolution |
|-------|------------|
| Non-compliant resource SKUs | Update resource SKUs to comply with allowed values |
| Missing required tags | Add required tags to resources in your infrastructure code |
| Disallowed resource types | Replace with allowed alternatives or request policy exception |
| Location restrictions | Deploy to allowed regions only |
| Network security violations | Update NSG rules, firewall settings, or virtual network configurations |

## Next Steps

Only proceed to deployment after all policy violations are resolved and compliance is confirmed.
region-availability.md 2.9 KB
# Azure Region Availability Reference

> **AUTHORITATIVE SOURCE** — Consult this file BEFORE recommending any region.
>
> Official reference: https://azure.microsoft.com/en-us/explore/global-infrastructure/products-by-region/table

## How to Use

1. Check if your architecture includes any **limited availability** services below
2. If yes → refer to the table or use the MCP tool to list supported regions with sufficient quota for that service, and only offer regions that support ALL services
3. If all services are "available everywhere" → offer common regions

## MCP Tools Used

| Tool | Purpose |
|------|---------|
| `mcp_azure_mcp_quota` | Check Azure region availability and quota by setting `command` to `quota_usage_check` or `quota_region_availability_list` |

---

## Services with LIMITED Region Availability

### Azure Static Web Apps (SWA)

⚠️ **NOT available in many common regions**

| ✅ Available | ❌ NOT Available (will FAIL) |
|-------------|------------------------------|
| `westus2` | `eastus` |
| `centralus` | `northeurope` |
| `eastus2` | `southeastasia` |
| `westeurope` | `uksouth` |
| `eastasia` | `canadacentral` |
| | `australiaeast` |
| | `westus3` |

---

### Azure OpenAI

⚠️ **Very limited — varies by model**

| Region | GPT-4o | GPT-4 | GPT-3.5 | Embeddings |
|--------|:------:|:-----:|:-------:|:----------:|
| `eastus` | ✅ | ✅ | ✅ | ✅ |
| `eastus2` | ✅ | ✅ | ✅ | ✅ |
| `westus` | ⚠️ | ⚠️ | ✅ | ✅ |
| `westus3` | ✅ | ⚠️ | ✅ | ✅ |
| `southcentralus` | ✅ | ✅ | ✅ | ✅ |
| `swedencentral` | ✅ | ✅ | ✅ | ✅ |
| `westeurope` | ⚠️ | ✅ | ✅ | ✅ |

> Check https://learn.microsoft.com/azure/ai-services/openai/concepts/models for current model availability.

---

### Azure Kubernetes Service (AKS)

It has limited quota in some regions, to get available regions with enough quota, use `mcp_azure_mcp_quota` tool.

---

### Azure Database for PostgreSQL

It has limited quota in some regions, to get available regions with enough quota, use `mcp_azure_mcp_quota` tool.

---

## Services Available in Most Regions

These services are available in all major Azure regions — no special consideration needed:

- **Container Apps**
- **Azure Functions**
- **App Service**
- **Azure SQL Database**
- **Cosmos DB**
- **Key Vault**
- **Storage Account**
- **Service Bus**
- **Event Grid**
- **Application Insights / Log Analytics**

---

## Common Architecture Patterns

| Pattern | Recommended Regions |
|---------|---------------------|
| SWA only | `westus2`, `centralus`, `eastus2`, `westeurope`, `eastasia` |
| SWA + backend services | `westus2`, `centralus`, `eastus2`, `westeurope`, `eastasia` |
| Container Apps (no SWA) | `eastus`, `eastus2`, `westus2`, `centralus`, `westeurope` |
| With Azure OpenAI (GPT-4o/4/3.5 + embeddings) | `eastus`, `eastus2`, `swedencentral` |
| SWA + Azure OpenAI (GPT-4o/4/3.5 + embeddings) | `eastus2` (only region with full SWA + model overlap) |

---

**Last updated:** 2026-03-02

role-verification.md 3.7 KB
# Role Assignment Verification

Verify that all RBAC role assignments in the generated infrastructure are correct and sufficient before deployment. Incorrect or missing roles are a common cause of runtime failures.

## When to Verify

After build verification (step 4) and **before** recording proof (step 6). Role issues surface as cryptic auth errors during deployment — catching them here saves debugging time.

## Verification Checklist

Review every resource-to-identity relationship in the generated Bicep/Terraform:

| Check | How |
|-------|-----|
| **Every service identity has roles** | Each app with a managed identity must have at least one role assignment |
| **Roles match data operations** | Use service-specific **data-plane** roles for data access (see mapping table below); use generic Reader/Contributor/Owner only for management-plane operations |
| **Scope is least privilege** | Roles scoped to specific resources, not resource groups or subscriptions |
| **No missing roles** | Cross-check app code operations against assigned roles (see table below) |
| **Local dev identity has roles** | If testing locally, the user's identity needs equivalent roles via `az login` |

## Common Service-to-Role Mapping

| Service Operation | Required Role | Common Mistake |
|-------------------|---------------|----------------|
| Read blobs | Storage Blob Data Reader | Using generic Reader (no data access) |
| Read + write blobs | Storage Blob Data Contributor | Missing write permission |
| Generate SAS via user delegation | Storage Blob Delegator + Data Reader/Contributor | Forgetting Delegator role |
| Read Key Vault secrets | Key Vault Secrets User | Using Key Vault Reader (no secret access) |
| Read + write Cosmos DB | Cosmos DB Built-in Data Contributor | Using generic Contributor |
| Send Service Bus messages | Azure Service Bus Data Sender | Using generic Contributor |
| Read queues | Storage Queue Data Reader | Using Blob role for queues |

## How to Verify (Static Code Review)

Review the generated Bicep/Terraform files directly — do **not** query live Azure state here. For each role assignment resource in your infrastructure code:

1. Identify the **principal** (which managed identity)
2. Identify the **role** (which role definition)
3. Identify the **scope** (which target resource)
4. Cross-check against the app code to confirm the role grants the required data-plane access

> 💡 **Tip:** Search your Bicep for `Microsoft.Authorization/roleAssignments` or your Terraform for `azurerm_role_assignment` to find all role assignments.

> ⚠️ **Live role verification** (querying Azure for actually provisioned roles) is handled by **azure-deploy** step 8 as a post-deployment check. This step is a static code review only.

## Decision Tree

```
For each app identity in the generated infrastructure:
├── Has role assignments?
│   ├── No → Add required role assignments to Bicep/Terraform
│   └── Yes → Check each role:
│       ├── Role matches code operations? → ✅ OK
│       ├── Role too broad? → Narrow to least privilege
│       └── Role insufficient? → Upgrade or add missing role
│
For local testing:
├── User identity has equivalent roles?
│   ├── No → Grant roles via CLI or inform user
│   └── Yes → ✅ Ready for functional verification
```

> ⚠️ **Warning:** Generic roles like `Contributor` or `Reader` do **not** include data-plane access. For example, `Contributor` on a Storage Account cannot read blobs — you need `Storage Blob Data Contributor`. This is the most common RBAC mistake.

## Record in Plan

After role verification, update `.azure/plan.md`:

```markdown
## Role Assignment Verification
- Status: Verified / Issues Found
- Identities checked: <list of app identities>
- Roles confirmed: <list of role assignments>
- Issues: <any missing or incorrect roles fixed>
```
references/recipes/
README.md 0.4 KB
# Recipes

Validation recipes for different infrastructure approaches.

| Recipe | When to Use |
|--------|-------------|
| [AZD](azd/README.md) | Projects using Azure Developer CLI |
| [AZCLI](azcli/README.md) | Projects using Azure CLI scripts |
| [Bicep](bicep/README.md) | Projects using Bicep templates |
| [Terraform](terraform/README.md) | Projects using Terraform |
references/recipes/azcli/
README.md 2.3 KB
# AZCLI Validation

Validation steps for Azure CLI deployments.

## Prerequisites

- `./infra/main.bicep` exists
- Docker available (if containerized)

## Validation Steps

- [ ] 1. Azure CLI Installation
- [ ] 2. Authentication
- [ ] 3. Bicep Compilation
- [ ] 4. Template Validation
- [ ] 5. What-If Preview
- [ ] 6. Docker Build (if containerized)
- [ ] 7. Azure Policy Validation

## Validation Details

### 1. Azure CLI Installation

Verify Azure CLI is installed:

```bash
az version
```

**If not installed:**
```
mcp_azure_mcp_extension_cli_install(cli-type: "az")
```

### 2. Authentication

```bash
az account show
```

**If not logged in:**
```bash
az login
```

**Set subscription:**
```bash
az account set --subscription <subscription-id>
```

### 3. Bicep Compilation

```bash
az bicep build --file ./infra/main.bicep
```

### 4. Template Validation

```bash
# Subscription scope
az deployment sub validate \
  --location <location> \
  --template-file ./infra/main.bicep \
  --parameters ./infra/main.parameters.json

# Resource group scope
az deployment group validate \
  --resource-group <rg-name> \
  --template-file ./infra/main.bicep \
  --parameters ./infra/main.parameters.json
```

### 5. What-If Preview

```bash
# Subscription scope
az deployment sub what-if \
  --location <location> \
  --template-file ./infra/main.bicep \
  --parameters ./infra/main.parameters.json

# Resource group scope
az deployment group what-if \
  --resource-group <rg-name> \
  --template-file ./infra/main.bicep \
  --parameters ./infra/main.parameters.json
```

### 6. Docker Build (if containerized)

**Before building**, validate the Docker build context:

1. Read the `Dockerfile` in `./src/<service>`
2. If the Dockerfile contains `npm ci`, verify `package-lock.json` exists in the same directory
3. If `package-lock.json` is missing, generate it:

```bash
cd ./src/<service>
npm install --package-lock-only
```

**Then build:**

```bash
docker build -t <image>:test ./src/<service>
```

### 7. Azure Policy Validation

See [Policy Validation Guide](../../policy-validation.md) for instructions on retrieving and validating Azure policies for your subscription.

## References

- [Error handling](./errors.md)

## Next

All checks pass → **azure-deploy**
errors.md 0.5 KB
# AZCLI Validation Errors

| Error | Fix |
|-------|-----|
| `AADSTS700082: Token expired` | `az login` |
| `Please run 'az login'` | `az login` |
| `AADSTS50076: MFA required` | `az login --use-device-code` |
| `AuthorizationFailed` | Request Contributor role |
| `npm ci` fails with `missing: package-lock.json` | Run `npm install --package-lock-only` in the service directory before building |
| `Template validation failed` | Check Bicep syntax |

## Debug

```bash
az <command> --verbose --debug
```
references/recipes/azd/
README.md 4.2 KB
# AZD Validation

Validation steps for Azure Developer CLI projects.

## Prerequisites

- `azure.yaml` exists in project root
- Infrastructure files exist:
  - For Bicep: `./infra/` contains Bicep files
  - For Terraform: `./infra/` contains `.tf` files and `azure.yaml` has `infra.provider: terraform`

## Validation Steps

- [ ] 1. AZD Installation
- [ ] 2. Schema Validation
- [ ] 3. Environment Setup
- [ ] 4. Authentication Check
- [ ] 5. Subscription/Location Check
- [ ] 6. Aspire Pre-Provisioning Checks
- [ ] 7. Provision Preview
- [ ] 8. Build Verification
- [ ] 9. Docker Build Context Validation
- [ ] 10. Package Validation
- [ ] 11. Azure Policy Validation
- [ ] 12. Aspire Post-Provisioning Checks

## Validation Details

### 1. AZD Installation

Verify AZD is installed:

```bash
azd version
```

**If not installed:**
```
mcp_azure_mcp_extension_cli_install(cli-type: "azd")
```

### 2. Schema Validation

Validate azure.yaml against official schema:

```
mcp_azure_mcp_azd(command: "validate_azure_yaml", parameters: { path: "./azure.yaml" })
```

### 3. Environment Setup

Verify AZD environment exists and is configured. See [Environment Setup](environment.md) for detailed steps.

### 4. Authentication Check

```bash
azd auth login --check-status
```

**If not logged in:**
```bash
azd auth login
```

### 5. Subscription/Location Check

Check environment values:
```bash
azd env get-values
```

**If AZURE_SUBSCRIPTION_ID or AZURE_LOCATION not set:**

Use Azure MCP tools to list subscriptions:
```
mcp_azure_mcp_subscription_list
```

Use Azure MCP tools to list resource groups (check for conflicts):
```
mcp_azure_mcp_group_list
  subscription: <subscription-id>
```

Prompt user to confirm subscription and location before continuing.

Refer to the region availability reference to select a region supported by all services in this template:
- [Region availability](../../region-availability.md)

```bash
azd env set AZURE_SUBSCRIPTION_ID <subscription-id>
azd env set AZURE_LOCATION <location>
```

### 6. Aspire Pre-Provisioning Checks

**If this is a .NET Aspire project** (detected by `*.AppHost.csproj` or `Aspire.Hosting` package reference), run the **Pre-Provisioning** checks in [Aspire Validation](aspire.md) before continuing. **If not Aspire, skip this step.**

### 7. Provision Preview

Validate IaC is ready (must complete without error):

```bash
azd provision --preview --no-prompt
```

> 💡 **Note:** This works for both Bicep and Terraform. azd will automatically detect the provider from `azure.yaml` and run the appropriate validation (`bicep build` or `terraform plan`).

### 8. Build Verification

Build the project and verify there are no errors. If the build fails, fix the issues and re-build until it succeeds. Do NOT proceed to packaging or deployment with build errors.

### 9. Docker Build Context Validation

**If any service in `azure.yaml` uses a Dockerfile** (check the service's `project` path from `azure.yaml` for a `Dockerfile`), validate the build context before packaging:

1. Read each service's `Dockerfile`
2. If the Dockerfile contains `npm ci`, verify `package-lock.json` exists in the same directory
3. If `package-lock.json` is missing, generate it in the service's `project` path directory before proceeding:

```bash
cd <service-project-path>
npm install --package-lock-only
```

> ⚠️ **Warning:** `npm ci` will fail during Docker build if `package-lock.json` is missing. This check prevents Docker build failures during `azd package` and `azd up`.

### 10. Package Validation

Confirm all services package successfully:

```bash
azd package --no-prompt
```

### 11. Azure Policy Validation

See [Policy Validation Guide](../../policy-validation.md) for instructions on retrieving and validating Azure policies for your subscription.

### 12. Aspire Post-Provisioning Checks

**If this is a .NET Aspire project**, run the **Post-Provisioning** checks in [Aspire Validation](aspire.md) before proceeding to deployment. **If not Aspire, skip this step.**

## References

- [Environment Setup](environment.md)
- [Aspire Validation](aspire.md)
- [Error Handling](./errors.md)

## Next

All checks pass → **azure-deploy**
aspire.md 2.9 KB
# Aspire Validation

> ⚠️ **Only load this file when the project is a .NET Aspire application.**

Validation steps specific to .NET Aspire projects deployed via AZD.

## Detection

A project is Aspire-based if any of these are true:

| Indicator | Check |
|-----------|-------|
| AppHost project | `find . -name "*.AppHost.csproj"` |
| Aspire.Hosting package | `grep -r "Aspire.Hosting" . --include="*.csproj"` |

**If none found → skip this file entirely.**

---

## Pre-Provisioning: Functions Secret Storage

> ⚠️ **CRITICAL — Must run BEFORE `azd provision`.**

Check if the project uses Azure Functions within Aspire and ensure `AzureWebJobsSecretStorageType` is configured.
See [Aspire Functions Secrets Reference](../../aspire-functions-secrets.md) for detection commands, fix examples, and full details.

**If `AddAzureFunctionsProject` is NOT found**, skip this section.

---

## Post-Provisioning: Container Apps Environment Variables

> ⚠️ **CRITICAL — Run AFTER `azd provision` but BEFORE `azd deploy`.**

When using Aspire with Container Apps in "limited mode" (in-memory infrastructure generation), `azd provision` creates Azure resources but doesn't automatically populate environment variables that `azd deploy` needs.

**Check if environment variables are set:**

```bash
azd env get-values | grep -E "AZURE_CONTAINER_REGISTRY_ENDPOINT|AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID|MANAGED_IDENTITY_CLIENT_ID"
```

**If any are missing, set them now BEFORE running `azd deploy`:**

```bash
# Get resource group name
RG_NAME=$(azd env get-values | grep AZURE_RESOURCE_GROUP | cut -d'=' -f2 | tr -d '"')

# Set required variables
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT $(az acr list --resource-group "$RG_NAME" --query "[0].loginServer" -o tsv)
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID $(az identity list --resource-group "$RG_NAME" --query "[0].id" -o tsv)
azd env set MANAGED_IDENTITY_CLIENT_ID $(az identity list --resource-group "$RG_NAME" --query "[0].clientId" -o tsv)
```

**PowerShell:**
```powershell
# Get resource group name
$rgName = (azd env get-values | Select-String 'AZURE_RESOURCE_GROUP').Line.Split('=')[1].Trim('"')

# Set required variables
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT (az acr list --resource-group $rgName --query "[0].loginServer" -o tsv)
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID (az identity list --resource-group $rgName --query "[0].id" -o tsv)
azd env set MANAGED_IDENTITY_CLIENT_ID (az identity list --resource-group $rgName --query "[0].clientId" -o tsv)
```

**Why this is needed:** Aspire's "limited mode" generates infrastructure in-memory. While `azd provision` creates all necessary Azure resources (Container Registry, Managed Identity, Container Apps Environment), it doesn't populate the environment variables that reference those resources. The `azd deploy` phase requires these variables to authenticate with the container registry and configure managed identity bindings.
environment.md 2.0 KB
# AZD Environment Setup

> **⛔ MANDATORY**: You MUST set up an AZD environment before running any deployment commands.

## Step 1: Check Existing Environments

```bash
azd env list
```

**If an environment is already selected** (marked with `*`), check its current values:

```bash
azd env get-values
```

If `AZURE_ENV_NAME`, `AZURE_SUBSCRIPTION_ID`, and `AZURE_LOCATION` are already set, confirm with user:

```
Question: "An AZD environment is already configured. Would you like to use it?"

  Environment: {env-name}
  Subscription: {subscription-id}
  Location: {location}

Choices: [
  "Yes, use this environment (Recommended)",
  "No, create a new environment"
]
```

If user confirms → skip to **Verify Configuration**. Otherwise → continue to Step 2.

**If NO environment exists or none is selected:**
- Continue to Step 2

---

## Step 2: Create New Environment

> **⛔ DO NOT use generic names like "dev", "prod", or "test"**
>
> These cause naming conflicts in Azure resource groups and resources. Always generate a unique name.

### Generate Suggested Name

Use this pattern:
```
{project-name}-{random-4-chars}
```

**Examples:**
- `dadjokes-x7k2`
- `todoapp-m3p9`
- `myapi-q5w8`

### Prompt User

**You MUST use `ask_user` to confirm the environment name:**

```
I need to create an AZD environment for this deployment.

Suggested name: {project-name}-{random-4-chars}

Would you like to use this name or enter a custom one?
```

### Create Environment

After user confirms:
```bash
azd env new <environment-name>
```

---

## Step 3: Configure Environment

Set subscription and location:

```bash
azd env set AZURE_SUBSCRIPTION_ID <subscription-id>
azd env set AZURE_LOCATION <location>
```

---

## Verify Configuration

```bash
azd env get-values
```

Confirm these values are set:
- `AZURE_ENV_NAME`
- `AZURE_SUBSCRIPTION_ID`
- `AZURE_LOCATION`

---

## Only Then Proceed

After environment is configured, proceed with `azd up --no-prompt`.
errors.md 2.6 KB
# AZD Validation Errors

## Pre-Deployment Errors

These errors can be caught **before** running `azd up`:

| Error | Cause | Resolution |
|-------|-------|------------|
| `Please run 'az login'` | Not authenticated | `az login` or `azd auth login` |
| `No environment selected` | Missing azd environment | `azd env select <name>` or `azd env new <name>` |
| `no default response for prompt 'Enter a unique environment name'` | No azd environment created, or missing `-e` flag | Run `azd env new <name>` OR use `azd init --from-code -e <name>` with the `-e` flag |
| `no default response for prompt 'Enter a value for the 'environmentName'` | Environment variables not set | Run `azd env set AZURE_ENV_NAME <name>` |
| `Service not found` | Service name mismatch | Check service name in azure.yaml |
| `Invalid azure.yaml` | YAML syntax error | Fix YAML syntax |
| `Project path does not exist` | Wrong service project path | Fix service project path in azure.yaml |
| `Cannot connect to Docker daemon` | Docker not running | Start Docker Desktop |
| `npm ci` fails with `missing: package-lock.json` | Dockerfile uses `npm ci` but `package-lock.json` not in build context | Run `npm install --package-lock-only` in the service directory before building |
| `Could not find a part of the path 'infra\main.bicep'` | Missing infrastructure files | Generate infra/ folder before `azd up` |
| `Invalid resource group location '<loc>'. The Resource group already exists in location '<other>'` | RG exists in different region | Check RG location first with `az group show`, use that region or new env name |
| `expecting only '1' resource tagged with 'azd-service-name: web', but found '2'` | Multiple resources with same tag **in the same RG** | Delete duplicate or rename service |

## Static Web App Errors

| Error | Cause | Fix |
|-------|-------|-----|
| `language 'html' is not supported` | Invalid language value | Omit `language` for pure static sites |
| `language 'static' is not supported` | Invalid language value | Omit `language` for pure static sites |
| `dist folder not found` | Wrong dist path or missing build | Check `dist` is relative to `project`; add `language: js` if build needed |
| `LocationNotAvailableForResourceType` | SWA not in region | See [Region Availability](../../region-availability.md) for valid regions |

## SWA Path Validation

Before deployment, verify:
1. `project` path exists and contains source files
2. For framework apps: `language: js` is set
3. `dist` is relative to `project` (not project root)
4. Bicep has `azd-service-name` tag matching service name

## Debug

```bash
azd <command> --debug
```
references/recipes/bicep/
README.md 2.0 KB
# Bicep Validation

Validation steps for standalone Bicep deployments.

## Prerequisites

- `./infra/main.bicep` exists
- `./infra/main.parameters.json` exists
- Azure CLI authenticated

## Validation Steps

- [ ] 1. Bicep Compilation
- [ ] 2. Template Validation
- [ ] 3. What-If Preview
- [ ] 4. Authentication
- [ ] 5. Linting (optional)
- [ ] 6. Azure Policy Validation

## Validation Details

### 1. Bicep Compilation

```bash
az bicep build --file ./infra/main.bicep
```

**Pass:** No output (compiles cleanly)
**Fail:** Shows line numbers and errors

### 2. Template Validation

```bash
# Subscription scope
az deployment sub validate \
  --location <location> \
  --template-file ./infra/main.bicep \
  --parameters ./infra/main.parameters.json

# Resource group scope
az deployment group validate \
  --resource-group <rg-name> \
  --template-file ./infra/main.bicep \
  --parameters ./infra/main.parameters.json
```

### 3. What-If Preview

```bash
az deployment sub what-if \
  --location <location> \
  --template-file ./infra/main.bicep \
  --parameters ./infra/main.parameters.json
```

**Expected output:**
```
Resource and property changes are indicated with these symbols:
  + Create
  ~ Modify
  - Delete
```

### 4. Authentication

```bash
az account show
```

### 5. Linting (optional)

Use Bicep linter rules:

```bash
az bicep lint --file ./infra/main.bicep
```

### 6. Azure Policy Validation

See [Policy Validation Guide](../../policy-validation.md) for instructions on retrieving and validating Azure policies for your subscription.

## Checklist

| Check | Command | Pass |
|-------|---------|------|
| Bicep compiles | `az bicep build` | ☐ |
| Template valid | `az deployment validate` | ☐ |
| What-if passes | `az deployment what-if` | ☐ |
| Auth valid | `az account show` | ☐ |
| Policies validated | MCP Policy tool | ☐ |

## References

- [Error handling](./errors.md)

## Next

All checks pass → **azure-deploy**
errors.md 0.4 KB
# Bicep Validation Errors

| Error | Fix |
|-------|-----|
| `BCP035: Invalid type` | Check API version |
| `BCP037: Not a member` | Check resource schema |
| `BCP018: Expected character` | Fix syntax |
| `Module not found` | Check relative paths |
| `Template validation failed` | Review error details |

## Debug

```bash
az bicep build --file ./infra/main.bicep 2>&1
```
references/recipes/terraform/
README.md 1.6 KB
# Terraform Validation

Validation steps for Terraform deployments.

## Prerequisites

- `./infra/main.tf` exists
- State backend accessible

## Validation Steps

- [ ] 1. Terraform Installation
- [ ] 2. Azure CLI Installation
- [ ] 3. Authentication
- [ ] 4. Initialize
- [ ] 5. Format Check
- [ ] 6. Validate Syntax
- [ ] 7. Plan Preview
- [ ] 8. State Backend
- [ ] 9. Azure Policy Validation

## Validation Details

### 1. Terraform Installation

Verify Terraform is installed:

```bash
terraform version
```

**If not installed:** See https://developer.hashicorp.com/terraform/install

### 2. Azure CLI Installation

Verify Azure CLI is installed:

```bash
az version
```

**If not installed:**
```
mcp_azure_mcp_extension_cli_install(cli-type: "az")
```

### 3. Authentication

```bash
az account show
```

**If not logged in:**
```bash
az login
az account set --subscription <subscription-id>
```

### 4. Initialize

```bash
cd infra
terraform init
```

### 5. Format Check

```bash
terraform fmt -check -recursive
```

**Fix if needed:**
```bash
terraform fmt -recursive
```

### 6. Validate Syntax

```bash
terraform validate
```

### 7. Plan Preview

```bash
terraform plan -out=tfplan
```

### 8. State Backend

Verify state is accessible:

```bash
terraform state list
```

### 9. Azure Policy Validation

See [Policy Validation Guide](../../policy-validation.md) for instructions on retrieving and validating Azure policies for your subscription.

## References

- [Error handling](./errors.md)

## Next

All checks pass → **azure-deploy**
errors.md 0.3 KB
# Terraform Validation Errors

| Error | Fix |
|-------|-----|
| `Backend init failed` | Check storage account access |
| `Provider version conflict` | Update required_providers |
| `State lock failed` | Wait or force unlock |
| `Validation failed` | Check terraform validate output |

## Debug

```bash
TF_LOG=DEBUG terraform plan
```

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.