Skip to content

Policy Compliance of the Modules

The modules are built to pass the Azure policies of the platform. This page explains how a module enforces a policy, which prerequisites a few modules have outside the resource, and which findings you can still see in the policy overview after a deployment. How the library tests this is in Testing. The rules for the people who build modules are in Create and contribute modules.

Reference design, your deployment may differ

The baselines of the library are the CIS Microsoft Azure Foundations Benchmark 2.0, ISO 27001:2013 and the Microsoft cloud security benchmark. The policies that your platform assigns can differ, and so can their parameters. The modules are tested against the policies of the test subscription of the maintaining team. See Governance and Policy assignments.

How a module enforces a policy

A module takes the values that a policy checks out of your hands. It does this in three ways:

Way Example Effect for you
A fixed value The Key Vault module sets the default network action to deny and switches legacy access policies off You cannot pass a value that breaks the policy. The parameter may not exist, or your value is overruled.
A default that is the compliant value The Bicep storage account module has public network access disabled by default You can change it, but you have to do it on purpose.
A required parameter The storage account module asks for a customer-managed key, an identity, a private endpoint and diagnostics for the private endpoint interface You supply the target (a key, a subnet, a workspace). The module then configures the rest.

In Terraform the fixed values are visible in the locals.tf of a module. This excerpt of the Key Vault module shows the idea:

locals {
  network_acls = merge(var.network_acls, {
    default_action = "Deny"
    ip_rules       = []
  })
  legacy_access_policies_enabled = false
  diagnostic_settings = { for key, settings in var.diagnostic_settings : key => merge(settings, {
    log_groups        = ["allLogs", "audit"]
    metric_categories = ["AllMetrics"]
    })
  }
}

Diagnostic settings are a good example: you only give the destination, and the module selects all log and metric categories. In a major upgrade of a module, parameters that the module now enforces are removed. The upgrade notes of the SQL server, container registry and network security group modules show this.

Policies with a parameter

Some policies take a parameter when the platform assigns them (for example a list of allowed values). The module uses the default value of the policy as a constant. When the policy has no default, the module offers an input variable and documents it. An example is the runtime version of web apps: the CIS policies for PHP, Java and Python versions have no default value, so the modules do not fix the version. Set the version in the assignment of the policy on your platform, and choose a supported version in your code (Parameterised policies).

Prerequisites outside the module

Some policies check things that a module cannot switch on. These are subscription-level settings of the platform.

Module Prerequisite Why
virtual_machine_windows, virtual_machine_linux The encryption at host feature registered on the subscription The modules enable encryption at host on the VM
virtual_machine_windows, virtual_machine_linux Microsoft Defender for Cloud enabled on the subscription The modules install the Defender extension for the VM
container_registry Defender for Containers on the subscription The vulnerability policy for registry images needs it. The assessment takes more than 24 hours after deployment.
postgresql_flexibleserver Defender for SQL enabled The policy for unprotected PostgreSQL servers depends on it
sql_server A storage account for vulnerability assessments, created before you deploy The server writes the scan results there. By default the Bicep module gives the system-assigned identity of the server the Storage Blob Data Contributor role on it.
virtual_machine_windows Outbound access to the Windows Update and the guest configuration endpoints (see the module README) VM updates and configuration management

Known findings per module

The policy overview can show non-compliance for a deployed module. The causes are in the table. The README of each module repeats them in its Notes section. Findings in the first group go away without action.

Module Finding Cause
All VM modules Guest configuration policies not yet compliant right after deployment Guest policies take more time to evaluate
sql_server Vulnerability assessment should be enabled on your SQL servers The module enables it, but the scan runs weekly. The finding should disappear within days after deployment.
sql_server SQL databases should have vulnerability findings resolved The findings of the scan are for the database administrator. New findings can appear while the database is in use.
container_registry Azure registry container images should have vulnerabilities resolved Needs Defender for Containers and time, see above
apim API Management should disable public network access to the service configuration endpoints The policy does not work for the Standard V2 SKU: Azure returns MethodNotAllowedInPricingTier
apim (Developer SKU) API endpoints that are unused should be disabled and removed and API endpoints should be authenticated The Developer SKU creates an Echo API by default. Remove it manually.
network_security_group Flow logs should be configured for every network security group The policy is no longer valid: flow logs cannot be enabled on the group. Use virtual network flow logs.
virtual_machine_windows, virtual_machine_linux Only approved VM extensions should be installed The default list of the policy does not contain the extensions that the module installs (for the Windows module azurepolicyforwindows and mde.windows). Add them in the policy assignment of your platform.
virtual_machine_windows, virtual_machine_linux Log Analytics Extension should be enabled for listed virtual machine images The Log Analytics extension is deprecated
virtual_machine_windows, virtual_machine_linux SQL servers on machines should have vulnerability findings resolved Related to SQL Server on the machine, not to the module
virtual_machine_linux Dependency agent should be enabled for listed virtual machine images, Linux machines should meet requirements for the Azure compute security baseline, Linux virtual machines should use only signed and trusted boot components Not supported for some Marketplace images, some guest settings need a manual action, and Azure does not perform the assessment
app_service_site_* The CIS policies for PHP, Java and Python versions The policies have no default version. Set the version in the policy assignment.

Windows baseline in ApplyAndMonitor mode

The Windows baseline guest configuration in ApplyAndMonitor mode can remove sign-in rights, so that an administrator cannot log on to the VM. The module README advises to use Audit mode, and describes a script that restores the right. Read the notes of the module before you change the mode.

Other module notes that influence compliance:

  • A VM with backup enabled cannot be restored into a vault with soft delete. The README of the Windows module describes the order of steps.
  • The Bicep Windows VM module supports automatic guest patching for specific images. For other images, set patchAssessmentMode to ImageDefault and patchMode to AutomaticByOS or Manual.
  • The SQL server module supports transparent data encryption with a customer-managed key. The identity of the server needs the Key Vault Crypto Service Encryption User role on the Key Vault.

What to do with a finding

  1. Look it up in the table above and in the Notes of the module README.
  2. If it is expected, wait for the evaluation, or fix the prerequisite of the platform.
  3. If the module blocks something you need, or you think a value is wrong, ask your platform team to extend the module (Ask for a change).
  4. If a policy cannot be met for a good reason, request an exemption (Request a policy exemption).