This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Plugins

Documentation for creating and using YAML plugins in azqr

Overview

YAML plugins provide a simple, declarative way to extend azqr with custom Azure Resource Graph (ARG) queries without writing Go code. This is ideal for:

  • Quick custom checks and validations
  • Organization-specific compliance rules
  • Temporary or experimental recommendations
  • Non-developers who want to extend azqr

Plugin Structure

A YAML plugin consists of a single .yaml file containing plugin metadata and one or more Azure Resource Graph queries.

Basic Structure

name: plugin-name
version: 1.0.0
description: Brief description of what this plugin does
author: Plugin Author Name (optional)
license: MIT (optional)

queries:
  - aprlGuid: unique-id-001
    description: Short description of the recommendation
    longDescription: |
      Detailed description of the issue and why it matters.
      Can be multiple lines.
    recommendationControl: Category Name
    recommendationImpact: Impact Level
    recommendationResourceType: Microsoft.Service/resourceType
    learnMoreLink:
      - name: Documentation Title
        url: https://learn.microsoft.com/...
    query: |
      resources
      | where type =~ 'microsoft.service/resourcetype'
      | where some_condition == true
      | project id, name, resourceGroup, location

Required Fields

Plugin Level

  • name: Unique plugin identifier (string)
  • version: Semantic version (e.g., “1.0.0”)
  • description: What the plugin does

Query Level

  • aprlGuid: Unique identifier for the recommendation
  • description: Short recommendation title
  • recommendationControl: Category (see Categories section)
  • recommendationImpact: Impact level (High, Medium, Low)
  • recommendationResourceType: Azure resource type (e.g., “Microsoft.Storage/storageAccounts”)
  • query OR queryFile: The KQL query to execute

Optional Fields

Plugin Level

  • author: Plugin author name
  • license: License type (e.g., MIT, Apache-2.0)

Query Level

  • longDescription: Detailed explanation
  • learnMoreLink: Array of documentation links
  • recommendationTypeId: Azure Policy or APRL recommendation ID
  • recommendationMetadataState: State (Active, Deprecated)
  • potentialBenefits: Benefits of implementing the recommendation
  • pgVerified: Whether verified by product group (boolean)
  • automationAvailable: Whether automation is available (boolean)
  • tags: Array of tags for categorization

Categories

Valid values for recommendationControl:

  • High Availability: Availability and redundancy
  • Security: Security and access control
  • Disaster Recovery: Backup and recovery
  • Scalability: Scaling and performance
  • Governance: Compliance and governance
  • Monitoring and Alerting: Observability
  • Business Continuity: Business continuity planning
  • Service Upgrade and Retirement: Service lifecycle
  • Other Best Practices: General best practices (default)

Impact Levels

Valid values for recommendationImpact:

  • High: Critical issues that should be addressed immediately
  • Medium: Important issues that should be addressed soon (default)
  • Low: Nice-to-have improvements

Query Format

Inline Query

Include the KQL query directly in the YAML file:

queries:
  - aprlGuid: example-001
    description: Example recommendation
    recommendationControl: Security
    recommendationImpact: High
    recommendationResourceType: Microsoft.Storage/storageAccounts
    query: |
      resources
      | where type =~ 'microsoft.storage/storageaccounts'
      | where properties.supportsHttpsTrafficOnly == false
      | project id, name, resourceGroup, location

External Query File

Reference an external .kql file:

queries:
  - aprlGuid: example-002
    description: Example with external query
    recommendationControl: Governance
    recommendationImpact: Medium
    recommendationResourceType: Microsoft.Network/publicIPAddresses
    queryFile: ./kql/unused-public-ips.kql

The path is relative to the YAML file location. Create a kql/ subdirectory next to your plugin YAML file.

Query Requirements

Your Azure Resource Graph queries must:

  1. Return resources: Query the resources table

  2. Project required fields: Include at minimum:

    • id: Resource ID
    • name: Resource name
    • resourceGroup: Resource group name
    • location: Azure region
  3. Filter appropriately: Use where clauses to identify non-compliant resources

  4. Use case-insensitive comparisons: Use =~ instead of == for type comparisons

Query Example

resources
| where type =~ 'microsoft.network/networkinterfaces'
| where properties.virtualMachine == "" or isnull(properties.virtualMachine)
| where properties.privateEndpoint == "" or isnull(properties.privateEndpoint)
| project id, name, resourceGroup, location,
          tags,
          sku = properties.ipConfigurations[0].properties.privateIPAllocationMethod

Plugin Discovery

YAML plugins are discovered from the following locations:

  1. Current directory: ./plugins/*.yaml
  2. User plugins directory: ~/.azqr/plugins/*.yaml
  3. System plugins directory: /etc/azqr/plugins/*.yaml (Linux/macOS)

azqr searches recursively in these directories for any .yaml or .yml files.

Complete Example

Here’s a complete example plugin (custom-checks.yaml):

name: example-custom-checks
version: 1.0.0
description: Example YAML plugin with custom Azure Resource Graph queries
author: Azure Quick Review Team
license: MIT

queries:
  # Check for unused network interfaces
  - description: Network interfaces not attached to any VM
    aprlGuid: yaml-001-unused-nics
    recommendationTypeId: null
    recommendationControl: Governance
    recommendationImpact: Low
    recommendationResourceType: Microsoft.Network/networkInterfaces
    recommendationMetadataState: Active
    longDescription: |
      Network interfaces that are not attached to any virtual machine.
      These resources incur costs and should be reviewed for cleanup.
    potentialBenefits: Cost optimization and resource cleanup
    pgVerified: false
    automationAvailable: false
    tags:
      - cost-optimization
      - cleanup
    learnMoreLink:
      - name: Network Interface Overview
        url: "https://learn.microsoft.com/azure/virtual-network/virtual-network-network-interface"
    query: |
      resources
      | where type =~ 'Microsoft.Network/networkInterfaces'
      | where properties.virtualMachine == "" or isnull(properties.virtualMachine)
      | where properties.privateEndpoint == "" or isnull(properties.privateEndpoint)
      | project id, name, resourceGroup, location, tags

  # Check for unused public IPs (from external file)
  - description: Public IP addresses not associated with any resource
    aprlGuid: yaml-002-unused-public-ips
    recommendationControl: Governance
    recommendationImpact: Medium
    recommendationResourceType: Microsoft.Network/publicIPAddresses
    longDescription: |
      Public IP addresses that are not associated with any Azure resource.
      These IPs cost money even when not in use.
    learnMoreLink:
      - name: Public IP Addresses
        url: "https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses"
    queryFile: kql/unused-public-ips.kql

  # Security check
  - description: Storage accounts without secure transfer enabled
    aprlGuid: yaml-003-storage-secure-transfer
    recommendationControl: Security
    recommendationImpact: High
    recommendationResourceType: Microsoft.Storage/storageAccounts
    longDescription: |
      Storage accounts that do not have secure transfer (HTTPS) required.
      This is a security risk as data can be transmitted over insecure connections.
    potentialBenefits: Improved security and data protection
    learnMoreLink:
      - name: Require secure transfer
        url: "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer"
    query: |
      resources
      | where type =~ 'Microsoft.Storage/storageAccounts'
      | where properties.supportsHttpsTrafficOnly == false
      | project id, name, resourceGroup, location,
                sku = sku.name,
                tier = sku.tier

Usage

Once you’ve created your YAML plugin:

  1. Place the file in one of the plugin directories

  2. Run azqr scan as normal:

    azqr scan
    
  3. View plugin info:

    azqr plugins list
    azqr plugins info <plugin-name>
    

The recommendations from your YAML plugin will be included in all outputs (Excel, CSV, JSON) alongside built-in recommendations.

Best Practices

1. Use Descriptive Names

name: org-security-checks
description: Organization-specific security compliance checks

Put related recommendations in the same plugin file:

name: network-optimization
queries:
  - aprlGuid: net-001-unused-nics
    description: Unused network interfaces
    ...
  - aprlGuid: net-002-unused-ips
    description: Unused public IPs
    ...

3. Version Your Plugins

Follow semantic versioning:

  • 1.0.0: Initial release
  • 1.1.0: Add new queries
  • 2.0.0: Breaking changes

Always include documentation links:

learnMoreLink:
  - name: Official Documentation
    url: https://learn.microsoft.com/...
  - name: Best Practices Guide
    url: https://learn.microsoft.com/...

5. Test Your Queries

Test queries in Azure Resource Graph Explorer first:

6. Use External Files for Complex Queries

For queries over ~10 lines, use external .kql files:

my-plugin/
├── custom-checks.yaml
└── kql/
    ├── query1.kql
    ├── query2.kql
    └── query3.kql

7. Document Your Plugin

Include comprehensive descriptions:

longDescription: |
  This check identifies resources that...
  
  Why it matters:
  - Cost implications
  - Security risks
  - Performance impact
  
  How to fix:
  1. Step one
  2. Step two

Troubleshooting

Plugin Not Discovered

  1. Check the file extension (.yaml or .yml)
  2. Verify the file is in a plugin directory
  3. Run with debug logging:
    azqr scan --debug
    

Query Errors

  1. Syntax errors: Test the query in Azure Resource Graph Explorer
  2. No results: Verify the resource type filter
  3. Permission errors: Ensure you have Reader access to subscriptions

Invalid YAML

Use a YAML validator to check syntax:

yamllint custom-checks.yaml

Limitations

  1. Query-based only: YAML plugins can only use Azure Resource Graph queries, not ARM API calls
  2. Subscription scope: Queries run within subscription context
  3. No custom logic: Cannot include complex evaluation logic (use built-in plugins for that)

Migration from Graph Queries

If you have existing ARG queries, convert them to YAML plugins:

Before (separate .kql files):

resources
| where type =~ 'microsoft.storage/storageaccounts'
| where properties.supportsHttpsTrafficOnly == false

After (YAML plugin):

name: my-checks
version: 1.0.0
description: My custom checks
queries:
  - aprlGuid: check-001
    description: Storage accounts without HTTPS
    recommendationControl: Security
    recommendationImpact: High
    recommendationResourceType: Microsoft.Storage/storageAccounts
    query: |
      resources
      | where type =~ 'microsoft.storage/storageaccounts'
      | where properties.supportsHttpsTrafficOnly == false
      | project id, name, resourceGroup, location

1 - Internal Plugins

Built-in analysis plugins for advanced Azure resource insights

Overview

Azure Quick Review (azqr) includes internal plugins - specialized built-in scanners that provide advanced analytics beyond standard best practice recommendations. Unlike YAML plugins (which add custom Resource Graph queries), internal plugins perform complex data analysis, API integrations, and multi-source data correlation.

Internal plugins are disabled by default and must be explicitly enabled using command-line flags.

Available Internal Plugins

1. OpenAI Throttling

Plugin Name: openai-throttling
Flag: --openai-throttling
Version: 1.0.0

Monitors Azure OpenAI and Cognitive Services accounts for throttling (429 errors) to identify capacity constraints.

Key Features:

  • Tracks 429 throttling errors by hour, model, and deployment
  • Analyzes spillover configuration effectiveness
  • Reports request counts by status code
  • Identifies peak throttling periods

Use Cases:

  • Capacity planning for OpenAI deployments
  • Troubleshooting throttling issues
  • Optimizing deployment spillover configuration
  • Monitoring API usage patterns

Output Columns:

  • Subscription, Resource Group, Account Name
  • Kind (OpenAI, Cognitive Services)
  • SKU and deployment details
  • Model name and spillover settings
  • Hourly throttling statistics (status code, request count)

Data Source: Azure Monitor Metrics API (last 24-48 hours)


2. Carbon Emissions

Plugin Name: carbon-emissions
Flag: --carbon-emissions
Version: 1.0.0

Analyzes carbon emissions by Azure resource type to support sustainability reporting and optimization.

Key Features:

  • Tracks emissions by resource type across subscriptions
  • Calculates month-over-month change ratios
  • Aggregates emissions from multiple subscriptions
  • Supports sustainability compliance reporting

Use Cases:

  • Sustainability reporting and compliance
  • Identifying high-emission resource types
  • Tracking carbon reduction progress
  • Environmental impact analysis

Output Columns:

  • Period From/To (reporting period)
  • Resource Type
  • Latest Month Emissions
  • Previous Month Emissions
  • Month-over-Month Change Ratio
  • Monthly Change Value
  • Unit (metric tons CO2 equivalent)

Data Source: Azure Carbon Optimization API


3. Zone Mapping

Plugin Name: zone-mapping
Flag: --zone-mapping
Version: 1.0.0

Retrieves logical-to-physical availability zone mappings for all Azure regions in each subscription.

Key Features:

  • Maps logical zones (1, 2, 3) to physical zone identifiers
  • Reveals subscription-specific zone mappings
  • Helps ensure proper zone alignment across subscriptions
  • Supports multi-subscription architecture planning

Use Cases:

  • Multi-subscription architecture design
  • DR planning with zone awareness
  • Zone alignment for latency optimization
  • Compliance and audit documentation

Output Columns:

  • Subscription, Location, Display Name
  • Logical Zone (1, 2, or 3)
  • Physical Zone (e.g., eastus-az1, westeurope-az2)

Data Source: Azure Resource Manager Subscriptions API

📖 Full Documentation


Usage

Enabling Internal Plugins

Internal plugins are opt-in and must be enabled individually using command-line flags:

# Enable OpenAI throttling plugin
azqr scan --openai-throttling

# Enable carbon emissions plugin
azqr scan --carbon-emissions

# Enable zone mapping plugin
azqr scan --zone-mapping

# Enable multiple plugins
azqr scan --openai-throttling --carbon-emissions --zone-mapping

# Combine with other scan options
azqr scan --subscription-id <sub-id> --output-name analysis

Listing Available Plugins

View all registered plugins (internal and YAML):

azqr plugins list

Sample Output:

NAME                  VERSION    TYPE       DESCRIPTION
openai-throttling     1.0.0      internal   Checks OpenAI/Cognitive Services accounts for...
carbon-emissions      1.0.0      internal   Analyzes carbon emissions by Azure resource type
zone-mapping          1.0.0      internal   Retrieves logical-to-physical availability zone mappings...

Plugin Details

Get detailed information about a specific plugin:

azqr plugins info zone-mapping

Output Formats

Internal plugin results are included in all output formats:

Excel (Default)

Each internal plugin creates a dedicated worksheet in the Excel workbook:

  • Zone Mapping sheet
  • OpenAI Throttling sheet
  • Carbon Emissions sheet
azqr scan --openai-throttling --carbon-emissions --zone-mapping
# Generates: azqr_action_plan_YYYY_MM_DD_THHMMSS.xlsx

JSON

Plugin results are included in the pluginResults array:

azqr scan --zone-mapping --json

JSON Structure:

{
  "recommendations": [...],
  "resources": [...],
  "pluginResults": [
    {
      "pluginName": "zone-mapping",
      "sheetName": "Zone Mapping",
      "description": "Retrieves logical-to-physical availability zone mappings for all Azure regions in each subscription",
      "table": [
        ["Subscription", "Location", "Display Name", "Logical Zone", "Physical Zone"],
        ["Production", "East US", "East US", "1", "eastus-az1"]
      ]
    }
  ]
}

CSV

Plugin results are exported to separate CSV files:

azqr scan --zone-mapping --csv
# Generates: 
#   <filename>.zone-mapping.csv
#   <filename>.recommendations.csv
#   <filename>.inventory.csv
#   ...

Interactive Dashboard

View plugin results interactively using the show command:

# Generate report with plugins
azqr scan --openai-throttling --carbon-emissions --zone-mapping --output-name analysis

# Launch interactive viewer
azqr show -f analysis.xlsx --open

The dashboard provides:

  • Filterable columns (dropdowns, search)
  • Sortable data tables
  • Export capabilities
  • Real-time filtering

Permissions

Internal plugins may require additional permissions beyond standard Reader access:

PluginRequired PermissionsAPI Dependencies
zone-mappingReaderSubscriptions API (locations endpoint)
openai-throttlingReader + Monitoring ReaderCognitive Services, Monitor Metrics
carbon-emissionsReaderCarbon Optimization API

Recommended: Assign Reader and Monitoring Reader roles at subscription or management group scope.

Performance Considerations

Internal plugins add processing time to scans:

  • openai-throttling: 1-3 minutes (depends on number of OpenAI accounts)
  • carbon-emissions: 1-2 minutes (depends on subscription count)
  • zone-mapping: <10 seconds (very fast, one API call per subscription)

Optimization Tips:

  • Enable only needed plugins
  • Use subscription/resource group filters to reduce scope