Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to create user entitlement for service principal using full-access PAT of org owner #1071

Open
tdg5 opened this issue Jun 11, 2024 · 3 comments
Labels

Comments

@tdg5
Copy link

tdg5 commented Jun 11, 2024

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform (and Azure DevOps Provider) Version

$ terraform -v
Terraform v1.8.3
on darwin_arm64
+ provider registry.terraform.io/hashicorp/azuread v2.50.0
+ provider registry.terraform.io/hashicorp/azurerm v3.105.0
+ provider registry.terraform.io/microsoft/azuredevops v1.1.1

Affected Resource(s)

  • azuredevops_user_entitlement

Terraform Configuration Files

# providers.tf
terraform {
  required_providers {
    azuread = {
      source  = "hashicorp/azuread"
      version = "~> 2.50.0"
    }

    azuredevops = {
      source  = "microsoft/azuredevops"
      version = "1.1.1"
    }
  }
  required_version = "~> 1.8"
}

provider "azuread" {
  tenant_id = "TENANT_ID"
}

provider "azuredevops" {
  org_service_url = "https://dev.azure.com/MY_URL"
  tenant_id       = "TENANT_ID"
}

# main.tf
data "azuread_service_principal" "this" {
  display_name = "SERVICE_PRINCIPAL"
}

resource "azuredevops_user_entitlement" "this" {
  account_license_type = "basic"
  origin               = "aad"
  origin_id            = data.azuread_service_principal.this.object_id
}

Debug Output

https://gist.github.com/tdg5/30e58f99ab019e04b577755c4e8d3578

Panic Output

Expected Behavior

I should be able to add a user entitlement to a service principal using a full-access PAT belonging to the ADO organization owner.

Actual Behavior

Server side failure :(

Creating user entitlement: Adding user entitlement: (5000) The Id, OriginId, or User.PrincipalName must be set. The Principal Name is usually an email address.

I can add the service principal through the UI and then import the resource, for what it's worth, so it doesn't seem like it's a credential issue.

Steps to Reproduce

  1. Create a new ADO org, or use an existing one.
  2. Authenticate as org owner.
  3. Create a PAT that is granted full access
  4. Make PAT available to terraform
  5. terraform apply
  6. Weep

Important Factoids

This is a vanilla US azure tenant. I've tried this with several ADO orgs and with several service principals, the result is the same.

References

I think @fredgate may have also hit this error and thought it was something else: #444 (comment)

@tdg5 tdg5 changed the title Unable to create user entitlement for service principal using PAT of org owner Unable to create user entitlement for service principal using full-access PAT of org owner Jun 11, 2024
@mnkll
Copy link

mnkll commented Oct 4, 2024

We re also hitting this issue with a managed identity

@ggeorge-pros
Copy link

The azuredevops_user_entitlement will not work for service principals because the REST API endpoint is different for user entitlements and service principal entitlements.

There is, however, a PR to add the resource azuredevops_service_principal_entitlement - #1028.

@bconrad-op
Copy link

While waiting for #1028 to get released, here's a hack for registering an Azure SPN via data.http and adding it to a group (I'm sorry). Check the status of that PR before adding this to your codebase.

locals {
  organization_id = "Acme"
  entitlement_url = "https://vsaex.dev.azure.com/${local.organization_id}/_apis/serviceprincipalentitlements?api-version=7.1-preview.1"
}

data "http" "set_sp_entitlement" {
  url    = local.entitlement_url
  method = "POST"
  request_headers = {
    Authorization = "Basic ${base64encode(":${var.azuredevops_pat}")}"
    Content-Type  = "application/json"
  }

  request_body = jsonencode({
    accessLevel = {
      accountLicenseType = "express"
    },
    servicePrincipal = {
      origin      = "aad", # Specifies that the principal is from Azure AD
      originId    = azuread_service_principal.main.object_id
      subjectKind = "servicePrincipal"
    }
  })

  lifecycle {
    postcondition {
      condition     = contains([200], self.status_code)
      error_message = "Service Principal entitlement grant unsuccessful"
    }
  }
}

# Uncomment this to debug the result
# resource "null_resource" "x" {
#   provisioner "local-exec" {
#     command = "echo ${jsonencode(data.http.set_sp_entitlement.response_body)}"
#   }

#   triggers = {
#     always_run = "${timestamp()}"
#   }
# }

resource "azuredevops_group_membership" "service_principal_reader" {
  group   = data.azuredevops_group.project_reader.descriptor
  members = [jsondecode(data.http.set_sp_entitlement.response_body).servicePrincipalEntitlement.servicePrincipal.descriptor]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants