Using Postman with Azure Resource Manager API - Commercial and Government

Cloud resources are provisioned and managed in Azure using the Azure Resource Manager, which is really an API that you can access using HTTP requests. There are a number of front-end tools that can be used to interact with this API such as the Azure Portal, AzureRM PowerShell modules, or the Azure CLI. These are all great tools, but there are times when they don't quite give you access to the information you need or the ability to manipulate the settings that you want. In such cases, the API is the authoritative source of truth and the lowest level of access to settings.

For commercial Azure you can use the https://resources.azure.com site for an API level access to your resources, but this service is not available for Azure Government. There is also a command line tool ARMClient, which is an unofficial tool that takes care of authentication and provides you low level access to the API.

If you are a developer and you are used to debugging and querying APIs with Postman, you will probably want to continue using Postman for low level API access. Similarly, you may have a preference for Fiddler. In this blog post, I will discuss how you can authenticate and get a bearer token to pass on to the Azure Resource Manager API using a tool for API querying and debugging. I will use Postman as an example, since it is what I normally use.

There are a few examples (here and here) on how to obtain a bearer token using PowerShell. They all obtain a token for accessing Azure Commercial. With some inspiration from those examples and the ARMClient source code. I have made a PowerShell function that should allow you to obtain a token from any of the Azure clouds (commercial, Government, or sovereign):

[ps]
function Get-AzureBearerToken {
param(
[Parameter(Mandatory = $false)]
[ValidateSet("AzureCloud", "AzureUsGovernment", "AzureGermanCloud", "AzureChinaCloud")]
[String]$Environment = "AzureCloud"
)

# Inspiration for this function from:
# - ArmClient: https://github.com/projectkudu/ARMClient
# - https://www.deployazure.com/security/identity/authenticating-to-the-azure-resource-manager-api/
# - https://www.bizbert.com/bizbert/2015/07/08/SettingUpPostManToCallTheAzureManagementAPIs.aspx
# - https://gallery.technet.microsoft.com/Get-Azure-AD-Bearer-Token-37f3be03

$azcontext = Get-AzureRmContext
if ([string]::IsNullOrEmpty($azcontext.Account) -or
!($azcontext.Environment.Name -eq $Environment)) {
$azcontext = Login-AzureRmAccount -Environment $Environment
}
$azcontext = Get-AzureRmContext
$azenvironment = Get-AzureRmEnvironment -Name $azcontext.Environment

# Load ADAL Assemblies
$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"
$ignore = [System.Reflection.Assembly]::LoadFrom($adal)
$ignore = [System.Reflection.Assembly]::LoadFrom($adalforms)

$adTenant = $azcontext.Tenant.Id

$authority = $azenvironment.ActiveDirectoryAuthority + $adTenant
$resourceAppIdURI = $azenvironment.ResourceManagerUrl

# ClientId and Redirect URL
# Can be found in ArmClient code or with AzureAD:
# PS> Connect-AzureAD
# PS> $sp = Get-AzureADServicePrincipal -SearchString "Microsoft Azure PowerShell"
# PS> $sp.AppId
# 1950a258-227b-4e31-a9cf-717495945fc2
# PS> $sp.ReplyUrls
# urn:ietf:wg:oauth:2.0:oob

$clientId = "1950a258-227b-4e31-a9cf-717495945fc2"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"

# Create Authentication Context tied to Azure AD Tenant
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority

# Acquire token
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $redirectUri, "Auto")

# Create Authorization Header
$authHeader = $authResult.CreateAuthorizationHeader()

#Remove "Bearer " and return token
$token = $authHeader.Substring(7)

return @{
'managementUrl' = $azenvironment.ResourceManagerUrl
'bearerToken' = $token
'tenantId' = $adTenant
}
}
[/ps]

It is included in my HansenAzurePS PowerShell module (as of version 0.4). You can find the code for the entire module on GitHub. It is easy to install with:

[ps]
Install-Module HansenAzurePS
[/ps]

After installing the module, you can get a token for say AzureUSGovernment cloud with:

[ps]
$tk = $(Get-AzureBearerToken -Environment AzureUSGovernment)
[/ps]

To copy the bearer token to the clipboard:

[ps]
$tk.bearerToken | Set-Clipboard
[/ps]

Now that you have the token in the clipboard, it is pretty straight forward to use in a tool such as Postman:

Notice that I am accessing the Azure Government API. The Get-AzureBearerToken function will actually return this URL as well:

[ps]
$tk.managementUrl
https://management.usgovcloudapi.net/
[/ps]

Also notice that I have selected "Bearer Token" as authentication and I have simply pasted in the value returned by the Get-AzureBearerToken function. Finally notice that I get a list of the subscriptions back (there is only one in this instance).

As an more complex scenario, suppose that we would like to enable Azure AD Easy Authentication, and at the same time, we want to make sure that the application can use the Graph API. I have discussed this scenario in a previous blog post, where I also provide some instructions to do it. In this scenario, it is necessary to set the additionalLoginParams to be:

[js]
"additionalLoginParams": [
"resource=https://graph.microsoft.com"
]
[/js]

But there is no way to do this in the portal and https://resources.azure.com does not work for Azure Government. Consequently, we need to interact with the API more directly. There are many ways to do this, and I have described a few of them before, but interacting directly with the API using Postman is certainly as good as any of the other methods. To set the easy authentication setting, we need:

[plain]
PUT https://management.usgovcloudapi.net/subscriptions/SUBSCRIPTION ID/resourceGroups/RGNAME/providers/Microsoft.Web/sites/WEBAPP-NAME/config/authsettings?api-version=2016-08-01
[/plain]

with the payload:

[js]
{
"id": "/subscriptions/SUBSCRIPTION-ID/resourceGroups/RGNAME/providers/Microsoft.Web/sites/WEBAPP-NAME/config/authsettings",
"name": "authsettings",
"type": "Microsoft.Web/sites/config",
"location": "USGov Virginia",
"properties": {
"enabled": true,
"unauthenticatedClientAction": "RedirectToLoginPage",
"tokenStoreEnabled": true,
"allowedExternalRedirectUrls": null,
"defaultProvider": "AzureActiveDirectory",
"clientId": "90b54944-13f8-4baa-8005-XXXXXXXXXX",
"clientSecret": "D5jXXXXXXXXXXg/2Rw==",
"issuer": "https://login.microsoftonline.com/TENANT-ID/",
"allowedAudiences": null,
"additionalLoginParams": [
"resource=https://graph.microsoft.com"
],
"isAadAutoProvisioned": false,
"googleClientId": null,
"googleClientSecret": null,
"googleOAuthScopes": null,
"facebookAppId": null,
"facebookAppSecret": null,
"facebookOAuthScopes": null,
"twitterConsumerKey": null,
"twitterConsumerSecret": null,
"microsoftAccountClientId": null,
"microsoftAccountClientSecret": null,
"microsoftAccountOAuthScopes": null
}
}
[/js]

You will have to make some adjustments for your particular scenario. After this modification, your Web App should be asking for credentials and if your code is written accordingly, you will be able to query the Graph API. Again, I have discussed this scenario here, where you can find links to some application code.

And that's it. You should now be able to obtain a bearer token to access the Azure Resource Manager API from tools such as Postman. Let me know if you have questions/comments/suggestions.