You might remember me writing a post on how you can set up your site with SSL while using Let’s Encrypt and Azure App Services.

Well, as it goes, the same post applies for Azure Functions. You just have to do some extra work for it, but it’s not very hard.

Simon Pedersen, the author of the Azure Let’s Encrypt site extension, has done some work in explaining the steps on his GitHub wiki page. This page is based on some old screenshots, but it still applies.

The first thing you need to do is create a new function which will be able to do the ACME challenge. This function will look something like this.

public static class LetsEncrypt
    public static HttpResponseMessage Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "letsencrypt/{code}")]
        HttpRequestMessage req, 
        string code, 
        TraceWriter log)
        log.Info($"C# HTTP trigger function processed a request. {code}");

        var content = File.ReadAllText(@"D:\home\site\wwwroot\.well-known\acme-challenge\" + code);
        var resp = new HttpResponseMessage(HttpStatusCode.OK);
        resp.Content = new StringContent(content, System.Text.Encoding.UTF8, "text/plain");
        return resp;

As you can see, this function will read the ACME challenge file from the disk of the App Service it is running on and return the content of it. Because Azure Functions run in an App Service (even the functions in a Consumption plan), this is very possible. The Principal (created in the earlier post) can create these type of files, so everything will work just perfectly.

This isn’t all we have to do, because the url of this function is not the url which the ACME challenge will use to retrieve the appropriate response. In order for you to actually use this site extension you need to add a new proxy to your Function App. Proxies are still in preview, but very usable! The proxy you have to create will have to redirect the url `/.well-known/acme-challenge/[someCode]` to your Azure Function. The end result will look something like the following proxy.

"acmechallenge": {
  "matchCondition": {
    "methods": [ "GET", "POST" ],
    "route": "/.well-known/acme-challenge/{rest}"
  "backendUri": "https://%WEBSITE_HOSTNAME%/api/letsencrypt/{rest}"

Publish your new function and proxy to the Function App and you are good to go!

If you haven’t done this before, be sure to follow all of the steps mentioned in the earlier post! Providing the appropriate application settings should be easy now and if you just follow each step of the wizard you’ll see a green bar when the certificate is successfully requested and installed!


This makes my minifier service even more awesome, because now I can finally use HTTPS, without getting messages the certificate isn’t valid.

It has become increasingly important to have your site secured via some kind of certificate. Even your Google ranking is affected by it.

The main problem with SSL/TLS certificates is the fact most of them cost money. Now, I don’t have any problem with paying some money for something like a certificate, but it will cost quite a lot if I want to set this up for all of my sites & domains. In theory it’s possible to create a self-signed certificate and publish your site with it, but that’s not a very good idea as there’s no one who trusts your self-signed certificate besides yourself.

Luckily Mozilla is helping us, poor content-creators, out with their service called Let’s Encrypt. Let’s Encrypt is a rather new Certificate Authority which is offering a free, open and automated service to create certificates. Their Getting Started guide contains some details on how to set this up for your website or hosting provider.

This is all fun and games, but when hosting your site(s) in the Azure App Service ecosystem you can’t do much with the steps defined in the Getting Started guide. At least, I couldn’t make any sense off it.

There’s a developer who has been so kind to create a so called Site extension for an Azure App Service called Azure Let’s Encrypt. It comes in two flavors for both x86 and x64 systems. Depending on which platform you have deployed your site to, you need to activate one corresponding this platform.


In order to access these site extensions you’ll have to log in to the Kudu environment of your site (

Once it’s installed you can launch the extension and will navigate to the configuration area of this extension. This screen will show you a number of fields for which most of them have to be filled with correct data.


This form can look quite impressive if you are not familiar with these things. I’m not very familiar with these terms also, but Nik Molnar has a nice post with some details on the matter.

He mentions you should first create two new application settings within the Azure Portal for the App Service you want to enable SSL. The name/key of these settings are AzureWebJobsStorage and AzureWebJobsDashboard. Both should contain a connectionstring to your Azure Storage account, which will look something like the following DefaultEndpointsProtocol=https;AccountName=[storage account name];AccountKey=[storage account key]. The storage account is necessary for the WebJobs, which will be created by the site extension in order to refresh the SSL certificate.

Next up is the hardest part, creating a Server Principal and retrieving a Client Id and Client Secret from it. In this context, a Server Principal can be seen as some kind of authentication server.
If you already have a Server Principal, you can skip the step of creating one. I still had to add one to my subscription. The following script will create one for you.

$uri = ''
$password = 'SomeStrongPassword'

$app = New-AzureRmADApplication -DisplayName 'MySNP' -HomePage $uri -IdentifierUris $uri -Password $password

Needles to say, your PowerShell context needs to be logged in into your Azure subscription before you are able to run this command.

You are now ready to add your application to the server principal with the following commands.

New-AzureRmADServicePrincipal -ApplicationId $app.ApplicationId

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

These commands will add the application and make sure it has the Contributor role, so it will have enough permissions to install and configure certificates.
Make sure you write down the $app.ApplicationId which will be used as the Client Id in the site extension later on.

Now that we have all the information to configure the Let’s Encrypt site extension, we are ready to install it on our App Service. In order to make this even easier, please configure the following Application Settings in your App Service.



Your AAD domain


Your Azure Subscription Id
Can be found on the Overview page of an App Service


The $app.ApplicationId we saved from before


The $password value used in the earlier script


The resource group name your App Service is created on

After installing the site extension, navigate to the configuration page. If all is set up correctly, the fields will all be prefilled with the correct information.


Check the settings and adjust them if necessary. When you are sure everything is set up correct, proceed to the next page.

This next page isn’t very interesting at this time, so we can continue to the final page of the wizard.


Nothing very special over here, just make sure to fill out your e-mail address so you are able to receive notifications from Let’s Encrypt when necessary.

Also good to note, don’t check the Use Staging option. By checking this box the extension will use the test API of Let’s Encrypt and will not create a certificate for you.

Press the big blue button and your site will be available with the certificate after a few moments. The extension uses the challenge-response system of Let’s Encrypt to create a certificate for you. This means it will create a couple of directories in the wwwroot folder of your App Service. This folder structure will look like .well-known\acme-challenge.


If this succeeds, Let’s Encrypt is able to create your certificate.

The challenge-response system folders are hard-coded in the extension. If you run your site in subfolder, like public, website, build, etc. you have to specify this via a special variable. You can add the letsencrypt:WebRootPath key in the application settings and specify the site folder in the value, for example site\wwwroot\public. This is very important to remember. I had forgotten about this on one of my sites and couldn’t figure out why the creation of the SSL certificate didn’t work.

Now that you know how to secure your sites with a free certificate, go set this up right away!

It’s one of those things you need to do once and forget about it. Sometimes it’s necessary to develop something which required talking to a webservice. A lot of the times, the webservice is secured with an SSL certificate in the real world.

As most companies don’t want to spend good money to real SSL certificates for development workstations/servers, we have to create our own. You can of course develop the functionality with a non-secured environment, but for testing purposes it’s probably useful to have the test environment match the QA or production servers.

A while back I had an issue in some production software. We discovered something was malfunctioning I was needed to figure out what was wrong. As the code hadn’t changed in quite some time and it appeared the code was good (enough), I started looking at the infrastructure and discovered it might have something to do with the webservice (in SSL) it was talking to. As I couldn’t connect to the production environment, I had to connect to a local service which was running in SSL, so I did.

If you want to do this, you need to take quite some steps if you are running on IIS 6.0. This feature has improved a lot IIS 7.0/7.5. ScotGu has written a nice walkthough about this. Just hit the Create Self-Signed Certificate link and you are done. Too bad I was still developing in an IIS 6.0 environment (Windows 2003R2). I’ll describe the needed steps below.

The first thing which needs to be done is downloading the IIS 6.0 Resource Kit Tools. This doesn’t appear to be a big problem, but for me it was. I had found a lot of pages linking to the kit, but all of them were dead. After finally having found the correct link I was good to go and installed the needed SelfSSL application.

The tool comes with a decent help which you can check by typing selfssl /? in the command prompt. As we need to add a self-signed certificate to a website in IIS on a specific port number, we need the arguments /T, /S and /P. The values we need can be found in IIS Manager. The site ID and port number is specified in the overview of the websites:


In this case the site ID is 165159687 and the SSL port number we want to use is 82. The command we need to use will look like this:

selfssl /T /S:165159687 /P:82

Now the certificate is in place and you can visit the secured website in the browser. Once there you’ll see a message, something like this (depending on the browser)
(note: the following steps are also needed if you are running on the IIS7.0 webserver and are optional):


As this is our development site we can safely choose Continue on this website (not recommended). Once we are on the website you can see a small message next to the address bar stating there’s a Certificate Error.


You can click on this message and a popup will appear.


By clicking the link View certificates you can add the certificate to your local store so this error won’t be shown again. The following popup will appear:

(machine name and dates will vary)

If you want you can check some of the details in this popup, but as we know this is all good we can just click the Install Certificate button in the lower corner.

Stepping through the wizard you will get the option to place the certificate in a store. I first tried out the Automatically select…., but that didn’t have the desired effect. After that I’ve tried the Personal store, but that didn’t help much either. After having tried those two options, I’ve placed the certificate in the Trusted Root Certification Authorities.


This had the desired effect, I could check the local SSL webservice without the annoying warning messages. With everything up and running the code could be debugged to check it was working properly with an SSL webservice. Lucky for me, it did, so I had to look for another solution for the problem.

Remember, only apply the above steps if you know you can trust the certificate. Don’t add certificates from the web from ‘fishy’ sites. It can cause a lot of problems to you and your computer.