How to call the Azure Resource Manager REST API from C#

Calling the Azure Resource Manager REST API from C# is pretty straightforward. You just add an access token to the request header. Getting that access token though, especially for the first time, does involve a few steps.

The purpose of this article is to put all the steps in one place in order to show how to write a C# program that makes REST calls to view and create basic Azure infrastructure resources.

Note: There are two deployment models currently available in Azure. The Cloud Services model, and the more recent Azure Resource Manager model, also referred to as ARM. Go here to learn about the differences between the two models: Understanding Resource Manager deployment and classic deployment. This article is all about programming to the ARM model in REST. There is also a managed library available for Azure Resource Manager. I’m picking REST here so I can make some calls which are not in the managed library yet, and also use the same calls from other programming languages.

High Level Steps

Let’s divide the beginning-to-end REST app development process into 7 simple steps:

The first four steps are one-time application setup steps – creating and registering an application with Azure, granting permissions and getting the details you need. There is a great write-up of these steps here: Authenticating a Service Principal with Azure Resource Manager.

1. Create a new Azure Active Directory application. This creates a definition of your app and registers it with Azure.

2. Create a Service Principal. This is an Active Directory “user” which represents an automated application. For a more detailed explanation of what Application and Service Principal objects are, see: Application Objects and Service Principal Objects.

3. Grant the Service Principal permissions (e.g. Contributor) on your subscription. Don’t create “Reader” or you won’t be able to do much, unless that is your intention.

4. Create a credential object for your application, and use that to get the tenant Id for the authentication context. For more information see What is an Azure AD Tenant?

Steps 5 to 7 cover configuring Visual Studio and the basic authentication your app code does. One of these steps: Step 6 – getting an access token, is also partially covered in the aforementioned authenticating a service principal write-up.

5. Install the Active Directory Authentication package in Visual Studio.

6. Get an access token for the app in your C# program.

7. Use the token to authorize a REST call.

Detailed Steps

If you’ve already completed, or are familiar with any of these steps, skips to the ones that interest you.

Pre-requisites

The one-time application setup steps detailed here make use of Azure command line tools. You will need the latest version of Azure PowerShell or CLI. In this case I used Azure PowerShell 1.0+, but both PowerShell and CLI instructions can be found in the Authenticating a Service Principal with Azure Resource Manager link. The best way to install Azure PowerShell (if you ask me, which you didn’t) is to install the Azure module from the PowerShell Gallery.

The basic PowerShell commands to install Azure PowerShell and login to your account are:

Set-ExecutionPolicy RemoteSigned
Install-Module AzureRM
Install-AzureRM
Login-AzureRmAccount

Note: the commands would be different if you use an older (pre-1.0) version of Azure PowerShell.

You will also need Visual Studio. I’ve tested with 2015 Professional.

1. Create a New Azure Active Directory Application

Make sure you’ve selected the Azure subscription you want to use (if you have more than one):

select-azurermsubscription –SubscriptionName

When you register an app give it a display name, a home page (which doesn’t need to exist) and a password, e.g.

$azureAdApplication = New-AzureRmADApplication -DisplayName “my ARM App” -HomePage “https://msftstack.wordpress.com/” -IdentifierUris “https://msftstack.wordpress.com/” -Password “xxxxxxx”

Make a note of $azureAdApplication.ApplicationId – your C# app will use it.

2. Create a Service Principal

Creating an application generates an application ID, which you then use to create the Service Principal:

New-AzureRmADServicePrincipal -ApplicationId $azureAdApplication.ApplicationId

3. Grant the Service Principal permissions

Now grant the permissions your app instance will have. For example, if you assign a role of “Reader”, your app would not be able to delete or create Azure resources. You can find a lost of role definitions to choose from here: RBAC: Built in Roles.

This example assigns basic read-write permissions using the Contributor role:

New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $azureAdApplication.ApplicationId

4. Create a credential object for your application

Get subscription in which role assignment was created. It will be used to get tenant id:

$subscription = Get-AzureRmSubscription –SubscriptionName

$creds = Get-Credential

A prompt will appear. Here you are logging on on behalf of the application, so when it asks for the user name, enter the ApplicationId, and use the password you chose when creating the application.

Now get the tenantId for the authentication context:

Login-AzureRmAccount -Credential $creds -ServicePrincipal -Tenant $subscription.TenantId

You’ll get a list like this back:

Environment : AzureCloud
Account :
TenantId :
SubscriptionId :

The AccountId (AKA ApplicationId) and TenantId, along with your application password, are the values your program will need to authenticate.

5. Install the Active directory authentication package in Visual Studio

The C# app will be creating an AuthenticationContext. For those calls to resolve you need to install the Microsoft.IdentityModel.Clients.ActiveDirectory Nuget package in Visual Studio (reference: http://www.cloudidentity.com/blog/2013/09/12/active-directory-authentication-library-adal-v1-for-net-general-availability/).

The package is available in the NuGet Gallery here: https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/1.0.0

6. Get an access token for the app in your C# program

In your C# code, add an assembly reference for the ActiveDirectory identity model:

using Microsoft.IdentityModel.Clients.ActiveDirectory;

And add a method to get an access token using your tenantId, applicationId and app password:

public string GetAccessToken()
{
    string authContextURL = "https://login.windows.net/" + tenantId;
    var authenticationContext = new AuthenticationContext(authContextURL);
    var credential = new ClientCredential(clientId: , clientSecret: );
    var result = authenticationContext.AcquireToken(resource: "https://management.azure.com/", clientCredential: credential);

    if (result == null)
    {
        throw new InvalidOperationException("Failed to obtain the JWT token");
    }

    string token = result.AccessToken;
    return token;
}


Don’t hardcode these values in a real program. For my demo app I add a setup tab where I can save subscription specific values as application metadata.

7. Use the token to authorize a REST call

Now everything is set to make REST calls defined in the Azure Resource Manager REST API.

For example to do a GET with a call to list resource groups in a subscription your URI would look like this: https://management.azure.com/subscriptions//resourceGroups?api-version=2015-01-01:

Here’s a generic method to do a GET call and return output as a string. Note how the authentication token is added as a header:

private string doGET(string URI, String token)
{
    Uri uri = new Uri(String.Format(URI));

    // Create the request
    var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
    httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token);
    httpWebRequest.ContentType = "application/json";
    httpWebRequest.Method = "GET";

    // Get the response
    HttpWebResponse httpResponse = null;
    try
    {
        httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error from : " + uri + ": " + ex.Message,
                        "HttpWebResponse exception", MessageBoxButton.OK, MessageBoxImage.Error);
        return null;
    }

    string result = null;
    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
    {
        result = streamReader.ReadToEnd();
    }

    return result;
}


or to do a PUT:

private string doPUT(string URI, string body, String token)
{
    Uri uri = new Uri(String.Format(URI));

    // Create the request
    var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
    httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token);
    httpWebRequest.ContentType = "application/json";
    httpWebRequest.Method = "PUT";

    try
    {
        using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
            streamWriter.Write(body);
            streamWriter.Flush();
            streamWriter.Close();
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error setting up stream writer: " + ex.Message,
            "GetRequestStream exception", MessageBoxButton.OK, MessageBoxImage.Error);
    }

    // Get the response
    HttpWebResponse httpResponse = null;
    try
    {
        httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error from : " + uri + ": " + ex.Message,
                        "HttpWebResponse exception", MessageBoxButton.OK, MessageBoxImage.Error);
        return null;
    }

    string result = null;
    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
    {
        result = streamReader.ReadToEnd();
    }
    return result;
}



Putting it all together

To put these concepts together here’s a demo app which makes basic ARM calls. In this example an authentication token is requested every time there’s a GET/PUT/DELETE button push, as the token has a timeout. There are also some arbitrary buttons to build a URI and add the API version. Arbitrary because I happen to be working on Azure Virtual Machine Scale Sets at the moment, so added a button to list them, and will probably add other shortcut buttons as needed: https://github.com/gbowerman/armapp/

armapp

What to do next

Next would be to use JSON deserialization to process the JSON output from REST calls.

Another area I plan to look into is getting an authentication token for other languages like Python.

Advertisements
This entry was posted in Cloud, Computers and Internet and tagged . Bookmark the permalink.

18 Responses to How to call the Azure Resource Manager REST API from C#

  1. Pingback: Azure Resource Manager Authentication with Python | MSFT Stack

  2. Pingback: This week in Azure – January 11, 2016 | This week in Azure

  3. Hi thank you for your post.
    I make a get request to get informations about the virtual machine.
    I can now get information about the VM. But i don’t see any informations about the state of VM: ” Starting , restarting , ready stopped etc…” Can you

  4. gonace says:

    Hi
    I’m trying to follow your guide but GetAuthToken only returns a access token with the Status: WaitingForActivation.

    Can’t understand why.

    • sendmarsh says:

      Hi, were you able to successfully get to step 4.to get the tenant ID? I’ve not seen this error before, so clutching at straws, but I’m wondering if your account is a corporate one or a non-AD account like outlook/live/hotmail etc…

  5. nina qiu says:

    Hi,
    Thank you for your post.
    By exactly following your steps, I can successfully get the token, but failed to call the API with error message: {“The remote server returned an error: (400) Bad Request.”}

    But it’s fine to call anther API:
    https://management.azure.com/subscriptions/subscription-id/resourceGroups/resource-group-name/providers/Microsoft.Compute/virtualmachines?api-version=api-version

    What’s the matter here with get resource groups list API?

    • sendmarsh says:

      Hi, one way you could troubleshoot this is to go to https://resources.azure.com and list the resource groups in your subscription. The nice thing about that site is that it shows you the exact REST call it is making. Compare this rest call with the one in your program byte by byte.

      • ninaq says:

        you are so great, works like a charm.
        The only difference is the api-version, should be 2014-04-01, and why is that?

    • sendmarsh says:

      Hi Nina, thanks! You found a bug in my post. I have edited the article to put the correct API version: 2015-01-01. Different resource providers have different API versions, and in the example I copied the version for the Compute and Network RP, but the latest API version for subscription calls is 2015-01-01.

  6. vidya says:

    Thanks a lot for the post !! i was successfully able to get the access token and call the azure resource manager rest API .

  7. Pingback: Creating an Azure VM Scale Set with the azurerm Python library | MSFT Stack

  8. Pingback: How to add autoscale to an Azure VM scale set | MSFT Stack

  9. abhay says:

    # use this script for first 5 steps
    $name = ”
    $applicationName = ”
    $subscriptionId = “”

    # 1.Sign in to your account.
    Write-Output “BEGIN STEP 1”
    $account = Login-AzureRmAccount

    if ($account -eq $null) {
    throw “You must sign in to continue running this script.”
    }

    Select-AzureRmSubscription -SubscriptionId $subscriptionId

    # 2.Create the Certificate
    Write-Output “BEGIN STEP 2”

    $thumbprint = (New-SelfSignedCertificate -DnsName “$name” -CertStoreLocation Cert:\CurrentUser\My -KeySpec KeyExchange).Thumbprint
    $cert = (Get-ChildItem -Path cert:\CurrentUser\My\$thumbprint)
    mkdir “C:\${name}”
    Export-Certificate -Cert $cert -FilePath “C:\${name}\${name}.cer” -Type CERT
    $password = Read-Host -Prompt “Enter a password for the new .pfx certificate:” -AsSecureString
    if ($password -eq $null) {
    throw “You must enter a password so the .pfx can be created”
    }
    Export-PfxCertificate -Cert $cert -FilePath “C:\${name}\${name}.pfx” -Password $password

    # 3. create an X509Certificate object from your certificate and retrieve the key value.
    Write-Output “BEGIN STEP 3”
    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate(“C:\${name}\${name}.pfx”, $password)
    $keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())

    # 4. Create an application in the directory with key values.
    Write-Output “BEGIN STEP 4”
    $azureAdApplication = New-AzureRmADApplication -DisplayName “${applicationName}” -HomePage “https://${applicationName}” -IdentifierUris “https://${applicationName}” -KeyValue $keyValue -KeyType AsymmetricX509Cert

    # 5.Create a service principal
    Write-Output “BEGIN STEP 5”
    $servicePrincipal= New-AzureRmADServicePrincipal -ApplicationId $azureAdApplication.ApplicationId

    # 6. Grant the Service Principal role
    Write-Output “BEGIN STEP 6”
    New-AzureRmRoleAssignment -RoleDefinitionName Owner -ServicePrincipalName $azureAdApplication.ApplicationId

    Write-Output “Done.”

  10. abhay says:

    This blog is missing very important uri
    string authContextURL = “https://login.windows.net/” + “”;
    use below instead

    string authContextURL = “https://login.windows.net/[tennantid]/oauth2/token”

    struggled for several hrs before figuring this out.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s