aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

AspNetCore.DataProtection `ProtectKeysWithCertificate` rotation mechanism

Open msschl opened this issue 3 years ago • 4 comments

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

msschl avatar Feb 11 '22 14:02 msschl

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.

ghost avatar Feb 11 '22 21:02 ghost

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.

blowdart avatar Feb 11 '22 21:02 blowdart

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.

msschl avatar Feb 12 '22 20:02 msschl

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.

ghost avatar Sep 09 '22 21:09 ghost

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 avatar Nov 22 '22 03:11 jeremy-morren

@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?

amcasey avatar Aug 31 '23 21:08 amcasey

I see a few things going on here:

  1. There's no built-in way to rotate (non-key store) certificates without re-deploying
  2. 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)
  3. 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).

amcasey avatar Aug 31 '23 21:08 amcasey