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 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.