aspnetcore
aspnetcore copied to clipboard
AspNetCore.DataProtection `ProtectKeysWithCertificate` rotation mechanism
Is there an existing issue for this?
- [X] I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
Protecting keys at rest is a good practice and is often done via the ProtectKeysWith...
methods like ProtectKeysWithCertificate
.
However, protecting the keys with for example ProtectKeysWithCertificate
and an X509Certificate2
keeps the problem of rotating the certificate used for protecting the keys at rest. Is there a good pattern or some documentation on this topic on how to proceed with rotation certificates used for key protection at rest without restarting the application?
Describe the solution you'd like
Some docs or a API to configure propper certificate rotation for the protection of key in rest.
Additional context
No response
Thanks for contacting us.
We're moving this issue to the .NET 7 Planning
milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
There's no good pattern if you're trying to keep things with certificate locally, rather than key store.
The flow would be
- Generate new certificate
- Load it along side the existing one (whether in Windows Certificate store, or the folder in linux where you have your cert files)
- Deploy that to your servers
- Then update your code or configure to point to the new certificate
- Deploy that
- Done
And never, ever, delete old certificates, even once they've expired, otherwise your old keys aren't going to work (if you know you haven't encrypted anything at rest with the old certs, then you can clean up eventually when you feel like it.
We do use ef core to persist the keys into a database.
- Then update your code or configure to point to the new certificate
Unfortunately, there is no way to update the configuration to point to the new certificates, or is there?
As soon as ProtectKeysWithCertificate
is called it seems like the certificate is configured to be used for the application lifetime.
Thanks for contacting us.
We're moving this issue to the .NET 8 Planning
milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
I would like to state that the current API works, however there is practically no documentation or examples available online. Having literally any documentation (beyond the fact that the methods exist) would be nice. As mentioned, there is no way to change the certificates once the application has started. If you have long-running processes, this is a problem.
Another problem (not with .NET itself, all crypto has this problem) is that the private keys have to be stored somewhere. The whole keyring must itself be encrypted, this is still the developers problem.
The current workflow is as follows (as far as I can make out) - it would be nice if this was officially documented somewhere:
- At any time, there is 1 certificate that is used for encryption and decryption, and 0 or more used for decryption only. These function as 'superkeys': i.e. encryption keys used to encrypt the encryption keys.
- To generate a new encryption key:
- The key is generated
- The key is encrypted using the current encryption certificate. This is done by the
CertificateXmlEncryptor
class. - The public portion of the certificate is stored in the key.
- The key is persisted to the configured
IXmlRepository
(Redis, File etc).
- When a key is loaded and needs to be decrypted
- The thumbprint of the encryption certificate is loaded from the previously stored public portion.
- The thumbprint is looked up in the internal
XmlKeyDecryptionOptions
class. If the certificate is not found, an error occurs (i.e. no payloads encrypted with this key can be decrypted). - The key is decrypted using the private key of the loaded certificate.
As already mentioned, this process is not officially documented anywhere I can find. I am also not 100% sure if that is a correct explanation either, due to the lack of documentation.
@jeremy-morren We have some docs but they're not very discoverable.
https://learn.microsoft.com/aspnet/core/security/data-protection/introduction https://learn.microsoft.com/aspnet/core/host-and-deploy/scaling-aspnet-apps/scaling-aspnet-apps
I think the second one might have been authored after you made your comment. Did you already have a look at these docs (at least, the ones that existed at the time) and find them inadequate or were they too hard to find?
By the way, were the steps you listed intended to address the original question in this issue (how do you swap out the cert that's protecting your keys) or were they just general steps for using Data Protection in aspnetcore?
I see a few things going on here:
- There's no built-in way to rotate (non-key store) certificates without re-deploying
- There are no documents saying as much (generally speaking, I think not documenting missing functionality is fine if it's not a surprising gap that requires a mitigation)
- The general Data Protection documentation is lacking
Have I missed anything? If not, I'd say this should be two issues - one for improving the docs and another proposing we add certificate rotation support (no promises).