8

Our situation is that we expect to be frequently adding new custom sub-domains to a number of Azure Websites and we need to be able to automate the process so we can minimize any need for manual intervention and the risk of screwing something up.

The Azure Cross-Platform CLI tools and PowerShell cmdlets provide enough functionality for me to script it all out, with the apparent exception of the SSL bindings... The websites are all HTTPS-only, and every domain that we add requires an SNI SSL binding.

The Azure management portals allow you to manually configure the SSL bindings for a website's domains. How can I achieve the same using the PowerShell cmdlets or the cross-platform CLI tools? If it's not possible using either of those tools, is there some other way I can script out the process for when we add/remove domains to the sites?

2 Answers 2

7

I've finally managed to successfully do this by using the Azure Web Sites Management REST API.

The original documentation which I based my example code below on back in 2014 is no longer available, but the Azure Resource Explorer which Zain mentioned and linked to a blog post about in the comments is in my opinion a superior resource. Direct link: https://resources.azure.com/

The Service Management REST API Reference appears to be the closest thing to the original documentation I used but presently lacks anything specifically about Azure Web Apps (previously known as Azure Websites): https://msdn.microsoft.com/library/azure/ee460799.aspx

E.g.:

using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

private const string managementThumbprint = "0000000000000000000000000000000000000000";
private const string subscriptionId = "00000000-0000-0000-0000-000000000000";

private const string sslThumbprint = "0000000000000000000000000000000000000000";
private const string webspace = "eastasiawebspace";
private const string websiteName = "myWebsite";
private const string websiteDomain = "myDomain";
private const SslState sslState = SslState.SniEnabled;

public async Task SetSslState()
{
    //Retrieve management certificate
    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly);
    var certificate = store.Certificates.Cast<X509Certificate2>().First(xc => xc.Thumbprint.Equals(managementThumbprint, StringComparison.OrdinalIgnoreCase));

    //Setup http client
    var handler = new WebRequestHandler();
    handler.ClientCertificates.Add(certificate);
    var client = new HttpClient(handler) {
        BaseAddress = new Uri("https://management.core.windows.net/" + subscriptionId + "/services/WebSpaces/")
    };
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Add("x-ms-version", "2014-06-01");

    var requestData = new {
        HostNameSslStates = new[] {
            new {
                Name = websiteDomain,
                SslState = (long)sslState,
                Thumbprint = sslThumbprint,
                ToUpdate = true
            }
        }
    };
    var response = await client.PutAsJsonAsync(webspace + "/sites/" + websiteName, requestData);
}

public enum SslState
{
    Disabled = 0,
    SniEnabled = 1,
    IpBasedEnabled = 2
}
Sign up to request clarification or add additional context in comments.

2 Comments

@zain-rizvi At the linked Service Management REST API Reference (msdn.microsoft.com/library/azure/ee460799.aspx) I'm unable to find any documentation about Azure Websites (which existed once upon a time last year), am I missing something there?
Check out Azure Resource Explorer. It'll help you figure out the REST api for Azure Websites (now renamed to Azure Web Apps) azure.microsoft.com/blog/2015/04/02/…
4

This action is now possible using the Azure Resource Manager mode of the Azure Powershell library. This also assumes the chosen certficate is already available within Azure, I already had the certificate in use on other websites, so didn't need to upload it before adding it to a new site.

First, set the library to use the Azure Resource Manager mode. This article contains a good introduction to what this mode provides.

Switch-AzureMode -Name AzureResourceManager
Add-AzureAccount
Select-AzureSubscription -SubscriptionId $subscriptionId

The following variables are used in the code below:

$apiVersion = "2015-08-01"
$subscriptionId = "" #The ID of your Azure subscription
$siteName = "myWebApp"
$resGroup = "myResourceGroup"
$appServicePlan = "myAppServicePlan"
$location = "East US" #Select the appropriate Azure data centre.
$hostName = "mywebapp.mydomain.com"
$sslThumbprint = "" # Thumbprint of SSL certificate uploaded for use in Azure.

Once the correct mode is selected, the following code block will retrieve the current site info. The new SSL info can then be added into a new object which can be added onto the end of the current HostNameSslStates array.

Finally, this can be pushed back into Azure with the Set-AzureResource cmdlet.

# Add SSL binding to custom domain
$r = Get-AzureResource -Name $siteName -ResourceGroupName $resGroup -ResourceType Microsoft.Web/sites -ApiVersion $apiVersion -OutputObjectFormat New
# Create an object containing the desired new SSL configuration
$newSSL = @(
    @{
        "Name" = $hostName;
        "SslState" = 1;
        "Thumbprint" = $sslThumbprint;
        "ToUpdate" = $true;
    }
)
# Create an object which concatenates the existing SSL config with the new config object.
$ssl = @{
    "HostNameSslStates" = $r.Properties.HostNameSslStates + $newSSL
}
# Upload the new configuration into the web app.
Set-AzureResource -ApiVersion $apiVersion -Name $siteName -ResourceGroupName $resGroup -ResourceType Microsoft.Web/sites -PropertyObject $ssl -OutputObjectFormat New

4 Comments

I presume you are copying an SSL certificate from one site to the new one so that you don't need to do the "upload certificate" step for the site. Is that correct? I don't see how this actually works to get an SSL certificate into a brand new website. Or is this an SSL cert held in the Management Certificates area of Azure?
NB: I can only get this to work AFTER the SSL certificate has been uploaded manually to the website I am creating in powershell
The certificate I was using for my new site was a wildcard certificate which had already been uploaded and was in use on an existing site.
The above works for me as well. Wildcard certificate already uploaded into another web site in the same server farm. Please note that you cannot take the output of Get-AzureRMResource and adjust that - this fails silently. But if you create the properties object cleanly, it works fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.