Skip to main content
Pulumi logo Pulumi logo
  1. Docs
  2. Reference
  3. Pre-built Policy Packs
  4. Pulumi Best Practices
  5. Azure

Pulumi Best Practices - Azure

This Pulumi Cloud feature is available in the Essentials, Pro, and Enterprise editions.

    This page lists all 30 policies in the Pulumi Best Practices pack for Azure, as published in pulumi-best-practices-azure version 1.1.1.

    Policies by control

    1. Least Privilege — Ensure all identities and services have only the minimum permissions required to perform their tasks.

    2. Resource Encryption at Rest — Encrypt all stored data using approved encryption mechanisms to protect against unauthorized access.

    3. Transport Layer Encryption — Require secure protocols (e.g., TLS) for all data in transit to prevent interception or tampering.

    4. No Public Access — Prohibit direct public exposure of resources unless explicitly approved and required.

    5. Tagging — Enforce standardized resource tags for ownership, environment, and compliance tracking.

    6. Enforce Logging — Enable and retain audit logs for all security-relevant actions and events.

    7. High Availability — Deploy resources in redundant, fault-tolerant configurations to ensure service continuity.

    8. Require DLQ — Ensure all asynchronous messaging systems are configured with a dead-letter queue to handle failures.

    9. Resource Availability — Define and enforce timeouts, quotas, and capacity limits to prevent resource exhaustion.

    10. Approved Versions — Only allow deployment of approved, patched, and supported versions of runtimes, images, and dependencies.

    11. Networking — Only allow required inbound and outbound traffic through network security groups, firewalls, or ACLs.

    13. Data Backup and Recovery — Regularly back up critical data and systems, store backups securely, and test recovery procedures to ensure timely restoration after failures or disasters.

    14. Key Management & Rotation — Manage encryption keys securely and enforce periodic key rotation to reduce the risk of compromise.

    Policy details

    application-gateway-has-health-probes

    Severity: medium · Enforcement: advisory

    Require Application Gateway to enable health probes

    • 9. Resource Availability — Define and enforce timeouts, quotas, and capacity limits to prevent resource exhaustion.
    Remediation
    Fix: Configure Health Probes
    const appGateway = new azurenative.network.ApplicationGateway("my-app-gateway", {
        probes: [{
            name: "health-probe",
            protocol: "Https",
            path: "/health",
            interval: 30,
            timeout: 30,
            unhealthyThreshold: 3,
            match: {
                statusCodes: ["200-399"],
            },
        }],
        backendHttpSettingsCollection: [{
            name: "backend-settings",
            probe: { id: healthProbe.id },  // Associate probe with backend settings
            // ... other config
        }],
        // ... other config
    });
    

    application-gateway-multi-az

    Severity: medium · Enforcement: advisory

    Require Application Gateway to be configured across multiple availability zones

    • 7. High Availability — Deploy resources in redundant, fault-tolerant configurations to ensure service continuity.
    Remediation
    Fix: Deploy Across Multiple Availability Zones
    const appGateway = new azurenative.network.ApplicationGateway("my-app-gateway", {
        zones: ["1", "2", "3"],  // Deploy across at least 2 availability zones
        // ... other config
    });
    

    application-gateway-tls

    Severity: high · Enforcement: advisory

    Require Application Gateway to have secure TLS configuration

    • 3. Transport Layer Encryption — Require secure protocols (e.g., TLS) for all data in transit to prevent interception or tampering.
    Remediation
    Fix: Configure Secure TLS Policy
    const appGateway = new azurenative.network.ApplicationGateway("my-app-gateway", {
        sslPolicy: {
            policyType: "Predefined",
            policyName: "AppGwSslPolicy20220101",  // Use modern policy with TLS 1.2+
        },
        // ... other config
    });
    

    cosmos-db-backup-policies

    Severity: medium · Enforcement: advisory

    Require Cosmos DB account to have backup policies configured

    • 13. Data Backup and Recovery — Regularly back up critical data and systems, store backups securely, and test recovery procedures to ensure timely restoration after failures or disasters.
    Remediation
    Fix: Configure Cosmos DB Backup Policies
    // Option 1: Continuous Backup (recommended)
    const cosmosDbContinuous = new azurenative.cosmosdb.DatabaseAccount("my-cosmosdb", {
        databaseAccountOfferType: "Standard",
        backupPolicy: {
            type: "Continuous",  // Enable continuous backup
            continuousModeProperties: {
                tier: "Continuous30Days",  // 30-day point-in-time restore
            },
        },
        // ... other config
    });
    
    // Option 2: Periodic Backup
    const cosmosDbPeriodic = new azurenative.cosmosdb.DatabaseAccount("my-cosmosdb", {
        databaseAccountOfferType: "Standard",
        backupPolicy: {
            type: "Periodic",  // Enable periodic backup
            periodicModeProperties: {
                backupIntervalInMinutes: 240,  // 4 hours
                backupRetentionIntervalInHours: 720,  // 30 days
            },
        },
        // ... other config
    });
    

    front-door-tls

    Severity: high · Enforcement: advisory

    Require Front Door custom domains to use secure TLS configuration

    • 3. Transport Layer Encryption — Require secure protocols (e.g., TLS) for all data in transit to prevent interception or tampering.
    Remediation
    Fix: Configure Secure TLS Settings
    const customDomain = new azurenative.cdn.AFDCustomDomain("my-custom-domain", {
        tlsSettings: {
            minimumTlsVersion: "TLS12",  // Enforce minimum TLS 1.2
            certificateType: "ManagedCertificate",  // Use Azure-managed certificates
        },
        // ... other config
    });
    

    key-vault-key-configuration

    Severity: high · Enforcement: advisory

    Require proper Key Vault key creation and configuration

    • 14. Key Management & Rotation — Manage encryption keys securely and enforce periodic key rotation to reduce the risk of compromise.
    Remediation
    Fix: Configure Key with Proper Type, Size, and Operations
    const key = new azurenative.keyvault.Key("my-key", {
        properties: {
            kty: "RSA",  // or "RSA-HSM" for hardware protection
            keySize: 2048,  // Minimum 2048 bits for RSA
            keyOps: ["encrypt", "decrypt"],  // Specify exact operations needed
            attributes: {
                exportable: false,
            },
        },
        // ... other config
    });
    

    key-vault-key-lifecycle

    Severity: high · Enforcement: advisory

    Require proper Key Vault key deletion and lifecycle management

    • 14. Key Management & Rotation — Manage encryption keys securely and enforce periodic key rotation to reduce the risk of compromise.
    Remediation
    Fix: Configure Key Vault Key Lifecycle Attributes
    const key = new azurenative.keyvault.Key("my-key", {
        properties: {
            kty: "RSA",
            attributes: {
                exp: 1735689600,  // Set expiration date (Unix epoch timestamp)
                nbf: 1704067200,  // Set not-before date (Unix epoch timestamp)
            },
            // ... other config
        },
    });
    

    key-vault-key-rotation

    Severity: high · Enforcement: advisory

    Require Key Vault keys to have rotation policies configured

    • 14. Key Management & Rotation — Manage encryption keys securely and enforce periodic key rotation to reduce the risk of compromise.
    Remediation
    Fix: Configure Key Vault Key Rotation Policy
    const key = new azurenative.keyvault.Key("my-key", {
        properties: {
            kty: "RSA",
            rotationPolicy: {
                attributes: {
                    expiryTime: "P2Y",  // Set expiry time for key versions
                },
                lifetimeActions: [{
                    action: { type: "rotate" },
                    trigger: { timeAfterCreate: "P90D" },  // Rotate 90 days after creation
                }],
            },
            // ... other config
        },
    });
    

    key-vault-soft-delete

    Severity: high · Enforcement: advisory

    Require Key Vault to have soft delete enabled with appropriate retention

    • 13. Data Backup and Recovery — Regularly back up critical data and systems, store backups securely, and test recovery procedures to ensure timely restoration after failures or disasters.
    Remediation
    Fix: Enable Key Vault Soft Delete
    const vault = new azurenative.keyvault.Vault("my-key-vault", {
        properties: {
            sku: { name: "standard" },
            enableSoftDelete: true,  // Enable soft delete
            softDeleteRetentionInDays: 90,  // Set retention period (minimum 90 days)
            // ... other config
        },
    });
    

    load-balancer-health-probes

    Severity: medium · Enforcement: advisory

    Require Load Balancer to enable health probes

    • 9. Resource Availability — Define and enforce timeouts, quotas, and capacity limits to prevent resource exhaustion.
    Remediation
    Fix: Configure Load Balancer Health Probes
    const loadBalancer = new azurenative.network.LoadBalancer("my-load-balancer", {
        sku: { name: "Standard" },
        probes: [{
            name: "http-health-probe",
            properties: {
                protocol: "Http",
                port: 80,
                requestPath: "/health",  // Configure health check endpoint
            },
        }],
        loadBalancingRules: [{
            name: "http-rule",
            properties: {
                probe: { id: probeId },  // Associate probe with rule
                // ... other config
            },
        }],
    });
    

    load-balancer-multi-az

    Severity: medium · Enforcement: advisory

    Require Load Balancer to be configured across multiple availability zones

    • 7. High Availability — Deploy resources in redundant, fault-tolerant configurations to ensure service continuity.
    Remediation
    Fix: Configure Load Balancer for Multiple Availability Zones
    const loadBalancer = new azurenative.network.LoadBalancer("my-lb", {
        sku: {
            name: "Standard",  // Standard SKU required for zone redundancy
        },
        frontendIPConfigurations: [{
            zones: ["1", "2", "3"],  // Deploy across multiple zones
            // ... other config
        }],
    });
    

    log-analytics-retention

    Severity: medium · Enforcement: advisory

    Require Log Analytics workspace to have appropriate retention policies

    • 6. Enforce Logging — Enable and retain audit logs for all security-relevant actions and events.
    Remediation
    Fix: Configure Log Analytics Workspace Retention Policy
    const workspace = new azurenative.operationalinsights.Workspace("my-workspace", {
        sku: {
            name: "PerGB2018",
        },
        retentionInDays: 90,  // Set to meet compliance requirements (minimum 90 days)
        // ... other config
    });
    

    network-interface-no-public-ip

    Severity: critical · Enforcement: advisory

    Require Network Interfaces to have no public IP address associations

    • 4. No Public Access — Prohibit direct public exposure of resources unless explicitly approved and required.
    Remediation
    Fix: Remove Public IP Address from Network Interface
    const nic = new azurenative.network.NetworkInterface("my-nic", {
        ipConfigurations: [{
            privateIPAllocationMethod: "Dynamic",
            // Do NOT include publicIPAddress property
            // ... other config
        }],
    });
    

    nsg-disallow-public-internet-ingress

    Severity: high · Enforcement: advisory

    Require Network Security Groups to disallow public internet ingress

    • 11. Networking — Only allow required inbound and outbound traffic through network security groups, firewalls, or ACLs.
    Remediation
    Fix: Remove Public Internet Ingress from Network Security Group
    const nsg = new azurenative.network.NetworkSecurityGroup("secure-nsg", {
        securityRules: [
            {
                protocol: "Tcp",
                sourceAddressPrefix: "203.0.113.0/24",  // Use specific IP ranges, not 0.0.0.0/0
                access: "Allow",
                direction: "Inbound",
                // ... other config
            },
        ],
    });
    

    nsg-strict-rules

    Severity: high · Enforcement: advisory

    Require strict Network Security Group rules with explicit allow/deny configuration

    • 11. Networking — Only allow required inbound and outbound traffic through network security groups, firewalls, or ACLs.
    Remediation
    Fix: Configure Strict Network Security Group Rules
    const nsg = new azurenative.network.NetworkSecurityGroup("strict-nsg", {
        securityRules: [
            {
                protocol: "Tcp",
                sourceAddressPrefix: "10.0.0.0/16",  // Use specific IP ranges, not * or 0.0.0.0/0
                destinationAddressPrefix: "10.0.1.0/24",  // Use specific destinations
                access: "Allow",
                direction: "Inbound",
                // ... other config
            },
        ],
    });
    

    rbac-least-privilege

    Severity: critical · Enforcement: advisory

    Enforce least privilege access control by prohibiting overly broad RBAC role assignments

    • 1. Least Privilege — Ensure all identities and services have only the minimum permissions required to perform their tasks.
    Remediation
    Fix: Use Specific Least-Privilege Roles
    const roleAssignment = new azurenative.authorization.RoleAssignment("my-assignment", {
        roleDefinitionId: "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7",  // Reader role instead of Owner/Contributor
        principalId: servicePrincipalId,
        scope: "/subscriptions/{sub-id}/resourceGroups/my-rg",  // Scope to resource group instead of subscription
    });
    

    resources-change-tracking-tags

    Severity: low · Enforcement: advisory

    Require all Azure resources to have proper tagging for change tracking

    • 5. Tagging — Enforce standardized resource tags for ownership, environment, and compliance tracking.
    Remediation
    Fix: Add Change Tracking Tags to Resources
    const storageAccount = new azurenative.storage.StorageAccount("app-storage", {
        sku: {
            name: "Standard_LRS",
        },
        tags: {
            "last-modified": "2025-10-07",  // ISO 8601 date format (YYYY-MM-DD)
            "modified-by": "jane.doe@company.com",
            "change-reason": "Added storage account for new application deployment",
        },
        // ... other config
    });
    

    resources-environment-tags

    Severity: low · Enforcement: advisory

    Require all resources to have environment tags

    • 5. Tagging — Enforce standardized resource tags for ownership, environment, and compliance tracking.
    Remediation
    Fix: Add Environment Tag
    const resource = new azurenative.storage.StorageAccount("my-storage", {
        tags: {
            environment: "prod",  // Use "dev", "test", "staging", or "prod"
        },
        // ... other config
    });
    

    service-bus-dead-letter-queue

    Severity: medium · Enforcement: advisory

    Validate Service Bus queues have proper dead letter queue configuration

    • 8. Require DLQ — Ensure all asynchronous messaging systems are configured with a dead-letter queue to handle failures.
    Remediation
    Fix: Configure Service Bus Queue Dead Letter Settings
    const queue = new azurenative.servicebus.Queue("my-queue", {
        maxDeliveryCount: 10,  // Maximum delivery attempts before dead lettering
        deadLetteringOnMessageExpiration: true,  // Enable dead lettering when messages expire
        // ... other config
    });
    

    sql-database-backup-retention

    Severity: medium · Enforcement: advisory

    Require Azure SQL Database to have backup retention configured with redundant storage

    • 13. Data Backup and Recovery — Regularly back up critical data and systems, store backups securely, and test recovery procedures to ensure timely restoration after failures or disasters.
    Remediation
    Fix: Enable SQL Database Backup Retention with Redundant Storage
    const database = new azurenative.sql.Database("my-database", {
        sku: {
            name: "S0",
            tier: "Standard",
        },
        requestedBackupStorageRedundancy: "Geo",  // Use geo-redundant backup storage
        // ... other config
    });
    

    sql-database-customer-managed-keys

    Severity: high · Enforcement: advisory

    Require Azure SQL databases to use customer-managed keys for transparent data encryption

    • 2. Resource Encryption at Rest — Encrypt all stored data using approved encryption mechanisms to protect against unauthorized access.
    Remediation
    Fix: Enable SQL Database Customer-Managed Keys for TDE
    const encryptionProtector = new azurenative.sql.EncryptionProtector("tde-protector", {
        serverKeyType: "AzureKeyVault",  // Use customer-managed key from Azure Key Vault
        serverKeyName: serverKey.name,
        autoRotationEnabled: true,  // Enable auto-rotation when key version changes
        // ... other config
    });
    

    sql-database-high-availability

    Severity: medium · Enforcement: advisory

    Require Azure SQL Database to have high availability configuration

    • 7. High Availability — Deploy resources in redundant, fault-tolerant configurations to ensure service continuity.
    Remediation
    Fix: Enable SQL Database High Availability
    const database = new azurenative.sql.Database("my-database", {
        sku: {
            name: "P1",
            tier: "Premium",
        },
        zoneRedundant: true,  // Enable zone redundancy for high availability
        // ... other config
    });
    

    sql-server-audit-logging

    Severity: medium · Enforcement: advisory

    Require Azure SQL Server to have audit logging enabled

    • 6. Enforce Logging — Enable and retain audit logs for all security-relevant actions and events.
    Remediation
    Fix: Enable SQL Server Audit Logging
    const auditPolicy = new azurenative.sql.ServerBlobAuditingPolicy("audit-policy", {
        state: "Enabled",  // Enable audit logging
        storageEndpoint: storageEndpoint,
        retentionDays: 90,  // Retain audit logs for 90 days
        // ... other config
    });
    

    sql-server-disable-public-access

    Severity: critical · Enforcement: advisory

    Require Azure SQL Server to disable public network access

    • 4. No Public Access — Prohibit direct public exposure of resources unless explicitly approved and required.
    Remediation
    Fix: Disable SQL Server Public Network Access
    const sqlServer = new azurenative.sql.Server("my-sql-server", {
        publicNetworkAccess: "Disabled",  // Disable public network access
        // ... other config
    });
    

    storage-account-geo-replication

    Severity: medium · Enforcement: advisory

    Require Storage Accounts to have geo-replication enabled for business continuity

    • 13. Data Backup and Recovery — Regularly back up critical data and systems, store backups securely, and test recovery procedures to ensure timely restoration after failures or disasters.
    Remediation
    Fix: Enable Geo-Replication
    const storageAccount = new azurenative.storage.StorageAccount("mystorageaccount", {
        sku: { name: "Standard_GRS" },  // Use geo-replicated SKU for redundancy
        kind: "StorageV2",
        // ... other config
    });
    

    storage-account-https-only

    Severity: high · Enforcement: advisory

    Require Storage Accounts to enforce HTTPS-only traffic

    • 3. Transport Layer Encryption — Require secure protocols (e.g., TLS) for all data in transit to prevent interception or tampering.
    Remediation
    Fix: Enable HTTPS-Only Traffic
    const storageAccount = new azurenative.storage.StorageAccount("mystorageaccount", {
        sku: { name: "Standard_LRS" },
        kind: "StorageV2",
        enableHttpsTrafficOnly: true,  // Enforce HTTPS-only traffic
        // ... other config
    });
    

    storage-account-public-access

    Severity: critical · Enforcement: advisory

    Require Storage Accounts to disable public blob access

    • 4. No Public Access — Prohibit direct public exposure of resources unless explicitly approved and required.
    Remediation
    Fix: Disable Public Blob Access
    const storageAccount = new azurenative.storage.StorageAccount("mystorageaccount", {
        sku: { name: "Standard_LRS" },
        kind: "StorageV2",
        allowBlobPublicAccess: false,  // Disable public blob access
        // ... other config
    });
    

    storage-account-uses-customer-managed-keys

    Severity: high · Enforcement: advisory

    Require Storage Accounts to use customer-managed keys for encryption

    • 2. Resource Encryption at Rest — Encrypt all stored data using approved encryption mechanisms to protect against unauthorized access.
    Remediation
    Fix: Configure Customer-Managed Keys
    const storageAccount = new azurenative.storage.StorageAccount("mystorageaccount", {
        sku: { name: "Standard_LRS" },
        kind: "StorageV2",
        encryption: {
            keySource: "Microsoft.Keyvault",  // Use customer-managed keys
            keyVaultProperties: {
                keyName: "my-encryption-key",
                keyVaultUri: "https://my-keyvault.vault.azure.net/",
            },
        },
        // ... other config
    });
    

    vm-approved-images

    Severity: medium · Enforcement: advisory

    Require pre-approved hardened VM images from trusted publishers

    • 10. Approved Versions — Only allow deployment of approved, patched, and supported versions of runtimes, images, and dependencies.
    Remediation
    Fix: Use Approved VM Images
    const vm = new azurenative.compute.VirtualMachine("my-vm", {
        hardwareProfile: { vmSize: "Standard_D2s_v3" },
        storageProfile: {
            imageReference: {
                publisher: "Canonical",              // Use approved publisher
                offer: "UbuntuServer",               // Use approved offer
                sku: "20.04-LTS",                    // Use approved SKU
                version: "latest",
            },
            // ... other config
        },
        // ... other config
    });
    

    vm-requires-managed-disks

    Severity: medium · Enforcement: advisory

    Require VMs to use managed disks only

    • 2. Resource Encryption at Rest — Encrypt all stored data using approved encryption mechanisms to protect against unauthorized access.
    Remediation
    Fix: Configure VM to Use Managed Disks
    const vm = new azurenative.compute.VirtualMachine("my-vm", {
        hardwareProfile: { vmSize: "Standard_D2s_v3" },
        storageProfile: {
            osDisk: {
                createOption: "FromImage",
                managedDisk: {  // Use managed disk, not vhd property
                    storageAccountType: "Premium_LRS",
                },
            },
            dataDisks: [{
                lun: 0,
                createOption: "Empty",
                diskSizeGB: 128,
                managedDisk: {  // Use managed disk, not vhd property
                    storageAccountType: "Premium_LRS",
                },
            }],
            // ... other config
        },
        // ... other config
    });
    

      The infrastructure as code platform for any cloud.