Files
awesome-copilot/skills/azure-architecture-autopilot/references/azure-common-patterns.md
Jeonghoon Lee 3e01810473 Add azure-architecture-autopilot skill 🤖🤖🤖 (#1158)
* Add azure-architecture-autopilot skill

E2E Azure infrastructure automation skill:
- Natural language → Architecture diagram → Bicep → Deploy
- 70+ service types with 605+ official Azure icons
- Interactive HTML diagrams (drag, zoom, click, PNG export)
- Scans existing resources or designs new architecture
- Modular Bicep with RBAC, Private Endpoints, DNS
- Multi-language support (auto-detects user language)
- Zero dependencies (diagram engine embedded)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix generator.py import for flat scripts/ structure + sync README

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: whoniiii <whoniiii@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-25 10:20:38 +11:00

4.2 KiB

Azure Common Patterns (Stable)

This file contains only near-immutable patterns that are repeated across Azure services. Dynamic information such as API version, SKU, and region is not included here → See azure-dynamic-sources.md.


1. Network Isolation Patterns

Private Endpoint 3-Component Set

All services using PE must have the 3-component set configured:

  1. Private Endpoint — Placed in pe-subnet
  2. Private DNS Zone + VNet Link (registrationEnabled: false)
  3. DNS Zone Group — Linked to PE

If any one is missing, DNS resolution fails even with PE present, causing connection failure.

PE Subnet Required Settings

resource peSubnet 'Microsoft.Network/virtualNetworks/subnets' = {
  properties: {
    addressPrefix: peSubnetPrefix              // ← CIDR as parameter — prevent existing network conflicts
    privateEndpointNetworkPolicies: 'Disabled'  // ← Required. PE deployment fails without it
  }
}

publicNetworkAccess Pattern

Services using PE must include:

properties: {
  publicNetworkAccess: 'Disabled'
  networkAcls: {
    defaultAction: 'Deny'
  }
}

2. Security Patterns

Key Vault

properties: {
  enableRbacAuthorization: true    // Do not use Access Policy method
  enableSoftDelete: true
  softDeleteRetentionInDays: 90
  enablePurgeProtection: true
}

Managed Identity

When AI services access other resources:

identity: {
  type: 'SystemAssigned'  // or 'UserAssigned'
}

Sensitive Information

  • Use @secure() decorator
  • Do not store plaintext in .bicepparam files
  • Use Key Vault references

3. Naming Conventions (CAF-based)

rg-{project}-{env}          Resource Group
vnet-{project}-{env}        Virtual Network
st{project}{env}             Storage Account (no special characters, lowercase+numbers only)
kv-{project}-{env}           Key Vault
srch-{project}-{env}         AI Search
foundry-{project}-{env}      Cognitive Services (Foundry)

Name collision prevention: Recommend using uniqueString(resourceGroup().id)

param storageName string = 'st${uniqueString(resourceGroup().id)}'

4. Bicep Module Structure

<project>/
├── main.bicep              # Orchestration — module calls + parameter passing
├── main.bicepparam         # Environment-specific values (excluding sensitive info)
└── modules/
    ├── network.bicep           # VNet, Subnet
    ├── <service>.bicep         # Per-service modules
    ├── keyvault.bicep          # Key Vault
    └── private-endpoints.bicep # All PE + DNS Zone + VNet Link

Dependency Management

// ✅ Correct: Implicit dependency via resource reference
resource project '...' = {
  properties: {
    parentId: foundry.id  // foundry reference → automatically deploys foundry first
  }
}

// ❌ Avoid: Explicit dependsOn (use only when necessary)

5. PE Bicep Common Template

// ── Private Endpoint ──
resource pe 'Microsoft.Network/privateEndpoints@<fetch>' = {
  name: 'pe-${serviceName}'
  location: location
  properties: {
    subnet: { id: peSubnetId }
    privateLinkServiceConnections: [{
      name: 'pls-${serviceName}'
      properties: {
        privateLinkServiceId: serviceId
        groupIds: ['<groupId>']  // ← Varies by service. See service-gotchas.md
      }
    }]
  }
}

// ── Private DNS Zone ──
resource dnsZone 'Microsoft.Network/privateDnsZones@<fetch>' = {
  name: '<dnsZoneName>'  // ← Varies by service
  location: 'global'
}

// ── VNet Link ──
resource vnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@<fetch>' = {
  parent: dnsZone
  name: '${dnsZone.name}-link'
  location: 'global'
  properties: {
    virtualNetwork: { id: vnetId }
    registrationEnabled: false  // ← Must be false
  }
}

// ── DNS Zone Group ──
resource dnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@<fetch>' = {
  parent: pe
  name: 'default'
  properties: {
    privateDnsZoneConfigs: [{
      name: 'config'
      properties: { privateDnsZoneId: dnsZone.id }
    }]
  }
}

@<fetch>: Always verify the latest stable API version from MS Docs before deployment.