The Problem

Writing Azure Policies is tedious. Each policy requires understanding the ARM resource provider schema, knowing which aliases exist, writing the correct policy rule logic, and then bundling everything into initiatives with proper parameterization, non-compliance messages, and assignments. For a single resource type, this can easily take a full day of work.

When we needed to create guardrails for MySQL Flexible Server, a resource with zero existing custom policies in the community, and resource-specific diagnostic settings for 38+ Azure services, I decided to try a different approach: using Claude AI to generate the policies.

The Approach

The key was providing Claude with the right context. I didn't just say "write me a policy". I gave it:

  1. The ARM resource provider schema for MySQL Flexible Server, so it understood exactly which properties and aliases were available
  2. Existing policy examples from our repository as reference for structure, naming conventions, and the EPAC (Enterprise Policy as Code) format we use
  3. Clear requirements for what each policy should enforce: SSL/TLS, minimum version, logging, encryption, public access restrictions
  4. The Enterprise Policy as Code (EPAC) schema and formatting conventions

MySQL Flexible Server: From Zero to 7 Policies

For MySQL Flexible Server, there were only a handful of built-in policies (around 5, covering things like public network access, Entra authentication and threat protection). But there were no custom policies for the more granular settings we needed. We had to create policies covering:

  • Network isolation: Deny public access via firewall rules
  • Authentication: Enforce Entra ID-only authentication
  • Encryption: Require SSL/TLS connections, audit customer-managed keys
  • Resilience: Audit geo-redundant backup
  • Version compliance: Audit minimum MySQL version (8.0)
  • Security logging: Deny FILE-based log output (PII risk), enforce TABLE-based audit logging, monitor slow query logs

By providing the ARM template structure for MySQL Flexible Server and our existing policy patterns, Claude generated all 7 custom policy definitions in the correct JSONC format in under 10 minutes. Each policy included proper aliases, parameter definitions, and descriptions.

Here's an example of what was generated, a policy to block FILE-based log output to prevent accidental PII exposure:

{
  "name": "Deny-MySqlFlex-LogFileOutput",
  "properties": {
    "displayName": "MySQL Flexible Server should not use FILE-based log output",
    "description": "Prevents MySQL Flexible Server from using FILE as the log output destination. FILE output writes logs to the local filesystem which may expose sensitive data. Use TABLE output instead.",
    "mode": "Indexed",
    "policyRule": {
      "if": {
        "allOf": [
          {
            "field": "type",
            "equals": "Microsoft.DBforMySQL/flexibleServers/configurations"
          },
          {
            "field": "name",
            "equals": "log_output"
          },
          {
            "field": "Microsoft.DBforMySQL/flexibleServers/configurations/value",
            "contains": "FILE"
          }
        ]
      },
      "then": {
        "effect": "[parameters('effect')]"
      }
    }
  }
}

Resource-Specific Diagnostic Settings: 38 Policies at Scale

The other major win was generating 38 DeployIfNotExists policies for resource-specific diagnostic settings. Each policy needed to:

  • Target a specific Azure resource type
  • Deploy a diagnostic settings resource using an embedded ARM template
  • Use logAnalyticsDestinationType: "Dedicated" for resource-specific tables
  • Include proper role definitions for the managed identity (Monitoring Contributor + Log Analytics Contributor)
  • Use the allLogs category group for comprehensive log streaming

Manually writing 38 nearly-identical-but-slightly-different policies would take days. The differences are subtle since each resource type has different diagnostic log categories, some support metrics, and the resource type strings and API versions all vary.

By providing Claude with the ARM resource provider schemas and one reference policy, it generated all 38 policies plus a 1,068-line initiative definition bundling them together with per-resource effect parameters.

Validation

AI gets you 90% there fast. The remaining 10% is validation:

  1. Schema validation: Running the EPAC framework's built-in validation against the policy definition schema
  2. Alias verification: Confirming each policy alias actually exists in the ARM resource provider using Get-AzPolicyAlias
  3. Deployment testing: Deploying to a test subscription with enforcementMode: DoNotEnforce to verify compliance evaluation works correctly
  4. Effect testing: Switching to Deny mode and confirming non-compliant resources are actually blocked
  5. Policy remediation: Running remediation tasks for the DeployIfNotExists policies to verify that non-compliant resources are correctly brought into compliance

We caught a few issues during validation. Claude didn't always parse the ARM schema correctly and would sometimes guess policy aliases rather than derive them from the documentation. Once we pointed out the correct aliases, the fixes were quick, but it's a good reminder to always verify with Get-AzPolicyAlias before deploying.

Time Saved

Let's estimate our time savings:

Task Manual With Claude
7 MySQL policies + initiative 1–2 days ~10 minutes
38 diagnostic policies + initiative 3–5 days ~30 minutes
Assignments + non-compliance messages 0.5–1 day ~10 minutes
Validation & fixes - ~1 hour

What would have been a full week of work was completed in about 2 hours, including validation.

Key Takeaways

  1. Context is everything. Don't just ask for "an Azure Policy." Provide the ARM schema, existing examples, and your specific naming conventions. The output quality is directly proportional to the input quality.
  2. AI is a force multiplier, not a replacement. You still need to understand Azure Policy, know what you're looking for, and validate the output. The skill shifts from writing JSON to reviewing and validating it.
  3. Repetitive patterns are the sweet spot. The 38 diagnostic policies were nearly identical in structure. This is where AI truly shines, generating variations of a known pattern across many resource types.
  4. Always verify aliases. AI can hallucinate property paths. Always verify policy aliases exist with Get-AzPolicyAlias before deploying.

If you're managing Azure Policy at scale, I strongly recommend giving this workflow a try. The combination of EPAC for lifecycle management and AI for policy generation is a massive productivity boost.

//Sebastian