Azure Devops assign read permissions for everyone

Azure Devops assign read permissions for everyone header image

Storing your code in a git repository is kind of a no brainer. We internally use a lot of Azure Devops for that, and you can imagine that we have spun up quite some team projects. Yet in some cases those team projects where created a while back. And when attracting new talent, they are onboarded after a project was created. We ended up with the requirement to add new people to team projects and wanted to look at ways to automate that.

Our goal was to add a specific group to the team project readers group so that all our developers at least would have read access to team projects. Making sure they could checkout the project structure, code, and the user stories. We wanted to run a process at a specific time interval, so we picked the Azure Runbook option and used PowerShell to do so.

Azure Devops and scripting

Azure Devops provides a REST API. But only supports an authentication through a personal access token (PAT). So, make sure to get your PAT first. Creating a pat can be done using through the menu. Make sure to use the Custom Defined option and give it Full Access.

Creating a custom PAT

By passing the PAT and your username you can sign each request and only with that info you are able to get or update the information you need. In our script we get all the groups that are available and walk through each option to see if they are of type Readers. For each reader group we add our developers’ group and update the project. Adding a group can only be done using the Group Descriptor, something that took a minute to figure out. You can find the group descriptor

Adding a group can only be done using the Group Descriptor, something that took a minute to figure out. You can find the group descriptor by going to the admin side of things. Use the permissions menu item and search for the group you need. This can be any Azure Group assuming you have the Azure Active Directory synced with your Devops environment.

Search for your group

Once you open the group you can find the group descriptor in the URL and use that in the script.

Find the Group Descriptor in the URL

Once you have the Group Descriptor and the PAT you can construct all the REST calls. You will need some logic to process larger data sets, but that is what the continuationToken is for. You can use the following snippet to add your Azure AD group with defined descriptor to the readers group of each Azure Devops Team Project.

Param(
   [string]$user = "tbd",
   [string]$token = "tbd",
   [string]$domain = "digiwijs",
   [string]$groupDescriptor = "aadgp.Uy0xLTktMTU1MTM3NDI0NS0xMjA0NDAwOTY5LTI0MDI5ODY0MTMtMjE3OTQwODYxNi0zLTMwODgzMjQ0MTUtMTQwOTgxNzE1OS0yNjgxNDEwMTYxLTMxNTkxMTE5NjQ",
)

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$allGroupsRequest = "https://$domain.vssps.visualstudio.com/_apis/graph/groups?api-version=4.1-preview.1";
$lastToken = "";

function UpdateTeamProjects {

    Param(
        [Parameter(Mandatory=$false)]
        [string]$continuationToken
    )

    if($continuationToken){
        $allGroupsRequest = "https://$domain.vssps.visualstudio.com/_apis/graph/groups?continuationToken="+$continuationToken+"&api-version=4.1-preview.1"
    }

    $groupsWebRequest = Invoke-WebRequest -Uri $allGroupsRequest -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -UseBasicParsing
    $groupsResult = ConvertFrom-Json $groupsWebRequest.Content

    if ($groupsResult.count -eq 0)
    {
         throw "Unable to get groups, or no groups have been found";
    }
    else {
        foreach($groupResult in $groupsResult.value){
            if($groupResult.principalName -LIKE "*\Readers"){
                Write-Host "Updating group:" $groupResult.principalName;

                $url = "https://$domain.vssps.visualstudio.com/_apis/graph/memberships/"+$groupDescriptor+"/"+$groupResult.descriptor+"?api-version=4.1-preview.1"
                $groupAddedRequest = Invoke-RestMethod -Uri $url -Method Put -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -UseBasicParsing
        }

        # Process remaining projects
        if($groupsWebRequest.Headers.ContainsKey("X-MS-ContinuationToken")){
            $token = $groupsWebRequest.Headers["X-MS-ContinuationToken"]
            if($token -ne $lastToken) {
                $lastToken = $token;

                Write-Host "New continuationToken found, move to next batch";

                UpdateTeamProjects -continuationToken $token
            }
        }
    }
 }
}

UpdateTeamProjects;
Loading comments…