April 2015

Volume 30 Number 4


Microsoft Azure - Automate Creating, Developing and Deploying Azure Websites

By Gyan Jadal

Microsoft Azure is a quick and easy way to create and deploy Web sites or APIs for your cloud consumers. Much has been written on different aspects of Azure Websites, including security, deployment and so on. It’s always a challenge to bring this information into a real-life implementation. In this article, I’ve pulled together these various facets to help you quickly create a production-ready Azure Website. I’ll walk you through the end-to-end lifecycle of creating, deploying, configuring and monitoring an Azure Website.

I’ll start by creating a Web site with Visual Studio 2013 and deploy it to Azure. Then I’ll set up continuous integration from my source code repository to Azure, establishing authentication using the API key or certificates. Finally, I’ll show how to create and deploy the site to a production environment using Windows PowerShell.

Create an Azure Web Site

This is the simplest step of the whole process. I’ll create an Azure Website and add a controller, skipping the business logic inside it to illustrate the key points. To start, I need the Windows Azure SDK for .NET 2.5, which can be downloaded from bit.ly/1GlhJpu.

Using Visual Studio 2013, I’ll create a new ASP.NET Web application by choosing empty template. You can select WebAPI if you want to expose an interface using the same Web site. I select the AppInsights and Hosted in Azure checkboxes. I don’t choose any Authentication for now because I’ll add it later. I’ll also configure Application Insights for deploying to different environments.

When it prompts for Azure Website details, as shown in Figure 1, I enter the Site name, select a Region and click OK.

This will set up an empty Web site and publish it to Azure. Now, I’ll add some content to the site and use the Open Web Interface for .NET (OWIN) as the middleware. To enable OWIN, I add the following NugGet Packages: Microsoft.Owin.Host.SystemWeb and Microsoft.AspNet.WebApi.Owin.

Configure Microsoft Azure Website Details
Figure 1 Configure Microsoft Azure Website Details

After installing the NuGet packages, I right-click on the Project and select Add OWIN startup class. I’ll name the class Startup and add the following code to the Configuration method, which sets up the controller routing:

public void Configuration(IAppBuilder app) {
  var config = new HttpConfiguration();
  config.Routes.MapHttpRoute("default", "{controller}/{id}",
    new { id = RouteParameter.Optional});
  app.UseWebApi(config);
}

Next, I’ll add a controller to provide an API by right-clicking the Project and clicking Add Web API Controller class. I’ll name the class MyWebController and leave the generated code alone. Next, I right-click the Project and Publish. In the publish dialog under the Settings tab, I choose the Debug configuration so the site can be debugged remotely. Then I click Next and Publish.

When I navigate to my Azure Website, the controller Get method is invoked by default, which returns a JSON string as [“value1”,“value2”]. My Web site is up and running on Azure. So far, so good.

Now, I’ll add a Client application to invoke the Web site API I just exposed on the cloud. I create a new Console application called MyConsoleClient and add the ASP.NET Web API 2.2 Cient Libraries NuGet Package. This package provides the HttpClient object I’ll use to invoke the API. The following code is added to the main method:

var httpClient = new HttpClient();
var requestMineType = 
  new MediaTypeWithQualityHeaderValue("application/json");
httpClient.DefaultRequestHeaders.Accept.Add(requestMineType);
var httpResponse =
  httpClient.GetAsync(
  "https://MyAzureWebsiteSample.azurewebsites.net/MyWeb").Result;
Console.WriteLine(httpResponse.Content.ReadAsStringAsync().Result);
Console.ReadLine();

Now I’ll run the client and see how the controller Get method is invoked and the [“value1”,“value2”] is printed on the console. I published Debug configuration for my Web site. Although you can debug the site locally, sometimes it’s helpful to remotely debug the published Web site while it’s still in development. To debug the published site, I go to its Configure tab on the portal and turn on remote debugging, selecting the version of Visual Studio being used (see Figure 2).

Enabling Remote Debugging for Microsoft Azure Websites
Figure 2 Enabling Remote Debugging for Microsoft Azure Websites

To debug the Web site remotely and debug my console client, I put a break on the GetAsync line. Next, I open Server Explorer, right-click the Web site and select Attach Debugger, as shown in Figure 3.

Attach Debugger to the Published Web site
Figure 3 Attach Debugger to the Published Web site

Now I can step into the code and debug the site remotely from my machine and commit my changes to the source repository.

Set up Continuous Integration

Now I’ll work through integrating my site with the Source Repository for Continuous Integration (CI). How cool it would be that, when you check in code to your repository, the Web site project is built and automatically deployed to Azure? The Integrate Source Control feature of Azure Websites gives you an easy way to link your source repository to the Azure Website for continuous integration. On the Azure portal, I navigate to the home tab of the Web site and click on Set up deployment from source control, as shown in Figure 4.

Set up Deployment from Source Control
Figure 4 Set up Deployment from Source Control

Depending on what you’re using as your source control provider, you have options to choose from Visual Studio Online, local Git repository, GitHub and so on. As my code is in the Visual Studio Online repository, I choose it on the next screen. Next, I enter my Visual Studio Online account name and authorize my account. I have to provide consent to allow the connection request from Azure to my Visual Studio Online account. Then I choose the Repository name, which is my team project name. After I click Next, the link is established between my Azure Website and Visual Studio Online team project.

In the Builds option in Team Explorer in Visual Studio, I should now see the build definition created for me as MyAzureWebsite­Sample_CD so I can right-click and edit the definition. The queue processing is disabled by default on the general tab, so I’ll set it to Enabled. In the process parameters under Build/Projects, I browse and select the solution to build.

At this point, I’ll make any other changes to the process parameters in the Process tab. While on the Process tab, take a look at the Deployment parameter. This is where integration is set up for the build definition to the Azure service. If you have multiple projects in the repository, the first Web site as alphabetically ordered will be deployed. To avoid this, ensure you have a separate solution for each Web site for which you have CI enabled. Check in your code or right-click and queue a build. You should see the Web site being built and published to Azure.

You can verify whether continuous integration is working by clicking on the Deployments tab of the Web site, as shown in Figure 5. Here, you’ll see the last time a successful deployment took place from the CI build.

Deployment History with Continuous Integration
Figure 5 Deployment History with Continuous Integration

Configure Authentication

The Azure Website is now ready for development, adding business functionality and reaping the benefits of CI. You’ll want to set up authentication for the site so you can authenticate and authorize consumers. There are different scenarios for this setup, details of which you’ll find at bit.ly/1CHVni3.

Before I set up my Azure Website for authentication, I’ll add Authorize attribute to my controller and publish the site. Running the client to access the site will return the following message:

{"Message": "Authorization has been denied for this request."}

Here, I’ll enable authentication on my Azure Website and update the console client to provide either the API key or certificate credentials for authentication. Authentication and token generation is delegated to Azure Active Directory (AAD). Figure 6 shows the authentication workflow between the client, AAD and the service.

Azure Active Directory Authentication Workflow
Figure 6 Azure Active Directory Authentication Workflow

For AAD Authentication, both the client and Web site should have corresponding application entries registered on AAD. To do this, I navigate to the Active Directory tab on the portal and select the org. directory and click Applications. Next, I select Add an application/Add an application my org. is developing, and enter the name of the Website.

In my case, I enter MyAzureWebsiteSample, then select the Web application or Web API option and click Next. On the next screen, I enter the address to open my site at MyAzureWebsiteSample.azurewebsites.net for the Sign on URL and [mydomain].onmicrosoft.com/MyAzureWebsiteSample as the App ID URI and click OK. This will create an AAD application for the Web site. Next, I add the Client application entry to the AAD, repeating the same steps. For the Sign on URL and App ID URI, I enter http://myconsoleclient.

Because this is a client app, it doesn’t have to be a physical URL; a valid URI is sufficient. Now I want to let the client access the MyAzureWebsiteSample application once it has been authenticated. For this, on the Configure tab, in the Permissions to other applications section, I click Add Application, which will open a pop-up window. I select Show Other and search for MyAzureWebsiteSample, then select it and click OK. Back on the Configure tab, in Delegated Permissions is a permission to access MyAzureWebsiteSample (see Figure 7). I check it and then click Add application.

Setting Permissions on Client Application to Access the Azure Website in Azure Active Directory
Figure 7 Setting Permissions on Client Application to Access the Azure Website in Azure Active Directory

Also, I’ll note the ClientId for the Client application entry because I’ll need it soon. If you want to use API Key for authentication, then a key would be created on this configuration page. Because I’m using certificate authentication, I need to associate my certificate with the Client application entry in AAD. To do this, I’ll use the Azure AD Module for Windows PowerShell to automate the process. You can download this at bit.ly/1D4gt8j.

I run the following Windows PowerShell commands to import a .cer file from the local machine and upload the certificate to the client application entry:

Connect-msolservice
$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate
$cer.Import("$pwd\MyConsoleClientCert.cer")
$binCert = $cer.GetRawCertData()
$credValue = [System.Convert]::ToBase64String($binCert);
New-MsolServicePrincipalCredential -AppPrincipalId "<client id>" -Type asymmetric -Value $credValue -StartDate $cer.GetEffectiveDateString() -EndDate $cer.GetExpirationDateString() -Usage verify

The clientid in this command is the one I copied in the previous step. To verify the certificate uploaded successfully, I run the following cmdlet providing the clientid:

Get-MsolServicePrincipalCredential -AppPrincipalId "<clientid>" -ReturnKeyValues 1

This will display all certificates associated with the clientid. In this case, it should display one. I’m done setting up my apps in AAD. The next step is to enable the Web site and client for which I’ll use AAD for authentication. First, I’ll update MyAzureWebsiteSample project to be set up for AAD. I’ll add the following OWIN security NuGet packages related to authentication: Microsoft.Owin.Security and Microsoft.Owin.Security.ActiveDirectory.

In the Startup class of the MyAzureWebsiteSample, I add the following code to the Configuration method:

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
  new WindowsAzureActiveDirectoryBearerAuthenticationOptions {
    TokenValidationParameters = new TokenValidationParameters
      {
        ValidAudience = "https://[mydomain].onmicrosoft.com/MyAzureWebsiteSample",
        ValidateAudience = true,
      },
      Tenant = "[mydomain].onmicrosoft.com"
});

You’ll replace [mydomain] with the name of your AAD directory domain. This will tell the Web site to use AAD authentication for the specified audience URI. Clients accessing the service will need to provide this URI for getting a token from AAD. On the client console, I use the Active Directory Authentication Library, also called ADAL, for authentication logic and add the MyConsoleClient NuGet package to the console application.

ADAL

In the client, I’ll use APIs provided by ADAL to acquire a token from AAD by providing the certificate credentials. I replace the previously added code with the code in Figure 8, which includes authentication.

Figure 8 Add Authentication to the API

var httpClient = new HttpClient();
var requestMineType = new MediaTypeWithQualityHeaderValue("application/json");
  httpClient.DefaultRequestHeaders.Accept.Add(requestMineType);
var authContext = new  AuthenticationContext(
  "https://login.windows.net/[mydomain].onmicrosoft.com");
var clientAssertionCertificate = new ClientAssertionCertificate("<clientId>",
  GetX509CertObject("CN=MyClientConsoleCert"));
var authResult = authContext.AcquireTokenAsync(
  "https://[mydomain].onmicrosoft.com/MyAzureWebsiteSample",
  clientAssertionCertificate).Result;
httpClient.DefaultRequestHeaders.Authorization =
  new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
var httpResponse =
  httpClient.GetAsync(
  "https://MyAzureWebsiteSample.azurewebsites.net/MyWeb").Result;
Console.WriteLine(httpResponse.Content.ReadAsStringAsync().Result);
Console.ReadLine();

You’ll replace the clientid and the name of my certificate with your own. I’ve abstracted the certificate retrieval code into the GetX509CertObject method, which reads the certificate store and creates the X509Certificate object. If you use the APIKey instead of certificate authentication, then you’ll construct a ClientCredential object passing in the clientId and the APIKey noted down from the portal, instead of passing the ClientAssertionCertificate object. If no client credentials are provided to acquire the token, you’ll be prompted for AAD tenant user credentials.

I run the code in Figure 8 to authenticate the client and invoke the MyAzureWebsiteSample controller method and print [“value1”, “value2”]. The controller will be presented with the Claims of the client I can use to further authorize the client. 

Automate Deployment

So far, I’ve worked with a development environment to deploy the Azure Website. I just check in the code and the site is deployed, or right-click and it’s published—it’s that easy.

However, that’s not the case for QA or production environments. It may not be feasible to deploy from Visual Studio. Now I’ll show you how to automate deployment to any environment using Windows PowerShell. I can perform all these steps from the Portal, as well, but that will involve many manual steps.

Azure PowerShell provides cmdlets to create Azure resources such as Web sites, storage and so on. I’ll go over a few of the important aspects of my automation script. The full script is available in the source code download accompanying this article. The resource manager mode in Azure PowerShell lets you logically group multiple resources like Web site, redis cache, SQL Azure and others into a resource group. I use the Switch-AzureMode cmdlet to switch my Azure PowerShell environment between ResourceManager mode and ServiceManagement mode.

The following code illustrates a few noteworthy points from the script. First, the Add-AzureAccount displays an interactive window prompting me to sign in to my Azure account. The Select-AzureSubscription sets the current Subscription. Then I switch modes to ResourceManager and create a new ResourceGroup and add my Web site as a new resource:

$SubscriptionId = "<subscriptionid>"
Add-AzureAccount
Select-AzureSubscription -SubscriptionId $SubscriptionId -Current
Switch-AzureMode -Name AzureResourceManager
$myResourceGroup = New-AzureResourceGroup -Name "MyResourceGroup" -Location "West US"
$mywebsite = New-AzureResource -Name "MyAzureWebsiteSample"
  -ResourceType "Microsoft.Web/sites" -ResourceGroupName "MyResourceGroup"
  -Location "West US" -ApiVersion "2014-04-01" -PropertyObject @{}

I use the resourcetype as Microsoft.Web/sites. There are other resourcetypes such as Microsoft.Sql/servers/databases you can create with the New-resource cmdlet. In this snippet, I’ll create an AzureStorageAccount to associate it to my Web site for storing diagnostics tracing. Here I am not using ResourceManager cmdlets. I created the AzureStorageAccount outside my ResourceGroup. At this time, adding storage accounts to ResourceGroups is not yet supported. To create a table in the storage, I need to obtain the context. I get the context by passing in the storageAccountKey. The storageAccountKey is passed from one cmdlet to another without the user having to know specifics: 

$myStorage = New-AzureStorageAccount -StorageAccountName "MyStorageAccount"
  -Location "West US"
$storageAccountKey = Get-AzureStorageKey -StorageAccountName "MyStorageAccount"
$context = New-AzureStorageContext -StorageAccountName "MyStorageAccount"
  -StorageAccountKey $storageAccountKey.Primary
$logTable = New-AzureStorageTable -Name $MyStorageTableName -Context $context

The Enable-AzureWebsiteApplicationDiagnostic cmdlet will enable the diagnostics using the storage account I provided:

Enable-AzureWebsiteApplicationDiagnostic -Name "MyAzureWebsiteSample"
  -Verbose -LogLevel Information -TableStorage
  -StorageAccountName "MyStorageAccount" –StorageTableName $MyStorageTableName

For any Web site, there are some settings in the AppSettings of the web.config that are environment-specific. The following snippet shows how to replace Appsettings for an Azure Web site based on the environment to which it’s being deployed. These settings will override the values present in the Web site’s web.config:

$appSettings = @{
  "CurrentEnv" = “Test”;
  "ida:Audience" = “https://[mydomain].onmicrosoft.com/MyAzureWebsiteSample”;
  "ida:ClientId" = "8845acba-0820-4ed5-8926-5652s5353s662";
  "ida:Tenant" = "[mydomain].onmicrosoft.com";
  "any:other" = "some other setting";
} 
Set-AzureWebsite -Name “MyAzureWebsiteSample” -AppSettings $appSettings

A collection of key values are created and set on the Web site by invoking Set-AzureWebsite. This will override the settings in the web.config. You can also change this from the portal later.

So far, I’ve set up my Web site’s infrastructure. Now, I want the application logic in my service to be published. I’ll use the Publish-­AzureWebsiteProject cmdlet to do this job. I have to provide my sitename and the package produced as part of the build output for my project:

Publish-AzureWebsiteProject -Package "<packagepath>" -Name "MyAzureWebsiteSample"

I took the package path from my build output:

drop\_PublishedWebsites\MyAzureWebsiteSample_Package\MyAzureWebsiteSample.zip

The script also uploads the certificate to AAD. You can download the full script from the code download accompanying this article. You can also check bit.ly/1zTBeQo to learn more about the feature-rich experiences the Azure Websites portal provides for managing Web site settings and secrets as you move from development to integration to production deployment environments.  

Enable Application Insights

Once your site is in production, you can get the telemetry to understand how the site is behaving in terms of scaling and performance needs. Application Insights provides a telemetry solution for Azure deployed resources. To enable Application Insights, I had to select it as part of the site template. This adds the necessary NuGet packages and an ApplicationInsights.config file (which contains the instrumentation key) to the project. Now when the site is published, the ApplicationInsights resource is created and linked with the key in the config file.

For production environments, create an ApplicationInsights resource on the new portal. At this time, there are no Azure PowerShell cmdlets available to set up the AppInsights on the portal. From the properties, make a note of the Instrumentation key. You need to add this key to the ApplicationInsights.config file before the Web site is published to ensure it’s deployed with the site.

However, there’s no way to update this file during site publishing. You can get around this issue by not relying on the key from the ApplicationInsights.config file. Instead, add the key to appsettings. This way, you can override it for each environment. How does the site know to use this key? For that, I updated the startup code in my Web site to read the key from the web.config and set it in the App Insights configuration object:

Microsoft.ApplicationInsights.Extensibility.
  TelemetryConfiguration.Active.InstrumentationKey = "<read key from appsettings>";

I also removed the key from my ApplicationInsights.config file because it’s no longer required. Now I pass the key to my automation Azure PowerShell script. This updates the appsettings during site deployment. Once you’ve set up Application Insights, you can view performance data on the portal or by installing monitoring agents.

Wrapping up

This is a basic step-by-step article for taking an Azure Website from a development environment and setting up authentication and automating deployment in Azure, all the way to a production environment. Azure has come a long way in providing rich and powerful APIs using Azure PowerShell and the new enhanced portal at portal.azure.com.

You can extend this setup to add your own resources such as SQL Azure or additional storage resources. Using the techniques mentioned here, you should be able to quickly spin up a new Azure Website and set up authentication and automation for deployments to any environment.


Gyan Jadal is a software engineer working for Microsoft. He has extensive experience designing and developing solutions for applications based on Azure and enterprise on-premises systems. Reach him at gjadal@microsoft.com.

Thanks to the following Microsoft technical expert for reviewing this article: Mani Sengodan