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