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.49k stars 4.59k forks source link

Moving subscription to another management group failed #21930

Open jasmineteh opened 1 year ago

jasmineteh commented 1 year ago

Is there an existing issue for this?

Community Note

Terraform Version

1.3.4

AzureRM Provider Version

3.57.0

Affected Resource(s)/Data Source(s)

azurerm_management_group_subscription_association, azurerm_management_group, azurerm_subscription

Terraform Configuration Files

resource "azurerm_management_group" "this" {
  display_name               = "New Management Group Here"
  parent_management_group_id = azurerm_management_group.parent_management_group.id

  subscription_ids = [
    data.azurerm_subscription.current.subscription_id,
  ]
}

resource "azurerm_management_group_subscription_association" "mg_assignment" {
  management_group_id = data.azurerm_management_group.assigned_mg[count.index].id
  subscription_id     = data.azurerm_subscription.current.id
}

Debug Output/Panic Output

2023-05-25T12:04:44.279+0800 [DEBUG] provider.terraform-provider-azurerm_v3.57.0_x5: AzureRM Response for https://management.azure.com/providers/Microsoft.Management/managementGroups/gvt/subscriptions/<subscription-id>?api-version=2020-05-01:
HTTP/2.0 400 Bad Request

{"error":{"code":"BadRequest","message":"Failed to complete the move operation","details":"Role assignment cannot be separated from its custom role's definition assigned on /subscriptions/<subscription-id>. See https://aka.ms/MGCustomRoleMove for more information. Role Definition ID: /subscriptions/<subscription-id>/providers/Microsoft.Authorization/roleDefinitions/<custom-role-id>"}}: timestamp=2023-05-25T12:04:44.279+0800
2023-05-25T12:04:44.285+0800 [ERROR] provider.terraform-provider-azurerm_v3.57.0_x5: Response contains error diagnostic: diagnostic_summary="deleting Management Group Subscription Association between Management Group "gvt" and Subscription "<subscription-id>": managementgroups.SubscriptionsClient#Delete: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="BadRequest" Message="Failed to complete the move operation" Details=[{"raw":"Role assignment cannot be separated from its custom role's definition assigned on /subscriptions/<subscription-id>. See https://aka.ms/MGCustomRoleMove for more information. Role Definition ID: /subscriptions/<subscription-id>/providers/Microsoft.Authorization/roleDefinitions/<custom-role-id>"}]" tf_req_id=1c97ddf4-0548-8665-fb05-f389297264fa tf_rpc=ApplyResourceChange @module=sdk.proto diagnostic_severity=ERROR tf_provider_addr=provider tf_resource_type=azurerm_management_group_subscription_association @caller=github.com/hashicorp/terraform-plugin-go@v0.14.3/tfprotov5/internal/diag/diagnostics.go:55 diagnostic_detail= tf_proto_version=5.3 timestamp=2023-05-25T12:04:44.285+0800
2023-05-25T12:04:44.286+0800 [ERROR] vertex "azurerm_management_group_subscription_association.mg_assignment[0] (destroy)" error: deleting Management Group Subscription Association between Management Group "gvt" and Subscription "<subscription-id>": managementgroups.SubscriptionsClient#Delete: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="BadRequest" Message="Failed to complete the move operation" Details=[{"raw":"Role assignment cannot be separated from its custom role's definition assigned on /subscriptions/<subscription-id>. See https://aka.ms/MGCustomRoleMove for more information. Role Definition ID: /subscriptions/<subscription-id>/providers/Microsoft.Authorization/roleDefinitions/<custom-role-id>"}]

Expected Behaviour

  1. Under Tenant root management group, there is one child management group, A.
  2. Under A, there are 2 management groups, A1 and A2.
  3. Custom role "Custom Contributor" is defined in management group A, with assignable_scopes set to A.
  4. Subscription "Sub A" is created under management group A1.
  5. "Custom Contributor" is assigned to a user in "Sub A".
  6. Move "Sub A" from A1 to A2.
  7. "Sub A" successfully moved to A2.

Actual Behaviour

  1. Move "Sub A" from A1 to A2.
  2. 400 error response "Failed to complete the move operation" which seems to be this error https://learn.microsoft.com/en-gb/azure/governance/management-groups/overview#issues-with-breaking-the-role-definition-and-assignment-hierarchy-path.

Steps to Reproduce

  1. Under Tenant root management group, create one child management group, A.
  2. Under A, create 2 management groups, A1 and A2.
  3. Create a custom role "Custom Contributor" in management group A, with assignable_scopes set to A.
  4. Create subscription "Sub A" under management group A1.
  5. Assign "Custom Contributor" to a user in "Sub A".
  6. Run terraform apply to move "Sub A" to A2 by adding the subscription id using azurerm_management_group or update the management_group_id in azurerm_management_group_subscription_association.

Note: Moving the "Sub A" to another management group worked via Azure portal and command line: https://learn.microsoft.com/en-us/cli/azure/account/management-group/subscription?view=azure-cli-latest#az-account-management-group-subscription-add

Important Factoids

No response

References

No response

juicybaba commented 5 months ago

it happens when remove subscription from a management group too while a RBAC with custom role( data action is in the role definition) in place. my fix is removing the RBAC and rerun terraform.

Mike-Nahmias commented 4 months ago

I ran into this issue today and found that it doesn't occur if you go into the portal and move the subscription yourself from there. Terraform wants to delete the association before it creates a new one to move the subscription, so the subscription will temporarily reside in the root management group. The custom role doesn't exist at the root management group, which is why the error appears.

My half-workaround to this was to use create_before_destroy on the association resource. The apply will still fail (because the original association won't exist anymore when it tries to delete it), but it'll move the subscription for you.

resource "azurerm_management_group_subscription_association" "example" {
  management_group_id = var.management_group_id
  subscription_id     = var.subscription_id

  lifecycle {
    create_before_destroy = true
  }
}

I think the resource needs to be reworked so instead of replacing the resource when the management group changes it will update in place.

jkroepke commented 2 months ago

I will take a look into this, since we got the error, too.

jkroepke commented 2 months ago

@katbyte @stephybun Sorry for mention there, but I would like to share my design/idea here before starting a implementation.

It seems like Azure naively supports moving subscription to other management groups. This is important where a subscription has role assignments with custom role and the custom role has an assignable scope. which is not the Tenant Root.

Currently, Terraform tries to remove the Management group association which does work in such scenario. However, moving subscription to other management groups works without issues.

Since a subscription can be only assigned to management group, I would suggest to change the ID of azurerm_management_group_subscription_association to the subscriptions id, e.g. /subscription/<ID> instead /managementGroup/MyManagementGroup/subscription/<ID>. I would also add an state migration to avoid a breaking change.

Then, I would remove the ForceNew flag from management_group_id. Bit similar to #26282

Would you agree with that proposal?