hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.53k stars 4.6k forks source link

azurerm_management_group_policy_assignment : Error Policy not yet available at requested scope, even if definition is readable #12478

Open jhauray opened 3 years ago

jhauray commented 3 years ago

Community Note

Terraform (and AzureRM Provider) Version

Affected Resource(s)

Terraform Configuration Files

# Copy-paste your Terraform configurations here - for large Terraform configs,
# please use a service like Dropbox and share a link to the ZIP file. For
# security, you can also encrypt the files using our GPG public key: https://keybase.io/hashicorp

policy_assignments = {
    "deny_public_load_balancer" = {
      assignment_name                = "[AZU][DENY][e2e] Deny Public LoadBalancer"
      policy_definition_display_name = "Deny Public LoadBalancer"
      parameters                     = null
    }
}

resource "azurerm_management_group" "mg" {
  name                       = "e2e_child"
  display_name               = "e2e_child"
  parent_management_group_id = data.azurerm_management_group.mg_parent.id
}

data "azurerm_policy_definition" "policy_defs" {
  for_each              = var.policy_assignments
  display_name          = each.value.policy_definition_display_name
  management_group_name = azurerm_management_group.mg.name
}

resource "random_id" "policies_on_mg_names" {
  for_each    = var.policy_assignments
  byte_length = 10
  prefix      = "tf-"
}

resource "azurerm_management_group_policy_assignment" "policies_on_mg" {
  for_each = var.policy_assignments
  name                 = random_id.policies_on_mg_names[each.key].hex
  display_name         = each.value.assignment_name
  policy_definition_id = data.azurerm_policy_definition.policy_defs[each.key].id
  management_group_id  = azurerm_management_group.mg.id

  parameters = each.value.parameters
}

Debug Output

https://gist.github.com/jhauray/9cf6e5e4193912b958d33abb744e90df

Panic Output

Expected Behaviour

azurerm_management_group_policy_assignment shoud be created without error, even if azurerm_management_group is created in the same Terraform code. If data azurerm_policy_definition is readable on the "management group" scope, the "policy assignment" provisionning must be successful.

Actual Behaviour

Resource azurerm_management_group is well created, data azurerm_policy_definition are correctly read. But `azurerm_management_group_policy_assignment fail, with this error message :

Error: creating Policy Assignment ID: (Assignment Name "tf-d9a92661e25c15b9fb75" / Scope "/providers/Microsoft.Management/managementGroups/e2e_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 'tf-d9a92661e25c15b9fb75' 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."

Currently, I use a workaround with time_sleep resource to add a delay between "policy definitions read", and "policy assignment creation" :

resource "time_sleep" "wait_30_seconds" {
  depends_on = [data.azurerm_policy_definition.policy_defs]

  create_duration = "30s"
}

resource "azurerm_management_group_policy_assignment" "policies_on_mg" {
  for_each = var.policy_assignments
  name                 = random_id.policies_on_mg_names[each.key].hex
  display_name         = each.value.assignment_name
  policy_definition_id = data.azurerm_policy_definition.policy_defs[each.key].id
  management_group_id  = azurerm_management_group.mg.id

  parameters = each.value.parameters

  depends_on = [time_sleep.wait_30_seconds]
}

Steps to Reproduce

  1. Create a Management Group named "parent".
  2. Add a custom role on this new Management Group.
  3. Wait for an hour.
  4. terraform apply the previous configuration, to create a child Management Group to your "parent" MG, and a azurerm_management_group_policy_assignment, usine your custom role azurerm_policy_definition.
  5. Notice the relevant error.

Important Factoids

References

MaxiPalle commented 3 years ago

Same problem here when trying to assign a custom policy set to management group. No problem when trying to assign the same policy set on subscription level, only with management group assignment.

Tried to use azurerm_policy_assignment instead but same problem.

magodo commented 2 years ago

I can also reproduce it locally, thank you @jhauray for the detailed reproduce step :+1:

Meanwhile, I've submit an issue towards the Azure policy repo: https://github.com/Azure/azure-policy/issues/918