0
votes

I'm trying to get the status of agents in a deployment pool at release time. The use case is I have 2 servers with shared disk, I want the release to run on one server only. I have two Deployment groups that run based on a custom condition:

eq(variables['DeployGroupSelector'], '1')

With a job that runs prior to those that will determine the value of the DeployGroupSelector var, essentially a case statement.

In the job that sets the var, I'm trying to reach out to the Azure DevOps REST API:

$headers = @{
    Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}

$url = "https://dev.azure.com/$($organization)/_apis/distributedtask/pools/$($poolId)/agents?api-version=5.1"
$response = Invoke-RestMethod $url -Headers $headers -Verbose
write-host "Output: $response"
$status = ($response.value | where {$_.name -eq $($env:primaryPoolName)}).status
if($status -eq "online")
{
    Write-Output("##vso[task.setvariable variable=DeployGroupSelector;]1")
}
else
{
    Write-Output("##vso[task.setvariable variable=DeployGroupSelector;]2")
}

For the group containing the script above the "Allow scripts access to the OAuth token" box is checked.

When I run this powershell locally using a PAT it returns data. When I run the release in ADO, it hits the service, but returns an empty data set:

2019-10-07T14:16:18.8942915Z VERBOSE: GET https://dev.azure.com/xxxxxx/_apis/distributedtask/pools/13/agents?api-version=5.1 with 0-byte payload
2019-10-07T14:16:19.3235204Z VERBOSE: received 22-byte response of content type application/json
2019-10-07T14:16:19.9626359Z VERBOSE: Content encoding: utf-8
2019-10-07T14:16:19.9835101Z Output: @{count=0; value=System.Object[]}

I have tried giving the "Project Collection Build Service Accounts" group read access to pools and groups, I even tried bumping it up to user. I tried adding the build service accounts group to release administrators. I even tried using the old url format just in case.

Added picture of data returned from powershell:

enter image description here

UPDATE: Just to further rule out an issue with how I was using the token, I added a second powershell task to the task group in question. This script hits a different segment of the AzDO Rest API (below). This successfully gets a response. So the OAuth token is working, it just doesn't seem to have access to the entire API.

$headers = @{ Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }

$url = "https://dev.azure.com/$($organization)/$($project)/_apis/git/repositories?api-version=5.1"
$response = Invoke-RestMethod $url -Headers $headers -Verbose
write-host "Output: $($response)"

Response: Output: @{value=System.Object[]; count=10}

2
From where you get the $pooId?Shayki Abramczyk
I went to the Deployment Pools in the UI, selected the pool, and got the ID from the URI. It can also be queried through the rest api.Justin Holbrook
I asked because there are also agents queues with different id and the api its for agent pools. I can not reproduce your issue, in my release I got the agents in the response.Shayki Abramczyk
Can you upload here a screenshot of your PowerShell script results with the same URL the release executed?Shayki Abramczyk
Added picture..Justin Holbrook

2 Answers

0
votes

Since you're using the System_AccessToken variable, did you also enable the "Allow scripts to access OAuth token" checkbox in the agent job? https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=classic#systemaccesstoken This link shows where it is in build but you'll find it at the bottom of the Agent Job panel in release. If that's not checked, that may be why you're getting an empty response.

enter image description here

0
votes

Had exactly the same issue. Were considered two options, the same as you have been trying.

  1. System.AccessToken
  2. PAT

Problem was solved by putting PAT into a KeyVault and using it as a basic auth token for REST API call in a pipeline.

My suggestion is that it seems expected and right behavior. Why do I think so? From Azure DevOps point of view there are two levels in our case Organization's level and Project's level. You can notice the difference by URI that were used:

$url = "https://dev.azure.com/$($organization)/_apis/distributedtask/pools/$($poolId)/agents?api-version=5.1"

$url = "https://dev.azure.com/$($organization)/$($project)/_apis/git/repositories?api-version=5.1

From security point of view it's a bad practice, let entities from lower layers, which is project in our case, access and manipulate on the higher layer, which is organization in our case.

As a conclusion I would say that SystemToken and PAT in essence have slightly different nature, one is devoted for agent, and another for one's personal profile.