GetSSL - Azure Automation


#1

Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. https://crt.sh/?q=example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is: azure.rokkesoft.dk

I ran this command:
$challenge = Submit-ACMEChallenge -Ref $identifier -ChallengeType http-01

It produced this output:
Certificate generation failed. Status is ‘invalid’, can’t continue as it is not ‘valid’. Let’s Encrypt could not
retrieve the expected content from
azure.foreningonline.dk/.well-known/acme-challenge/7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM/index.html
+ CategoryInfo : NotSpecified: (:slight_smile: [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

My web server is (include version):
Azure

The operating system my web server runs on is (include version):
Azure / Windows

My hosting provider, if applicable, is:
Microsoft Azure

I can login to a root shell on my machine (yes or no, or I don’t know):
Yes

I’m using a control panel to manage my site (no, or provide the name and version of the control panel):
Azure

Notes:
I am using the published script https://www.powershellgallery.com/packages/GetSSL-LetsEncrypt/1.4.3/DisplayScript

To obtain the token. I am able to access the given url: http://azure.foreningonline.dk/.well-known/acme-challenge/7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM/index.html and get the content:

7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM.fTrcNoJ6nPoTPq0V4ICIn-x69W_62sDPY8K2T98iIR0

I use Let’s encrypt from the hosting provider for other subdomains e.g. https://fresh.foreningonline.dk - I realize this is an entirely other case, but just wanted to mention if for completeness.

I really hop you can help.

Kind regards
Søren Rokkedal


#2

Hi Rokke,
We can see that everything has worked well on the script side. The script has successfully created the token in the specific path, sent the validation request to Let’s Encrypt, but Let’s Encrypt has invalidated that request.
Did you follow all the steps in the implementation guide?

For the site https://fresh.foreningonline.dk did you follow the same method?

Best regards,
Dani Alonso


#3

Hi danialonso

I did follow the guide and ran in to the problem described in the bottom of the document. And the Azure job completes.

The solution for fresh.foreningonline.dk is done using a dashboard by my web hotel provider (https://www.unoeuro.com). To the best of my knowledge this is not based on Azure.

Hope You will be able to help me go forward.

Kind regards
Søren Rokkedal


#4

That /index.html at the end is weird because that’s not the URL used by the certificate authority. Indeed, on your site it currently works with the /index.html but not without it. That would presumably be a problem at validation time.

As I’m not familiar with the client software that you’re using, I’m not sure exactly where this problem is being introduced or why it chose to refer to that URL instead of the form without /index.html.


#5

IIS notoriously has issues with extensionless files. It’s possible that some Windows integrations instead create a directory matching the filename with a default document containing the validation token, and rely on the validation server to follow the 301/302 redirect generated by the web server adding the slash. In this case, I would expect to see a trailing slash added to the path and not /index.html though.

Indeed, as you point out, both http://azure.foreningonline.dk/.well-known/acme-challenge/7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM and http://azure.foreningonline.dk/.well-known/acme-challenge/7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM/ fail while http://azure.foreningonline.dk/.well-known/acme-challenge/7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM/index.html returns a token.

So, @rokke there may be a web.config file placed at .well-known/acme-challenge/7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM/web.config that actually should be placed at .well-known/acme-challenge/web.config instead.

If there is no web.config file here, or it is already placed at a higher level, then there is a general issue with your web server configuration where URLs like /foo or /foo/ don’t return /foo/index.html that needs to be fixed to validate your domain in this way.


#6

Hi all

Thanks for all your help. I now have a theory to test out. I created a new blank Azure project and followed the guide referenced by @danialonso. This does indeed work as expected.

The project that I have hosted in the problem app service is an Asp.Net Core 2.0 MVC site. In order to make that serve the needed file, some configuration is needed, namely:

 app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @".well-known")),
                RequestPath = new PathString("/.well-known"),
                ServeUnknownFileTypes = true // serve extensionless files
            });

In contrast to the simple web site I created this does not by default server index.html when accessing e.g. http://azure.foreningonline.dk/.well-known/acme-challenge/7l8AoUiU64XTPnFHXq7U2IuzCYYNNnaB57PPWWy4-IM or the same postfixed / - It does work when postfixing with /Index.html, as that addresses the file directly.

What I need to do is make it serve default files (index.html, default.html, etc.) from within this special folder. In the MVC world these default files does not exist. My current theory is to use app.UseDefaultFiles(), but I’m not sure if that plays well with an MVC project. I will work on that today and will get back to you with my findings.

Once again thanks for taking the time to help me.

Kind regards


#7

It’s hard to tell because I cannot view the source of this script and what this option actually does is not documented, but just guessing by its name I think that setting the UseUnixFileVerification option to true may stop the script from using /index.html, which should work better with your setup.


#8

I finally got it working. I decided to stop struggling with the middleware of Asp.Net Core and just did what I know how to do. I created a special LetsEnryptController to serve up the acme-challenges:

[route=".well-known/acme-challenge"]
public class LetsEncryptController {
  [Route("{challenge}/{filename?}"}
  public IActionResult Index(string challenge, string filename = null)
  {
    var rootPath = Path.Combine(Directory.GetCurrentDirectory(), ".well-known", "acme-challenge");
    var challengeDirectory = Path.Combine(rootPath, challenge);
    var challengeFilename = Path.Combine(challengeDirectory, "index.html");
    return Ok(System.IO.File.ReadAllText(challengeFilename));
  }
}

Obviously with some error handling etc. In Azure with this powershell script the token is stored in the root of the web site, so this works with this setup.

It could probably be solved with some magic configuration, but it works.


#9

This is marked as the solving post, as this was what led me to the core of the problem, namely is is actually not the index.html that is requested, but rather the / of the challenge directory and depending on the default file setup to supply the index.html file.