Question:
I am trying to update permissions for a pipeline in Azure DevOps using the REST API, but although I get a 204 No Content response, the permissions are not actually being applied or updated.
What I'm Doing: I'm using the Azure DevOps REST API to update the Access Control Entries (ACL) for a specific pipeline. Below is the POST request payload I am using:
`permissions_payload = {
"value": [
{
"inheritPermissions": False,
"token": "vstfs:///Classification/TeamProject/{project_id}/{pipeline_id}",
"acesDictionary": {
"Microsoft.TeamFoundation.Identity;S-1-9-1551374245-1204400969-2402986413-2179408616-0-0-0-0-1": {
"descriptor": "Microsoft.TeamFoundation.Identity;S-1-9-1551374245-1204400969-2402986413-2179408616-0-0-0-0-1",
"principalName": "[{project_name}]\\Contributors",
"allow": 0,
"deny": 1
}
}
}
]
}
# POST request
response = requests.post(
permission_url,
headers=headers,
json=permissions_payload,
verify=False
)
if response.status_code == 200 or response.status_code == 204:
print("Permissions updated successfully.")
else:
print(f"Failed to update permissions: {response.status_code}")`
Response: I receive a 204 No Content, indicating the request was successful. However, when I check the pipeline's security settings via the Azure DevOps UI, the permissions are not updated.
Steps I've Tried: Checked the descriptor: I'm using the correct descriptor for the "Contributors" group retrieved from the Graph API. Verified the token: The token I'm using follows the format: vstfs:///Classification/TeamProject/{project_id}/{pipeline_id} Tried both inheritPermissions: True and inheritPermissions: False, but the outcome is the same.
My Goal: I want to deny certain permissions for the "Contributors" group on a specific pipeline, but nothing seems to work despite receiving a successful response from the API.
Based on your description, you need to use Rest API to update the Pipeline permissions.
To meet your requirement, you can use the Rest API: Access Control Entries - Set Access Control Entries
Update Pipeline permission SecurityNamespaceId : 33344d9c-fc72-4d6f-aba5-fa317101a7e9
POST https://dev.azure.com/{organization}/_apis/accesscontrolentries/33344d9c-fc72-4d6f-aba5-fa317101a7e9?api-version=6.0
Request Body:
{
"token":"{ProjectID}/{PipelineID}",
"merge":true,
"accessControlEntries":[{
"descriptor":"Microsoft.TeamFoundation.Identity;S-1-9-1551374245-491114055-2098815309-2189422963-3385397751-1-479303010-554652490-2991085287-3350433821",
"allow":16384,
"deny":16
}]
}
To get the descriptor ID, you can use the Rest API: Identities - Read Identities
GET https://vssps.dev.azure.com/fabrikam/_apis/identities?searchFilter=General&filterValue=[{project_name}]\Contributors&queryMembership=None&api-version=7.0
Python Script sample:
import requests
import json
url = "https://dev.azure.com/{orgname}/_apis/accesscontrolentries/33344d9c-fc72-4d6f-aba5-fa317101a7e9?api-version=6.0"
payload = json.dumps({
"token": "{ProjectID}/{PipelineID}",
"merge": True,
"accessControlEntries": [
{
"descriptor": "Microsoft.TeamFoundation.Identity;S-1-9-1551374245-491114055-2098815309-2189422963-3385397751-1-479303010-554652490-2991085287-3350433821",
"allow": 16384,
"deny": 16
}
]
})
headers = {
'Content-Type': 'application/json',
'Authorization': 'Basic {Base64PAT}'
}
response = requests.request("POST", url, headers=headers, data=payload)
if response.status_code == 200 or response.status_code == 204:
print("Permissions updated successfully.")
else:
print(f"Failed to update permissions: {response.status_code}")
print(response.text)
Permission value list:
Administer build permissions: 16384
Delete build pipeline: 4096
Delete builds: 8
Destroy builds: 32
Edit build pipeline: 2048
Edit build quality: 2
Edit queue build configuration: 65536
Manage build qualities: 16
Manage build queue: 256
Override check-in validation by build: 8192
Queue builds: 128
Retain indefinitely: 4
Stop builds: 512
Update build information: 64
View build pipeline: 1024
View builds: 1
If you need to deny multiple permissions, you can plus related numbers.
For example: deny View builds and View build pipeline permission: 1 + 1024 = 1025
{
.....
"accessControlEntries":[{
"descriptor":"Microsoft.TeamFoundation.Identity;S-1-9-1551374245-491114055-2098815309-2189422963-3385397751-1-479303010-554652490-2991085287-3350433821",
"allow":0,
"deny":1025
}]
}
Result:
Update:
If you need to keep using the Rest API and Request body shared in Question: Access Control Lists - Set Access Control Lists, you need to change the token value:
From:
"token": "vstfs:///Classification/TeamProject/{project_id}/{pipeline_id}",
To:
"token": "{project_id}/{pipeline_id}",
In this case, it will work as expected too.