3
Hello,
We have two requests as we are trying to automate certificate management:
Recommended Answer
By the way, is this regardless of how the certificate part is configured during the initial installation?
Well, this behavior is specific to the Windows certificate store, but as long as you have configured it to use the certificate store and not import a certificate file, you should be good. We're reviewing the code right now and there's a possibility that we may just pick the first matching certificate instead of the one with the furthest expiration date in the future. If that's not the case, we'll open a ticket to fix this behavior. If it just picks the first as of today, then simply removing the old certificate after adding the new certificate should do the trick.
Best regards,
Marc-André Moreau
Hi,
You can find the source code for Set-DGatewayConfig here: https://github.com/Devolutions/devolutions-gateway/blob/master/powershell/DevolutionsGateway/Public/DGateway.ps1#L363
Here are the parameters it accepts regarding the certificate configuration:
[string] $TlsCertificateFile,
[string] $TlsPrivateKeyFile,
[string] $TlsPrivateKeyPassword,
[ValidateSet("External", "System")]
[string] $TlsCertificateSource,
[string] $TlsCertificateSubjectName,
[string] $TlsCertificateStoreName,
[ValidateSet("CurrentUser", "LocalMachine", "CurrentService")]
[string] $TlsCertificateStoreLocation,
Those are mapped to the gateway.json file which is parsed by Devolutions Gateway:
https://github.com/Devolutions/devolutions-gateway/blob/master/devolutions-gateway/src/config.rs#L949
For the Windows cert store, we took inspiration from Kestrel in ASP.NET, and didn't put an explicit cert thumbprint. Is there a reason why you would prefer to select the certificate by its thumbprint? Aren't the current selection criteria sufficient to find the good certificate? There's also the possibility of using the service certificate store instead of local machine to avoid mixing your certificate with others, and ensuring proper certificate selection.
Best regards,
Marc-André Moreau
Hi,
You can find the source code for Set-DGatewayConfig here: https://github.com/Devolutions/devolutions-gateway/blob/master/powershell/DevolutionsGateway/Public/DGateway.ps1#L363
Here are the parameters it accepts regarding the certificate configuration:
[string] $TlsCertificateFile,
[string] $TlsPrivateKeyFile,
[string] $TlsPrivateKeyPassword,
[ValidateSet("External", "System")]
[string] $TlsCertificateSource,
[string] $TlsCertificateSubjectName,
[string] $TlsCertificateStoreName,
[ValidateSet("CurrentUser", "LocalMachine", "CurrentService")]
[string] $TlsCertificateStoreLocation,
Those are mapped to the gateway.json file which is parsed by Devolutions Gateway:
https://github.com/Devolutions/devolutions-gateway/blob/master/devolutions-gateway/src/config.rs#L949
For the Windows cert store, we took inspiration from Kestrel in ASP.NET, and didn't put an explicit cert thumbprint. Is there a reason why you would prefer to select the certificate by its thumbprint? Aren't the current selection criteria sufficient to find the good certificate? There's also the possibility of using the service certificate store instead of local machine to avoid mixing your certificate with others, and ensuring proper certificate selection.
Best regards,
Hello,
Thank you for the reply.
Well, imagine you have a certificate that is near it's expiration date and want to import a new certificate into Windows cert store, using an automated renewal process. You would want to be able to use the same SubjectName, store it in the same same location etc. when designing the renewal solution, especially when the cert store itself supports having multiple certificates in the same location with the same SubjectName. Using the parameters above for selecting certificate, would end up with multiple matches.
We could (and probably will) remove the old certificate as a step in this whole process (to segway to my 2nd point); the lack of error codes whenever Set-DGatewayConfig fails to set a new ceritificate for whatever reason. In the best of worlds we wouldn't want to delete the old certificate unless the Set-DGatewayConfig is successful, as this will otherwise risk causing downtime.
Hi Simon,
Here is the original pull request where the Windows certificate support was added, it has some explanation for the logic used:
https://github.com/Devolutions/devolutions-gateway/pull/576#issuecomment-1772675506
We've tried to match how Kestrel handles certificate configuration instead of coming up with our own:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-7.0#certificate-sources
The logic is that it picks the matching certificate with the furthest expiration date: this means that if you add the new certificate and leave the old one, it will correctly pick up the new one.
I'm not saying no to adding explicit thumbprint certificate selection, but maybe you don't need it after all: done properly you may not even need to touch the Devolutions Gateway configuration, only renew the certificate and let it load the new one automatically using the same selection criteria originally configured.
However, I would need to double-check when Devolutions Gateway reloads the configuration, I'll come back to you on this.
Best regards,
Marc-André Moreau
Hi Simon,
Ok, so I just inquired and you're probably going to prefer the current way it works. Simply put, once you've set the Windows certificate store criteria (subject name, cert store, etc) Devolutions Gateway will automatically pick the matching certificate with the furthest expiration date on every TLS accept. This means that as soon as you've added the new certificate to the cert store, it will get picked up for new connections without having to reload the configuration by restarting Devolutions Gateway. zero downtime, even if the old certificate remains in the cert store, it will get discarded in favor of the new one with an expiration date further in the future.
This is better in many ways: no need to manually reconfigure Devolutions Gateway on every certificate renewal, and there's nothing to be done to force it to pick up the new certificate, it will be transparent. Would this solve your problem or is there something else where it may not fit your needs?
Best regards,
Marc-André Moreau
Hi Simon,
Ok, so I just inquired and you're probably going to prefer the current way it works. Simply put, once you've set the Windows certificate store criteria (subject name, cert store, etc) Devolutions Gateway will automatically pick the matching certificate with the furthest expiration date on every TLS accept. This means that as soon as you've added the new certificate to the cert store, it will get picked up for new connections without having to reload the configuration by restarting Devolutions Gateway. zero downtime, even if the old certificate remains in the cert store, it will get discarded in favor of the new one with an expiration date further in the future.
This is better in many ways: no need to manually reconfigure Devolutions Gateway on every certificate renewal, and there's nothing to be done to force it to pick up the new certificate, it will be transparent. Would this solve your problem or is there something else where it may not fit your needs?
Best regards,
Hello,
Ok, if that work it would be optimal, we would just monitor the published certificate pretty much to see that the renewal is working. We will try it out, thank you.
Regards,
Simon
Hi Simon,
Ok, so I just inquired and you're probably going to prefer the current way it works. Simply put, once you've set the Windows certificate store criteria (subject name, cert store, etc) Devolutions Gateway will automatically pick the matching certificate with the furthest expiration date on every TLS accept. This means that as soon as you've added the new certificate to the cert store, it will get picked up for new connections without having to reload the configuration by restarting Devolutions Gateway. zero downtime, even if the old certificate remains in the cert store, it will get discarded in favor of the new one with an expiration date further in the future.
This is better in many ways: no need to manually reconfigure Devolutions Gateway on every certificate renewal, and there's nothing to be done to force it to pick up the new certificate, it will be transparent. Would this solve your problem or is there something else where it may not fit your needs?
Best regards,
By the way, is this regardless of how the certificate part is configured during the initial installation?
By the way, is this regardless of how the certificate part is configured during the initial installation?
Well, this behavior is specific to the Windows certificate store, but as long as you have configured it to use the certificate store and not import a certificate file, you should be good. We're reviewing the code right now and there's a possibility that we may just pick the first matching certificate instead of the one with the furthest expiration date in the future. If that's not the case, we'll open a ticket to fix this behavior. If it just picks the first as of today, then simply removing the old certificate after adding the new certificate should do the trick.
Best regards,
Marc-André Moreau
Hi,
You can find the source code for Set-DGatewayConfig here: https://github.com/Devolutions/devolutions-gateway/blob/master/powershell/DevolutionsGateway/Public/DGateway.ps1#L363
Here are the parameters it accepts regarding the certificate configuration:
[string] $TlsCertificateFile,
[string] $TlsPrivateKeyFile,
[string] $TlsPrivateKeyPassword,
[ValidateSet("External", "System")]
[string] $TlsCertificateSource,
[string] $TlsCertificateSubjectName,
[string] $TlsCertificateStoreName,
[ValidateSet("CurrentUser", "LocalMachine", "CurrentService")]
[string] $TlsCertificateStoreLocation,
Those are mapped to the gateway.json file which is parsed by Devolutions Gateway:
https://github.com/Devolutions/devolutions-gateway/blob/master/devolutions-gateway/src/config.rs#L949
For the Windows cert store, we took inspiration from Kestrel in ASP.NET, and didn't put an explicit cert thumbprint. Is there a reason why you would prefer to select the certificate by its thumbprint? Aren't the current selection criteria sufficient to find the good certificate? There's also the possibility of using the service certificate store instead of local machine to avoid mixing your certificate with others, and ensuring proper certificate selection.
Best regards,
What's your take on my 2nd request? I just found out that we didn't use the (mandatory?) ProvisionerPublicKeyFile parameter during a renewal procedure with Set-DGatewayConfig, resulting in downtime (#00085017). Can you add some kind output to this command?
For additional parameter validation:
The provisioner public key file is indeed mandatory in the configuration for the service to start, but Set-DGatewayConfig only serves as a setter for all the fields of the gateway.json file, without having 20+ different "Set" cmdlets.
You say you've hit issues during a renewal, but if you are renewing certificates, don't you update an existing configuration that already has the provisioner public key? Set-DGatewayConfig updates the config, it won't remove it or require everything to be passed again.
A New-GatewayConfig cmdlet could have stricter validation that leads to a fully functional configuration in one go, assuming you're making a new configuration that overwrites what is already there instead of updating it. I'm not sure this would really help if you're updating a configuration and want to tell if you're missing anything.
A Test-DGatewayConfig cmdlet could perform some generic validation of the configuration file and throw warnings if important fields are missing. Maybe we could run it automatically during Set-DGatewayConfig, would this have helped in the case you encountered?
Marc-André Moreau
Devolutions Gateway will automatically pick the matching certificate with the furthest expiration date on every TLS accept. This means that as soon as you've added the new certificate to the cert store, it will get picked up for new connections without having to reload the configuration by restarting Devolutions Gateway.
Hello again,
I can't replicate this behavior though. Once I install en new certificate (same CN) and remove the old, the web service still present the old certificate. Not sure how often TLS accept is triggered, but eventually the service switches to not showing any certificate at all, displaying a ERR_SSL_PROTOCOL_ERROR. Once I restart the GW service, it picks up the new certificate and the service is restored.
Regarding my other post about we experiencing downtime when renewing certificates was likely more related to exactly this, and not us running Set-DGatewayConfig without ProvisionerPublicKeyFile as I first thought.