I tried this end-to-end approach in my test environment, which I succeeded in. Using a pipeline strategy, the agenda is to assign managed delivery plan
across projects under the org. To assign this permission to all the projects in a single attempt, the UI approach will not work because it does not have much feature yet. However, we can do this by using REST API's
make sure the personal access token needs to create and grant the appropriate permissions like Graph > Read
Project and Team > Read
Token Administration > Read & Manage Permissions
To assign security roles, you also need:
Security > Manage permissions
or oken Administration > Manage
Then directly define the YAML pipeline:
delivery-plan-access.yml
trigger: none
pool:
vmImage: ubuntu-latest
variables:
organization: 'XXX-XXX-Organization'
userEmail: '******@XXX.com'
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$organization = '$(organization)'
$myEmail = '$(userEmail)'
$pat = "$(System.AccessToken)"
if (-not $pat) {
exit 1
}
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$headers = @{ Authorization = "Basic $base64AuthInfo" }
Write-Host "Retrieving all projects for organization '$organization'..."
$projectsUrl = "https://dev.azure.com/$organization/_apis/projects?api-version=7.0"
$projectsResponse = Invoke-RestMethod -Uri $projectsUrl -Headers $headers
$projects = $projectsResponse.value
Write-Host "Total projects found: $($projects.Count)"
Write-Host "Retrieving descriptor for user '$myEmail'..."
$graphUrl = "https://vssps.dev.azure.com/$organization/_apis/graph/users?api-version=7.1-preview.1"
$response = Invoke-RestMethod -Uri $graphUrl -Headers $headers
$userEntry = $response.value | Where-Object { $_.principalName -eq $myEmail }
if (-not $userEntry) {
Write-Host "##vso[task.logissue type=error]Descriptor not found for user: $myEmail"
exit 1
}
$userDescriptor = $userEntry.descriptor
Write-Host "Descriptor found: $userDescriptor"
$securityNamespaceId = "52d39943-cb85-4d7f-8fa8-c6baac873819"
foreach ($project in $projects) {
Write-Host "Applying permission to project: $($project.name)"
$token = "Project/$($project.id)"
$aclUrl = "https://dev.azure.com/$organization/_apis/accesscontrolentries/$securityNamespaceId?api-version=7.0"
$ace = @{
descriptor = $userDescriptor
allow = 1
deny = 0
}
$accessControlEntry = @{
token = $token
accessControlEntries = @($ace)
}
$body = @{
accessControlEntries = @($accessControlEntry)
} | ConvertTo-Json -Depth 5
try {
$result = Invoke-RestMethod -Uri $aclUrl -Headers $headers -Method Patch -ContentType "application/json" -Body $body
Write-Host "Permission applied successfully to project: $($project.name)"
} catch {
$statusCode = $_.Exception.Response.StatusCode.value__
$responseBody = ""
try {
$responseBody = (New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())).ReadToEnd()
} catch {
$responseBody = "Failed to read error response."
}
Write-Host "Failed to apply permission to project: $($project.name)"
Write-Host "Status Code: $statusCode"
Write-Host "Response Body: $responseBody"
}
}
Write-Host "Permission assignment process completed."
env:
System.AccessToken: $(System.AccessToken)
Later, create a new pipeline along with the existing yml file delivery-plan-access.yml then store your token under variables by naming it System. AccessToken because System. AccessToken is a special OAuth token automatically provided by Azure Pipelines. Add your token value and then save and run the pipeline.
Here is the output:
I have created three test projects under the same org after the pipeline executed the managed delivery plan
has allowed successful entry into three projects at a single attempt.
Here is the output for the permissions status:
I hope this has been helpful!
If above is unclear and/or you are unsure about something add a comment below.
Please click the answer as original posters help the community find answers faster by identifying the correct answer.