tfsazure-devopsaclazure-devops-rest-apitfs-security

How to grant a repository read permissions to a certain group in Azure Devops programmatically


I have Azure Devops organization and would like to set readonly permission to a certain group in a list of given repositories.

The following specifies how to do it manually via web console: https://learn.microsoft.com/en-us/azure/devops/organizations/security/set-git-tfvc-repository-permissions?view=azure-devops

How can it be done via Rest API or other programmatic manner?

I found the following to set global permissions: https://jessehouwing.net/azure-devops-git-setting-default-repository-permissions/ and there also seem to be an API to set ACL, but nothing there specifies how I can identify the trustee group or the target repository: https://learn.microsoft.com/en-us/rest/api/azure/devops/graph/groups/list?view=azure-devops-rest-5.1


Solution

  • Using Azure Devops Rest API:

    First, you need to get the identifier of your group. This can be done with Identities api.

    If you have your group unique id:

    GET https://vssps.dev.azure.com/fabrikam/_apis/Identities/{id}?queryMembership=None
    

    Then get the descriptor from the json response .Descriptor.Identifier.

    If you don't have the group id, but have the display name:

    GET https://vssps.dev.azure.com/fabrikam/_apis/Identities?searchFactor=DisplayName&factorValue={display name url encoded}&options=None&queryMembership=None
    

    Then get the descriptor from the json response [0].Descriptor.Identifier.

    Get your repository id and project id (that's much easier than group identifier so I won't elaborate), then you have all the required data. Build you request body:

    { 
       "token":"repoV2/{projectId}/{repoId}/",
       "merge":true,
       "accessControlEntries":[ 
          { 
             "descriptor":"Microsoft.TeamFoundation.Identity;{groupIdentifier}",
             "allow":2,
             "deny":0,
             "extendedInfo":{ 
                "effectiveAllow":2,
                "effectiveDeny":0,
                "inheritedAllow":2,
                "inheritedDeny":0
             }
          }
       ]
    }
    

    and

    POST https://dev.azure.com/fabrikam/_apis/AccessControlEntries/2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87
    

    Note the id in the url is hardcoded because its a constant. But you can also fetch from the response of

    GET https://dev.azure.com/fabrikam/_apis/securitynamespaces