letsencrypt-siteextension
letsencrypt-siteextension copied to clipboard
[Azure Function NODEJS] The Lets Encrypt ACME server was probably unable to reach
Hi, I've read a lot of issues out there but I have not found one similar to my case. What I'm having trouble with is that with Azure Functions, after I've configured the function and the proxy, I trigger the extension (No Job) and then I see the call coming to the function and the proper code catched in the function. But I get this log in the function:
2018-12-12T15:00:24.975 [Information] ACME challenge response file 'D:\home\site\wwwroot.well-known\acme-challenge\BKbHYP_KvC6AO7BLfQY2ZJUN-CR_j-gWa700EsRmuUI' not found.
and the result of the extension links to this error:
{
"identifier": {
"type": "dns",
"value": "mysubdomain.mydomain.com"
},
"status": "invalid",
"expires": "2018-12-19T15:00:05Z",
"challenges": [
{
"type": "http-01",
"status": "invalid",
"error": {
"type": "urn:acme:error:unauthorized",
"detail": "The key authorization file from the server did not match this challenge [BKbHYP_KvC6AO7BLfQY2ZJUN-CR_j-gWa700EsRmuUI.wnp07H8xywSb29RajsY9IT_uZYHQd_20GJGfiEDouoI] != []",
"status": 403
},
"uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/CMSt4ykFxDhHXiPE2qQdcHQlOSzlJMbchsv4T7C54_c/208039685",
"token": "BKbHYP_KvC6AO7BLfQY2ZJUN-CR_j-gWa700EsRmuUI",
"validationRecord": [
{
"url": "http://mysubdomain.mydomain.com/.well-known/acme-challenge/BKbHYP_KvC6AO7BLfQY2ZJUN-CR_j-gWa700EsRmuUI",
"hostname": "mysubdomain.mydomain.com",
"port": "80",
"addressesResolved": [
"40.114.210.78"
],
"addressUsed": "40.114.210.78"
}
]
},
{
"type": "dns-01",
"status": "invalid",
"uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/CMSt4ykFxDhHXiPE2qQdcHQlOSzlJMbchsv4T7C54_c/208039686",
"token": "Gv_xLZOrNVtERqen82r660HBmOzHLSZprNRfhtOY4Do"
},
{
"type": "tls-alpn-01",
"status": "invalid",
"uri": "https://acme-staging.api.letsencrypt.org/acme/challenge/CMSt4ykFxDhHXiPE2qQdcHQlOSzlJMbchsv4T7C54_c/208039687",
"token": "AEHGDHZiWxy-KeJzr7BsIExaNg1PZfLgbdOfFmXlYls"
}
],
"combinations": [
[
2
],
[
1
],
[
0
]
]
}
This is the code of the function "renewcert":
const fs = require('fs');
module.exports = function(context, request) {
let code = request['query'].letscode;
const responseFilePath = "D:\\home\\site\\wwwroot\\.well-known\\acme-challenge\\${code}";
context.log("Checking for ACME challenge response at '${responseFilePath}'...");
fs.exists(responseFilePath, (exists) => {
if (!exists) {
context.log("ACME challenge response file '${responseFilePath}' not found.");
context.done(null, {
status: 404,
headers: { "Content-Type": "text/plain" },
body: 'ACME challenge response not found.'
});
return;
}
context.log("ACME challenge response file '${responseFilePath}' found. Reading file...");
fs.readFile(responseFilePath, (error, data) => {
if (error) {
context.log.error("An error occured while reading file '${responseFilePath}'.", error);
context.done(null, { status: 500 });
return;
}
context.log("ACME challenge response file '${responseFilePath}' read successfully.");
context.done(null, {
status: 200,
headers: { "Content-Type": "text/plain" },
body: data
});
});
});
};
And the proxy JSON:
"LetsEncryptProxy": {
"matchCondition": {
"route": "/.well-known/acme-challenge/{code}"
},
"backendUri": "https://azfunctionresourcename.azurewebsites.net/api/renewcert?code=AzUrEfUnCtIOnCoDe==",
"requestOverrides": {
"backend.request.querystring.letscode": "{code}"
}
}
It seems like the extension somehow is not able to create the file in acme-challenge folder. Can you please help me with this?
Thanks in advance!
I had this same problem and here is how I got it to work. First off, I think this only applies to Azure Functions so I'm not sure that there is much here for someone running a web app. My setup is a an Azure Function that uses proxies to call a different Storage account that is setup as a static website. When you click the button for the Lets Encrypt extension to get a certificate at some point in the process it loads a file onto your site that it then requests is from .well-known\acme-challenge. 2 problems, 1) I never saw a folder with that name in my static website, and 2) the real problem, Azure functions can't serve files without extensions, which that challenge file is. So I tried to see if there was a config setting that would allow Azure functions to serve files without extensions, but there is not one I can find. To fix it 2 things need to be done, and you can read more about it here https://matt-roberts.me/lets-encrypt-on-azure-appservices-with-local-cache/ . In your static website create a new container called 'letsencrypt-challenge', and then add these two entries in your Azure Function application settings
letsencrypt:AuthorizationChallengeBlobStorageAccount : your connection string to your static website storage container
letsencrypt:AuthorizationChallengeBlobStorageContainer : letsencrypt-challenge
next you need to create a proxy on your Azure function to the challenge folder like this:
Route Template: /.well-known/acme-challenge/{*restOfChallenge}
https://[yourstaticwebsitehere].blob.core.windows.net/letsencrypt-challenge/.well-known/acme-challenge/{restOfChallenge}
Once I did this, I could see that the Lets Encrypt extension was able to create a file in the new letsencrypt-challenge container that I had made, and it was able to serve up the extension-less file to complete the challenge.
@ewild, thanks for referencing this blog post. It was down the moment I tried to reach the post, but still available in Google cache.
Especially helpful for me was the mentioned change of the URL:
Then, in your code that calls the site extension API, rather than call
letsencrypt/api/certificates/challengeprovider/http/kudu/certificateinstall/azurewebapp
, change that toletsencrypt/api/certificates/challengeprovider/http/blob/certificateinstall/azurewebapp
.
@sjkp, could you please add this important information concerning the API Blob endpoint to the docs as well?
https://github.com/sjkp/letsencrypt-siteextension/wiki/Azure-Function,-Multi-Region,-Local-Cache-support
P.S.: Your site extension works perfectly - thanks a lot for all your work! 😃