Using Terraform to Manage Azure DevOps Project Permissions

This is the 4th part in the series of the blog posts on managing the Azure DevOps using Terraform. You can find the series index here. In this part, we’ll discuss how to create user entitlements, create groups and manage group membership for Azure DevOps Project all using Terraform. For this, we have to use multiple resources from the Terraform Provider and also use data sources to read information back from the Azure DevOps. There are lots of permutations and combinations possible here. Since its not possible to cover every situation, we’ll discuss only some of them.

Create Azure DevOps User Entitlement

User entitlements generally refer to the privileges assigned to the users when their accounts are created and over their lifecycle in the application. In Azure DevOps, user entitlement refers to associate a user with the identification, license, any extensions, and assign them group memberships. As part of the initial process, we’ll create users, associate them with license and later we’ll add them to the groups. To manage user entitlement we need to use the azuredevops_user_entitlement resource. To define the user, we can use below minimum properties:

  • principal_name – The principal name is the PrincipalName of a graph member from the source provider. Usually, it is the e-mail address of the user
  • account_license_type – This is optional but default licensing type is basic. We would add the user as stakeholder in our case.

The official documentation is a little incorrect as of writing of this code, in the sense that all properties listed are optional.

Below is our code block for the same:

resource "azuredevops_user_entitlement" "tf-user" {
principal_name = "einbenutzer@mohitgoyal.co"
account_license_type = "stakeholder"
}

At this point, you can run terraform validate to verify that syntactically it looks correct.

Create Azure DevOps Groups

We can create Azure DevOps Groups using azuredevops_group resource. We can choose to create empty groups or we can choose to add already existing users or new users created as part of the group membership. Again the documentation specifies all of the properties as optional, which is a little incorrect. With some trials, the only mandatory property seems to be the group name. We will provide below properties to create an empty group:

  • scope – It is a descriptor referencing the scope (collection, project) in which the group should be created.
  • display_name – Name of a new Azure DevOps group that is not backed by an external provider. 
  • description – Optional description for the group

We can use below code to create an empty group:

resource "azuredevops_group" "tf-group" {
scope = azuredevops_project.tf-example.id
display_name = "Tf test group"
description = "This group is created using terraform"
}

Modify Group Membership for Groups

We can choose to modify group membership as part of the inline code in the azuredevops_group resource, but as we discussed previously wherever possible, use a different resource. So we would be using azuredevops_group_membership resource. However, before we add users, we need to tell which group to operate on. So we need to use data source azuredevops_group for this purpose. Below is our code to do the same:

# Partially complete blocks below – will not work in isolation
data "azuredevops_group" "group" {
project_id = azuredevops_project.tf-example.id
name = "Readers"
}
resource "azuredevops_group_membership" "membership" {
group = data.azuredevops_group.group.descriptor
members = [
azuredevops_user_entitlement.tf-user.descriptor
]
}

In above code, first we fetched the group id for the group named “Readers” in the project and then defined the group membership using properties group, and members. Instead of providing a single user, we can also provide a list of users to add.

Alternatively, since we are creating group ‘Tf test group’ using our code only, we can directly refer to it without using data source. So we can use something like below:

# Partially complete blocks below – will not work in isolation
resource "azuredevops_group_membership" "tf-group-membership" {
group = azuredevops_group.tf-group.descriptor
members = [
azuredevops_user_entitlement.tf-user.descriptor
]
mode = "add"
}

View and Apply the changes

Lets combine everything from above so that our code looks like below:

provider "azuredevops" {
version = ">= 0.0.1"
}
resource "azuredevops_project" "tf-example" {
project_name = "tf-example"
description = "Project deployed using Terraform"
version_control = "git"
visibility = "private"
work_item_template = "Agile"
}
resource "azuredevops_user_entitlement" "tf-user" {
principal_name = "einbenutzer@mohitgoyal.co"
account_license_type = "stakeholder"
}
resource "azuredevops_group" "tf-group" {
scope = azuredevops_project.tf-example.id
display_name = "Tf test group"
description = "This group is created using terraform"
}
resource "azuredevops_group_membership" "tf-group-membership" {
group = azuredevops_group.tf-group.descriptor
members = [
azuredevops_user_entitlement.tf-user.descriptor
]
mode = "add"
}

We can run terraform plan now to validate the changes that is going to make:

We can now run terraform apply to apply our changes:

Let’s hop over to Azure DevOps and verify that the required changes are done:

One thought on “Using Terraform to Manage Azure DevOps Project Permissions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s