Azure / terraform-azurerm-caf-enterprise-scale

Azure landing zones Terraform module
https://aka.ms/alz/tf
MIT License
857 stars 569 forks source link

Enforcement mode for policies when using multiple module declarations #786

Open tlfzhylj opened 1 year ago

tlfzhylj commented 1 year ago

Community Note

Versions

module: 4.1.0 and 4.2.0

Description

Describe the bug

When using multiple module declarations (much like the one described here: [Examples] Deploy using multiple module declarations with remote state, where I have one declaration with its own state which handles the core part with policies, etc., one with management resources and one with connectivity resources.

From 4.1.0 it looks like I have to have deploy_connectivity_resources set to true to have the enforcement mode for Deploy-Private-DNS-Zones set to true.

The solution which I describe in this issue and thread does not work after module version 4.1.0.

If I'm running a tf plan upgrading module version from 4.0.2 to 4.1.0 or 4.2.0 I see that Deploy-Private-DNS-Zones will be set to false.

How can I configure this, so it remains true?

Additional context

721

758

matt-FFFFFF commented 1 year ago

Hi @tlfzhylj

You can use archetype_config_overrides in the module instance that deploys the MGs and policies. We support setting enforcement mode there.

tlfzhylj commented 1 year ago

Hi, @matt-FFFFFF

I already have this in my config, and it works in module version 4.0.2. After 4.1.0 this configuration have no effect.

archetype_config_overrides = {
  myorg-corp = {
    enforcement_mode = {
      Deploy-Private-DNS-Zones = true
    }
  }
}

Any ideas?

tlfzhylj commented 1 year ago

This is what I see in TF plan, even when using the archetype_config_overrides as shown above.

  # module.alz_core.azurerm_management_group_policy_assignment.enterprise_scale["/providers/Microsoft.Management/managementGroups/myorg-corp/providers/Microsoft.Authorization/policyAssignments/Deploy-Private-DNS-Zones"] will be updated in-place
  ~ resource "azurerm_management_group_policy_assignment" "enterprise_scale" {
      ~ enforce              = true -> false
        id                   = "/providers/Microsoft.Management/managementGroups/myorg-corp/providers/Microsoft.Authorization/policyAssignments/Deploy-Private-DNS-Zones"
        name                 = "Deploy-Private-DNS-Zones"
        # (8 unchanged attributes hidden)

      ~ non_compliance_message {
          ~ content = "Azure PaaS services must use private DNS zones." -> "Azure PaaS services should use private DNS zones."
        }

        # (1 unchanged block hidden)
    }

If interesting, I also see the same for the Deploy-Log-Analytics policy assignment when running TF plan.

matt-FFFFFF commented 1 year ago

Deploy-log-analytics was intentional change, as TF deploys the LA workspace intentionally. But should be able to be overridden.

The other policy behaviour is not expected.

We will look into this.

larsakerlund commented 9 months ago

Ran into this issue when troubleshooting why no private endpoint records were registered.

After going through the module code I could find that the enforcement_mode for Deploy-Private-DNS-Zones is set within module/connectivity/locals.tf:

locals {
    # Only true if connectivity resources are deployed
    deploy_dns = local.enabled && local.settings.dns.enabled
    ...
    archetype_config_overrides = {
    ...
        "${local.root_id}-corp" = {
        enforcement_mode = {
                Deploy-Private-DNS-Zones = local.deploy_dns
            }
    }
    ...
    }
}

The results are then passed down to local.es_landing_zones_map within local.management_groups.tf:

locals {
    es_landing_zones_map = {
        for key, value in local.es_landing_zones_merge :
        "${local.provider_path.management_groups}${key}" => {
        ...
            archetype_config = {
                ...
                enforcement_mode = merge(
                    lookup(module.connectivity_resources.configuration.archetype_config_overrides, key, local.enforcement_mode_default).enforcement_mode,
                    lookup(module.identity_resources.configuration.archetype_config_overrides, key, local.enforcement_mode_default).enforcement_mode,
                    lookup(module.management_resources.configuration.archetype_config_overrides, key, local.enforcement_mode_default).enforcement_mode,
                    lookup(value.archetype_config, "enforcement_mode", local.empty_map)
                )
        }
        }
    }
}

None of the other modules pass enforcement_mode for Deploy-Private-DNS-Zones.

Values from var.archetype_config_overrides should be applied last in the merge, but the problem comes when local.es_landing_zone_map is generated. Since the input variable values are added through the core default management group archetypes, it is possible to remove them by not enabling parts of the management group tree. This means that if var.deploy_corp_landing_zones is set to false (which is the default behaviour) the overrides are no longer set, since it is no longer added to the generated local.es_landing_zone_map.

This means that when using var.custom_landing_zones to configure a custom management group tree, where the default archetypes like corp can be used, the overrides are lost, and the value from module.connectivity_resources is used.

My workaround for this has been to simply add the enforcement_mode parameter to the archetype config in the custom landing zone structure:

custom_landing_zones = {
    "${var.root_id}-corp" = {
        display_name               = "Corp"
        parent_management_group_id = "${var.root_id}-landing-zones"
        subscription_ids           = []
        archetype_config = {
            archetype_id = "es_corp"
            parameters = {}
            access_control = {}
            # Ensures that private DNS policy is enforced
            enforcement_mode = {
                Deploy-Private-DNS-Zones = true
            }
        }
    }
}

Not sure this is the intended way of doing it (probably not), but it works and hopefully someone else running into this can make use of it.