1
votes

I'm using the Azure Fluent Management API to automate our deployment process. Up until now, I've had minimal problems.

We have SSL certificates already uploaded into Azure and can manually bind them to a web site through the Azure portal. But I can't find a mechanism for doing this programmatically.

The closest I can find is below and in the documentation here.

webApp.Update()
    .DefineSslBinding()
    .ForHostname(domainName)
    .WithPfxCertificateToUpload(pfxFile, password)
    .WithSniBasedSsl()
    .Attach();

However, this is obviously uploading a new certificate, not using an existing one. There are two other options after the ForHostName() call:

WithExistingAppServiceCertificateOrder(certificateOrder)

and

WithNewStandardSslCertificateOrder(certificateOrderName)

But my understanding is that these are related to purchasing the certificates through Azure/Microsoft.

I also can't see anything in the REST API documentation.

So, how can I associate an existing certificate with a web app, in code?

3

3 Answers

2
votes

Obviously this was not critical given I've only found an answer 9 months later.

Anyhow, the answer below is copied from the link provided.

await azure
        .WebApps
        .Inner
        .CreateOrUpdateHostNameBindingWithHttpMessagesAsync(
            resourceGroupName, 
            webAppName, 
            domain,
            new HostNameBindingInner(
                azureResourceType: AzureResourceType.Website,
                hostNameType: HostNameType.Verified,
                customHostNameDnsRecordType: CustomHostNameDnsRecordType.CName,
                sslState: SslState.SniEnabled,
                thumbprint: thumbprint));
0
votes

As far as I know, the Azure Fluent Management API’s version is 1.0.0-beta50, so it maybe not contain the method add existing certificate to the host name.

I suggest you could use REST API to achieve it.

I suggest you could send request to below url.

Url: https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/sites/{snapshotName}?api-version={api-version}

Method: PUT

Parameter:
subscriptionId  The identifier of your subscription where the snapshot is being created.
resourceGroup   The name of the resource group that will contain the snapshot.
WebappName    The name of the WebappName. 
api-version The version of the API to use.

Request content:
{
  "properties": {
    "HostNameSslStates": [ 
      {
        "SslState": "the SSL state",
        "ToUpdate": "True",
       "Thumbprint": "The Thumbprint of the certificate, you could find it in the portal",
        "Name": "yourwebsitename"
      }
    ]
},
  "kind": "app",
  "location": "yourlocation",
  "tags": {
    "hidden-related:/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/providers/Microsoft.Web/serverfarms/{yourserviceplan}": "empty"
  }
}

More details, you could refer to below C# codes:

Json.txt:

{
  "properties": {
    "HostNameSslStates": [ 
      {
        "SslState": "1",
        "ToUpdate": "True",
        "Thumbprint": "BE58B05C5CADE03628D0D58B369D0DA6F535B0FA",
        "Name": "test.azureclubs.com"
      }
    ]
},
  "kind": "app",
  "location": "East Asia",
  "tags": {
    "hidden-related:/subscriptions/xxxxxxxxxxxxxxxx/resourcegroups/xxxxxxxxxxxxx/providers/Microsoft.Web/serverfarms/BrandoTestServicePlan": "empty"
  }
}

Code:

string body = File.ReadAllText(@"D:\json.txt");

            // Display the file contents to the console. Variable text is a string.

            string tenantId = "xxxxxxxxxxxxxxxxxxxxxxxxx";
            string clientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
            string clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxx";
            string subscriptionid = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
            string resourcegroup = "BrandoSecondTest";

            string appname = "BrandoTestApp";
            string version = "2015-08-01";

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

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

            string token = result.AccessToken;

            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Web/sites/{2}?api-version={3}", subscriptionid, resourcegroup, appname, version));

            request.Method = "PUT";
            request.Headers["Authorization"] = "Bearer " + token;


            request.ContentType = "application/json";
            try
            {
                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write(body);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            // Get the response
            var httpResponse = (HttpWebResponse)request.GetResponse();
            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                Console.WriteLine(streamReader.ReadToEnd());
            }
0
votes

This solution works in 2021. You only need to know the thumbprint of your certificate and it should be in the same resource group as your web app.

var webApp = azure.WebApps
            .GetById("webapp resource Id goes here")
            .Update()
            .DefineSslBinding()
            .ForHostname("host name goes here")
            .WithExistingCertificate("thumbprint goes here")
            .WithSniBasedSsl()
            .Attach()
            .Apply();