Azure Validate
MicrosoftOfficialCreated by Microsoft
- Skill
- Workflow
- Cloud and DevOps
- MIT
- Low risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The azure-validate skill provides a structured, step-by-step workflow to ensure Azure readiness before deployment. It performs deep checks on infrastructure definitions (Bicep or Terraform), RBAC role assignments, managed identity permissions, and other prerequisites. This skill is designed to be used as the second step in a three-part deployment process: azure-prepare, azure-validate, and azure-deploy. It uses a script-based approach to guide the user through validation steps, tracking progress in a local JSON file to ensure all requirements are met before allowing a deployment to proceed.
What it does
- Validates infrastructure configurations including Bicep and Terraform files.
- Verifies RBAC role assignments and managed identity permissions.
- Runs preflight checks to ensure environment readiness.
- Tracks validation progress through a structured, multi-step script.
- Ensures all prerequisites are met before deployment can occur.
- Provides a mechanism to troubleshoot common deployment errors.
When to use it
- Before executing an Azure deployment to ensure all configurations are correct.
- When troubleshooting deployment errors to identify configuration or permission issues.
- After completing the azure-prepare step to verify the deployment plan.
- When you need to confirm that RBAC and managed identity settings are correctly configured.
Advantages
- Prevents deployment failures by catching configuration issues early.
- Ensures consistent and repeatable validation processes.
- Integrates seamlessly into a standard deployment workflow.
- Provides clear, actionable feedback on validation status.
Usage examples
- “Validate my Azure deployment readiness.”
- The agent initiates the azure-validate workflow script, guiding you through the necessary checks for your infrastructure and permissions.
- “Check if my Bicep files are ready for deployment.”
- The agent runs the validation script against your Bicep files and reports any configuration errors or missing prerequisites.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/microsoft/azure-validate/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip azure-validate.zip -d .agents/skills
Documentation by Microsoft
Azure Validate
AUTHORITATIVE GUIDANCE — Follow these instructions exactly unless they contradict security policies given to you.
⛔ STOP — PREREQUISITE CHECK REQUIRED
Before proceeding, verify this prerequisite is met:
azure-prepare was invoked and completed →
.azure/deployment-plan.mdexists with statusApprovedor laterIf 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
Run after azure-prepare, before azure-deploy
All checks must pass—do not deploy with failures
⛔ Destructive actions require
ask_user— global-rules
Steps
Run the workflow script and follow its instructions. It walks you through each validation step one at a time, recording progress in .azure/validate-status.json. Use references/scripts/workflow.ps1 on Windows or references/scripts/workflow.sh on macOS/Linux.
Start by calling the script without the completed-step argument:
pwsh references/scripts/workflow.ps1 -WorkspacePath <workspace-path>
# macOS/Linux: bash references/scripts/workflow.sh --workspace-path <workspace-path>Each run prints the next action and the value to pass next. Perform the action, then re-run with that value (-CompletedStep <value> for pwsh, --completed-step <value> for bash). Repeat until it reports the azure-validate workflow is complete.
The steps reference recipe details in references/recipes/README.md and role checks in references/role-verification.md.
⛔ VALIDATION AUTHORITY
This skill is the officially verified way to set plan status to
Validated. You MUST follow the script's instructions to completion before setting status toValidated. Do NOT set status toValidatedwithout doing so.
⚠️ NEXT STEP — DEPENDS ON USER INTENT
After ALL validations pass, check whether the user asked to deploy:
If the user explicitly requested deployment, you MUST invoke azure-deploy to execute it. Do NOT run
azd up,azd deploy, or any deployment commands directly — let azure-deploy handle execution.If the user only asked to validate or prepare (not deploy), STOP after recording proof and setting status to
Validated. Report the validation results and do NOT invoke azure-deploy.If any validation failed, fix the issues and re-run azure-validate before proceeding.
Files
- ATTRIBUTION.mdAdded by AutoGineer974 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md3.5 KiB
- references/aspire-functions-secrets.md3.7 KiB
- references/global-rules.md1.2 KiB
- references/policy-validation.md1.5 KiB
- references/recipes/README.md374 B
- references/recipes/azcli/README.md2.7 KiB
- references/recipes/azcli/errors.md505 B
- references/recipes/azd/README.md5.3 KiB
- references/recipes/azd/aspire.md1.7 KiB
- references/recipes/azd/environment.md1.9 KiB
- references/recipes/azd/errors.md2.6 KiB
- references/recipes/azd/scripts/set-aspire-aca-env.ps1Script3.5 KiB
- references/recipes/azd/scripts/set-aspire-aca-env.shScript3.6 KiB
- references/recipes/bicep/README.md2.5 KiB
- references/recipes/bicep/errors.md374 B
- references/recipes/scripts/validate-deployment.ps1Script5.2 KiB
- references/recipes/scripts/validate-deployment.shScript6.1 KiB
- references/recipes/terraform/README.md3.9 KiB
- references/recipes/terraform/errors.md2.8 KiB
- references/recipes/terraform/scripts/validate-terraform.ps1Script6.8 KiB
- references/recipes/terraform/scripts/validate-terraform.shScript6.6 KiB
- references/region-availability.md3.0 KiB
- references/role-verification.md3.9 KiB
- references/scripts/scan-aspire-functions-secrets.ps1Script3.0 KiB
- references/scripts/scan-aspire-functions-secrets.shScript3.3 KiB
- references/scripts/workflow.ps1Script5.2 KiB
- references/scripts/workflow.shScript5.7 KiB
references/recipes/terraform/scripts/validate-terraform.sh
#!/usr/bin/env bash
# validate-terraform.sh
# Runs the Terraform pre-deployment validation preflight sequence and prints a
# compact PASS/FAIL/SKIP summary plus the captured error text for any failed step.
#
# The script runs every check even if an earlier one fails, so you get a complete
# verdict in a single call. It never fixes anything - it only runs and reports, so
# you can jump straight to remediation for any failed step.
#
# Steps: terraform present, az present, authenticated, init, fmt -check, validate,
# plan, state list, Go-style {{ .Env.* }} template-variable scan.
#
# Usage:
# ./validate-terraform.sh [infra-dir] [subscription-id]
#
# Arguments:
# infra-dir Path to the Terraform infra directory (default: ./infra).
# subscription-id Optional subscription to select before checks.
#
# Examples:
# ./validate-terraform.sh # Validate ./infra
# ./validate-terraform.sh ./infra # Validate an explicit directory
# ./validate-terraform.sh ./infra 00000000-0000-0000-0000-000000000000
#
# Exit code: 0 when every non-skipped step passes, 1 when any step fails.
set -uo pipefail
INFRA_DIR="${1:-./infra}"
SUBSCRIPTION_ID="${2:-}"
# --- result tracking ---------------------------------------------------------
STEP_NAMES=()
STEP_STATUS=() # PASS | FAIL | SKIP
STEP_ERRORS=() # captured error text (empty unless FAIL)
record() {
# record <name> <status> [error-text]
# Results are collected here and rendered once in the summary at the end.
STEP_NAMES+=("$1")
STEP_STATUS+=("$2")
STEP_ERRORS+=("${3:-}")
}
echo "Terraform validation preflight - infra dir: $INFRA_DIR"
echo ""
# --- 1. Terraform installed --------------------------------------------------
if command -v terraform >/dev/null 2>&1; then
record "Terraform installed" "PASS"
else
record "Terraform installed" "FAIL" "terraform not found on PATH. Install: https://developer.hashicorp.com/terraform/install"
fi
# --- 2. Azure CLI installed --------------------------------------------------
if command -v az >/dev/null 2>&1; then
record "Azure CLI installed" "PASS"
else
record "Azure CLI installed" "FAIL" "az not found on PATH. Install the Azure CLI: mcp_azure_mcp_extension_cli_install(cli-type: \"az\")"
fi
# --- 3. Authentication -------------------------------------------------------
if command -v az >/dev/null 2>&1; then
if [ -n "$SUBSCRIPTION_ID" ]; then
if SUB_OUT=$(az account set --subscription "$SUBSCRIPTION_ID" 2>&1); then
record "Select subscription" "PASS"
else
record "Select subscription" "FAIL" "$SUB_OUT"
fi
fi
if ACCOUNT_OUT=$(az account show -o none 2>&1); then
record "Authenticated (az account show)" "PASS"
else
record "Authenticated (az account show)" "FAIL" "$ACCOUNT_OUT"
fi
else
record "Authenticated (az account show)" "SKIP" "Azure CLI not installed"
fi
# --- infra dir presence gate -------------------------------------------------
HAVE_TF=false
if command -v terraform >/dev/null 2>&1 && [ -d "$INFRA_DIR" ]; then
HAVE_TF=true
fi
run_tf() {
# run_tf <name> <terraform args...>
local name="$1"; shift
if [ "$HAVE_TF" != true ]; then
record "$name" "SKIP" "terraform unavailable or infra dir '$INFRA_DIR' not found"
return
fi
# Stream output to a temp file so large output (e.g. terraform plan) is not
# held in memory; only read it back when the command fails.
local tmp
tmp=$(mktemp)
if (cd "$INFRA_DIR" && terraform "$@") >"$tmp" 2>&1; then
record "$name" "PASS"
else
record "$name" "FAIL" "$(cat "$tmp")"
fi
rm -f "$tmp"
}
# --- 4. Initialize -----------------------------------------------------------
run_tf "terraform init" init -input=false
# --- 5. Format check ---------------------------------------------------------
run_tf "terraform fmt -check" fmt -check -recursive
# --- 6. Validate syntax ------------------------------------------------------
run_tf "terraform validate" validate
# --- 7. Plan preview ---------------------------------------------------------
run_tf "terraform plan" plan -input=false -out=tfplan
# --- 8. State backend --------------------------------------------------------
run_tf "terraform state list" state list
# --- 9. Go-style template-variable scan --------------------------------------
if [ -d "$INFRA_DIR" ]; then
TEMPLATE_HITS=$(grep -rn '{{ *\.Env\.' "$INFRA_DIR" --include='*.tf' --include='*.tfvars.json' 2>/dev/null || true)
if [ -n "$TEMPLATE_HITS" ]; then
record "Template-variable scan ({{ .Env.* }})" "FAIL" \
"Found unresolved Go-style template variables - replace {{ .Env.VAR }} with \${VAR} (azd envsubst format):
$TEMPLATE_HITS"
else
record "Template-variable scan ({{ .Env.* }})" "PASS"
fi
else
record "Template-variable scan ({{ .Env.* }})" "SKIP" "infra dir '$INFRA_DIR' not found"
fi
# --- 10. main.tfvars.json JSON syntax ----------------------------------------
TFVARS="$INFRA_DIR/main.tfvars.json"
if [ -f "$TFVARS" ]; then
if command -v python3 >/dev/null 2>&1; then
if JSON_ERR=$(python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$TFVARS" 2>&1); then
record "main.tfvars.json is valid JSON" "PASS"
else
record "main.tfvars.json is valid JSON" "FAIL" "$JSON_ERR"
fi
elif command -v jq >/dev/null 2>&1; then
if JSON_ERR=$(jq empty "$TFVARS" 2>&1); then
record "main.tfvars.json is valid JSON" "PASS"
else
record "main.tfvars.json is valid JSON" "FAIL" "$JSON_ERR"
fi
else
record "main.tfvars.json is valid JSON" "SKIP" "no JSON parser (python3/jq) available"
fi
else
record "main.tfvars.json is valid JSON" "SKIP" "$TFVARS not found"
fi
# --- summary -----------------------------------------------------------------
echo ""
echo "==================== SUMMARY ===================="
printf '%-40s %s\n' "STEP" "RESULT"
printf '%-40s %s\n' "----" "------"
FAILED=0
for i in "${!STEP_NAMES[@]}"; do
printf '%-40s %s\n' "${STEP_NAMES[$i]}" "${STEP_STATUS[$i]}"
[ "${STEP_STATUS[$i]}" = "FAIL" ] && FAILED=$((FAILED + 1))
done
echo "================================================="
if [ "$FAILED" -gt 0 ]; then
echo ""
echo "----- FAILURE DETAILS -----"
for i in "${!STEP_NAMES[@]}"; do
if [ "${STEP_STATUS[$i]}" = "FAIL" ]; then
echo ""
echo "### ${STEP_NAMES[$i]}"
echo "${STEP_ERRORS[$i]}"
fi
done
echo ""
echo "RESULT: $FAILED step(s) failed. See remediation guidance in README.md."
exit 1
fi
echo ""
echo "RESULT: All checks passed. Ready for azure-deploy."
exit 0
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
What our scanner noticed· Low risk
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills · .github/plugins/azure-skills/skills/azure-validate · commit 0696600
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from .github/plugins/azure-skills/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- microsoft/azure-skills
AutoGineer is not affiliated with or endorsed by Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download azure-validate.zip