hashicorp / terraform-provider-azuread

Terraform provider for Azure Active Directory
https://registry.terraform.io/providers/hashicorp/azuread/latest/docs
Mozilla Public License 2.0
419 stars 287 forks source link

OData 400: The group must have at least one owner / Removing a 2nd... Owner from Entra ID Group with Role Assignable = false #1435

Open philmph opened 1 month ago

philmph commented 1 month ago

Community Note

Terraform (and AzureAD Provider) Version

Terraform v1.8.5
on windows_amd64
+ provider registry.terraform.io/hashicorp/azuread v2.53.1

Affected Resource(s)

Terraform Configuration Files

Notes:

When a group is role_assignable = true it is possible to remove all Owner objects but one remaining via Terraform and the Portal in all test cases.

When a group is role_assignable = false it is NOT possible to remove all Owner objects but one remaining via Terraform. Terraform removes all until count = 2 and errors on one random last remaining one.

Within the Portal the request also errors if Owner objects count = 2 but works if count = 3 and two are removed with multiple select.

-> Single object remove works fine with role_assignable = true but fails with role_assignable = false. Multiple object remove is not implemented in Terraform but works in the Portal. Always requires a count = 3 or higher.

Also worth noting that I haven't seen any highlights towards this only being the case in role_assignable = false groups thats why I open this issue.

variable "tenant" {}

variable "client_id" {
  sensitive = true
}

variable "client_secret" {
  sensitive = true
}

variable "additional_owners" {
  type = list(string)
}

provider "azuread" {
  tenant_id     = var.tenant
  client_id     = var.client_id
  client_secret = var.client_secret
}

data "azuread_client_config" "current" {}

locals {
  owners = concat([data.azuread_client_config.current.object_id], var.additional_owners)
}

resource "azuread_group" "role_assignable_group" {
  assignable_to_role = true

  description  = "Test Group 1"
  display_name = "Test Group 1"
  owners       = local.owners

  mail_enabled      = false
  security_enabled  = true
  writeback_enabled = false
}

resource "azuread_group" "non_role_assignable_group" {
  assignable_to_role = false

  description  = "Test Group 2"
  display_name = "Test Group 2"
  owners       = local.owners

  mail_enabled      = false
  security_enabled  = true
  writeback_enabled = false
}

Debug Output

Here Terraform tries to remove two Owner from a group with role_assignable = false. Outcome is that one Owner from 3 is removed and the error raised when the 2nd Owner is to be removed (resulting in only one Owner left).

Steps to repoduce described in Run 5 - Removing the 2nd and 3rd Owner from group (-2 Owner in one plan / apply)

azuread_group.non_role_assignable_group: Modifying... [id=REDACTED-420e-4192-81da-3197c080d11d]
azuread_group.role_assignable_group: Modifying... [id=REDACTED-5cda-4016-a8d6-56add63669db]
azuread_group.role_assignable_group: Modifications complete after 1s [id=REDACTED-5cda-4016-a8d6-56add63669db]
╷
│ Error: Could not remove owners from group with object ID: "REDACTED-420e-4192-81da-3197c080d11d"
│
│   with azuread_group.non_role_assignable_group,
│   on main.tf line 46, in resource "azuread_group" "non_role_assignable_group":
│   46: resource "azuread_group" "non_role_assignable_group" {
│
│ GroupsClient.BaseClient.Delete(): unexpected status 400 with OData error: Request_BadRequest: The group must have at least one owner, hence this owner cannot be removed.
╵

Panic Output

Not relevant.

Expected Behavior

All objects but one remaining Owner can be removed from the group.

Actual Behavior

All objects but two Owner remain. Terraform errors on the last one it wants to remove before count = 1.

Steps to Reproduce

Note: I am running the configuration with an SPN with Group.Create and Directory.Read.All. Thats why SPN as Owner is stated in the runs. The role_assignable = true group was state imported since the Graph API permissions are not sufficient to create such a group. The behavior does not change if running with User context.

Run 1

Creation with no additional Owners -> SUCCESS: Both groups exist with SPN as Owner

Run 2

Adding a 2nd Owner to both groups -> SUCCESS: Both groups exist with SPN and 2nd as Owner

Run 3

Removing the 2nd Owner from both groups -> SUCCESS: for Group with assignable_to_role = true -> FAIL: for Group with assignable_to_role = false

Error: GroupsClient.BaseClient.Delete(): unexpected status 400 with OData error: Request_BadRequest: The group must have at least one owner, hence this owner cannot be removed.

Portal 1

Removing the 2nd Owner from both groups -> SUCCESS: for Group with assignable_to_role = true -> FAIL: for Group with assignable_to_role = false

Error: Failed to remove group owner. The group must have at least one owner.

Below only the group with assignable_to_role = false is tested further

Run 4

Adding a 3rd Owner to group -> SUCCESS: Group exist with SPN, 2nd and 3rd as Owner

Run 5

Removing the 2nd and 3rd Owner from group (-2 Owner in one plan / apply) -> FAIL: Removes one and errors on the 2nd

Error: GroupsClient.BaseClient.Delete(): unexpected status 400 with OData error: Request_BadRequest: The group must have at least one owner, hence this owner cannot be removed.

Portal 2

Removing the 2nd and 3rd Owner from group (-2 Owner selected in the UI) -> SUCCESS: Removes both Owners successfully at once

Important Factoids

Not relevant.

References

manicminer commented 1 month ago

Hi @philmph, thanks for reporting this. I suspect an API bug here since the Portal tends to use the $batch API which we do not support. The API should not be erroring in this case, since the premise is clearly false (it's not the last owner). I am not sure that we work around this in the short term, since we don't support the $batch API and it's unlikely that we will in the near future.

philmph commented 1 month ago

@manicminer Thanks. I've somewhat expected this to be out of scope for the provider.

Do you have a hint where I can raise this issue directly with Microsoft? Happy to follow along there.

manicminer commented 1 month ago

@philmph You could raise an issue at https://github.com/microsoftgraph/msgraph-metadata/issues, this is the most likely place I've found outside of Azure tech support.

philmph commented 1 month ago

@manicminer I've raised the Issue at the suggested repo. I don't think anything further can be done here since this provider depends on the Graph API implementation.

manicminer commented 1 month ago

@philmph Great, thanks.

Thinking about it, I have encountered this same bug in the past and it did go away at one point. At that previous time, it seemed to be related to unified groups - additional validation had just been added to the API for unified groups (not allowed to remove the last user owner) and it was inadvertently affecting security groups. I see that your example config is not creating a unified groups, perhaps the same is happening again.