Azure / terraform-azurerm-caf-enterprise-scale

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

root_id variable length #291

Closed jpinsolle-bc closed 2 years ago

jpinsolle-bc commented 2 years ago

Community Note

Versions

terraform: 1.1.7 azure provider: 2.94 module: 1.1.3

Description

Describe the bug

Can't associate custom policy definition to management group when root_id length is greater than 10 characters (mycompany-root in my case).

I would like to create the following management group hierarchy:

- "[Test] root" as Name and "mycompany-root" as ID (policy definition Deny-PublicIP)
      - "[Test] child" as Name and "mycompany-child" as ID (policy assignment Deny-Public-IP)

Terraform error

 Error: Invalid value for variable
│
│   on caf.tf line 13, in module "caf_enterprise_scale":
│   13:   root_id                   = "mycompany-root"
│
│ Value must be between 2 to 10 characters long, consisting of alphanumeric characters and hyphens

Why does root_id is limited to 10 characters? This limitation restricts the naming of the management group which receives the caf-enterprise-scale framework. caf-enterprise-scale will not be applied at the root level, that's why the root_id need to be greater than 10 characters in my use case.

Steps to Reproduce

Step 1: Terraform configuration archetype_definition_lz_bug_root.json

{
  "lz_bug_root": {
    "policy_assignments": [],
    "policy_definitions": [
      "Deny-PublicIP"
    ],
    "policy_set_definitions": [],
    "role_definitions": [],
    "archetype_config": {
      "parameters": {},
      "access_control": {}
    }
  }
}

archetype_definition_lz_bug_child.json

{
  "lz_bug_child": {
    "policy_assignments": [
      "Deny-Public-IP"
    ],
    "policy_definitions": [],
    "policy_set_definitions": [
    ],
    "role_definitions": [
    ],
    "archetype_config": {
      "parameters": {},
      "access_control": {}
    }
  }
}
locals {
  landing_zone = {
    "mycompany-child" = {
      "archetype_config" = {
        "access_control" = {}
        "archetype_id" = "lz_bug_child"
        "parameters" = {}
      }
      "display_name" = "[Test] child"
      "parent_management_group_id" = "mycompany-root"
      "subscription_ids" = []
    }
    "mycompany-root" = {
      "archetype_config" = {
        "access_control" = {}
        "archetype_id" = "lz_bug_root"
        "parameters" = {}
      }
      "display_name" = "[Test] root"
      "parent_management_group_id" = "xxx"
      "subscription_ids" = []
    }
}

module "caf_enterprise_scale" {
  source  = "Azure/caf-enterprise-scale/azurerm"
  version = "1.1.3"

  providers = {
    azurerm              = azurerm
    azurerm.connectivity = azurerm
    azurerm.management   = azurerm
  }

  default_location          = local.location
  root_id                         = "mycompany-root" # <----------- length is greater than 10
  root_parent_id            = local.parent_management_group_id
  deploy_core_landing_zones = false
  custom_landing_zones      = local.landing_zone

  library_path = "${path.cwd}/lib"
}

Terraform result

 Error: Invalid value for variable
│
│   on caf.tf line 13, in module "caf_enterprise_scale":
│   13:   root_id                   = "mycompany-root"
│
│ Value must be between 2 to 10 characters long, consisting of alphanumeric characters and hyphens

Additional context I also tried to not specify root_id parameter, I get another error because policy_definition_id computed value for policy assignment contains the default value "es" which doesn't match with any of my management groups.

Terraform plan

  # module.caf_enterprise_scale.azurerm_management_group_policy_assignment.enterprise_scale["/providers/Microsoft.Management/managementGroups/mycompany-child/providers/Microsoft.Authorization/policyAssignments/Deny-Public-IP"] will be created
  + resource "azurerm_management_group_policy_assignment" "enterprise_scale" {
      + description          = "This policy denies creation of Public IPs under the assigned scope."
      + display_name         = "Deny the creation of public IP"
      + enforce              = true
      + id                   = (known after apply)
      + location             = "northeurope"
      + management_group_id  = "/providers/Microsoft.Management/managementGroups/mycompany-child"
      + metadata             = (known after apply)
      + name                 = "Deny-Public-IP"
      + not_scopes           = []
      + policy_definition_id = "/providers/Microsoft.Management/managementGroups/es/providers/Microsoft.Authorization/policyDefinitions/Deny-PublicIP"
    }

Terraform error

Error: creating Policy Assignment ID: (Assignment Name "Deny-Public-IP" / Scope "/providers/Microsoft.Management/managementGroups/mycompany-child"): policy.AssignmentsClient#Create: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="InvalidCreatePolicyAssignmentRequest" Message="The policy definition specified in policy assignment 'Deny-Public-IP' is out of scope. Policy definitions should be specified only at or above the policy assignment scope. If the management groups hierarchy changed recently or if assigning a management group policy to new subscription, please allow up to 30 minutes for the hierarchy changes to apply and try again."
│
│   with module.caf_enterprise_scale.azurerm_management_group_policy_assignment.enterprise_scale["/providers/Microsoft.Management/managementGroups/mycompany-child/providers/Microsoft.Authorization/policyAssignments/Deny-Public-IP"]

The default value for root_idis es

krowlandson commented 2 years ago

Hi @jpinsolle-betclic... thank you for raising this question.

Why does root_id is limited to 10 characters?

In short, the 10 character limit is due to the way we use this as a prefix for many of the other resources created by this module, allowing us to ensure we do not exceed the name length limits which vary by resource type.

We recommend using the display name for more descriptive and "human friendly" names within the management group hierarchy, as this isn't used for any other resources.

I also tried to not specify root_id parameter, I get another error because policy_definition_id computed value for policy assignment contains the default value "es" which doesn't match with any of my management groups.

The root_id is also a crucial part of how the module uses the calculated names of resources to convert the input templates into a valid list of resources to deploy. As such, it's required (when building a custom hierarchy as you are doing) that this value matches the id assigned to your root management group or you will get the error you've already observed.

It's probably also worth noting that all of our built-in templates work on the expectation that Policy Definitions and Initiatives are declared at the root management group scope, as this is our recommended approach.

I hope this explanation helps? I am going to close this issue as we have no plans to increase this limit further.