references/auth-best-practices.md
# Azure Authentication Best Practices
> Source: [Microsoft — Passwordless connections for Azure services](https://learn.microsoft.com/azure/developer/intro/passwordless-overview) and [Azure Identity client libraries](https://learn.microsoft.com/dotnet/azure/sdk/authentication/).
## Golden Rule
Use **managed identities** and **Azure RBAC** in production. Reserve `DefaultAzureCredential` for **local development only**.
## Authentication by Environment
| Environment | Recommended Credential | Why |
|---|---|---|
| **Production (Azure-hosted)** | `ManagedIdentityCredential` (system- or user-assigned) | No secrets to manage; auto-rotated by Azure |
| **Production (on-premises)** | `ClientCertificateCredential` or `WorkloadIdentityCredential` | Deterministic; no fallback chain overhead |
| **CI/CD pipelines** | `AzurePipelinesCredential` / `WorkloadIdentityCredential` | Scoped to pipeline identity |
| **Local development** | `DefaultAzureCredential` | Chains CLI, PowerShell, and VS Code credentials for convenience |
## Why Not `DefaultAzureCredential` in Production?
1. **Unpredictable fallback chain** — walks through multiple credential types, adding latency and making failures harder to diagnose.
2. **Broad surface area** — checks environment variables, CLI tokens, and other sources that should not exist in production.
3. **Non-deterministic** — which credential actually authenticates depends on the environment, making behavior inconsistent across deployments.
4. **Performance** — each failed credential attempt adds network round-trips before falling back to the next.
## Production Patterns
### .NET
```csharp
using Azure.Identity;
var credential = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") == "Development"
? new DefaultAzureCredential() // local dev — uses CLI/VS credentials
: new ManagedIdentityCredential(); // production — deterministic, no fallback chain
// For user-assigned identity: new ManagedIdentityCredential("<client-id>")
```
### TypeScript / JavaScript
```typescript
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
const credential = process.env.NODE_ENV === "development"
? new DefaultAzureCredential() // local dev — uses CLI/VS credentials
: new ManagedIdentityCredential(); // production — deterministic, no fallback chain
// For user-assigned identity: new ManagedIdentityCredential("<client-id>")
```
### Python
```python
import os
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
credential = (
DefaultAzureCredential() # local dev — uses CLI/VS credentials
if os.getenv("AZURE_FUNCTIONS_ENVIRONMENT") == "Development"
else ManagedIdentityCredential() # production — deterministic, no fallback chain
)
# For user-assigned identity: ManagedIdentityCredential(client_id="<client-id>")
```
### Java
```java
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;
var credential = "Development".equals(System.getenv("AZURE_FUNCTIONS_ENVIRONMENT"))
? new DefaultAzureCredentialBuilder().build() // local dev — uses CLI/VS credentials
: new ManagedIdentityCredentialBuilder().build(); // production — deterministic, no fallback chain
// For user-assigned identity: new ManagedIdentityCredentialBuilder().clientId("<client-id>").build()
```
## Local Development Setup
`DefaultAzureCredential` is ideal for local dev because it automatically picks up credentials from developer tools:
1. **Azure CLI** — `az login`
2. **Azure Developer CLI** — `azd auth login`
3. **Azure PowerShell** — `Connect-AzAccount`
4. **Visual Studio / VS Code** — sign in via Azure extension
```typescript
import { DefaultAzureCredential } from "@azure/identity";
// Local development only — uses CLI/PowerShell/VS Code credentials
const credential = new DefaultAzureCredential();
```
## Environment-Aware Pattern
Detect the runtime environment and select the appropriate credential. The key principle: use `DefaultAzureCredential` only when running locally, and a specific credential in production.
> **Tip:** Azure Functions sets `AZURE_FUNCTIONS_ENVIRONMENT` to `"Development"` when running locally. For App Service or containers, use any environment variable you control (e.g. `NODE_ENV`, `ASPNETCORE_ENVIRONMENT`).
```typescript
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
function getCredential() {
if (process.env.NODE_ENV === "development") {
return new DefaultAzureCredential(); // picks up az login / VS Code creds
}
return process.env.AZURE_CLIENT_ID
? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID) // user-assigned
: new ManagedIdentityCredential(); // system-assigned
}
```
## Security Checklist
- [ ] Use managed identity for all Azure-hosted apps
- [ ] Never hardcode credentials, connection strings, or keys
- [ ] Apply least-privilege RBAC roles at the narrowest scope
- [ ] Use `ManagedIdentityCredential` (not `DefaultAzureCredential`) in production
- [ ] Store any required secrets in Azure Key Vault
- [ ] Rotate secrets and certificates on a schedule
- [ ] Enable Microsoft Defender for Cloud on production resources
## Further Reading
- [Passwordless connections overview](https://learn.microsoft.com/azure/developer/intro/passwordless-overview)
- [Managed identities overview](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview)
- [Azure RBAC overview](https://learn.microsoft.com/azure/role-based-access-control/overview)
- [.NET authentication guide](https://learn.microsoft.com/dotnet/azure/sdk/authentication/)
- [Python identity library](https://learn.microsoft.com/python/api/overview/azure/identity-readme)
- [JavaScript identity library](https://learn.microsoft.com/javascript/api/overview/azure/identity-readme)
- [Java identity library](https://learn.microsoft.com/java/api/overview/azure/identity-readme)
references/azqr-recommendations.md
# azqr Recommendation Categories
This document describes how to interpret azqr recommendations and prioritize remediation.
## Recommendation Sources
azqr aggregates recommendations from multiple sources:
| Source | Description | Priority |
|--------|-------------|----------|
| **APRL** | Azure Proactive Resiliency Library - reliability-focused best practices | High |
| **Orphaned Resources** | Resources that are unused or disconnected | Medium |
| **Azure Advisor** | Microsoft's built-in recommendation engine | Medium |
| **Defender for Cloud** | Security-focused recommendations | Critical |
| **Azure Policy** | Governance compliance status | Varies |
## Impact Categories
### Reliability
Recommendations that affect service availability and resiliency:
| Issue | Risk | Example Resources |
|-------|------|-------------------|
| No zone redundancy | Single zone failure causes outage | VMs, Storage, SQL, AKS |
| Single instance | No failover capability | App Service, Redis, VMs |
| No backup configured | Data loss risk | VMs, SQL, Cosmos DB |
| No disaster recovery | Regional failure exposure | Storage, SQL, Key Vault |
### Security
Recommendations that affect security posture:
| Issue | Risk | Example Resources |
|-------|------|-------------------|
| Public endpoint exposed | Attack surface exposure | Storage, SQL, Key Vault |
| Missing encryption | Data exposure risk | Storage, Disks, SQL |
| No private endpoint | Traffic on public internet | PaaS services |
| Weak TLS version | Protocol vulnerabilities | App Service, API Management |
| No managed identity | Credential management risk | App Service, Functions, AKS |
### Operational Excellence
Recommendations for better operations:
| Issue | Risk | Example Resources |
|-------|------|-------------------|
| No diagnostic settings | Blind to failures | All resources |
| Missing alerts | Delayed incident response | All resources |
| No tags | Governance/cost tracking gaps | All resources |
| Outdated SKU/version | Missing features/security fixes | All resources |
### Cost Optimization
Recommendations to reduce spending:
| Issue | Risk | Example Resources |
|-------|------|-------------------|
| Orphaned disk | Paying for unused storage | Managed Disks |
| Orphaned public IP | Paying for unused IP | Public IP |
| Oversized SKU | Excess capacity cost | VMs, SQL, App Service |
| No reserved capacity | Missing discounts | VMs, SQL, Cosmos DB |
## Severity Levels
Prioritize remediation using this severity matrix:
| Severity | Criteria | Response Time |
|----------|----------|---------------|
| **Critical** | Security vulnerability with active exploit risk | Immediate |
| **High** | Reliability risk affecting availability | Within 1 week |
| **Medium** | Best practice violation with moderate risk | Within 1 month |
| **Low** | Optimization opportunity | As capacity allows |
## Excel Report Columns
### Recommendations Sheet
| Column | Description |
|--------|-------------|
| Recommendation ID | Unique identifier for the recommendation |
| Category | Reliability, Security, Cost, etc. |
| Recommendation | Description of the issue |
| Learn More | Link to documentation |
| Impacted Resources | Count of affected resources |
### ImpactedResources Sheet
| Column | Description |
|--------|-------------|
| Subscription | Subscription ID (may be masked) |
| Resource Group | Resource group name |
| Type | Azure resource type |
| Name | Resource name |
| Recommendation ID | Links to Recommendations sheet |
| Recommendation | Issue description |
| Learn More | Documentation link |
| Param1-5 | Additional context (varies by recommendation) |
### Inventory Sheet
| Column | Description |
|--------|-------------|
| Subscription | Subscription ID |
| Resource Group | Resource group name |
| Location | Azure region |
| Type | Resource type |
| Name | Resource name |
| SKU | SKU tier/name |
| SLA | Calculated SLA percentage |
| Availability Zones | Zone configuration |
| Private Endpoint | Private endpoint status |
| Diagnostic Settings | Diagnostic configuration status |
## Common Recommendation IDs
High-impact recommendations to prioritize:
### Storage Accounts
| ID | Issue |
|----|-------|
| `st-001` | Enable soft delete for blobs |
| `st-002` | Enable soft delete for containers |
| `st-003` | Enable versioning |
| `st-004` | Use private endpoints |
| `st-005` | Disable public blob access |
### Virtual Machines
| ID | Issue |
|----|-------|
| `vm-001` | Enable Azure Backup |
| `vm-002` | Use managed disks |
| `vm-003` | Deploy in availability zones |
| `vm-004` | Enable boot diagnostics |
| `vm-005` | Use managed identity |
### Azure Kubernetes Service
| ID | Issue |
|----|-------|
| `aks-001` | Enable Azure Policy |
| `aks-002` | Use managed identity |
| `aks-003` | Enable Defender for Containers |
| `aks-004` | Use availability zones |
| `aks-005` | Enable cluster autoscaler |
### Key Vault
| ID | Issue |
|----|-------|
| `kv-001` | Enable soft delete |
| `kv-002` | Enable purge protection |
| `kv-003` | Use private endpoints |
| `kv-004` | Enable diagnostic logging |
| `kv-005` | Use RBAC for data plane |
### SQL Database
| ID | Issue |
|----|-------|
| `sql-001` | Enable Transparent Data Encryption |
| `sql-002` | Enable auditing |
| `sql-003` | Use private endpoints |
| `sql-004` | Enable zone redundancy |
| `sql-005` | Enable Advanced Threat Protection |
## Additional Resources
- [Azure Proactive Resiliency Library](https://aka.ms/aprl)
- [Azure Orphaned Resources](https://github.com/dolevshor/azure-orphan-resources)
- [Azure Advisor Documentation](https://learn.microsoft.com/azure/advisor/)
- [Defender for Cloud Recommendations](https://learn.microsoft.com/azure/defender-for-cloud/recommendations-reference)
references/azqr-remediation-patterns.md
# Remediation Patterns for Common azqr Findings
This document provides remediation templates for frequently identified compliance issues.
## Storage Account Issues
### Enable Private Endpoints
**Issue:** Storage account accessible via public endpoint
**Azure CLI:**
```bash
# Create private endpoint
az network private-endpoint create \
--name pe-storage \
--resource-group <rg-name> \
--vnet-name <vnet-name> \
--subnet <subnet-name> \
--private-connection-resource-id $(az storage account show -n <storage-name> -g <rg-name> --query id -o tsv) \
--group-id blob \
--connection-name pe-storage-connection
# Disable public access
az storage account update \
--name <storage-name> \
--resource-group <rg-name> \
--public-network-access Disabled
```
**Bicep:**
```bicep
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-05-01' = {
name: 'pe-${storageAccount.name}'
location: location
properties: {
subnet: {
id: subnet.id
}
privateLinkServiceConnections: [
{
name: 'pe-${storageAccount.name}-connection'
properties: {
privateLinkServiceId: storageAccount.id
groupIds: ['blob']
}
}
]
}
}
```
### Enable Soft Delete
**Issue:** No soft delete protection for blobs
**Azure CLI:**
```bash
az storage account blob-service-properties update \
--account-name <storage-name> \
--resource-group <rg-name> \
--enable-delete-retention true \
--delete-retention-days 7 \
--enable-container-delete-retention true \
--container-delete-retention-days 7
```
**Bicep:**
```bicep
resource blobServices 'Microsoft.Storage/storageAccounts/blobServices@2023-01-01' = {
parent: storageAccount
name: 'default'
properties: {
deleteRetentionPolicy: {
enabled: true
days: 7
}
containerDeleteRetentionPolicy: {
enabled: true
days: 7
}
}
}
```
---
## Key Vault Issues
### Enable Purge Protection
**Issue:** Key Vault can be permanently deleted
**Azure CLI:**
```bash
az keyvault update \
--name <vault-name> \
--resource-group <rg-name> \
--enable-purge-protection true
```
**Bicep:**
```bicep
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
name: keyVaultName
location: location
properties: {
enableSoftDelete: true
softDeleteRetentionInDays: 90
enablePurgeProtection: true
// ... other properties
}
}
```
### Use RBAC for Data Plane
**Issue:** Using access policies instead of RBAC
**Azure CLI:**
```bash
az keyvault update \
--name <vault-name> \
--resource-group <rg-name> \
--enable-rbac-authorization true
```
---
## Virtual Machine Issues
### Enable Diagnostic Settings
**Issue:** No diagnostics configured for VM
**Azure CLI:**
```bash
# Create Log Analytics workspace (if needed)
az monitor log-analytics workspace create \
--resource-group <rg-name> \
--workspace-name <workspace-name>
# Enable diagnostics
az monitor diagnostic-settings create \
--name diag-vm \
--resource $(az vm show -g <rg-name> -n <vm-name> --query id -o tsv) \
--workspace $(az monitor log-analytics workspace show -g <rg-name> -n <workspace-name> --query id -o tsv) \
--metrics '[{"category": "AllMetrics", "enabled": true}]'
```
**Bicep:**
```bicep
resource diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
name: 'diag-${vm.name}'
scope: vm
properties: {
workspaceId: logAnalyticsWorkspace.id
metrics: [
{
category: 'AllMetrics'
enabled: true
}
]
}
}
```
### Enable Azure Backup
**Issue:** VM not protected by Azure Backup
**Azure CLI:**
```bash
# Create Recovery Services vault (if needed)
az backup vault create \
--resource-group <rg-name> \
--name <vault-name> \
--location <location>
# Enable backup with default policy
az backup protection enable-for-vm \
--resource-group <rg-name> \
--vault-name <vault-name> \
--vm $(az vm show -g <rg-name> -n <vm-name> --query id -o tsv) \
--policy-name DefaultPolicy
```
---
## AKS Issues
### Enable Defender for Containers
**Issue:** No security monitoring for AKS
**Azure CLI:**
```bash
az aks update \
--resource-group <rg-name> \
--name <cluster-name> \
--enable-defender
```
**Bicep:**
```bicep
resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-01-01' = {
name: clusterName
location: location
properties: {
securityProfile: {
defender: {
securityMonitoring: {
enabled: true
}
logAnalyticsWorkspaceResourceId: logAnalyticsWorkspace.id
}
}
// ... other properties
}
}
```
### Use Managed Identity
**Issue:** AKS using service principal instead of managed identity
**Azure CLI:**
```bash
az aks update \
--resource-group <rg-name> \
--name <cluster-name> \
--enable-managed-identity
```
---
## SQL Database Issues
### Enable Auditing
**Issue:** SQL Server auditing not enabled
**Azure CLI:**
```bash
# Enable to Log Analytics
az sql server audit-policy update \
--resource-group <rg-name> \
--name <server-name> \
--state Enabled \
--lats Enabled \
--lawri $(az monitor log-analytics workspace show -g <rg-name> -n <workspace-name> --query id -o tsv)
```
**Bicep:**
```bicep
resource sqlAudit 'Microsoft.Sql/servers/auditingSettings@2023-05-01-preview' = {
parent: sqlServer
name: 'default'
properties: {
state: 'Enabled'
isAzureMonitorTargetEnabled: true
retentionDays: 90
}
}
```
### Enable Private Endpoint
**Issue:** SQL Server accessible via public endpoint
**Azure CLI:**
```bash
# Create private endpoint
az network private-endpoint create \
--name pe-sql \
--resource-group <rg-name> \
--vnet-name <vnet-name> \
--subnet <subnet-name> \
--private-connection-resource-id $(az sql server show -g <rg-name> -n <server-name> --query id -o tsv) \
--group-id sqlServer \
--connection-name pe-sql-connection
# Disable public access
az sql server update \
--resource-group <rg-name> \
--name <server-name> \
--enable-public-network false
```
---
## App Service Issues
### Use Managed Identity
**Issue:** App Service not using managed identity
**Azure CLI:**
```bash
az webapp identity assign \
--resource-group <rg-name> \
--name <app-name>
```
**Bicep:**
```bicep
resource webApp 'Microsoft.Web/sites@2023-01-01' = {
name: appName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
// ... other properties
}
}
```
### Enforce HTTPS Only
**Issue:** HTTP traffic allowed
**Azure CLI:**
```bash
az webapp update \
--resource-group <rg-name> \
--name <app-name> \
--https-only true
```
### Set Minimum TLS Version
**Issue:** TLS version below 1.2
**Azure CLI:**
```bash
az webapp config set \
--resource-group <rg-name> \
--name <app-name> \
--min-tls-version 1.2
```
---
## Bulk Remediation Script
For multiple resources of the same type, use a loop:
```powershell
# Example: Enable soft delete on all storage accounts
$storageAccounts = az storage account list --query "[].{name:name, rg:resourceGroup}" -o json | ConvertFrom-Json
foreach ($sa in $storageAccounts) {
Write-Host "Enabling soft delete on $($sa.name)..."
az storage account blob-service-properties update `
--account-name $sa.name `
--resource-group $sa.rg `
--enable-delete-retention true `
--delete-retention-days 7
}
```
---
## Remediation Validation
After applying fixes, re-run the azqr scan using the Azure MCP tool to verify the issues have been resolved:
```
mcp_azure_mcp_extension_azqr
subscription: <subscription-id>
```
## Additional Resources
- [Azure CLI Reference](https://learn.microsoft.com/cli/azure/)
- [Bicep Documentation](https://learn.microsoft.com/azure/azure-resource-manager/bicep/)
- [Azure Policy Built-in Definitions](https://learn.microsoft.com/azure/governance/policy/samples/built-in-policies)
references/azure-keyvault-expiration-audit.md
# Key Vault Expiration Audit & Compliance
Automated auditing of Azure Key Vault resources to identify expired or expiring keys, secrets, and certificates before they cause service disruptions.
## Overview
This skill monitors Azure Key Vault resources (keys, secrets, certificates) for expiration issues. It helps prevent service disruptions by identifying:
- **Expired resources** causing active problems
- **Expiring soon** (within customizable days threshold)
- **Missing expiration dates** (security risk)
- **Disabled resources** needing cleanup
## Core Workflow
1. **List Resources**: Enumerate keys, secrets, and certificates in target vault(s)
2. **Get Details**: Retrieve expiration metadata for each resource
3. **Analyze Status**: Compare expiration dates against current date and threshold
4. **Generate Report**: Organize findings by priority with actionable recommendations
## Audit Patterns
### Pattern 1: Single Vault Quick Scan
Check one Key Vault for all expiration issues with configurable day threshold (default: 30 days).
**Tools**: `keyvault_key_list`, `keyvault_key_get`, `keyvault_secret_list`, `keyvault_secret_get`, `keyvault_certificate_list`, `keyvault_certificate_get`
### Pattern 2: Multi-Vault Compliance Report
Scan multiple vaults across subscription for comprehensive security review.
**Use for**: Quarterly audits, organization-wide compliance checks
### Pattern 3: Resource Type Focus
Audit only keys, secrets, OR certificates when specific resource type is mentioned.
**Use for**: Certificate renewal planning, secret rotation tracking
### Pattern 4: Emergency Expired Finder
Quick scan for already-expired resources (negative days) to troubleshoot active incidents.
**Use for**: Production issues, authentication failures
## Key Data Fields
When retrieving resource details, analyze these fields:
- **expiresOn**: Expiration timestamp (null = no expiration set - security risk!)
- **enabled**: Resource is active (false = disabled/inactive)
- **notBefore**: When resource becomes valid
- **createdOn/updatedOn**: For tracking resource age and last rotation
- **subject/issuer**: Certificate-specific metadata
## Report Format
Organize findings into:
- **Summary Statistics**: Total count, expired count, expiring count, no-expiration count per resource type
- **Critical Issues**: Expired resources requiring immediate action
- **Warnings**: Expiring within threshold (e.g., 30 days)
- **Risks**: Resources without expiration dates
- **Recommendations**: Set expiration policies, rotate credentials, remove disabled items
## Remediation Priority
**🔴 Critical** - Expired (< 0 days): Rotate immediately
**🟠 High** - Expiring 0-7 days: Schedule rotation within 24 hours
**🟡 Medium** - Expiring 8-30 days: Plan rotation within 1 week
**🟡 Medium** - No expiration set: Apply expiration policy
**🟢 Low** - Active (> 30 days): Monitor on regular schedule
## Best Practices
- Run weekly audits to catch issues early
- All resources should have expiration dates (Azure Policy recommendation)
- Configure Azure Event Grid for 30-day advance notifications
- Rotation schedule: Secrets every 60-90 days, Keys annually, Certificates per CA requirements (max 1 year)
- Prioritize production Key Vaults over dev/test
- Automate rotation with Azure Functions or Logic Apps
## MCP Tools Used
| Tool | Purpose |
|------|---------|
| `keyvault_key_list` | List all keys in a vault |
| `keyvault_key_get` | Get key details including expiration |
| `keyvault_secret_list` | List all secrets in a vault |
| `keyvault_secret_get` | Get secret details including expiration |
| `keyvault_certificate_list` | List all certificates in a vault |
| `keyvault_certificate_get` | Get certificate details including expiration |
**Required**: `vault` (Key Vault name)
**Optional**: `subscription`, `tenant`
## Fallback Strategy: Azure CLI Commands
If Azure MCP Key Vault tools fail, timeout, or are unavailable, use Azure CLI commands as fallback.
### CLI Command Reference
| Operation | Azure CLI Command |
|-----------|-------------------|
| List secrets | `az keyvault secret list --vault-name <vault-name>` |
| Get secret details | `az keyvault secret show --vault-name <vault-name> --name <secret-name>` |
| List keys | `az keyvault key list --vault-name <vault-name>` |
| Get key details | `az keyvault key show --vault-name <vault-name> --name <key-name>` |
| List certificates | `az keyvault certificate list --vault-name <vault-name>` |
| Get certificate details | `az keyvault certificate show --vault-name <vault-name> --name <cert-name>` |
### When to Fallback
Switch to Azure CLI when:
- MCP tool returns timeout error
- MCP tool returns "service unavailable" or connection errors
- MCP tool takes longer than 30 seconds to respond
- Empty response when vault is known to have resources
## Common Issues
- **Access Denied**: Verify RBAC permissions (Key Vault Reader + data plane access)
- **Vault Not Found**: Check vault name and subscription context
- **Null expiresOn**: Resource has no expiration (security risk - requires policy)
- **Time zones**: All timestamps are UTC
references/azure-quick-review.md
# Azure Quick Review Compliance Assessment
This skill enables comprehensive Azure compliance assessments using Azure Quick Review (azqr), analyzing findings against Azure best practices, and providing actionable remediation guidance.
## Prerequisites
- **Azure authentication** - Logged in via Azure CLI (`az login`) or using Service Principal/Managed Identity
- **Reader permissions** - Minimum Reader role on target subscription or management group
## Assessment Workflow
### Step 1: Determine Scan Scope
Ask the user or detect from context:
| Scope | Use Case | Required Info |
|-------|----------|---------------|
| Subscription | Full subscription assessment | Subscription ID |
| Resource Group | Targeted assessment | Subscription ID + Resource Group name |
| Management Group | Enterprise-wide assessment | Management Group ID |
| Specific Service | Deep-dive on one resource type | Subscription ID + Service abbreviation |
### Step 2: Run Compliance Scan
Use the Azure MCP tool to run the scan:
```
mcp_azure_mcp_extension_azqr
subscription: <subscription-id>
resource-group: <optional-rg-name>
```
### Step 3: Analyze Scan Results
The scan produces an Excel file with these sheets:
| Sheet | Contents | Priority |
|-------|----------|----------|
| **Recommendations** | All recommendations with impacted resource count | High |
| **ImpactedResources** | Resources with specific issues to address | High |
| **Inventory** | All scanned resources with SKU, Tier, SLA details | Medium |
| **Advisor** | Azure Advisor recommendations | Medium |
| **DefenderRecommendations** | Microsoft Defender for Cloud findings | High |
| **Azure Policy** | Non-compliant resources per Azure Policy | Medium |
| **Costs** | 3-month cost history by subscription | Low |
| **Defender** | Defender plan status and tiers | Medium |
| **OutOfScope** | Resources not scanned | Low |
**Focus analysis on:**
1. High-severity recommendations from ImpactedResources
2. Defender recommendations (security-critical)
3. Advisor recommendations (reliability/performance)
4. Policy non-compliance (governance)
### Step 4: Categorize Findings
Group findings by category for prioritized remediation:
| Category | Examples | Severity |
|----------|----------|----------|
| **Security** | Public endpoints, missing encryption, no private endpoints | Critical |
| **Reliability** | No zone redundancy, single instance, no backup | High |
| **Performance** | Undersized SKUs, missing caching, no CDN | Medium |
| **Cost** | Orphaned resources, oversized SKUs, unused reservations | Medium |
| **Operations** | Missing diagnostics, no alerts, no tags | Low |
### Step 5: Generate Remediation Guidance
For each high-priority finding:
1. Explain the risk in plain language
2. Provide remediation options (Portal, CLI, Bicep)
3. Estimate effort and impact
See [azqr-remediation-patterns.md](azqr-remediation-patterns.md) for common fix templates.
### Step 6: Present Summary
Provide a structured summary:
```markdown
## Compliance Assessment Summary
**Scope:** [Subscription/RG/MG name]
**Scanned:** [Date/Time]
**Resources Analyzed:** [Count]
### Key Findings
| Severity | Count | Top Issues |
|----------|-------|------------|
| Critical | X | [List top 3] |
| High | X | [List top 3] |
| Medium | X | [List top 3] |
### Recommended Actions
1. **[Issue]** - [Brief remediation]
2. **[Issue]** - [Brief remediation]
3. **[Issue]** - [Brief remediation]
### Next Steps
- [ ] Address critical security findings
- [ ] Review and remediate high-severity items
- [ ] Schedule follow-up scan to verify fixes
```
## Supported Azure Services
azqr supports 70+ Azure resource types including:
- Azure Kubernetes Service (AKS)
- API Management
- App Configuration
- App Service
- Container Apps
- Cosmos DB
- Container Registry
- Key Vault
- Load Balancer
- Azure Database for MySQL
- Azure Database for PostgreSQL
- Azure Cache for Redis
- Service Bus
- Azure SQL Database
- Storage Accounts
- Virtual Machines
- Virtual Networks
## Tools Used
| Tool | Purpose |
|------|---------|
| `mcp_azure_mcp_extension_azqr` | Run azqr scans via Azure MCP |
| `mcp_azure_mcp_subscription_list` | List available subscriptions |
| `mcp_azure_mcp_group_list` | List resource groups in subscription |
## Troubleshooting
| Issue | Symptom | Solution |
|-------|---------|----------|
| Permission denied | 403 errors during scan | Verify Reader role on scope |
| Not authenticated | `AADSTS` errors | Run `az login` first |
| Slow scan | Scan takes very long | Use resource group scope |
## Example Prompts
- "Check my Azure subscription for compliance issues"
- "Run azqr on my production resource group"
- "What Azure resources don't follow best practices?"
- "Assess my storage accounts for security issues"
## Reference Documentation
- [Recommendation Categories](azqr-recommendations.md)
- [Remediation Patterns](azqr-remediation-patterns.md)
- [Azure Quick Review Documentation](https://azure.github.io/azqr/docs/)
- [Azure Proactive Resiliency Library](https://aka.ms/aprl)
references/azure-resource-graph.md
# Azure Resource Graph Queries for Compliance Auditing
Azure Resource Graph (ARG) enables fast, cross-subscription resource querying using KQL via `az graph query`. Use it for compliance scanning, tag audits, and configuration validation.
## How to Query
Use the `extension_cli_generate` MCP tool to generate `az graph query` commands:
```yaml
mcp_azure_mcp_extension_cli_generate
intent: "query Azure Resource Graph to <describe what you want to audit>"
cli-type: "az"
```
Or construct directly:
```bash
az graph query -q "<KQL>" --query "data[].{name:name, type:type}" -o table
```
> ⚠️ **Prerequisite:** `az extension add --name resource-graph`
## Key Tables
| Table | Contains |
|-------|----------|
| `Resources` | All ARM resources (name, type, location, properties, tags) |
| `ResourceContainers` | Subscriptions, resource groups, management groups |
| `AuthorizationResources` | Role assignments and role definitions |
| `AdvisorResources` | Azure Advisor recommendations |
## Compliance Query Patterns
**Find resources missing a required tag:**
```kql
Resources
| where isnull(tags['Environment']) or isnull(tags['CostCenter'])
| project name, type, resourceGroup, tags
```
**Tag coverage analysis:**
```kql
Resources
| extend hasEnvTag = isnotnull(tags['Environment'])
| summarize total=count(), tagged=countif(hasEnvTag) by type
| extend coverage=round(100.0 * tagged / total, 1)
| order by coverage asc
```
**Find storage accounts without HTTPS enforcement:**
```kql
Resources
| where type =~ 'microsoft.storage/storageaccounts'
| where properties.supportsHttpsTrafficOnly == false
| project name, resourceGroup, location
```
**Find resources with public network access enabled:**
```kql
Resources
| where properties.publicNetworkAccess =~ 'Enabled'
| project name, type, resourceGroup, location
```
**Query role assignments across subscriptions:**
```kql
AuthorizationResources
| where type == 'microsoft.authorization/roleassignments'
| extend principalType = tostring(properties.principalType)
| summarize count() by principalType
```
**Find resource groups without locks:**
```kql
ResourceContainers
| where type == 'microsoft.resources/subscriptions/resourcegroups'
| project rgName=name, rgId=id
| join kind=leftanti (
Resources
| where type == 'microsoft.authorization/locks'
| project rgId=tostring(properties.resourceId)
) on rgId
```
## Tips
- Use `=~` for case-insensitive type matching (resource types are lowercase)
- Navigate properties with `properties.fieldName`
- Use `--first N` to limit result count
- Use `--subscriptions` to scope to specific subscriptions
- Combine with `AdvisorResources` for security recommendations
references/sdk/azure-keyvault-certificates-rust.md
# Key Vault Certificates — Rust SDK Quick Reference
> Condensed from **azure-keyvault-certificates-rust**. Full patterns
> (certificate policies, import, lifecycle management)
> in the **azure-keyvault-certificates-rust** plugin skill if installed.
## Install
cargo add azure_security_keyvault_certificates azure_identity
## Quick Start
```rust
use azure_identity::DeveloperToolsCredential;
use azure_security_keyvault_certificates::CertificateClient;
let credential = DeveloperToolsCredential::new(None)?;
let client = CertificateClient::new("https://<vault>.vault.azure.net/", credential.clone(), None)?;
```
## Best Practices
- Use Entra ID auth — `DeveloperToolsCredential` for dev
- Use managed certificates — auto-renewal with supported issuers
- Set proper validity period — balance security and maintenance
- Use certificate policies — define renewal and key properties
- Monitor expiration — set up alerts for expiring certificates
- Enable soft delete — required for production vaults
references/sdk/azure-keyvault-keys-rust.md
# Key Vault Keys — Rust SDK Quick Reference
> Condensed from **azure-keyvault-keys-rust**. Full patterns (EC keys,
> backup/restore, crypto operations, RBAC permissions)
> in the **azure-keyvault-keys-rust** plugin skill if installed.
## Install
cargo add azure_security_keyvault_keys azure_identity
## Quick Start
```rust
use azure_identity::DeveloperToolsCredential;
use azure_security_keyvault_keys::KeyClient;
let credential = DeveloperToolsCredential::new(None)?;
let client = KeyClient::new("https://<vault>.vault.azure.net/", credential.clone(), None)?;
```
## Best Practices
- Use Entra ID auth — `DeveloperToolsCredential` for dev, `ManagedIdentityCredential` for production
- Use HSM keys for sensitive workloads — hardware-protected keys
- Use EC for signing — more efficient than RSA
- Use RSA for encryption — when encrypting data
- Backup keys for disaster recovery
- Enable soft delete — required for production vaults
- Use key rotation — create new versions periodically
## Non-Obvious Patterns
```rust
use azure_security_keyvault_keys::models::{CreateKeyParameters, KeyType};
let params = CreateKeyParameters { kty: KeyType::Rsa, key_size: Some(2048), ..Default::default() };
client.create_key("name", params.try_into()?, None).await?.into_model()?;
```
references/sdk/azure-keyvault-keys-ts.md
# Key Vault Keys — TypeScript SDK Quick Reference
> Condensed from **azure-keyvault-keys-ts**. Full patterns (crypto operations,
> key rotation policies, backup/restore, CryptographyClient)
> in the **azure-keyvault-keys-ts** plugin skill if installed.
## Install
npm install @azure/keyvault-keys @azure/identity
## Quick Start
```typescript
import { KeyClient } from "@azure/keyvault-keys";
import { DefaultAzureCredential } from "@azure/identity";
const keyClient = new KeyClient(`https://${vaultName}.vault.azure.net`, new DefaultAzureCredential());
```
## Best Practices
- Use DefaultAzureCredential for **local development only**. In production, use ManagedIdentityCredential — see [auth-best-practices.md](../auth-best-practices.md)
- Enable soft-delete — required for production vaults
- Set expiration dates on keys
- Use key rotation policies — automate key rotation
- Limit key operations — only grant needed operations (encrypt, sign, etc.)
- Browser not supported — this SDK is Node.js only
references/sdk/azure-keyvault-py.md
# Key Vault — Python SDK Quick Reference
> Condensed from **azure-keyvault-py**. Full patterns (async clients,
> cryptographic operations, certificate management, error handling)
> in the **azure-keyvault-py** plugin skill if installed.
## Install
pip install azure-keyvault-secrets azure-keyvault-keys azure-keyvault-certificates azure-identity
## Quick Start
```python
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
client = SecretClient(vault_url="https://<vault>.vault.azure.net/", credential=DefaultAzureCredential())
```
## Best Practices
- Use DefaultAzureCredential for **local development only**. In production, use ManagedIdentityCredential — see [auth-best-practices.md](../auth-best-practices.md)
- Use managed identity in Azure-hosted applications
- Enable soft-delete for recovery (enabled by default)
- Use RBAC over access policies for fine-grained control
- Rotate secrets regularly using versioning
- Use Key Vault references in App Service/Functions config
- Cache secrets appropriately to reduce API calls
- Use async clients for high-throughput scenarios
references/sdk/azure-keyvault-secrets-rust.md
# Key Vault Secrets — Rust SDK Quick Reference
> Condensed from **azure-keyvault-secrets-rust**. Full patterns (versioning,
> update properties, tags, soft delete recovery)
> in the **azure-keyvault-secrets-rust** plugin skill if installed.
## Install
cargo add azure_security_keyvault_secrets azure_identity
## Quick Start
```rust
use azure_identity::DeveloperToolsCredential;
use azure_security_keyvault_secrets::SecretClient;
let credential = DeveloperToolsCredential::new(None)?;
let client = SecretClient::new("https://<vault>.vault.azure.net/", credential.clone(), None)?;
```
## Best Practices
- Use Entra ID auth — `DeveloperToolsCredential` for dev, `ManagedIdentityCredential` for production
- Use `into_model()?` to deserialize responses
- Use `ResourceExt` trait for extracting names from IDs
- Handle soft delete — deleted secrets can be recovered within retention period
- Set content type — helps identify secret format
- Use tags for organizing and filtering secrets
- Version secrets — new values create new versions automatically
## Non-Obvious Patterns
```rust
use azure_security_keyvault_secrets::models::SetSecretParameters;
let params = SetSecretParameters { value: Some("secret-value".into()), ..Default::default() };
client.set_secret("name", params.try_into()?, None).await?.into_model()?;
```
references/sdk/azure-keyvault-secrets-ts.md
# Key Vault Secrets — TypeScript SDK Quick Reference
> Condensed from **azure-keyvault-secrets-ts**. Full patterns (key rotation,
> cryptographic operations, backup/restore, wrap/unwrap)
> in the **azure-keyvault-secrets-ts** plugin skill if installed.
## Install
npm install @azure/keyvault-secrets @azure/identity
## Quick Start
```typescript
import { DefaultAzureCredential } from "@azure/identity";
import { SecretClient } from "@azure/keyvault-secrets";
const client = new SecretClient("https://<vault>.vault.azure.net", new DefaultAzureCredential());
```
## Best Practices
- Use DefaultAzureCredential for **local development only**. In production, use ManagedIdentityCredential — see [auth-best-practices.md](../auth-best-practices.md)
- Enable soft-delete — required for production vaults
- Set expiration dates on both keys and secrets
- Use key rotation policies — automate key rotation
- Limit key operations — only grant needed operations (encrypt, sign, etc.)
- Browser not supported — these SDKs are Node.js only
references/sdk/azure-security-keyvault-keys-dotnet.md
# Key Vault Keys — .NET SDK Quick Reference
> Condensed from **azure-security-keyvault-keys-dotnet**. Full patterns
> (crypto operations, key rotation, backup/restore, HSM, KeyResolver)
> in the **azure-security-keyvault-keys-dotnet** plugin skill if installed.
## Install
dotnet add package Azure.Security.KeyVault.Keys
dotnet add package Azure.Identity
## Quick Start
```csharp
using Azure.Security.KeyVault.Keys;
using Azure.Identity;
var client = new KeyClient(new Uri("https://<vault>.vault.azure.net"), new DefaultAzureCredential());
```
## Best Practices
- Use DefaultAzureCredential for **local development only**. In production, use ManagedIdentityCredential — see [auth-best-practices.md](../auth-best-practices.md)
- Enable soft-delete — protect against accidental deletion
- Use HSM-backed keys — set `HardwareProtected = true` for sensitive keys
- Implement key rotation — use automatic rotation policies
- Limit key operations — only enable required KeyOperations
- Set expiration dates — always set ExpiresOn for keys
- Use specific versions — pin to versions in production
- Cache CryptographyClient — reuse for multiple operations
references/sdk/azure-security-keyvault-keys-java.md
# Key Vault Keys — Java SDK Quick Reference
> Condensed from **azure-security-keyvault-keys-java**. Full patterns
> (crypto operations, HSM keys, key rotation, backup/restore, import)
> in the **azure-security-keyvault-keys-java** plugin skill if installed.
## Install
```xml
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-keys</artifactId>
<version>4.9.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
```
## Quick Start
> **Auth:** `DefaultAzureCredential` is for local development. See [auth-best-practices.md](../auth-best-practices.md) for production patterns.
```java
import com.azure.security.keyvault.keys.KeyClientBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;
var keyClient = new KeyClientBuilder()
.vaultUrl("https://<vault>.vault.azure.net")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
```
## Best Practices
- Use HSM keys for production — set `setHardwareProtected(true)` for sensitive keys
- Enable soft delete — protects against accidental deletion
- Key rotation — set up automatic rotation policies
- Least privilege — use separate keys for different operations
- Local crypto when possible — use CryptographyClient with local key material to reduce round-trips
references/sdk/azure-security-keyvault-secrets-java.md
# Key Vault Secrets — Java SDK Quick Reference
> Condensed from **azure-security-keyvault-secrets-java**. Full patterns
> (async client, secret rotation, backup/restore, config loader)
> in the **azure-security-keyvault-secrets-java** plugin skill if installed.
## Install
```xml
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-secrets</artifactId>
<version>4.9.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
```
## Quick Start
> **Auth:** `DefaultAzureCredential` is for local development. See [auth-best-practices.md](../auth-best-practices.md) for production patterns.
```java
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;
var secretClient = new SecretClientBuilder()
.vaultUrl("https://<vault>.vault.azure.net")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
```
## Best Practices
- Enable soft delete — protects against accidental deletion
- Use tags — tag secrets with environment, service, owner
- Set expiration — use `setExpiresOn()` for credentials that should rotate
- Content type — set contentType to indicate format (e.g., application/json)
- Version management — don't delete old versions immediately during rotation
- Access logging — enable diagnostic logging on Key Vault
- Least privilege — use separate vaults for different environments