Skip to content

Calling Azure REST API#

This blog Calling Azure REST API via curl is pretty good. Just two more things.

Auth token in curl#

We can use curl -X GET -u :$token instead of curl -X GET -H "Authorization: Bearer $token"

Azure DevOps API resource id for OAuth#

when using az rest to call Azure DevOps API, you will get a similar error as follows:

Can't derive appropriate Azure AD resource from --url to acquire an access token. If access token is required, use --resource to specify the resource.

This is because Azure DevOps API base url: https://dev.azure.com/ or https://vssps.dev.azure.com/, etc. are not an Azure cloud endpoint.

$ az rest --help
Command
    az rest : Invoke a custom request.
        This command automatically authenticates using the logged-in credential: If Authorization
        header is not set, it attaches header `Authorization: Bearer <token>`, where `<token>` is
        retrieved from AAD. The target resource of the token is derived from --url if --url starts
        with an endpoint from `az cloud show --query endpoints`. You may also use --resource for a
        custom resource.
        If Content-Type header is not set and --body is a valid JSON string, Content-Type header
        will default to application/json.
    Arguments
        [...redacted]
        --resource : Resource url for which CLI should acquire a token from AAD
                     in order to access the service. The token will be placed in
                     the Authorization header. By default, CLI can figure this
                     out based on --url argument, unless you use ones not in the
                     list of "az cloud show --query endpoints".
        [...redacted]
$ az cloud show --query endpoints
{
  "activeDirectory": "https://login.microsoftonline.com",
  "activeDirectoryDataLakeResourceId": "https://datalake.azure.net/",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "activeDirectoryResourceId": "https://management.core.windows.net/",
  "appInsightsResourceId": "https://api.applicationinsights.io",
  "appInsightsTelemetryChannelResourceId": "https://dc.applicationinsights.azure.com/v2/track",
  "attestationResourceId": "https://attest.azure.net",
  "azmirrorStorageAccountResourceId": null,
  "batchResourceId": "https://batch.core.windows.net/",
  "gallery": "https://gallery.azure.com/",
  "logAnalyticsResourceId": "https://api.loganalytics.io",
  "management": "https://management.core.windows.net/",
  "mediaResourceId": "https://rest.media.azure.net",
  "microsoftGraphResourceId": "https://graph.microsoft.com/",
  "ossrdbmsResourceId": "https://ossrdbms-aad.database.windows.net",
  "portal": "https://portal.azure.com",
  "resourceManager": "https://management.azure.com/",
  "sqlManagement": "https://management.core.windows.net:8443/",
  "synapseAnalyticsResourceId": "https://dev.azuresynapse.net",
  "vmImageAliasDoc": "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-compute/quickstart-templates/aliases.json"
}

So we need to find the resource url for Azure DevOps API. Hopefully, we can find it from this github issue, or from the official Azure DevOps doc, we can use 499b84ac-1321-427f-aa17-267ca6975798 as the value of --resource to call az rest:

az rest \
    --resource 499b84ac-1321-427f-aa17-267ca6975798 \
    --url <url>

When running az rest within Azure pipeline, we also need to add the authorization, as the SPN injected by azureSubscription cannot be recognized by Azure DevOps API, it's not a user account. The SPN support is in Azure DevOps road map, and planned to be released in 2023 Q1. I'll update this post once I've tested it.

- task: AzureCLI@2
  displayName: Az rest
  inputs:
    azureSubscription: $(azureResourceServiceConnection)
    scriptType: bash
    scriptLocation: inlineScript
    inlineScript: |
      az rest \
          --headers "Authorization=Bearer $SYSTEM_ACCESSTOKEN" \
          --resource 499b84ac-1321-427f-aa17-267ca6975798 \
          --url <url>
    failOnStandardError: true
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)

Comments