microsoft / terraform-provider-azuredevops

Terraform Azure DevOps provider
https://www.terraform.io/docs/providers/azuredevops/
MIT License
387 stars 278 forks source link

Way to get [TEAM FOUNDATION] group Ids for use in places requiring azdo id like securityrole_assignment or support descriptors #1106

Open drdamour opened 4 months ago

drdamour commented 4 months ago

Community Note

Description

not sure how this should be implemented...but certain things like Service Connection Auth Roles required an Id and NOT a descriptor for defining permissions. so when leveraging https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/resources/securityrole_assignment we cannot use any of the azdo provider's resources or data to use those [TEAM FOUNDATION] groups as their origin_id is the Entra ID guid which isn't recognized by AzDO, and their descriptor can't be used you get an error like

expected "identity_id" to be a valid UUID, got vssgp.Uy0xLTktMTU...

i think i read somewhere AzDO services are being moved to take descriptor or id's for most things, but seems like security role assignment still uses id's. For AzDO groups the origin_id works, but for [TEAM FOUNDATION] this wont' work.

There is the https://learn.microsoft.com/en-us/rest/api/azure/devops/ims/identities/read-identities?view=azure-devops-rest-7.1&tabs=HTTP service which turns descriptors into Ids maybe what this is asking for is a datasource for that service?

it'd be nice if this just happened automatically for https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/data-sources/group and https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/data-sources/groups i know id is already returning descriptor for those...so it'd be backwards breaking change, but maybe it could added as legacy_id there and similarily for https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs/resources/group

as it stands AFAIK my only workaround is to create an AzDO "wrapper" group that has the [TEAM FOUNDATION] group added as a member, and use the origin_id of the wrapper group for security permissions

New or Affected Resource(s)

Potential Terraform Configuration

if legacy_id was added to azuredevops_group

resource "azuredevops_group" "entra_group" {
  origin_id = "object id guid of Entra ID group"
}

resource "azuredevops_securityrole_assignment" "grant_secret_rotation_to_principal" {
  # value sniffed following https://bw861987.medium.com/azure-devops-terraform-change-serviceconnection-and-environment-permissions-for-a-project-a0d59bfa2da1
  # saw it as "distributedtask.collection.serviceendpointrole" in the url
  # but it keeps coming back in the body as "distributedtask.serviceendpointrole" so guessing AzDO made a synonym for it or something...going with this since it works
  scope       = "distributedtask.serviceendpointrole"
  resource_id = "collection_${var.service_connection.id}"
  identity_id = azuredevops_group.entra_group.legacy_id
  # i wish there was a more granular role that was just secret rotation...but there is not so we'll give em admin
  role_name   = "Administrator"
}

if data.azuredevops_identities was added

resource "azuredevops_group" "entra_group" {
  origin_id = "object id guid of Entra ID group"
}

data "azuredevops_identities" "groups" {
  descriptors = [
    azuredevops_group.entra_group.descriptor
  ]
  ignore_missing = false
}

resource "azuredevops_securityrole_assignment" "grant_secret_rotation_to_principal" {
  # value sniffed following https://bw861987.medium.com/azure-devops-terraform-change-serviceconnection-and-environment-permissions-for-a-project-a0d59bfa2da1
  # saw it as "distributedtask.collection.serviceendpointrole" in the url
  # but it keeps coming back in the body as "distributedtask.serviceendpointrole" so guessing AzDO made a synonym for it or something...going with this since it works
  scope       = "distributedtask.serviceendpointrole"
  resource_id = "collection_${var.service_connection.id}"
  identity_id = data.azuredevops_identities.groups.by_descriptor[azuredevops_group.entra_group.descriptor].id
  # i wish there was a more granular role that was just secret rotation...but there is not so we'll give em admin
  role_name   = "Administrator"
}

References