-
Notifications
You must be signed in to change notification settings - Fork 523
Allow to replace the server cert at runtime #2103
Comments
As an alternative, we hope to get SNI support at some point and one of the API proposals is for a callback where you can select your own cert for each connection. This would allow you to change the cert dynamically. |
I would say at worst, this should wait until the "option bag" for SslStream is completed, then you could expose that or pass it into Kestrel. At best you will get the callback as mentioned above... |
I doubt the new options bag will be exposed by kestrel APIs. For now it's Core only. |
The middleware could expose a callback today but before we do anything, somebody should hack together a lets encrypt connection adapter for kestrel so that we can see all of the touch points. |
I implemented a very rough draft here: No error handling and this is mostly to see that I could do it. |
@ayende Sweet!
Yea, but that's not a big deal it's only a few files. This should also let us prove out if a callback is enough. |
A callback for the certificate would be enough, yes. |
The major issue here is that we need some way to prove to Let's Encrypt that we are the owners of the domain. We can do that in various ways, but the easiest from our perspective at this point is to use the This basically means that we ask Let's Encrypt for a certificate, and we need to prove we own this domain. We do that by getting a token from Let's Encrypt and asking it to call back to us (over HTTP, using port 80) and thus proving how this can happen. I thought about having a kestrel instance that is always on using port 80, but it seems easier to just open it to the few seconds we need to do the verification. It would probably be easier to do this using DNS, but that require you to use some API and bind you to a specific DNS provider. I couldn't find a way to make Kestrel route based on the listen source anyway, and I don't think it matters too much. |
https://github.com/dotnet/corefx/issues/22510 Can't use protected data. Like secure string it either throws or just isn't (secure) |
Let me qualify that. On anything other than windows |
The actual problem here is that we need to persist the cert to disk. We can do that with OS permissions so only the current user can touch it, or provide callbacks to the user to handle caching the certificate if they want to customize that (such as storing in a vault). |
Why does it need to go to disk? Can't you just use the bytes [] ? |
Let's Encrypt encourages you to keep the same certificate around, rather than renew it on every start. |
I guess that's a problem for people with crappy code that restart often of which I am sure yours is not ;). Maybe make an option to "persist certificates to disk" |
@Drawaes Consider the case of a user running in development mode. For that matter, even CI that continuously deploy will have to deal with this, in production. |
I updated the code, so this should be clearer now. |
Yeah dev it's fine... |
@ayende for development mode user could use staging let's encrypt environment. |
Actually the more I think about it, when does a Dev have a publicly facing DNS to get a cert in the first place? |
@Drawaes In my case when Dev is developing let's encrypt's automated certificate renewal :) |
They only issue domain validated certs and only for 90 days at a time. Rate is 5 times a week for same cert; 20 times for domain and all its sub-domains; which is quite low for a test server - so you'd want to be caching it. @ayende's use ASP.NET's |
@Soarc Except that you want to hit your website in the browser (or from you manager's browser) and have it Just Work. @Drawaes dynamic DNS would do quite well for these cases. Or CI deployments, etc. @benaadams Yes, you have to cache that. |
It works via DI so is its externalized to the users choice of mechanism; though you'd probably need to change the |
The problem is that at this point you'll need to provide Not just how to protect it but also where to protect it. |
Apache has gone built-in for let's encrypt https://letsencrypt.org/2017/10/17/acme-support-in-apache-httpd.html |
@joshfree To implement this, we'll need SNI on Core to support something like this in a future release. Heads-up. cc @shirhatti |
SNI uses the SSLStream from .Net Core to transmit data. I am not sure how SNI is relevant here. |
@saurabh500 Proposal at this issue would possibly enable this. @Tratcher can share some more details. @shirhatti @DamianEdwards Let's decide if we want this feature in 2.2 which would drive feature requirements from the CoreFX side. |
We know this feature is not the intended purpose of SNI, however the the proposed SNI API with the delegate callback would also enable this scenario. |
Ah OK. The SNI here is |
Closing this one. We'll revisit the bigger scenario in the future. |
Right now, the SSL certificate that Kestrel will use is here:
https://github.com/aspnet/KestrelHttpServer/blob/dev/src/Kestrel.Https/Internal/HttpsConnectionAdapter.cs#L25-L26
There are certain scenarios that we want to support replacing the certificate while the server is still running. This can be done quite easily if we could set the
_serverCertificate
so all new connections will be able to use that.Scenarios for that include using Let's Encrypt certificates and not having to restart every 3 months.
While making it public is one option, I think it would be better to not hold a reference to the
_serverCertificate
from the options but use the value in the options itself. That will mean that the caller could hold on to the options and change the certificate value used without messing with any internal state.The text was updated successfully, but these errors were encountered: