How To Get a PAT (Personal Access Token) for Azure DevOps from the az cli

Another long title for a relatively short article.

In case you aren’t aware, the az cli has a great extension for Azure DevOps and supports automatically logging you in to the devops extension when you use az login. Very helpful and simple, no need to manually issue a PAT through the Azure DevOps portal.

Now, what about the scenario when you need a PAT to make a rest call to Azure DevOps? There are some scenarios that the devops az cli extension does not cover (such as queuing a yaml pipeline with parameters).

Here is a quick and easy PowerShell script to get you a PAT:

az login
$azureDevopsResourceId = "499b84ac-1321-427f-aa17-267ca6975798"
$token = az account get-accesstoken resource $azureDevopsResourceId | ConvertFrom-Json
$authValue = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":" + $token.accessToken))
$headers = @{
Authorization = "Basic $authValue";
'X-VSS-ForceMsaPassThrough' = $true
$organization = "myorg"
$pipelineRunUrl = "$organization/_apis/projects"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-RestMethod Uri $pipelineRunUrl Method GET Headers $headers ContentType 'application/json' Verbose

Note that there is not much documentation on using this mechanism with the az cli. I was able to work this out due to my previous experience obtaining an Azure Databricks token using the same command.

This is about as close as I can find to anything official:

How to Queue an Azure DevOps yaml Pipeline with Parameters from PowerShell

Long enough title? It might be longer than the actual article content.

If you need to queue a yaml pipeline in Azure DevOps from a script, you may be tempted to use the az cli and the devops extension. The extension is useful, but has some bugs/gaps I would recommend using it in combination with the Azure DevOps REST API.

This DOES NOT work:

az pipelines run --organization "" `
    --project "project" `
    --name "Pipeline" `
    --open `
    --variables foo=bar --debug

But this rest request does:

Content-Type: application/json
X-VSS-ForceMsaPassThrough: true
Authorization: Basic <PAT>
    "templateParameters": {"foo": "bar"}

Use this PowerShell to create your rest request:

$AzureDevOpsOrganization = "myorg"
$AzureDevOpsProject = "myproject"
$PAT = "<Azure DevOps Personal Access Token>"
$devopsProjectUrl = "$AzureDevOpsOrganization/$AzureDevOpsProject"
$headers = @{
Authorization = "Basic $PAT";
'X-VSS-ForceMsaPassThrough' = $true
$body = @{
templateParameters = @{foo = "bar"}
$json = $body | ConvertTo-Json
$pipelineRunUrl = "$devopsProjectUrl/_apis/pipelines/$pipelineId/runs?api-version=6.0-preview.1"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$pipelineRunResponse = Invoke-RestMethod Uri $pipelineRunUrl `
Method POST Headers $headers ContentType 'application/json' `
Body $json Verbose