GithubHelp home page GithubHelp logo

fluffyspoon.aspnet.encryptwemust's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fluffyspoon.aspnet.encryptwemust's Issues

Please make certificate password changable, this is a sequrity threat.

Issue:
Stuff like X509Certificate2(data, nameof(FluffySpoon)); with constant passwords makes the system quite vulnerable.

Solution:
A. Keep nameof(FluffySpoon) as sane default, yet allow the user to set his own password
B. Make it random\GUID based so that it would change on each automatic update.

System.NullReferenceException: Object reference not set to an instance of an object.

warn: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
Exception occured renewing certificates: 'Object reference not set to an instance of an object..'
System.NullReferenceException: Object reference not set to an instance of an object.

I just tried adding this to my project, I followed the instruction and looked at the sample but the error above shows up. Any idea what I did wrong?

Fail to load resource from 'https://acme-v02.api.letsencrypt.org/acme/new-order': urn:ietf:params:acme:error:badNonce

I've started getting the following error when renewing certificates:

Exception setting up Let's Encrypt certificate: Fail to load resource from 'https://acme-v02.api.letsencrypt.org/acme/new-order'.
urn:ietf:params:acme:error:badNonce: JWS has an invalid anti-replay nonce: "0001nQHjcj8V0RNRp1k9MRB5NheGz8TT0wLMJgZ9gaSqEiQ"

It happens in FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient.PlaceOrder.

Any idea how to solve this?

Sample applications throws on dns chalanges

First of all, thx for the effort of bringing LetsEncrypt goodness to .net devs!
I am trying to deploy asp.net core app with lets encrypt certificates and decided to try this library.
Unfortunately, I've spent a whole day fighting lets encrypt issues yesterday.

I believe I found a bug/issue in the LetsEncryptRenewalService.cs

With this line present, I am getting this execution log:

Hosting environment: Development
Content root path: C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt.Sample
Now listening on: http://[::]:9999
Now listening on: https://[::]:19999
Application started. Press Ctrl+C to shut down.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Checking to see if in-memory LetsEncrypt certificate needs renewal.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Checking to see if existing LetsEncrypt certificate has been persisted and is valid.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Ordering LetsEncrypt certificate for domains ffmathyletsencrypt2.ngrok.io.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Validating all pending order authorizations.
warn: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Exception occured renewing certificates: 'Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/26169143/dWaKCw'.
urn:ietf:params:acme:error:malformed: No such challenge.'
Certes.AcmeRequestException: Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/26169143/dWaKCw'.
urn:ietf:params:acme:error:malformed: No such challenge
   at Certes.Acme.IAcmeHttpClientExtensions.Post[T](IAcmeHttpClient client, Uri uri, Object payload, Boolean ensureSuccessStatusCode)
   at Certes.Acme.EntityContext`1.Resource()
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateChallengesAsync(IEnumerable`1 challengeContexts) in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 287
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 251
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 273
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.AcquireNewCertificateForDomains(String[] domains) in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 159
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 139
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 146
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync() in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 105

with it commented I am getting this

Hosting environment: Development
Content root path: C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt.Sample
Now listening on: http://[::]:9999
Now listening on: https://[::]:19999
Application started. Press Ctrl+C to shut down.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Checking to see if in-memory LetsEncrypt certificate needs renewal.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Checking to see if existing LetsEncrypt certificate has been persisted and is valid.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Ordering LetsEncrypt certificate for domains ffmathyletsencrypt2.ngrok.io.
info: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Validating all pending order authorizations.
warn: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Exception occured renewing certificates: 'One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it..'
FluffySpoon.AspNet.LetsEncrypt.Exceptions.OrderInvalidException: One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it. ---> System.AggregateException: One or more errors occurred. (urn:ietf:params:acme:error:unauthorized: Invalid response from http://ffmathyletsencrypt2.ngrok.io/.well-known/acme-challenge/dE2H582T8rOFyEfP__0D7Y1oOSBgnNHVJZOn_t1CXac [2600:1f16:d83:1200:6510:cd35:dbb5:e85d]: 404 (challenge type http-01)) ---> System.Exception: urn:ietf:params:acme:error:unauthorized: Invalid response from http://ffmathyletsencrypt2.ngrok.io/.well-known/acme-challenge/dE2H582T8rOFyEfP__0D7Y1oOSBgnNHVJZOn_t1CXac [2600:1f16:d83:1200:6510:cd35:dbb5:e85d]: 404 (challenge type http-01)
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 269
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 273
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.AcquireNewCertificateForDomains(String[] domains) in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 159
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 139
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 146
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync() in C:\work\FluffySpoon.AspNet.LetsEncrypt\src\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 105

It looks like the first log captures exception from the Certes itself, while the second demonstrates correct behavior.

Please let me know if I can configure something inside my code to make it work for http challenges?

If anything I would be glad to help to resolve the issue. (adding tests would be helpful)

One or more errors occurred. | unauthorized: Invalid response | 404 Not Found

Dear @ffMathy

When trying to use your example (in Docker), a problem arises:

info: FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptClient[0]
       Validating all pending order authorizations.
 warn: FluffySpoon.AspNet.EncryptWeMust.Certes.ILetsEncryptRenewalService[0]
       Exception occurred renewing certificates: 'One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it.'
 FluffySpoon.AspNet.EncryptWeMust.Exceptions.OrderInvalidException: One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it.
  ---> System.AggregateException: One or more errors occurred. (urn:ietf:params:acme:error:unauthorized: Invalid response from http://-----My domain--/.well-known/acme-challenge/s8jcPrdR057QevGDD8VFt4IVbDRhVC9Bf0FwTGXm-Y8 [2a0a:7d80:1:7::73:a6]: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p" (challenge type http-01))
  ---> System.Exception: urn:ietf:params:acme:error:unauthorized: Invalid response from http://-----My domain--/.well-known/acme-challenge/s8jcPrdR057QevGDD8VFt4IVbDRhVC9Bf0FwTGXm-Y8 [2a0a:7d80:1:7::73:a6]: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p" (challenge type http-01)
    --- End of inner exception stack trace ---
    --- End of inner exception stack trace ---
    at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptClient.ValidateChallenges(IChallengeContext[] challengeContexts) in /src/FluffySpoon.AspNet.EncryptWeMust/Certes/LetsEncryptClient.cs:line 79
    at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptClient.FinalizeOrder(PlacedOrder placedOrder) in /src/FluffySpoon.AspNet.EncryptWeMust/Certes/LetsEncryptClient.cs:line 59
    at FluffySpoon.AspNet.EncryptWeMust.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate() in /src/FluffySpoon.AspNet.EncryptWeMust/Certificates/CertificateProvider.cs:line 73
    at FluffySpoon.AspNet.EncryptWeMust.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate() in /src/FluffySpoon.AspNet.EncryptWeMust/Certificates/CertificateProvider.cs:line 83
    at FluffySpoon.AspNet.EncryptWeMust.Certificates.CertificateProvider.RenewCertificateIfNeeded(IAbstractCertificate current) in /src/FluffySpoon.AspNet.EncryptWeMust/Certificates/CertificateProvider.cs:line 59
    at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptRenewalService.RunOnceAsync() in /src/FluffySpoon.AspNet.EncryptWeMust/Certes/LetsEncryptRenewalService.cs:line 80
    at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptRenewalService.RunOnceAsync() in /src/FluffySpoon.AspNet.EncryptWeMust/Certes/LetsEncryptRenewalService.cs:line 120
    at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync() in /src/FluffySpoon.AspNet.EncryptWeMust/Certes/LetsEncryptRenewalService.cs:line 133
root@316614:~#  One or more errors occurred. (urn:ietf:params:acme:error:unauthorized: Invalid response from http:// -----My domain--- /.well-known/acme-challenge/s8jcPrdR057QevGDD8VFt4IVbDRhVC9Bf0FwTGXm-Y8 [2a0a:7d80:1:7::73:a6]: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>404 Not Found

And the same problem arises in their projects.
But everything worked fine until September.

Do we need to open port 80 or can some other port be assigned

We use EncryptWeMust on our Azure service fabric cluster to expose https endpoints for our services.

At present, everything works perfectly, i.e. certificates are persisted on the key vault and HTTPS is enabled on our endpoint.

However, our service is exposing from port 9000 (https) and the same service also exposes port 80 (http) for letsencrypt communication. I believe this is for challenge validation.

My question is do we need to always expose port 80 or can that be moved to a different port?
Or can route port 9000 to port 80 as well?

Azure support without needing to load X509 certs

(Sorry for the Azure noise, here, please feel free to ignore me)

The current Azure implementation needs a rather clever workaround for an issue where the Azure API no longer returns the raw bytes of an X509 certificate. #12 implemented this work around, which involves first getting the Azure certificate , and then using the Windows certificate store to get the full X509 certificate.

There are a couple of difficult things about using this technique:

  • It's Windows only (maybe that doesn't matter, and the Linux equivalent wouldn't be hard to implement)
  • I think it would need a very slightly different implementation on an "Isolated" Azure App Service. (This wouldn't be hard either)
  • It involves modifying an app setting to permit the Windows certificate store to load the certificate (this setting is a list of permitted thumbprints). This has the negative side effect of causing the application to restart whenever the settings are written, and also it's difficult to manage this setting properly, because it can end up being a mixture of manually added thumbprints (for other certs which the app is using) and automatically added ones (for LetsEncrypt). It's hard for the library to know what's actually needed in that string, and the current code somewhat dodges the issue by just appending new certificate thumbprints to the end, but never removing any. Eventually this would need to be done manually.

Taking a step back, there isn't actually an absolute requirement for an Azure system to have access to this raw certificate data - the only thing it needs to be able to do is to check if the certificate is still valid, and for that it needs only metadata (issue date, expiry date) which is available from the Azure API. It never needs to obtain the full X509 data.

The challenge to getting away from loading the X509 cert is that the current persistence provider mechanism is based on persisting byte arrays, and it's implicit for a site certificate that this byte array will be the representation of an X509 certificate.

If, instead of persisting a byte array, we persisted some sort of IAbstractCertificate which could be
implemented by both a real X509 certificate and an Azure certificate, then the certificate validator could work without ever needing to retrieve the full certificate.

I have done this here - it's not terribly complicated (and it simplifies the Azure code a lot), but it does touch a lot of code, so it would be a hell of a PR to review and I'm not going to post that unless there's an appetite.

Maybe @killswtch would have an opinion, as this is chiefly aimed at removing a bunch of his code :-)

adding domain names fails

Hi @ffMathy.

Thank you for this great lib.

I had initially setup everything with one domain name, running correctly.
Renewal is setup 30 days / 7 days

I've added two domain names.
Just starting the app produces no error, but the cert continues to have just one domain name.

I've tried wiping the saved _Account and _Site files.

This fails with: urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization.'

INFO  2020-05-14 20:52:22,429 [1    ] ncrypt.Certes.ILetsEncryptRenewalService - Application started
INFO  2020-05-14 20:52:22,429 [1    ] ncrypt.Certes.ILetsEncryptRenewalService - Application started
info: FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider[0]
      Checking to see if in-memory LetsEncrypt certificate needs renewal.
INFO  2020-05-14 20:52:22,435 [22   ] Encrypt.Certificates.CertificateProvider - Checking to see if in-memory LetsEncrypt certificate needs renewal.
INFO  2020-05-14 20:52:22,435 [22   ] Encrypt.Certificates.CertificateProvider - Checking to see if in-memory LetsEncrypt certificate needs renewal.
info: FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider[0]
      Checking to see if existing LetsEncrypt certificate has been persisted and is valid.
INFO  2020-05-14 20:52:22,437 [22   ] Encrypt.Certificates.CertificateProvider - Checking to see if existing LetsEncrypt certificate has been persisted and is valid.
INFO  2020-05-14 20:52:22,437 [22   ] Encrypt.Certificates.CertificateProvider - Checking to see if existing LetsEncrypt certificate has been persisted and is valid.
info: FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider[0]
      No valid certificate was found. Requesting new certificate from LetsEncrypt.
INFO  2020-05-14 20:52:22,441 [22   ] Encrypt.Certificates.CertificateProvider - No valid certificate was found. Requesting new certificate from LetsEncrypt.
INFO  2020-05-14 20:52:22,441 [22   ] Encrypt.Certificates.CertificateProvider - No valid certificate was found. Requesting new certificate from LetsEncrypt.
dbug: FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClientFactory[0]
      Creating LetsEncrypt account with email [email protected].
DEBUG 2020-05-14 20:52:22,447 [22   ] sEncrypt.Certes.LetsEncryptClientFactory - Creating LetsEncrypt account with email [email protected].
DEBUG 2020-05-14 20:52:22,447 [22   ] sEncrypt.Certes.LetsEncryptClientFactory - Creating LetsEncrypt account with email [email protected].
info: FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient[0]
      Ordering LetsEncrypt certificate for domains tenant-myname.mydomain.tld, defaulttenant-myname.mydomain.tld.
INFO  2020-05-14 20:52:24,014 [5    ] Net.LetsEncrypt.Certes.LetsEncryptClient - Ordering LetsEncrypt certificate for domains tenant-myname.mydomain.tld, defaulttenant-myname.mydomain.tld.
INFO  2020-05-14 20:52:24,014 [5    ] Net.LetsEncrypt.Certes.LetsEncryptClient - Ordering LetsEncrypt certificate for domains tenant-myname.mydomain.tld, defaulttenant-myname.mydomain.tld.
info: FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient[0]
      Validating all pending order authorizations.
INFO  2020-05-14 20:52:25,118 [6    ] Net.LetsEncrypt.Certes.LetsEncryptClient - Validating all pending order authorizations.
INFO  2020-05-14 20:52:25,118 [6    ] Net.LetsEncrypt.Certes.LetsEncryptClient - Validating all pending order authorizations.
dbug: FluffySpoon.AspNet.LetsEncrypt.Certes.ILetsEncryptChallengeApprovalMiddleware[0]
      Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
DEBUG 2020-05-14 20:52:25,849 [25   ] .ILetsEncryptChallengeApprovalMiddleware - Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
DEBUG 2020-05-14 20:52:25,849 [25   ] .ILetsEncryptChallengeApprovalMiddleware - Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
dbug: FluffySpoon.AspNet.LetsEncrypt.Certes.ILetsEncryptChallengeApprovalMiddleware[0]
      Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
DEBUG 2020-05-14 20:52:26,665 [15   ] .ILetsEncryptChallengeApprovalMiddleware - Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
DEBUG 2020-05-14 20:52:26,665 [15   ] .ILetsEncryptChallengeApprovalMiddleware - Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
dbug: FluffySpoon.AspNet.LetsEncrypt.Certes.ILetsEncryptChallengeApprovalMiddleware[0]
      Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
DEBUG 2020-05-14 20:52:27,676 [9    ] .ILetsEncryptChallengeApprovalMiddleware - Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
DEBUG 2020-05-14 20:52:27,676 [9    ] .ILetsEncryptChallengeApprovalMiddleware - Challenge invoked: /.well-known/acme-challenge/D431C3-xyZQOChKgiWUs7HX1HGc8PkQ6lblVrv50XKg
info: FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient[0]
      Acquiring certificate through signing request.
INFO  2020-05-14 20:52:28,350 [5    ] Net.LetsEncrypt.Certes.LetsEncryptClient - Acquiring certificate through signing request.
INFO  2020-05-14 20:52:28,350 [5    ] Net.LetsEncrypt.Certes.LetsEncryptClient - Acquiring certificate through signing request.
warn: FluffySpoon.AspNet.LetsEncrypt.Certes.ILetsEncryptRenewalService[0]
      Exception occured renewing certificates: 'Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/finalize/13676530/92465686'.
urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization.'
Certes.AcmeRequestException: Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/finalize/13676530/92465686'.
urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization
   at Certes.Acme.IAcmeHttpClientExtensions.Post[T](IAcmeHttpClient client, Uri uri, Object payload, Boolean ensureSuccessStatusCode)
   at Certes.Acme.OrderContext.Finalize(Byte[] csr)
   at Certes.IOrderContextExtensions.Finalize(IOrderContext context, CsrInfo csr, IKey key)
   at Certes.IOrderContextExtensions.Generate(IOrderContext context, CsrInfo csr, IKey key)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient.AcquireCertificateBytesFromOrderAsync(IOrderContext order)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient.FinalizeOrder(PlacedOrder placedOrder)
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate()
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate()
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RenewCertificateIfNeeded(X509Certificate2 current)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync()
WARN  2020-05-14 20:52:29,165 [7    ] ncrypt.Certes.ILetsEncryptRenewalService - Exception occured renewing certificates: 'Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/finalize/13676530/92465686'.
urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization.'
Certes.AcmeRequestException: Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/finalize/13676530/92465686'.
urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization
   at Certes.Acme.IAcmeHttpClientExtensions.Post[T](IAcmeHttpClient client, Uri uri, Object payload, Boolean ensureSuccessStatusCode)
   at Certes.Acme.OrderContext.Finalize(Byte[] csr)
   at Certes.IOrderContextExtensions.Finalize(IOrderContext context, CsrInfo csr, IKey key)
   at Certes.IOrderContextExtensions.Generate(IOrderContext context, CsrInfo csr, IKey key)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient.AcquireCertificateBytesFromOrderAsync(IOrderContext order)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient.FinalizeOrder(PlacedOrder placedOrder)
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate()
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate()
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RenewCertificateIfNeeded(X509Certificate2 current)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync()
WARN  2020-05-14 20:52:29,165 [7    ] ncrypt.Certes.ILetsEncryptRenewalService - Exception occured renewing certificates: 'Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/finalize/13676530/92465686'.
urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization.'
Certes.AcmeRequestException: Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/finalize/13676530/92465686'.
urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization
   at Certes.Acme.IAcmeHttpClientExtensions.Post[T](IAcmeHttpClient client, Uri uri, Object payload, Boolean ensureSuccessStatusCode)
   at Certes.Acme.OrderContext.Finalize(Byte[] csr)
   at Certes.IOrderContextExtensions.Finalize(IOrderContext context, CsrInfo csr, IKey key)
   at Certes.IOrderContextExtensions.Generate(IOrderContext context, CsrInfo csr, IKey key)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient.AcquireCertificateBytesFromOrderAsync(IOrderContext order)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptClient.FinalizeOrder(PlacedOrder placedOrder)
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate()
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate()
   at FluffySpoon.AspNet.LetsEncrypt.Certificates.CertificateProvider.RenewCertificateIfNeeded(X509Certificate2 current)
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.Certes.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync()

What is the correct way to add names to an already configured certificate ?

/.well-known/acme-challenge returning 404

First, thank you a lot on effort .
Am I doining something wrong .
I did configure my .Net core 2.2 according to your sample.
I did configure my router and dns record to be able to browse site from outside over http and https.

But app daying when try to get certificate
Here is what I get in exception
System.Exception: urn:ietf:params:acme:error:unauthorized: Invalid response from http://pfuprava.ddns.net/.well-known/acme-challenge/MWGmwqTYXeL3N8uJD7WfBdC3gfHUVKOUmuM7XQLZciU [92.36.176.89]: 404

RenewalService: Exception occured renewing certificates: 'Value cannot be null. Parameter name: source.'

I integrated the nuget package of this component some weeks ago into our prject and deployed it to our preview environment. Everything was working fine, certificates were acquired and https was working.
Yesterday I deployed a new version of our project that included the package update from 122 to 125. I am now no longer able to connect to the website. I can see the following error:

`FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService
Exception occured renewing certificates: 'Value cannot be null.
Parameter name: source.'

System.ArgumentNullException: Value cannot be null.
Parameter name: source
at System.Linq.Enumerable.Where[TSource](IEnumerable'1 source, Func'2 predicate)
at FluffySpoon.AspNet.LetsEncrypt.Persistence.PersistenceService.<>c__DisplayClass13_0.b__0(IChallengePersistenceStrategy x)
at System.Linq.Enumerable.SelectArrayIterator'2.MoveNext()
at System.Threading.Tasks.Task.WhenAll(IEnumerable'1 tasks)
at FluffySpoon.AspNet.LetsEncrypt.Persistence.PersistenceService.PersistChallengesAsync(IEnumerable'1 challenges, IEnumerable'1 strategies)
at FluffySpoon.AspNet.LetsEncrypt.Persistence.PersistenceService.PersistChallengesAsync(ChallengeDto[] challenges)
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order)
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.AcquireNewCertificateForDomains(String[] domains)
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync()
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync()
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync()`

I am a bit confused as I think I didn't change anything relevant - could there be a bug in the new package?
I am making very basic use of the component following almost exactly the tutorial (without the optional stuff). Any quick ideas? Any known issues?

Sample looking for `localhost` developer cert upon start

Running FluffySpoon.AspNet.EncryptWeMust.Sample gives me

System.InvalidOperationException: Unable to configure HTTPS endpoint. 
No server certificate was specified, and the default developer certificate could not be found or is out of date.
To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.
For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.

Repro 1

I cloned the ffMathy/FluffySpoon.AspNet.EncryptWeMust and opened in VS2019. Trying to run the sample immediately gives above error.

Repro 2

Same happens with my own repo (https://github.com/chgeuer/IdentityServer4-and-FluffySpoonEncryptWeMust/blob/master/src/IdentityServer/STSProgram.cs).

In an old version, I was able to retrieve the real cert and set it for the TLS endpoint, but that seems no longer suported.

On AzureAppServiceSslBindingCertificatePersistenceStrategy - existing certs can't be serialized into byte[]

Great job on this project! I'm trying it on Azure and am finding that when using the Azure persistence functionality, when it finds the existing certificate that the call to PfxBlob is returning null. This causes the rest of the code to always want to generate a new certificate every hour and then I get rate limiting errors behind the scenes and the application is crashing. Not a lot of info on PfxBlob and why it is no longer working. I'll try to find a fix/workaround but wanted to post here as well.

Error with .NET 6

System.MissingMethodException: Method not found: 'Void Certes.AcmeContext..ctor(System.Uri, Certes.IKey, Certes.Acme.IAcmeHttpClient)'.
at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptClientFactory.GetContext()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptClientFactory.GetContext()
at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptClientFactory.GetClient()
at FluffySpoon.AspNet.EncryptWeMust.Certificates.CertificateProvider.RequestNewLetsEncryptCertificate()
at FluffySpoon.AspNet.EncryptWeMust.Certificates.CertificateProvider.RenewCertificateIfNeeded(IAbstractCertificate current)
at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptRenewalService.RunOnceAsync()
at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptRenewalService.RunOnceAsync()
at FluffySpoon.AspNet.EncryptWeMust.Certes.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync()

Azure deployment slot support

I have been investigating some Azure issues using a deployment slot (the staging slot of our production application) which has thrown up some issues with the current slot support:
(Almost all the code I'm discussing is in AzureAppServiceSslBindingCertificatePersistenceStrategy.PersistAsync)

  1. By default, FS will not find apps in deployment slots when trying to find the app which matches a domain at the start of the persisting process.
  2. There is a string property in AzureOptions called "Slot" which is only ever used as a boolean (i.e. it's tested against null) - there's no use made of the string value of this property.
  3. There are three tests of AzureOptions.Slot against null in PersistAsync, but I think the second two should probably be testing the slot member of the (app,slot) tuple, not the Options member.
  4. This is the nasty one - if you get it working with a slot, then when it comes to update the WEBSITE_LOAD_CERTIFICATES configuration item, it will do it in the main app, not the slot (which was our production app, whoops...)

I would like to propose the following functional changes:

  1. Make the 'find all the apps for the domain' code at the top of PersistAsync search all the apps and any deployment slots. To me, this is what one would expect to happen.
  2. Fix the WEBSITE_LOAD_CERTIFICATES updating code so that if you're working on a slot, it's the slot which gets updated, not its 'base' app.
  3. Mark the 'Slot' property of AzureOptions as obsolete (or remove it, or change it into something with clearer functionality if that's needed)

In addition, I think the following refactoring would be worthwhile and would make the Azure code easier to maintain:

  1. Split PersistAsync in to a number of methods which have clearer responsibilities - it's a very large method at the moment which is doing a whole pile of separate things. This could be a very simple Resharper "Extract Method" sort of refactoring.
  2. Move from the (app,slot) tuple to a full custom class, which can provide accessors for some of the base-types which are common to both app and slot - this would facilitate:
  3. Some bits of code which are currently doubled into 'slot' and 'non-slot' clauses may be able to share more code than they do.

Would you be interested in a PR to do some/all of this?

Account Does not Exist

First time around using LetsEncrypt and this library - excuse if I miss the obvious. Getting the following error when I run the app. I configured the app just like the example + wiki page. Let me know if I'm missing something. It's connecting bus saying my account doesn't exist: Here's the stacktrace:

`2019-03-28 13:49:03 INF Checking to see if in-memory LetsEncrypt certificate needs renewal.
2019-03-28 13:49:03 INF Checking to see if existing LetsEncrypt certificate has been persisted and is valid.
2019-03-28 13:49:03 DBG Using existing LetsEncrypt account.

Unhandled Exception: Certes.AcmeRequestException: Fail to load resource from 'https://acme-staging-v02.api.letsencrypt.org/acme/new-acct'.
urn:ietf:params:acme:error:accountDoesNotExist: No account exists with the provided key
at Certes.Acme.IAcmeHttpClientExtensions.Post[T](IAcmeHttpClient client, Uri uri, Object payload, Boolean ensureSuccessStatusCode)
at Certes.Acme.AccountContext.NewAccount(IAcmeContext context, Account body, Boolean ensureSuccessStatusCode)
at Certes.AcmeContext.Account()
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.UseExistingLetsEncryptAccount(IKey existingAccountKey)
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.AuthenticateAsync()
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync()
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync()
at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.b__16_0(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ThreadPoolWorkQueue.Dispatch()
`

Would a PR to increase/improve logging be accepted?

We're currently trying to debug a problem with using LE with Azure App Services, and it would really help to have some more detailed logging on what is happening.

As an example, we're seeing The given challenge did not match /.well-known/acme-challenge/xxxx among [] - even though we have the challenge memory persistence enabled. It would be handy if we could see challenges being added to and removed from the memory persistence in more detail than is currently possible.

Would you consider taking a PR which substantially increased the logging (at the Debug level, I'd assume) in various bits of the project?

When having IIS in front ...

Hi @ffMathy,

The middleware works as expected 💪 - and I can see that files have been generated in my website root:

  • FluffySpoonAspNetLetsEncryptCertificate_Site
  • FluffySpoonAspNetLetsEncryptChallenge_Challenges
  • FluffySpoonAspNetLetsEncryptCertificate_Account

However, I'm running IIS in front of Kestrel - so what should I do in order to setup SSL bindings for the IIS web-site? I mean, I don't see any new server certificates in IIS, that I can use for my HTTPS -binding.

I just know I'm missing something obvious - hope that you can help 🙌

Samples for adding new domains during runtime

Amazing library! thanks for doing this.

I am looking for an example where I can add support for new domains during runtime after the Startup of an ASPNET CORE server.

Lets assume I start off by supporting www.test.com at startup.

Then after a while, we want to support www.next.com also from the same server. Is that possible? If so, how?

Thank you very much

Target latest lts .net core

I'd like to have a NuGet package targetting .net core 3.1
Let's discuss how we can achieve it.

We can do something similar to what peeps in https://github.com/justeat/JustEat.StatsD/blob/master/src/JustEat.StatsD/JustEat.StatsD.csproj did

E.g. target multiple frameworks + msbuild voodoo for determining depending asp.net core nugets versions

Also, it is unclear how current artifacts are being published. Is it possible to move build pipeline to something like TravisCI or similar?

Challenge fails with Connection refused (challenge type http-01)

I have been tracking down this problem. I have a seriously underpowered ATOM server where lots of problems like thread starvation, low memory situations, low cpu resource, etc. are found. This is part of edge testing.
I found that one of my Docker containers was unable to obtain a new cert even though this worked fine on a "normal" system (i.e., with enough resources).

The call to services.AddFluffySpoonLetsEncrypt will start the renewal process by calling RenewCertificateIfNeeded.

The call to app.UseFluffySpoonLetsEncrypt() will setup the letsencrypt challenge response handling.

Unfortunately, in my case due to the weak server, the LetsEncrypt challenge to my server arrives BEFORE the call to UseFluffySpoonLetsEncrypt is even made, so my server can't respond to the challenge, hence the "Connection refused" response.

The fact that the pipeline isn't ready (and can't be ready) when AddFluffySpoonLetsEncrypt is called and issues the renewal is a problem, at least in my scenario. It works fine on a reasonably well powered server, but with few available threads any server could (in theory) run into this problem.

I think AddFluffySpoonLetsEncrypt shouldn't issue the renewal, Instead, the renewal should be made in UseFluffySpoonLetsEncrypt. At this point enough of the pipeline is available to respond to the challenge.
I'll experiment with this and may submit a PR if I find a decent solution.

BTW, this problem caused me to find #35 when I tried retryandlog as a workaround :-)

Failure to order certificate for multiple domains

var anyValid = challenges.Any(x => x.Status == ChallengeStatus.Valid);

var anyValid = challenges.Any(x => x.Status == ChallengeStatus.Valid);
var allInvalid = challenges.All(x => x.Status == ChallengeStatus.Invalid);

if (anyValid || allInvalid)
    break;

Surely the All / Any is around the wrong way here? Shouldn't it be when all challenges are valid, or any are invalid? On line 41 we have var challengeContexts = await Task.WhenAll(allAuthorizations.Select(x => x.Http()));, and looking at Certes this is taking the first http-01 challenge for the authorization, and therefore each challenge represents an authorization. All authorizations need to be valid for the order to be valid. Therefore, this can exit before the order is valid.

I'm pretty sure this will be the cause of an exception I've been getting (my cert has four alternate names):

Certes.AcmeRequestException: Fail to load resource from 'https://acme-v02.api.letsencrypt.org/acme/finalize/...
urn:ietf:params:acme:error:orderNotReady: Order's status ("pending") is not acceptable for finalization

After the exception happens I still get more challenge verification requests coming in, so obviously Let's Encrypt hasn't finished validating the order, also indicated as the order status being pending. If I retry issuing certificates (i.e. restart the server) a couple of times it manages to get the cert.

I haven't actually tested the suggested change. I also haven't looked at your unit tests in detail, but the client tests seem to only test with one domain – might be a good idea to add a test with a few.

Calling Challenge.Validate() on a "dns-01" type sometimes invalidates all challenges.

Following the change in #21 I'm now able to better pinpoint the other issue I highlid in #20 - there were two issues, of which #21 only solved one. This is about the other.

I get the following error:

�[40m�[1m�[33mwarn�[39m�[22m�[49m: FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService[0]
      Exception occured renewing certificates: 'One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it..'
FluffySpoon.AspNet.LetsEncrypt.Exceptions.OrderInvalidException: One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it.
 ---> System.AggregateException: One or more errors occurred. (errortype null: null errordetails (challenge type http-01)) (urn:ietf:params:acme:error:dns: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.sub.domain.top (challenge type dns-01))
 ---> System.Exception: errortype null: null errordetails (challenge type http-01)
   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) System.Exception: urn:ietf:params:acme:error:dns: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.sub.domain.top (challenge type dns-01)<---

   --- End of inner exception stack trace ---
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 283
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 287
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.AcquireNewCertificateForDomains(String[] domains) in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 164
   at FluffySpoon.AspNetL.etsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 141
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 148
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync() in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 107
FluffySpoon.AspNet.LetsEncrypt.ILetsEncryptRenewalService: Warning: Exception occured renewing certificates: 'One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it..'

FluffySpoon.AspNet.LetsEncrypt.Exceptions.OrderInvalidException: One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it.
 ---> System.AggregateException: One or more errors occurred. (errortype null: null errordetails (challenge type http-01)) (urn:ietf:params:acme:error:dns: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.sub.domain.top (challenge type dns-01))
 ---> System.Exception: errortype null: null errordetails (challenge type http-01)
   --- End of inner exception stack trace ---
 ---> (Inner Exception #1) System.Exception: urn:ietf:params:acme:error:dns: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.sub.domain.top (challenge type dns-01)<---

   --- End of inner exception stack trace ---
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 283
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(String[] domains, IOrderContext order) in:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 287
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.AcquireNewCertificateForDomains(String[] domains) in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 164
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 141
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync() in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 148
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceWithErrorHandlingAsync() in C:\git\projectName\FluffySpoon.AspNet.LetsEncrypt\LetsEncryptRenewalService.cs:line 107

By looking at the acme challenge before and after the .Validate() call on the dns-01 challenge, I noticed that all three challenges change from Pending to Invalid:

{
  "identifier": {
    "type": "dns",
    "value": "sub.domain.top"
  },
  "status": "invalid",
  "expires": "2019-12-12T09:19:22Z",
  "challenges": [
    {
      "type": "http-01",
      "status": "invalid",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/snip",
      "token": "6m6lae8SI116dSCmKDJBpxBVdlI9g8dNhHzbxvCcS6Q"
    },
    {
      "type": "dns-01",
      "status": "invalid",
      "error": {
        "type": "urn:ietf:params:acme:error:dns",
        "detail": "DNS problem: NXDOMAIN looking up TXT for _acme-challenge.sub.domain.top",
        "status": 400
      },
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/snip",
      "token": "6m6lae8SI116dSCmKDJBpxBVdlI9g8dNhHzbxvCcS6Q"
    },
    {
      "type": "tls-alpn-01",
      "status": "invalid",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/snip",
      "token": "6m6lae8SI116dSCmKDJBpxBVdlI9g8dNhHzbxvCcS6Q"
    }
  ]
}

This does not happen when attempting the http-01 challenge (and there's no strategy implemented for tls-alpn-01)

By ignoring the ready-for-validation call for dns-01 like this zigszigsdk@b843ba3 it works, but obviously this is not a proper solution, as it removes the option for DNS challenges.

Whether it's an issue with how this project configures/uses https://github.com/fszlin/certes or if it's an issue with Certes itself, or even with LetsEncrypt, I haven't looked into.

Sadly new projects are moving into gear, so I do not expect to have more time for this, especially now that I have a hack-fix. However, perhaps someone else can use what I've found.

ASP.NET Core 3.0 LetsEncryptChallengeApprovalMiddleware not processing

First off, let me thank you for this awesome library that made my life just so much easier.
I am using it with ASP.NET Core 3.0, v1.137.0 (cloned repo) and v1.111.0 (nuget).
I found that with neither version, the LetsEncryptChallengeApprovalMiddleware would ever be processed. It would be called but passed the request on next.

It looks like
if (context.Request.Path.StartsWithSegments(MagicPrefix))
is causing the issue, because MagicPrefix has an ending slash, which results in the expression evaluating to false (see watch window below). By removing the trailing slash it evaluates correctly.
MagicPrefix is used elsewhere where a slash MUST be present.

image

I found some issues where others ran into this problem, like dotnet/aspnetcore#2713

For now I just made a MagicPrefixWithoutSlash variable in LetsEncryptChallengeApprovalMiddleware for

if (context.Request.Path.StartsWithSegments(MagicPrefixWithoutSlash))

in InvokeAsync.
And everything now magically works.

Again, 1000 thanks for your awesome library.

How to use at request time

I'd like to dynamically create a certificate at request-time - I'm trying to write a reverse proxy that won't know the host until runtime. Is there a way to do this then, instead of on-startup?

Main package missing after rename

It looks like the main core FluffySpoon.AspNet.EncryptWeMust package is not on Nuget - the dependent packages are there (Azure, etc) but not the main one.

I am getting Too many certificates (5) already issued for this exact set of domains in the last 168 hours

I am getting this error on Azure

"Fail to load resource from 'https://acme-v02.api.letsencrypt.org/acme/new-order'. urn:ietf:params:acme:error:rateLimited: Error creating new order :: too many certificates (5) already issued for this exact set of domains in the last 168 hours:"

Based on this discussion Certes package has to be updated
https://community.letsencrypt.org/t/getting-error-when-trying-to-get-a-new-certificate/213226/26

Can not find issuer 'C=US,O=Internet Security Research Group,CN=ISRG Root X1' for certificate 'C=US,O=Let's Encrypt,CN=R3'.

Any idea what we should do here?

Now that "LetsEncryptRenewalService.Certificate" is internal, how do you get the cert for ServerCertificateSelector?

I have the following code running an older version of what was then called LetsEncrypt:

        private static void ConfigureWebHostForHttpAndHttps(IWebHostBuilder webHostBuilder, StandardConfiguration standardConfiguration)
        {
            webHostBuilder.UseUrls($"http://0.0.0.0:{standardConfiguration.Http.HttpPort}", $"https://0.0.0.0:{standardConfiguration.Http.HttpsPort}");
            webHostBuilder.UseKestrel(kestrelOptions =>
                kestrelOptions.ConfigureHttpsDefaults(httpsOptions =>
                {
                    httpsOptions.ServerCertificateSelector = SslCertificateSelector;
                    httpsOptions.SslProtocols = sslProtocols;
                    httpsOptions.OnAuthenticate = SslOptionConfigurer;
                }));
        }

        private static X509Certificate2 SslCertificateSelector(ConnectionContext c, string s) => 
            LetsEncryptRenewalService.Certificate;

I want to update to a newer version of EncryptWeMust, however the above Certificate on LetsEncryptRenewalService was marked as internal in this commit.

How do I fetch the certificate now?

Edit: I suppose I could be naughty and get it with reflection, but I'd rather do it the right way.

Null pointer during validating all pending order authorizations

Hi i'm getting this null pointer exception:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.<>c.<ValidateOrderAsync>b__25_1(IChallengeContext x)
   at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.ValidateOrderAsync(IOrderContext order)
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.AcquireNewCertificateForDomains(String[] domains)
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.RunOnceAsync()
   at FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.<StartAsync>b__16_0(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

I'm currently running the app on the latest version of .net core 2.1, but I couldn't upgrade your package to the latest version (1.118.0). I'm now using version 1.109.0.

Could this be the issue?

Thanks in advance

Azure will not let certificates be updated if they're in use

We're seeing a failure to update our Azure App Service certificate - the message from FluffySpoon which gets logged by our application is:

Exception occured renewing certificates: 'Operation returned an invalid status code 'Conflict'.'

This is thrown by CertificatesOperationsExtensions.UpdateAsync called by PersistAsync in the Azure certificate persistence strategy.

In the Azure portal, you can see an associated activity log error:

Cannot remove certificate with thumbprint XXXX because it is used for hostname .

It appears that although it might once have been possible to call UpdateAsync to replace a cert which was currently bound, this is no longer possible.

My guess is that the general solution to this is to:

  1. Upload a new certificate with a new name
  2. Change the binding to point to the new certificate
  3. Remove the old certificate

I'm quite happy to implement this if it sounds like it would be useful, but I'm not quite sure why nobody else is having this problem, so perhaps I'm missing something. This is a problem which has prevented our main app renewing for the last couple of months (which is as long as it's been using FluffySpoon), and I've just repro'd it on a deployment slot.

There are some other slot-related problems I may file other issues on, but this doesn't seem to be slot-related, as we're seeing it on 'non-slot' apps too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.